Files
libreoffice/vcl/generic/fontmanager/parseAFM.cxx

1467 lines
54 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2001-05-08 10:46:10 +00:00
/*
* (C) 1988, 1989, 1990 by Adobe Systems Incorporated. All rights reserved.
*
* This file may be freely copied and redistributed as long as:
* 1) This entire notice continues to be included in the file,
* 2) If the file has been modified in any way, a notice of such
* modification is conspicuously indicated.
*
* PostScript, Display PostScript, and Adobe are registered trademarks of
* Adobe Systems Incorporated.
*
* ************************************************************************
* THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO CHANGE WITHOUT
* NOTICE, AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY ADOBE SYSTEMS
* INCORPORATED. ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY OR
* LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO WARRANTY OF ANY
* KIND (EXPRESS, IMPLIED OR STATUTORY) WITH RESPECT TO THIS INFORMATION,
* AND EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
* ************************************************************************
*/
/*
* Changes made for OpenOffice.org
*
* 10/24/2000 pl - changed code to compile with c++-compilers
* - added namespace to avoid symbol clashes
* - replaced BOOL by bool
* - added function to free space allocated by parseFile
* 10/26/2000 pl - added additional keys
* - added ability to parse slightly broken files
* - added charwidth member to GlobalFontInfo
* 04/26/2001 pl - added OpenOffice header
* 10/19/2005 pl - performance increase:
* - fread file in one pass
* - replace file io by buffer access
* 10/20/2005 pl - performance increase:
* - use one table lookup in token() routine
* instead of many conditions
* - return token length in token() routine
* - use hash lookup instead of binary search
* in recognize() routine
2001-05-08 10:46:10 +00:00
*/
/* parseAFM.c
*
Many spelling fixes: directories r* - z*. Attempt to clean up most but certainly not all the spelling mistakes that found home in OpenOffice through decades. We could probably blame the international nature of the code but it is somewhat shameful that this wasn't done before. (cherry picked from commit 28206a7cb43aff5adb10f8235ad1680c3941ee3e) Conflicts: include/osl/file.hxx include/osl/pipe_decl.hxx include/osl/socket.h include/osl/socket_decl.hxx include/sal/main.h include/svx/dbaexchange.hxx include/svx/dlgctrl.hxx include/svx/msdffdef.hxx include/svx/sdr/contact/objectcontactofpageview.hxx include/svx/svdpntv.hxx include/ucbhelper/content.hxx include/ucbhelper/interceptedinteraction.hxx include/ucbhelper/resultsethelper.hxx include/unotools/sharedunocomponent.hxx include/unotools/viewoptions.hxx include/vcl/pdfwriter.hxx include/xmloff/txtparae.hxx include/xmloff/uniref.hxx rhino/rhino1_7R3.patch rsc/inc/rscrsc.hxx sal/inc/osl/conditn.h sal/inc/osl/security.h sal/inc/osl/semaphor.h sal/inc/osl/semaphor.hxx sal/inc/rtl/string.hxx sal/inc/rtl/tres.h sal/inc/systools/win32/StrConvert.h sal/osl/os2/file_path_helper.h sal/osl/os2/file_path_helper.hxx sal/osl/os2/file_url.cxx sal/osl/os2/file_url.h sal/osl/os2/makefile.mk sal/osl/os2/pipe.cxx sal/osl/os2/process.c sal/osl/os2/profile.c sal/osl/os2/socket.c sal/osl/os2/system.h sal/osl/unx/asm/interlck_sparc.s sal/osl/unx/file_url.cxx sal/osl/unx/signal.c sal/osl/unx/system.h sal/osl/w32/MAKEFILE.MK sal/osl/w32/interlck.c sal/osl/w32/module.cxx sal/osl/w32/security.c sal/qa/buildall.pl sal/qa/osl/file/osl_File.cxx sal/qa/osl/module/osl_Module_Const.h sal/qa/osl/mutex/osl_Mutex.cxx sal/qa/osl/pipe/osl_Pipe.cxx sal/qa/osl/process/osl_Thread.cxx sal/qa/osl/socket/osl_StreamSocket.cxx sal/qa/osl/socket/sockethelper.cxx sal/qa/rtl_strings/rtl_OUString.cxx sal/rtl/source/unload.cxx sal/systools/win32/kill/kill.cxx sal/systools/win32/uwinapi/MoveFileExA.cpp sal/test/bootstrap.pl sal/typesconfig/typesconfig.c sal/workben/tgetpwnam.cxx sax/inc/sax/parser/saxparser.hxx sc/addin/datefunc/dfa.cl sc/addin/datefunc/dfa.src sc/addin/rot13/rot13.cl sc/addin/rot13/rot13.src sc/inc/attarray.hxx sc/inc/chgtrack.hxx sc/inc/column.hxx sc/inc/compressedarray.hxx sc/inc/document.hxx sc/inc/table.hxx sc/source/core/data/column.cxx sc/source/core/data/dptablecache.cxx sc/source/core/data/dptabres.cxx sc/source/core/data/dptabsrc.cxx sc/source/core/data/global.cxx sc/source/core/tool/chgtrack.cxx sc/source/core/tool/compiler.cxx sc/source/filter/excel/xestyle.cxx sc/source/filter/excel/xichart.cxx sc/source/filter/inc/fapihelper.hxx sc/source/filter/inc/xistyle.hxx sc/source/filter/xml/xmlsubti.cxx sc/source/ui/Accessibility/AccessibleCell.cxx sc/source/ui/Accessibility/AccessibleContextBase.cxx sc/source/ui/Accessibility/AccessibleDataPilotControl.cxx sc/source/ui/Accessibility/AccessibleDocumentPagePreview.cxx sc/source/ui/Accessibility/AccessibleEditObject.cxx sc/source/ui/Accessibility/AccessiblePreviewCell.cxx sc/source/ui/app/inputwin.cxx sc/source/ui/docshell/docfunc.cxx sc/source/ui/drawfunc/fupoor.cxx sc/source/ui/miscdlgs/linkarea.cxx sc/source/ui/unoobj/chart2uno.cxx sc/source/ui/unoobj/nameuno.cxx sc/source/ui/vba/vbacharacters.hxx sc/source/ui/vba/vbarange.cxx sc/source/ui/vba/vbawindow.cxx scaddins/source/analysis/analysishelper.cxx scaddins/source/analysis/analysishelper.hxx scaddins/source/datefunc/datefunc.cxx scripting/examples/python/Capitalise.py scripting/source/pyprov/officehelper.py sd/source/filter/eppt/eppt.cxx sd/source/filter/eppt/epptso.cxx sd/source/ui/dlg/prltempl.cxx sd/source/ui/dlg/tpoption.cxx sd/source/ui/func/fuediglu.cxx sd/source/ui/func/fupoor.cxx sd/source/ui/func/fusel.cxx sd/source/ui/func/smarttag.cxx sd/source/ui/inc/OutlinerIteratorImpl.hxx sd/source/ui/inc/SlideViewShell.hxx sd/source/ui/inc/fuediglu.hxx sd/source/ui/inc/fusel.hxx sd/source/ui/slideshow/slideshowimpl.cxx sd/source/ui/slidesorter/cache/SlsQueueProcessorThread.hxx sd/source/ui/slidesorter/controller/SlsHideSlideFunction.cxx sd/source/ui/slidesorter/controller/SlsSelectionCommand.hxx sd/source/ui/slidesorter/inc/controller/SlsAnimationFunction.hxx sd/source/ui/slidesorter/view/SlsButtonBar.cxx sd/source/ui/view/Outliner.cxx sd/source/ui/view/drviewsh.cxx sd/source/ui/view/frmview.cxx sdext/source/presenter/PresenterFrameworkObserver.hxx sdext/source/presenter/PresenterSlideShowView.cxx setup_native/scripts/deregister_extensions setup_native/scripts/register_extensions setup_native/source/opensolaris/bundledextensions/README setup_native/source/opensolaris/bundledextensions/svc-ooo_bundled_extensions setup_native/source/win32/customactions/patch/swappatchfiles.cxx setup_native/source/win32/customactions/reg4msdoc/registrar.cxx setup_native/source/win32/customactions/reg4msdoc/userregistrar.cxx sfx2/inc/sfx2/sfxbasemodel.hxx sfx2/qa/complex/sfx2/DocumentProperties.java sfx2/source/appl/appopen.cxx sfx2/source/appl/appquit.cxx sfx2/source/appl/appserv.cxx sfx2/source/bastyp/sfxhtml.cxx sfx2/source/dialog/dockwin.cxx sfx2/source/doc/docfile.cxx sfx2/source/doc/docvor.cxx sfx2/source/doc/graphhelp.cxx sfx2/source/doc/objcont.cxx sfx2/source/doc/objserv.cxx sfx2/source/doc/objstor.cxx sfx2/source/doc/objuno.cxx sfx2/source/doc/objxtor.cxx sfx2/source/doc/printhelper.cxx sfx2/source/doc/sfxbasemodel.cxx sfx2/source/notify/eventsupplier.cxx sfx2/source/view/frmload.cxx sfx2/source/view/sfxbasecontroller.cxx shell/qa/zip/ziptest.cxx shell/source/backends/wininetbe/wininetbackend.cxx shell/source/win32/shlxthandler/util/utilities.cxx solenv/bin/build.pl solenv/bin/build_release.pl solenv/bin/cws.pl solenv/bin/download_external_dependencies.pl solenv/bin/make_download.pl solenv/bin/make_installer.pl solenv/bin/modules/Cws.pm solenv/bin/modules/ExtensionsLst.pm solenv/bin/modules/installer/control.pm solenv/bin/modules/installer/downloadsigner.pm solenv/bin/modules/installer/javainstaller.pm solenv/bin/modules/installer/packagepool.pm solenv/bin/modules/installer/patch/InstallationSet.pm solenv/bin/modules/installer/scriptitems.pm solenv/bin/modules/installer/windows/feature.pm solenv/bin/modules/installer/windows/msiglobal.pm solenv/bin/modules/installer/windows/sign.pm solenv/bin/modules/installer/worker.pm solenv/bin/modules/installer/xpdinstaller.pm solenv/bin/modules/osarch.pm solenv/bin/modules/packager/work.pm solenv/bin/modules/pre2par/parameter.pm solenv/bin/patch_tool.pl solenv/bin/transform_description.pl solenv/doc/gbuild/doxygen.cfg solenv/gbuild/LinkTarget.mk solenv/gbuild/gbuild.mk solenv/inc/os2gcci.mk solenv/inc/settings.mk solenv/inc/startup/Readme solenv/inc/target.mk solenv/inc/tg_compv.mk solenv/inc/tg_javav.mk solenv/inc/unitools.mk solenv/inc/unxbsdi.mk solenv/inc/unxbsdi2.mk solenv/inc/unxbsds.mk solenv/inc/unxfbsd.mk solenv/inc/unxlng.mk sot/source/sdstor/stg.cxx sot/source/sdstor/stgelem.cxx sot/source/sdstor/ucbstorage.cxx starmath/inc/toolbox.hxx starmath/source/mathmlexport.cxx starmath/source/node.cxx starmath/source/toolbox.cxx starmath/source/view.cxx stoc/source/bootstrap/bootstrap.xml stoc/source/corereflection/criface.cxx stoc/source/invocation/invocation.cxx stoc/source/security/access_controller.cxx stoc/source/servicemanager/servicemanager.cxx stoc/source/tdmanager/tdmgr.cxx stoc/test/javavm/testjavavm.cxx stoc/test/testconv.cxx stoc/test/testcorefl.cxx stoc/test/testintrosp.cxx svl/inc/svl/inettype.hxx svl/inc/svl/urihelper.hxx svl/qa/complex/ConfigItems/helper/HistoryOptTest.cxx svl/qa/complex/ConfigItems/helper/HistoryOptTest.hxx svl/source/config/itemholder2.hxx svl/source/items/itemset.cxx svl/source/numbers/zforlist.cxx svl/source/numbers/zformat.cxx svl/source/numbers/zforscan.cxx svtools/bmpmaker/bmp.cxx svtools/inc/svtools/helpagentwindow.hxx svtools/inc/svtools/menuoptions.hxx svtools/inc/svtools/miscopt.hxx svtools/inc/svtools/optionsdrawinglayer.hxx svtools/inc/svtools/stringtransfer.hxx svtools/inc/svtools/svlbitm.hxx svtools/inc/svtools/svtdata.hxx svtools/inc/svtools/valueset.hxx svtools/source/brwbox/editbrowsebox.cxx svtools/source/config/itemholder2.hxx svtools/source/contnr/contentenumeration.hxx svx/inc/svx/fmsrcimp.hxx svx/inc/svx/svdobj.hxx svx/inc/svx/xtable.hxx svx/source/accessibility/DGColorNameLookUp.cxx svx/source/accessibility/svxrectctaccessiblecontext.cxx svx/source/dialog/pfiledlg.cxx svx/source/fmcomp/fmgridcl.cxx svx/source/fmcomp/fmgridif.cxx svx/source/fmcomp/gridctrl.cxx svx/source/form/filtnav.cxx svx/source/form/fmPropBrw.cxx svx/source/form/fmshimp.cxx svx/source/form/fmsrcimp.cxx svx/source/gallery2/galtheme.cxx svx/source/inc/docrecovery.hxx svx/source/sdr/event/eventhandler.cxx svx/source/svdraw/svdedtv2.cxx svx/source/svdraw/svdedxv.cxx svx/source/svdraw/svdhdl.cxx svx/source/svdraw/svdobj.cxx svx/source/svdraw/svdograf.cxx svx/source/svdraw/svdoole2.cxx svx/source/svdraw/svdotxtr.cxx svx/source/svdraw/svdundo.cxx svx/source/svdraw/svdxcgv.cxx svx/source/unodialogs/textconversiondlgs/chinese_translationdialog.cxx sw/inc/SwNumberTree.hxx sw/inc/ndnotxt.hxx sw/source/core/access/acccell.cxx sw/source/core/access/acccell.hxx sw/source/core/access/accframebase.cxx sw/source/core/access/accframebase.hxx sw/source/core/access/accmap.cxx sw/source/core/access/accpage.cxx sw/source/core/access/accpage.hxx sw/source/core/access/accpara.cxx sw/source/core/access/accpara.hxx sw/source/core/bastyp/swrect.cxx sw/source/core/crsr/findtxt.cxx sw/source/core/doc/docdde.cxx sw/source/core/doc/notxtfrm.cxx sw/source/core/docnode/section.cxx sw/source/core/draw/dcontact.cxx sw/source/core/edit/edlingu.cxx sw/source/core/inc/anchoredobjectposition.hxx sw/source/core/layout/paintfrm.cxx sw/source/core/layout/tabfrm.cxx sw/source/core/layout/trvlfrm.cxx sw/source/core/ole/ndole.cxx sw/source/core/text/atrstck.cxx sw/source/core/text/inftxt.cxx sw/source/core/text/itratr.cxx sw/source/core/text/itrform2.cxx sw/source/core/text/itrform2.hxx sw/source/core/text/porfld.cxx sw/source/core/text/txtfly.cxx sw/source/core/txtnode/thints.cxx sw/source/core/txtnode/txtedt.cxx sw/source/core/uibase/dochdl/swdtflvr.cxx sw/source/core/uibase/docvw/PostItMgr.cxx sw/source/core/uibase/docvw/SidebarWin.cxx sw/source/core/uibase/docvw/edtwin.cxx sw/source/core/uibase/envelp/labimg.cxx sw/source/core/uibase/uiview/pview.cxx sw/source/core/uibase/uno/unomailmerge.cxx sw/source/core/undo/unattr.cxx sw/source/core/undo/untbl.cxx sw/source/core/unocore/unochart.cxx sw/source/core/view/vdraw.cxx sw/source/core/view/vnew.cxx sw/source/filter/basflt/fltini.cxx sw/source/filter/html/wrthtml.cxx sw/source/filter/inc/wwstyles.hxx sw/source/filter/rtf/rtffly.cxx sw/source/filter/rtf/swparrtf.cxx sw/source/filter/ww8/docxattributeoutput.cxx sw/source/filter/ww8/dump/msvbasic.cxx sw/source/filter/ww8/dump/ww8scan.cxx sw/source/filter/ww8/dump/ww8scan.hxx sw/source/filter/ww8/dump/ww8struc.hxx sw/source/filter/ww8/wrtww8.cxx sw/source/filter/ww8/ww8graf.cxx sw/source/filter/ww8/ww8par.cxx sw/source/filter/ww8/ww8par2.cxx sw/source/filter/ww8/ww8par2.hxx sw/source/filter/ww8/ww8par3.cxx sw/source/filter/ww8/ww8par6.cxx sw/source/filter/ww8/ww8scan.cxx sw/source/filter/ww8/ww8scan.hxx sw/source/ui/dbui/dbinsdlg.cxx sw/source/ui/inc/tablemgr.hxx sw/source/ui/inc/uitool.hxx sw/source/ui/lingu/olmenu.cxx sw/source/ui/uiview/viewport.cxx sysui/desktop/productversion.mk sysui/desktop/slackware/makefile.mk testgraphical/source/CallExternals.pm testgraphical/source/fill_documents_loop.pl testgraphical/ui/java/ConvwatchGUIProject/src/IniFile.java toolkit/doc/layout/notes.txt toolkit/doc/layout/oldnotes.txt toolkit/source/awt/vclxtabcontrol.cxx toolkit/src2xml/source/srcparser.py toolkit/workben/layout/editor.cxx tools/inc/tools/simplerm.hxx tools/inc/tools/solar.h tools/source/communi/geninfo.cxx tools/source/fsys/dirent.cxx tools/source/fsys/filecopy.cxx tools/source/fsys/os2.cxx tools/source/inet/inetmime.cxx tools/source/rc/resmgr.cxx ucb/source/core/ucbcmds.cxx ucb/source/ucp/file/filglob.cxx ucb/source/ucp/odma/odma_content.cxx ucb/source/ucp/tdoc/ucptdoc.xml ucb/source/ucp/webdav/makefile.mk ucbhelper/inc/ucbhelper/simplecertificatevalidationrequest.hxx ucbhelper/source/client/content.cxx ucbhelper/source/client/interceptedinteraction.cxx udkapi/com/sun/star/beans/XPropertiesChangeListener.idl udkapi/com/sun/star/io/ObjectOutputStream.idl udkapi/com/sun/star/io/XMarkableStream.idl udkapi/com/sun/star/io/XTextOutputStream.idl udkapi/com/sun/star/reflection/CoreReflection.idl udkapi/com/sun/star/reflection/XTypeDescriptionEnumerationAccess.idl udkapi/com/sun/star/test/XSimpleTest.idl unodevtools/source/skeletonmaker/skeletoncommon.cxx unodevtools/source/skeletonmaker/skeletoncommon.hxx unotools/inc/unotools/cacheoptions.hxx unotools/inc/unotools/cmdoptions.hxx unotools/inc/unotools/dynamicmenuoptions.hxx unotools/inc/unotools/extendedsecurityoptions.hxx unotools/inc/unotools/fontoptions.hxx unotools/inc/unotools/historyoptions.hxx unotools/inc/unotools/idhelper.hxx unotools/inc/unotools/internaloptions.hxx unotools/inc/unotools/localisationoptions.hxx unotools/inc/unotools/moduleoptions.hxx unotools/inc/unotools/printwarningoptions.hxx unotools/inc/unotools/securityoptions.hxx unotools/inc/unotools/startoptions.hxx unotools/inc/unotools/workingsetoptions.hxx unotools/source/config/cmdoptions.cxx unotools/source/config/compatibility.cxx unotools/source/config/configitem.cxx unotools/source/config/configmgr.cxx unotools/source/config/dynamicmenuoptions.cxx unotools/source/config/fontcfg.cxx unotools/source/config/itemholder1.hxx unotools/source/config/moduleoptions.cxx unotools/source/config/pathoptions.cxx unotools/source/config/viewoptions.cxx unotools/source/misc/sharedunocomponent.cxx uui/source/fltdlg.cxx uui/source/iahndl-filter.cxx vbahelper/inc/vbahelper/collectionbase.hxx vbahelper/source/msforms/vbacontrol.cxx vbahelper/source/vbahelper/collectionbase.cxx vcl/aqua/source/gdi/atsfonts.cxx vcl/inc/aqua/salmathutils.hxx vcl/inc/graphite_cache.hxx vcl/inc/jobset.h vcl/inc/os2/salgdi.h vcl/inc/osx/saldata.hxx vcl/inc/salgdi.hxx vcl/inc/salwtype.hxx vcl/inc/unx/wmadaptor.hxx vcl/inc/vcl/print.hxx vcl/inc/vcl/strhelper.hxx vcl/os2/source/app/salinst.cxx vcl/os2/source/app/saltimer.cxx vcl/os2/source/gdi/salgdi2.cxx vcl/osx/salframeview.mm vcl/osx/salprn.cxx vcl/qa/cppunit/dndtest.cxx vcl/source/app/dbggui.cxx vcl/source/control/ilstbox.cxx vcl/source/gdi/cvtsvm.cxx vcl/source/gdi/gdimtf.cxx vcl/source/gdi/outdev4.cxx vcl/source/gdi/outdev6.cxx vcl/source/gdi/pdfwriter_impl.cxx vcl/source/gdi/pdfwriter_impl2.cxx vcl/source/gdi/print.cxx vcl/source/gdi/print2.cxx vcl/source/glyphs/gcach_layout.cxx vcl/source/glyphs/glyphcache.cxx vcl/source/glyphs/graphite_layout.cxx vcl/source/window/printdlg.cxx vcl/source/window/tabdlg.cxx vcl/source/window/window.cxx vcl/source/window/winproc.cxx vcl/unx/generic/app/saldisp.cxx vcl/unx/generic/dtrans/X11_selection.hxx vcl/unx/gtk/app/gtkdata.cxx vcl/win/source/gdi/salgdi2.cxx vcl/win/source/gdi/salgdi3.cxx vcl/win/source/window/salframe.cxx vos/inc/vos/pipe.hxx vos/inc/vos/process.hxx vos/inc/vos/signal.hxx vos/inc/vos/socket.hxx vos/inc/vos/thread.hxx vos/source/pipe.cxx vos/source/socket.cxx wizards/com/sun/star/wizards/agenda/AgendaTemplate.java wizards/com/sun/star/wizards/agenda/AgendaWizardDialogImpl.java wizards/com/sun/star/wizards/agenda/TopicsControl.java wizards/com/sun/star/wizards/web/FTPDialog.java wizards/com/sun/star/wizards/web/ImageListDialog.java wizards/com/sun/star/wizards/web/Process.java wizards/com/sun/star/wizards/web/ProcessStatusRenderer.java wizards/com/sun/star/wizards/web/TOCPreview.java wizards/com/sun/star/wizards/web/WWD_Startup.java wizards/com/sun/star/wizards/web/data/TypeDetection.java wizards/com/sun/star/wizards/web/export/ImpressHTMLExporter.java writerfilter/inc/doctok/WW8Document.hxx writerfilter/source/dmapper/DomainMapper.cxx writerfilter/source/dmapper/NumberingManager.cxx writerfilter/source/dmapper/PropertyMap.cxx writerfilter/source/dmapper/StyleSheetTable.cxx writerfilter/source/doctok/WW8StructBase.hxx writerfilter/source/doctok/resources.xmi writerfilter/source/ooxml/README.efforts xmerge/source/activesync/XMergeFilter.cpp xmerge/source/minicalc/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/SxcDocumentDeserializerImpl.java xmerge/source/palmtests/qa/comparator/pdbcomparison.java xmerge/source/palmtests/qa/test_spec/convertor_test_spec.html xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefinedName.java xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Workbook.java xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Worksheet.java xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/SymbolLookup.java xmerge/source/pocketword/java/org/openoffice/xmerge/converter/xml/sxw/pocketword/DocumentDescriptor.java xmerge/workben/jstyle.pl xmlhelp/source/cxxhelp/provider/databases.hxx xmlhelp/source/cxxhelp/provider/provider.cxx xmlhelp/source/treeview/tvread.cxx xmloff/inc/txtfldi.hxx xmloff/inc/xmloff/xmlmultiimagehelper.hxx xmloff/inc/xmloff/xmluconv.hxx xmloff/source/core/xmlexp.cxx xmloff/source/draw/shapeexport2.cxx xmloff/source/draw/shapeexport3.cxx xmloff/source/meta/xmlversion.cxx xmloff/source/style/impastp4.cxx xmloff/source/style/xmlaustp.cxx xmloff/source/text/XMLSectionExport.cxx xmloff/source/text/txtflde.cxx xmloff/source/text/txtimp.cxx xmloff/source/text/txtparae.cxx xmloff/source/text/txtparai.cxx xmloff/source/text/txtvfldi.cxx xmlscript/source/xmldlg_imexp/xmldlg_impmodels.cxx Change-Id: Ie072e7c3a60c5dae16a67ac36d1f372c5065c99c
2014-04-29 19:25:03 +00:00
* This file is used in conjunction with the parseAFM.h header file.
2001-05-08 10:46:10 +00:00
* This file contains several procedures that are used to parse AFM
* files. It is intended to work with an application program that needs
* font metric information. The program can be used as is by making a
* procedure call to "parseFile" (passing in the expected parameters)
* and having it fill in a data structure with the data from the
* AFM file, or an application developer may wish to customize this
* code.
*
* There is also a file, parseAFMclient.c, that is a sample application
* showing how to call the "parseFile" procedure and how to use the data
* after "parseFile" has returned.
*
* Please read the comments in parseAFM.h and parseAFMclient.c.
*
* History:
* original: DSM Thu Oct 20 17:39:59 PDT 1988
* modified: DSM Mon Jul 3 14:17:50 PDT 1989
* - added 'storageProblem' return code
* - fixed bug of not allocating extra byte for string duplication
* - fixed typos
* modified: DSM Tue Apr 3 11:18:34 PDT 1990
* - added free(ident) at end of parseFile routine
* modified: DSM Tue Jun 19 10:16:29 PDT 1990
* - changed (width == 250) to (width = 250) in initializeArray
*/
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include "parseAFM.hxx"
#include "vcl/strhelper.hxx"
#include "rtl/alloc.h"
2001-05-08 10:46:10 +00:00
#define lineterm EOL /* line terminating character */
#define normalEOF 1 /* return code from parsing routines used only */
/* in this module */
#define False "false" /* used in string comparison to check the value of */
/* boolean keys (e.g. IsFixedPitch) */
#define MATCH(A,B) (strncmp((A),(B), MAX_NAME) == 0)
namespace psp {
class FileInputStream
{
char* m_pMemory;
unsigned int m_nPos;
unsigned int m_nLen;
public:
explicit FileInputStream( const char* pFilename );
~FileInputStream();
int getChar() { return (m_nPos < m_nLen) ? int(m_pMemory[m_nPos++]) : -1; }
void ungetChar()
{
if( m_nPos > 0 )
m_nPos--;
}
};
2001-05-08 10:46:10 +00:00
FileInputStream::FileInputStream(const char* pFilename)
: m_pMemory(NULL)
, m_nPos(0)
, m_nLen(0)
{
FILE* fp = fopen( pFilename, "r" );
if( fp )
{
struct stat aStat;
if (!fstat(fileno(fp), &aStat) && S_ISREG(aStat.st_mode) && aStat.st_size > 0)
{
m_pMemory = static_cast<char*>(rtl_allocateMemory( aStat.st_size ));
m_nLen = (unsigned int)fread( m_pMemory, 1, aStat.st_size, fp );
}
fclose( fp );
}
}
2001-05-08 10:46:10 +00:00
FileInputStream::~FileInputStream()
{
rtl_freeMemory( m_pMemory );
}
2001-05-08 10:46:10 +00:00
/*************************** GLOBALS ***********************/
2001-05-08 10:46:10 +00:00
/* "shorts" for fast case statement
* 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
* parseKey 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, and it is used in the
* "recognize" procedure to calculate how many possible keys there are.
*/
// some metrics have Ascent, Descent instead Ascender, Descender or Em
// which is not allowed per afm spcification, but let us handle
// this gently
enum parseKey {
ASCENDER, ASCENT, CHARBBOX, CODE, COMPCHAR, CODEHEX, CAPHEIGHT, CHARWIDTH, CHARACTERSET, CHARACTERS, COMMENT,
2001-05-08 10:46:10 +00:00
DESCENDER, DESCENT, EM, ENCODINGSCHEME, ENDCHARMETRICS, ENDCOMPOSITES, ENDDIRECTION,
ENDFONTMETRICS, ENDKERNDATA, ENDKERNPAIRS, ENDTRACKKERN,
FAMILYNAME, FONTBBOX, FONTNAME, FULLNAME, ISBASEFONT, ISFIXEDPITCH,
ITALICANGLE, KERNPAIR, KERNPAIRXAMT, LIGATURE, MAPPINGSCHEME, METRICSSETS, CHARNAME,
NOTICE, COMPCHARPIECE, STARTCHARMETRICS, STARTCOMPOSITES, STARTDIRECTION,
STARTFONTMETRICS, STARTKERNDATA, STARTKERNPAIRS,
STARTTRACKKERN, STDHW, STDVW, TRACKKERN, UNDERLINEPOSITION,
2001-05-08 10:46:10 +00:00
UNDERLINETHICKNESS, VVECTOR, VERSION, XYWIDTH, X0WIDTH, XWIDTH, WEIGHT, XHEIGHT,
NOPE
};
/*************************** PARSING ROUTINES **************/
/*************************** token *************************/
/* A "AFM file Conventions" tokenizer. That means that it will
2001-05-08 10:46:10 +00:00
* return the next token delimited by white space. See also
* the `linetoken' routine, which does a similar thing but
* reads all tokens until the next end-of-line.
*/
// token white space is ' ', '\n', '\r', ',', '\t', ';'
static const bool is_white_Array[ 256 ] =
{ false, false, false, false, false, false, false, false, // 0-7
false, true, true, false, false, true, false, false, // 8-15
false, false, false, false, false, false, false, false, // 16-23
false, false, false, false, false, false, false, false, // 24-31
true, false, false, false, false, false, false, false, // 32-39
false, false, false, false, true, false, false, false, // 40-47
false, false, false, false, false, false, false, false, // 48-55
false, false, false, true, false, false, false, false, // 56-63
false, false, false, false, false, false, false, false, // 64 -
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, // 127
false, false, false, false, false, false, false, false, // 128 -
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, // 191
false, false, false, false, false, false, false, false, // 192 -
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, // 255
};
// token delimiters are ' ', '\n', '\r', '\t', ':', ';'
static const bool is_delimiter_Array[ 256 ] =
{ false, false, false, false, false, false, false, false, // 0-7
false, true, true, false, false, true, false, false, // 8-15
false, false, false, false, false, false, false, false, // 16-23
false, false, false, false, false, false, false, false, // 24-31
true, false, false, false, false, false, false, false, // 32-39
false, false, false, false, false, false, false, false, // 40-47
false, false, false, false, false, false, false, false, // 48-55
false, false, true, true, false, false, false, false, // 56-63
false, false, false, false, false, false, false, false, // 64 -
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, // 127
false, false, false, false, false, false, false, false, // 128 -
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, // 191
false, false, false, false, false, false, false, false, // 192 -
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, // 255
};
static char *token( FileInputStream* stream, int& rLen )
2001-05-08 10:46:10 +00:00
{
static char ident[MAX_NAME]; /* storage buffer for keywords */
2001-05-08 10:46:10 +00:00
int ch, idx;
/* skip over white space */
// relies on EOF = -1
while( is_white_Array[ (ch = stream->getChar()) & 255 ] )
;
2001-05-08 10:46:10 +00:00
idx = 0;
while( ch != -1 && ! is_delimiter_Array[ ch & 255 ] && idx < MAX_NAME-1 )
2001-05-08 10:46:10 +00:00
{
ident[idx++] = ch;
ch = stream->getChar();
}
2001-05-08 10:46:10 +00:00
if (ch == -1 && idx < 1) return (nullptr);
if (idx >= 1 && ch != ':' && ch != -1) stream->ungetChar();
2001-05-08 10:46:10 +00:00
if (idx < 1 ) ident[idx++] = ch; /* single-character token */
ident[idx] = 0;
rLen = idx;
2001-05-08 10:46:10 +00:00
return ident; /* returns pointer to the token */
2001-05-08 10:46:10 +00:00
} /* token */
/*************************** linetoken *************************/
/* "linetoken" will get read all tokens until the EOL character from
* the given stream. This is used to get any arguments that can be
* more than one word (like Comment lines and FullName).
*/
static char *linetoken( FileInputStream* stream )
2001-05-08 10:46:10 +00:00
{
static char ident[MAX_NAME]; /* storage buffer for keywords */
2001-05-08 10:46:10 +00:00
int ch, idx;
2008-10-10 13:02:43 +00:00
while ((ch = stream->getChar()) == ' ' || ch == '\t' ) ;
2001-05-08 10:46:10 +00:00
idx = 0;
while (ch != -1 && ch != lineterm && ch != '\r' && idx < MAX_NAME-1 )
2001-05-08 10:46:10 +00:00
{
ident[idx++] = ch;
ch = stream->getChar();
2001-05-08 10:46:10 +00:00
} /* while */
stream->ungetChar();
2001-05-08 10:46:10 +00:00
ident[idx] = 0;
return ident; /* returns pointer to the token */
2001-05-08 10:46:10 +00:00
} /* linetoken */
/*************************** recognize *************************/
/* This function tries to match a string to a known list of
* valid AFM entries (check the keyStrings array above).
* "ident" contains everything from white space through the
* next space, tab, or ":" character.
*
* The algorithm is a standard Knuth binary search.
*/
#if defined __clang__
#if __has_warning("-Wdeprecated-register")
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-register"
#endif
#endif
2011-04-29 19:19:30 +02:00
#include "afm_hash.hpp"
#if defined __clang__
#if __has_warning("-Wdeprecated-register")
#pragma GCC diagnostic pop
#endif
#endif
2001-05-08 10:46:10 +00:00
static inline enum parseKey recognize( char* ident, int len)
2001-05-08 10:46:10 +00:00
{
const hash_entry* pEntry = AfmKeywordHash::in_word_set( ident, len );
return pEntry ? pEntry->eKey : NOPE;
2001-05-08 10:46:10 +00:00
} /* recognize */
/************************* parseGlobals *****************************/
/* This function is called by "parseFile". It will parse the AFM file
2001-05-08 10:46:10 +00:00
* up to the "StartCharMetrics" keyword, which essentially marks the
* end of the Global Font Information and the beginning of the character
* metrics information.
*
* If the caller of "parseFile" specified that it wanted the Global
* Font Information (as defined by the "AFM file Specification"
2001-05-08 10:46:10 +00:00
* document), then that information will be stored in the returned
* data structure.
*
* Any Global Font Information entries that are not found in a
* given file, will have the usual default initialization value
* for its type (i.e. entries of type int will be 0, etc).
*
* This function returns an error code specifying whether there was
* a premature EOF or a parsing error. This return value is used by
* parseFile to determine if there is more file to parse.
*/
static int parseGlobals( FileInputStream* fp, GlobalFontInfo* gfi )
2001-05-08 10:46:10 +00:00
{
bool cont = true, save = (gfi != NULL);
int error = ok;
int direction = -1;
int tokenlen;
2001-05-08 10:46:10 +00:00
while (cont)
{
char *keyword = token(fp, tokenlen);
2001-05-08 10:46:10 +00:00
if (keyword == NULL)
/* Have reached an early and unexpected EOF. */
/* Set flag and stop parsing */
{
error = earlyEOF;
break; /* get out of loop */
}
if (!save)
/* get tokens until the end of the Global Font info section */
/* without saving any of the data */
switch (recognize(keyword, tokenlen))
2001-05-08 10:46:10 +00:00
{
case STARTCHARMETRICS:
cont = false;
break;
case ENDFONTMETRICS:
cont = false;
error = normalEOF;
break;
default:
break;
} /* switch */
else
/* otherwise parse entire global font info section, */
/* saving the data */
switch(recognize(keyword, tokenlen))
2001-05-08 10:46:10 +00:00
{
case STARTFONTMETRICS:
if ((keyword = token(fp,tokenlen)) != NULL)
gfi->afmVersion = strdup( keyword );
2001-05-08 10:46:10 +00:00
break;
case COMMENT:
linetoken(fp);
2001-05-08 10:46:10 +00:00
break;
case FONTNAME:
if ((keyword = token(fp,tokenlen)) != NULL)
gfi->fontName = strdup( keyword );
2001-05-08 10:46:10 +00:00
break;
case ENCODINGSCHEME:
if ((keyword = token(fp,tokenlen)) != NULL)
gfi->encodingScheme = strdup( keyword );
2001-05-08 10:46:10 +00:00
break;
case FULLNAME:
if ((keyword = linetoken(fp)) != NULL)
gfi->fullName = strdup( keyword );
2001-05-08 10:46:10 +00:00
break;
case FAMILYNAME:
if ((keyword = linetoken(fp)) != NULL)
gfi->familyName = strdup( keyword );
2001-05-08 10:46:10 +00:00
break;
case WEIGHT:
if ((keyword = token(fp,tokenlen)) != NULL)
gfi->weight = strdup( keyword );
2001-05-08 10:46:10 +00:00
break;
case ITALICANGLE:
if ((keyword = token(fp,tokenlen)) != NULL)
gfi->italicAngle = StringToDouble( keyword );
2001-05-08 10:46:10 +00:00
break;
case ISFIXEDPITCH:
if ((keyword = token(fp,tokenlen)) != NULL)
{
if (MATCH(keyword, False))
gfi->isFixedPitch = false;
else
gfi->isFixedPitch = true;
}
2001-05-08 10:46:10 +00:00
break;
case UNDERLINEPOSITION:
if ((keyword = token(fp,tokenlen)) != NULL)
gfi->underlinePosition = atoi(keyword);
2001-05-08 10:46:10 +00:00
break;
case UNDERLINETHICKNESS:
if ((keyword = token(fp,tokenlen)) != NULL)
gfi->underlineThickness = atoi(keyword);
2001-05-08 10:46:10 +00:00
break;
case VERSION:
if ((keyword = token(fp,tokenlen)) != NULL)
gfi->version = strdup( keyword );
2001-05-08 10:46:10 +00:00
break;
case NOTICE:
if ((keyword = linetoken(fp)) != NULL)
gfi->notice = strdup( keyword );
2001-05-08 10:46:10 +00:00
break;
case FONTBBOX:
if ((keyword = token(fp,tokenlen)) != NULL)
gfi->fontBBox.llx = atoi(keyword);
if ((keyword = token(fp,tokenlen)) != NULL)
gfi->fontBBox.lly = atoi(keyword);
if ((keyword = token(fp,tokenlen)) != NULL)
gfi->fontBBox.urx = atoi(keyword);
if ((keyword = token(fp,tokenlen)) != NULL)
gfi->fontBBox.ury = atoi(keyword);
2001-05-08 10:46:10 +00:00
break;
case CAPHEIGHT:
if ((keyword = token(fp,tokenlen)) != NULL)
gfi->capHeight = atoi(keyword);
2001-05-08 10:46:10 +00:00
break;
case XHEIGHT:
if ((keyword = token(fp,tokenlen)) != NULL)
gfi->xHeight = atoi(keyword);
2001-05-08 10:46:10 +00:00
break;
case DESCENT:
if ((keyword = token(fp,tokenlen)) != NULL)
gfi->descender = -atoi(keyword);
2001-05-08 10:46:10 +00:00
break;
case DESCENDER:
if ((keyword = token(fp,tokenlen)) != NULL)
gfi->descender = atoi(keyword);
2001-05-08 10:46:10 +00:00
break;
case ASCENT:
case ASCENDER:
if ((keyword = token(fp,tokenlen)) != NULL)
gfi->ascender = atoi(keyword);
2001-05-08 10:46:10 +00:00
break;
case STARTCHARMETRICS:
cont = false;
break;
case ENDFONTMETRICS:
cont = false;
error = normalEOF;
break;
case EM:
// skip one token
token(fp,tokenlen);
2001-05-08 10:46:10 +00:00
break;
case STARTDIRECTION:
if ((keyword = token(fp,tokenlen)) != NULL)
direction = atoi(keyword);
2001-05-08 10:46:10 +00:00
break; /* ignore this for now */
case ENDDIRECTION:
break; /* ignore this for now */
case MAPPINGSCHEME:
token(fp,tokenlen);
2001-05-08 10:46:10 +00:00
break; /* ignore this for now */
case CHARACTERS:
token(fp,tokenlen);
2001-05-08 10:46:10 +00:00
break; /* ignore this for now */
case ISBASEFONT:
token(fp,tokenlen);
2001-05-08 10:46:10 +00:00
break; /* ignore this for now */
case CHARACTERSET:
token(fp,tokenlen); //ignore
break;
case STDHW:
token(fp,tokenlen); //ignore
break;
case STDVW:
token(fp,tokenlen); //ignore
break;
2001-05-08 10:46:10 +00:00
case CHARWIDTH:
if ((keyword = token(fp,tokenlen)) != NULL)
{
if (direction == 0)
gfi->charwidth = atoi(keyword);
}
token(fp,tokenlen);
2001-05-08 10:46:10 +00:00
/* ignore y-width for now */
break;
case METRICSSETS:
token(fp,tokenlen); /*eat token*/
2001-05-08 10:46:10 +00:00
break; /* ignore this for now */
case NOPE:
default:
error = parseError;
break;
} /* switch */
} /* while */
return error;
2001-05-08 10:46:10 +00:00
} /* parseGlobals */
/************************* parseCharWidths **************************/
/* This function is called by "parseFile". It will parse the AFM file
2001-05-08 10:46:10 +00:00
* up to the "EndCharMetrics" keyword. It will save the character
* width info (as opposed to all of the character metric information)
* if requested by the caller of parseFile. Otherwise, it will just
* parse through the section without saving any information.
*
* If data is to be saved, parseCharWidths is passed in a pointer
* to an array of widths that has already been initialized by the
* standard value for unmapped character codes. This function parses
* the Character Metrics section only storing the width information
* for the encoded characters into the array using the character code
* as the index into that array.
*
* This function returns an error code specifying whether there was
* a premature EOF or a parsing error. This return value is used by
* parseFile to determine if there is more file to parse.
*/
static int parseCharWidths( FileInputStream* fp, int* cwi)
2001-05-08 10:46:10 +00:00
{
bool cont = true, save = (cwi != NULL);
int pos = 0, error = ok, tokenlen;
2001-05-08 10:46:10 +00:00
while (cont)
{
char *keyword = token(fp,tokenlen);
2001-05-08 10:46:10 +00:00
/* Have reached an early and unexpected EOF. */
/* Set flag and stop parsing */
if (keyword == NULL)
{
error = earlyEOF;
break; /* get out of loop */
}
if (!save)
/* get tokens until the end of the Char Metrics section without */
/* saving any of the data*/
switch (recognize(keyword,tokenlen))
2001-05-08 10:46:10 +00:00
{
case ENDCHARMETRICS:
cont = false;
break;
case ENDFONTMETRICS:
cont = false;
error = normalEOF;
break;
default:
break;
} /* switch */
else
/* otherwise parse entire char metrics section, saving */
/* only the char x-width info */
switch(recognize(keyword,tokenlen))
2001-05-08 10:46:10 +00:00
{
case COMMENT:
linetoken(fp); /*eat token*/
2001-05-08 10:46:10 +00:00
break;
case CODE:
if ((keyword = token(fp,tokenlen)) != NULL)
pos = atoi(keyword);
2001-05-08 10:46:10 +00:00
break;
case XYWIDTH:
/* PROBLEM: Should be no Y-WIDTH when doing "quick & dirty" */
token(fp,tokenlen); token(fp,tokenlen); /* eat values */
2001-05-08 10:46:10 +00:00
error = parseError;
break;
case CODEHEX:
if ((keyword = token(fp,tokenlen)) != NULL)
sscanf(keyword, "<%x>", &pos);
2001-05-08 10:46:10 +00:00
break;
case X0WIDTH:
(void) token(fp,tokenlen);
2001-05-08 10:46:10 +00:00
break;
case XWIDTH:
if ((keyword = token(fp,tokenlen)) != NULL)
if (pos >= 0) /* ignore unmapped chars */
cwi[pos] = atoi(keyword);
2001-05-08 10:46:10 +00:00
break;
case ENDCHARMETRICS:
cont = false;
break;
case ENDFONTMETRICS:
cont = false;
error = normalEOF;
break;
case CHARNAME: /* eat values (so doesn't cause parseError) */
token(fp,tokenlen);
2001-05-08 10:46:10 +00:00
break;
case CHARBBOX:
token(fp,tokenlen); token(fp,tokenlen);
token(fp,tokenlen); token(fp,tokenlen);
2001-05-08 10:46:10 +00:00
break;
case LIGATURE:
token(fp,tokenlen); token(fp,tokenlen);
2001-05-08 10:46:10 +00:00
break;
case VVECTOR:
token(fp,tokenlen); /*eat token*/
token(fp,tokenlen); /*eat token*/
2001-05-08 10:46:10 +00:00
break;
case NOPE:
default:
error = parseError;
break;
} /* switch */
} /* while */
return error;
2001-05-08 10:46:10 +00:00
} /* parseCharWidths */
/*
* number of char metrics is almost always inaccurate, so be gentle and try to
2001-05-08 10:46:10 +00:00
* adapt our internal storage by adjusting the allocated list
*/
static int
reallocFontMetrics( void **pp_fontmetrics, int *p_oldcount, int n_newcount, unsigned int n_size )
2001-05-08 10:46:10 +00:00
{
char *p_tmpmetrics = NULL;
if ((pp_fontmetrics == NULL) || (*pp_fontmetrics == NULL))
return storageProblem;
if (*p_oldcount == n_newcount)
return ok;
p_tmpmetrics = static_cast<char*>(realloc(*pp_fontmetrics, n_newcount * n_size));
2001-05-08 10:46:10 +00:00
if (p_tmpmetrics == NULL)
return storageProblem;
if ( n_newcount > *p_oldcount )
{
char *p_inimetrics = p_tmpmetrics + n_size * *p_oldcount;
int n_inimetrics = n_size * (n_newcount - *p_oldcount);
memset( p_inimetrics, 0, n_inimetrics );
}
*pp_fontmetrics = p_tmpmetrics;
*p_oldcount = n_newcount;
return ok;
}
static unsigned int
enlargeCount( unsigned int n_oldcount )
{
unsigned int n_newcount = n_oldcount + n_oldcount / 5;
if (n_oldcount == n_newcount )
n_newcount = n_oldcount + 5;
return n_newcount;
}
/************************* parseCharMetrics ************************/
/* This function is called by parseFile if the caller of parseFile
* requested that all character metric information be saved
* (as opposed to only the character width information).
*
* parseCharMetrics is passed in a pointer to an array of records
* to hold information on a per character basis. This function
* parses the Character Metrics section storing all character
* metric information for the ALL characters (mapped and unmapped)
* into the array.
*
* This function returns an error code specifying whether there was
* a premature EOF or a parsing error. This return value is used by
* parseFile to determine if there is more file to parse.
*/
static int parseCharMetrics( FileInputStream* fp, FontInfo* fi)
2001-05-08 10:46:10 +00:00
{
bool cont = true, firstTime = true;
int error = ok, count = 0, tokenlen;
CharMetricInfo *temp = fi->cmi;
2001-05-08 10:46:10 +00:00
while (cont)
{
char *keyword = token(fp,tokenlen);
2001-05-08 10:46:10 +00:00
if (keyword == NULL)
{
error = earlyEOF;
break; /* get out of loop */
}
switch(recognize(keyword,tokenlen))
2001-05-08 10:46:10 +00:00
{
case COMMENT:
linetoken(fp); /*eat token*/
2001-05-08 10:46:10 +00:00
break;
case CODE:
if (!(count < fi->numOfChars))
{
reallocFontMetrics( reinterpret_cast<void**>(&fi->cmi),
2001-05-08 10:46:10 +00:00
&(fi->numOfChars), enlargeCount(fi->numOfChars),
sizeof(CharMetricInfo) );
temp = &(fi->cmi[ count - 1 ]);
}
if (count < fi->numOfChars)
{
if (firstTime) firstTime = false;
else temp++;
if ((keyword = token(fp,tokenlen)) != NULL)
temp->code = atoi(keyword);
2001-05-08 10:46:10 +00:00
if (fi->gfi && fi->gfi->charwidth)
temp->wx = fi->gfi->charwidth;
count++;
}
else
{
error = parseError;
cont = false;
}
break;
case CODEHEX:
if (!(count < fi->numOfChars ))
{
reallocFontMetrics( reinterpret_cast<void**>(&fi->cmi),
2001-05-08 10:46:10 +00:00
&(fi->numOfChars), enlargeCount(fi->numOfChars),
sizeof(CharMetricInfo) );
temp = &(fi->cmi[ count - 1 ]);
}
if (count < fi->numOfChars) {
if (firstTime)
firstTime = false;
2001-05-08 10:46:10 +00:00
else
temp++;
if ((keyword = token(fp,tokenlen)) != NULL)
sscanf(keyword,"<%x>", &temp->code);
2001-05-08 10:46:10 +00:00
if (fi->gfi && fi->gfi->charwidth)
temp->wx = fi->gfi->charwidth;
count++;
}
else {
error = parseError;
cont = false;
2001-05-08 10:46:10 +00:00
}
break;
case XYWIDTH:
if ((keyword = token(fp,tokenlen)) != NULL)
temp->wx = atoi(keyword);
if ((keyword = token(fp,tokenlen)) != NULL)
temp->wy = atoi(keyword);
2001-05-08 10:46:10 +00:00
break;
case X0WIDTH:
if ((keyword = token(fp,tokenlen)) != NULL)
temp->wx = atoi(keyword);
2001-05-08 10:46:10 +00:00
break;
case XWIDTH:
if ((keyword = token(fp,tokenlen)) != NULL)
temp->wx = atoi(keyword);
2001-05-08 10:46:10 +00:00
break;
case CHARNAME:
if ((keyword = token(fp,tokenlen)) != NULL)
temp->name = strdup(keyword);
2001-05-08 10:46:10 +00:00
break;
case CHARBBOX:
if ((keyword = token(fp,tokenlen)) != NULL)
temp->charBBox.llx = atoi(keyword);
if ((keyword = token(fp,tokenlen)) != NULL)
temp->charBBox.lly = atoi(keyword);
if ((keyword = token(fp,tokenlen)) != NULL)
temp->charBBox.urx = atoi(keyword);
if ((keyword = token(fp,tokenlen)) != NULL)
temp->charBBox.ury = atoi(keyword);
2001-05-08 10:46:10 +00:00
break;
case LIGATURE: {
Ligature **tail = &(temp->ligs);
Ligature *node = *tail;
if (*tail != NULL)
{
while (node->next != NULL)
node = node->next;
tail = &(node->next);
}
*tail = static_cast<Ligature *>(calloc(1, sizeof(Ligature)));
if ((keyword = token(fp,tokenlen)) != NULL)
(*tail)->succ = strdup(keyword);
if ((keyword = token(fp,tokenlen)) != NULL)
(*tail)->lig = strdup(keyword);
2001-05-08 10:46:10 +00:00
break; }
case ENDCHARMETRICS:
2011-12-14 14:43:58 -05:00
cont = false;
2001-05-08 10:46:10 +00:00
break;
case ENDFONTMETRICS:
cont = false;
error = normalEOF;
break;
case VVECTOR:
token(fp,tokenlen); /*eat token*/
token(fp,tokenlen); /*eat token*/
2001-05-08 10:46:10 +00:00
break;
case NOPE:
default:
error = parseError;
break;
} /* switch */
} /* while */
if ((error == ok) && (count != fi->numOfChars))
error = reallocFontMetrics( reinterpret_cast<void**>(&fi->cmi), &(fi->numOfChars),
2001-05-08 10:46:10 +00:00
count, sizeof(CharMetricInfo) );
if ((error == ok) && (count != fi->numOfChars))
error = parseError;
return error;
2001-05-08 10:46:10 +00:00
} /* parseCharMetrics */
/************************* parseTrackKernData ***********************/
/* This function is called by "parseFile". It will parse the AFM file
2001-05-08 10:46:10 +00:00
* up to the "EndTrackKern" or "EndKernData" keywords. It will save the
* track kerning data if requested by the caller of parseFile.
*
* parseTrackKernData is passed in a pointer to the FontInfo record.
* If data is to be saved, the FontInfo record will already contain
* a valid pointer to storage for the track kerning data.
*
* This function returns an error code specifying whether there was
* a premature EOF or a parsing error. This return value is used by
* parseFile to determine if there is more file to parse.
*/
static int parseTrackKernData( FileInputStream* fp, FontInfo* fi)
2001-05-08 10:46:10 +00:00
{
bool cont = true, save = (fi->tkd != NULL);
int pos = 0, error = ok, tcount = 0, tokenlen;
2001-05-08 10:46:10 +00:00
while (cont)
{
char *keyword = token(fp,tokenlen);
2001-05-08 10:46:10 +00:00
if (keyword == NULL)
{
error = earlyEOF;
break; /* get out of loop */
}
if (!save)
/* get tokens until the end of the Track Kerning Data */
/* section without saving any of the data */
switch(recognize(keyword,tokenlen))
2001-05-08 10:46:10 +00:00
{
case ENDTRACKKERN:
case ENDKERNDATA:
cont = false;
break;
case ENDFONTMETRICS:
cont = false;
error = normalEOF;
break;
default:
break;
} /* switch */
else
/* otherwise parse entire Track Kerning Data section, */
/* saving the data */
switch(recognize(keyword,tokenlen))
2001-05-08 10:46:10 +00:00
{
case COMMENT:
linetoken(fp); /*eat token*/
2001-05-08 10:46:10 +00:00
break;
case TRACKKERN:
if (!(tcount < fi->numOfTracks))
{
reallocFontMetrics( reinterpret_cast<void**>(&fi->tkd), &(fi->numOfTracks),
2001-05-08 10:46:10 +00:00
enlargeCount(fi->numOfTracks), sizeof(TrackKernData) );
}
if (tcount < fi->numOfTracks)
{
if ((keyword = token(fp,tokenlen)) != NULL)
fi->tkd[pos].degree = atoi(keyword);
if ((keyword = token(fp,tokenlen)) != NULL)
fi->tkd[pos].minPtSize = StringToDouble(keyword);
if ((keyword = token(fp,tokenlen)) != NULL)
fi->tkd[pos].minKernAmt = StringToDouble(keyword);
if ((keyword = token(fp,tokenlen)) != NULL)
fi->tkd[pos].maxPtSize = StringToDouble(keyword);
if ((keyword = token(fp,tokenlen)) != NULL)
fi->tkd[pos++].maxKernAmt = StringToDouble(keyword);
2001-05-08 10:46:10 +00:00
tcount++;
}
else
{
error = parseError;
cont = false;
}
break;
case ENDTRACKKERN:
case ENDKERNDATA:
cont = false;
break;
case ENDFONTMETRICS:
cont = false;
error = normalEOF;
break;
case NOPE:
default:
error = parseError;
break;
} /* switch */
} /* while */
if (error == ok && tcount != fi->numOfTracks)
error = reallocFontMetrics( reinterpret_cast<void**>(&fi->tkd), &(fi->numOfTracks),
2001-05-08 10:46:10 +00:00
tcount, sizeof(TrackKernData) );
if (error == ok && tcount != fi->numOfTracks)
error = parseError;
return error;
2001-05-08 10:46:10 +00:00
} /* parseTrackKernData */
/************************* parsePairKernData ************************/
/* This function is called by "parseFile". It will parse the AFM file
2001-05-08 10:46:10 +00:00
* up to the "EndKernPairs" or "EndKernData" keywords. It will save
* the pair kerning data if requested by the caller of parseFile.
*
* parsePairKernData is passed in a pointer to the FontInfo record.
* If data is to be saved, the FontInfo record will already contain
* a valid pointer to storage for the pair kerning data.
*
* This function returns an error code specifying whether there was
* a premature EOF or a parsing error. This return value is used by
* parseFile to determine if there is more file to parse.
*/
static int parsePairKernData( FileInputStream* fp, FontInfo* fi)
2001-05-08 10:46:10 +00:00
{
bool cont = true, save = (fi->pkd != NULL);
int pos = 0, error = ok, pcount = 0, tokenlen;
2001-05-08 10:46:10 +00:00
while (cont)
{
char *keyword = token(fp,tokenlen);
2001-05-08 10:46:10 +00:00
if (keyword == NULL)
{
error = earlyEOF;
break; /* get out of loop */
}
if (!save)
/* get tokens until the end of the Pair Kerning Data */
/* section without saving any of the data */
switch(recognize(keyword,tokenlen))
2001-05-08 10:46:10 +00:00
{
case ENDKERNPAIRS:
case ENDKERNDATA:
cont = false;
break;
case ENDFONTMETRICS:
cont = false;
error = normalEOF;
break;
default:
break;
} /* switch */
else
/* otherwise parse entire Pair Kerning Data section, */
/* saving the data */
switch(recognize(keyword,tokenlen))
2001-05-08 10:46:10 +00:00
{
case COMMENT:
linetoken(fp); /*eat token*/
2001-05-08 10:46:10 +00:00
break;
case KERNPAIR:
if (!(pcount < fi->numOfPairs))
{
reallocFontMetrics( reinterpret_cast<void**>(&fi->pkd), &(fi->numOfPairs),
2001-05-08 10:46:10 +00:00
enlargeCount(fi->numOfPairs), sizeof(PairKernData) );
}
if (pcount < fi->numOfPairs)
{
if ((keyword = token(fp,tokenlen)) != NULL)
fi->pkd[pos].name1 = strdup( keyword );
if ((keyword = token(fp,tokenlen)) != NULL)
fi->pkd[pos].name2 = strdup( keyword );
if ((keyword = token(fp,tokenlen)) != NULL)
fi->pkd[pos].xamt = atoi(keyword);
if ((keyword = token(fp,tokenlen)) != NULL)
fi->pkd[pos++].yamt = atoi(keyword);
2001-05-08 10:46:10 +00:00
pcount++;
}
else
{
error = parseError;
cont = false;
}
break;
case KERNPAIRXAMT:
if (!(pcount < fi->numOfPairs))
{
reallocFontMetrics( reinterpret_cast<void**>(&fi->pkd), &(fi->numOfPairs),
2001-05-08 10:46:10 +00:00
enlargeCount(fi->numOfPairs), sizeof(PairKernData) );
}
if (pcount < fi->numOfPairs)
{
if ((keyword = token(fp,tokenlen)) != NULL)
fi->pkd[pos].name1 = strdup( keyword );
if ((keyword = token(fp,tokenlen)) != NULL)
fi->pkd[pos].name2 = strdup( keyword );
if ((keyword = token(fp,tokenlen)) != NULL)
fi->pkd[pos++].xamt = atoi(keyword);
2001-05-08 10:46:10 +00:00
pcount++;
}
else
{
error = parseError;
cont = false;
}
break;
case ENDKERNPAIRS:
case ENDKERNDATA:
cont = false;
break;
case ENDFONTMETRICS:
cont = false;
error = normalEOF;
break;
case NOPE:
default:
error = parseError;
break;
} /* switch */
} /* while */
if ((error == ok) && (pcount != fi->numOfPairs))
error = reallocFontMetrics( reinterpret_cast<void**>(&fi->pkd), &(fi->numOfPairs),
2001-05-08 10:46:10 +00:00
pcount, sizeof(PairKernData) );
if (error == ok && pcount != fi->numOfPairs)
error = parseError;
return error;
2001-05-08 10:46:10 +00:00
} /* parsePairKernData */
/************************* parseCompCharData **************************/
/* This function is called by "parseFile". It will parse the AFM file
2001-05-08 10:46:10 +00:00
* up to the "EndComposites" keyword. It will save the composite
* character data if requested by the caller of parseFile.
*
* parseCompCharData is passed in a pointer to the FontInfo record, and
* a boolean representing if the data should be saved.
*
* This function will create the appropriate amount of storage for
* the composite character data and store a pointer to the storage
* in the FontInfo record.
*
* This function returns an error code specifying whether there was
* a premature EOF or a parsing error. This return value is used by
* parseFile to determine if there is more file to parse.
*/
static int parseCompCharData( FileInputStream* fp, FontInfo* fi)
2001-05-08 10:46:10 +00:00
{
bool cont = true, firstTime = true, save = (fi->ccd != NULL);
int pos = 0, j = 0, error = ok, ccount = 0, pcount = 0, tokenlen;
2001-05-08 10:46:10 +00:00
while (cont)
{
char *keyword = token(fp,tokenlen);
2001-05-08 10:46:10 +00:00
if (keyword == NULL)
/* Have reached an early and unexpected EOF. */
/* Set flag and stop parsing */
{
error = earlyEOF;
break; /* get out of loop */
}
if (ccount > fi->numOfComps)
{
reallocFontMetrics( reinterpret_cast<void**>(&fi->ccd), &(fi->numOfComps),
2001-05-08 10:46:10 +00:00
enlargeCount(fi->numOfComps), sizeof(CompCharData) );
}
if (ccount > fi->numOfComps)
{
error = parseError;
break; /* get out of loop */
}
if (!save)
/* get tokens until the end of the Composite Character info */
/* section without saving any of the data */
switch(recognize(keyword,tokenlen))
2001-05-08 10:46:10 +00:00
{
case ENDCOMPOSITES:
cont = false;
break;
case ENDFONTMETRICS:
cont = false;
error = normalEOF;
break;
case COMMENT:
case COMPCHAR:
linetoken(fp);
2001-05-08 10:46:10 +00:00
break;
default:
break;
} /* switch */
else
/* otherwise parse entire Composite Character info section, */
/* saving the data */
switch(recognize(keyword,tokenlen))
2001-05-08 10:46:10 +00:00
{
case COMMENT:
linetoken(fp); /*eat token*/
2001-05-08 10:46:10 +00:00
break;
case COMPCHAR:
if (!(ccount < fi->numOfComps))
{
reallocFontMetrics( reinterpret_cast<void**>(&fi->ccd), &(fi->numOfComps),
2001-05-08 10:46:10 +00:00
enlargeCount(fi->numOfComps), sizeof(CompCharData) );
}
if (ccount < fi->numOfComps)
{
keyword = token(fp,tokenlen);
2001-05-08 10:46:10 +00:00
if (pcount != fi->ccd[pos].numOfPieces)
error = parseError;
pcount = 0;
if (firstTime) firstTime = false;
else pos++;
fi->ccd[pos].ccName = strdup( keyword );
if ((keyword = token(fp,tokenlen)) != NULL)
fi->ccd[pos].numOfPieces = atoi(keyword);
fi->ccd[pos].pieces = static_cast<Pcc *>(
calloc(fi->ccd[pos].numOfPieces, sizeof(Pcc)));
2001-05-08 10:46:10 +00:00
j = 0;
ccount++;
}
else
{
error = parseError;
cont = false;
}
break;
case COMPCHARPIECE:
if (pcount < fi->ccd[pos].numOfPieces)
{
if ((keyword = token(fp,tokenlen)) != NULL)
fi->ccd[pos].pieces[j].pccName = strdup( keyword );
if ((keyword = token(fp,tokenlen)) != NULL)
fi->ccd[pos].pieces[j].deltax = atoi(keyword);
if ((keyword = token(fp,tokenlen)) != NULL)
fi->ccd[pos].pieces[j++].deltay = atoi(keyword);
2001-05-08 10:46:10 +00:00
pcount++;
}
else
error = parseError;
break;
case ENDCOMPOSITES:
cont = false;
break;
case ENDFONTMETRICS:
cont = false;
error = normalEOF;
break;
case NOPE:
default:
error = parseError;
break;
} /* switch */
} /* while */
if (error == ok && ccount != fi->numOfComps)
reallocFontMetrics( reinterpret_cast<void**>(&fi->ccd), &(fi->numOfComps),
2001-05-08 10:46:10 +00:00
ccount, sizeof(CompCharData) );
if (error == ok && ccount != fi->numOfComps)
error = parseError;
return error;
2001-05-08 10:46:10 +00:00
} /* parseCompCharData */
/*************************** 'PUBLIC' FUNCTION ********************/
/*************************** parseFile *****************************/
/* parseFile is the only 'public' procedure available. It is called
* from an application wishing to get information from an AFM file.
* The caller of this function is responsible for locating and opening
* an AFM file and handling all errors associated with that task.
*
* parseFile expects 3 parameters: a filename pointer, a pointer
2001-05-08 10:46:10 +00:00
* to a (FontInfo *) variable (for which storage will be allocated and
* the data requested filled in), and a mask specifying which
* data from the AFM file should be saved in the FontInfo structure.
2001-05-08 10:46:10 +00:00
*
* The file will be parsed and the requested data will be stored in
* a record of type FontInfo (refer to ParseAFM.h).
*
* parseFile returns an error code as defined in parseAFM.h.
*
* The position of the read/write pointer associated with the file
* pointer upon return of this function is undefined.
*/
int parseFile( const char* pFilename, FontInfo** fi, FLAGS flags)
2001-05-08 10:46:10 +00:00
{
FileInputStream aFile( pFilename );
2001-05-08 10:46:10 +00:00
int code = ok; /* return code from each of the parsing routines */
int error = ok; /* used as the return code from this function */
int tokenlen;
2001-05-08 10:46:10 +00:00
char *keyword; /* used to store a token */
2001-05-08 10:46:10 +00:00
(*fi) = static_cast<FontInfo *>(calloc(1, sizeof(FontInfo)));
if ((*fi) == NULL) { error = storageProblem; return error; }
2001-05-08 10:46:10 +00:00
if (flags & P_G)
{
(*fi)->gfi = static_cast<GlobalFontInfo *>(calloc(1, sizeof(GlobalFontInfo)));
if ((*fi)->gfi == NULL) { error = storageProblem; return error; }
2001-05-08 10:46:10 +00:00
}
/* The AFM file begins with Global Font Information. This section */
2001-05-08 10:46:10 +00:00
/* will be parsed whether or not information should be saved. */
code = parseGlobals(&aFile, (*fi)->gfi);
2001-05-08 10:46:10 +00:00
if (code < 0) error = code;
/* The Global Font Information is followed by the Character Metrics */
/* section. Which procedure is used to parse this section depends on */
/* how much information should be saved. If all of the metrics info */
/* is wanted, parseCharMetrics is called. If only the character widths */
/* is wanted, parseCharWidths is called. parseCharWidths will also */
/* be called in the case that no character data is to be saved, just */
/* to parse through the section. */
if ((code != normalEOF) && (code != earlyEOF))
{
if ((keyword = token(&aFile,tokenlen)) != NULL)
(*fi)->numOfChars = atoi(keyword);
2001-05-08 10:46:10 +00:00
if (flags & (P_M ^ P_W))
{
(*fi)->cmi = static_cast<CharMetricInfo *>(
calloc((*fi)->numOfChars, sizeof(CharMetricInfo)));
if ((*fi)->cmi == NULL) { error = storageProblem; return error; }
code = parseCharMetrics(&aFile, *fi);
2001-05-08 10:46:10 +00:00
}
else
{
if (flags & P_W)
{
(*fi)->cwi = static_cast<int *>(calloc(256, sizeof(int)));
2001-05-08 10:46:10 +00:00
if ((*fi)->cwi == NULL)
{
error = storageProblem;
return error;
2001-05-08 10:46:10 +00:00
}
}
/* parse section regardless */
code = parseCharWidths(&aFile, (*fi)->cwi);
2001-05-08 10:46:10 +00:00
} /* else */
} /* if */
if ((error != earlyEOF) && (code < 0)) error = code;
/* The remaining sections of the AFM are optional. This code will */
/* look at the next keyword in the file to determine what section */
/* is next, and then allocate the appropriate amount of storage */
/* for the data (if the data is to be saved) and call the */
/* appropriate parsing routine to parse the section. */
while ((code != normalEOF) && (code != earlyEOF))
{
keyword = token(&aFile,tokenlen);
2001-05-08 10:46:10 +00:00
if (keyword == NULL)
/* Have reached an early and unexpected EOF. */
/* Set flag and stop parsing */
{
code = earlyEOF;
break; /* get out of loop */
}
switch(recognize(keyword,tokenlen))
2001-05-08 10:46:10 +00:00
{
case STARTKERNDATA:
break;
case ENDKERNDATA:
break;
case STARTTRACKKERN:
keyword = token(&aFile,tokenlen);
if ((flags & P_T) && keyword)
2001-05-08 10:46:10 +00:00
{
(*fi)->numOfTracks = atoi(keyword);
(*fi)->tkd = static_cast<TrackKernData *>(
calloc((*fi)->numOfTracks, sizeof(TrackKernData)));
2001-05-08 10:46:10 +00:00
if ((*fi)->tkd == NULL)
{
error = storageProblem;
return error;
2001-05-08 10:46:10 +00:00
}
} /* if */
code = parseTrackKernData(&aFile, *fi);
2001-05-08 10:46:10 +00:00
break;
case STARTKERNPAIRS:
keyword = token(&aFile,tokenlen);
if ((flags & P_P) && keyword)
2001-05-08 10:46:10 +00:00
{
(*fi)->numOfPairs = atoi(keyword);
(*fi)->pkd = static_cast<PairKernData *>(
calloc((*fi)->numOfPairs, sizeof(PairKernData)));
2001-05-08 10:46:10 +00:00
if ((*fi)->pkd == NULL)
{
error = storageProblem;
return error;
2001-05-08 10:46:10 +00:00
}
} /* if */
code = parsePairKernData(&aFile, *fi);
2001-05-08 10:46:10 +00:00
break;
case STARTCOMPOSITES:
keyword = token(&aFile,tokenlen);
if ((flags & P_C) && keyword)
2001-05-08 10:46:10 +00:00
{
(*fi)->numOfComps = atoi(keyword);
(*fi)->ccd = static_cast<CompCharData *>(
calloc((*fi)->numOfComps, sizeof(CompCharData)));
2001-05-08 10:46:10 +00:00
if ((*fi)->ccd == NULL)
{
error = storageProblem;
return error;
2001-05-08 10:46:10 +00:00
}
} /* if */
code = parseCompCharData(&aFile, *fi);
2001-05-08 10:46:10 +00:00
break;
case ENDFONTMETRICS:
code = normalEOF;
break;
case COMMENT:
linetoken(&aFile);
2001-05-08 10:46:10 +00:00
break;
case NOPE:
default:
code = parseError;
break;
} /* switch */
if ((error != earlyEOF) && (code < 0)) error = code;
} /* while */
if ((error != earlyEOF) && (code < 0)) error = code;
return error;
2001-05-08 10:46:10 +00:00
} /* parseFile */
void
freeFontInfo (FontInfo *fi)
{
2010-12-15 08:08:30 +01:00
int i;
2001-05-08 10:46:10 +00:00
if (fi->gfi)
{
free (fi->gfi->afmVersion);
free (fi->gfi->fontName);
free (fi->gfi->fullName);
free (fi->gfi->familyName);
free (fi->gfi->weight);
free (fi->gfi->version);
free (fi->gfi->notice);
free (fi->gfi->encodingScheme);
free (fi->gfi);
}
free (fi->cwi);
if (fi->cmi)
{
for (i = 0; i < fi->numOfChars; i++)
{
Ligature *ligs;
free (fi->cmi[i].name);
ligs = fi->cmi[i].ligs;
while (ligs)
{
Ligature *tmp;
tmp = ligs;
ligs = ligs->next;
free (tmp->succ);
free (tmp->lig);
free (tmp);
}
}
free (fi->cmi);
}
free (fi->tkd);
if (fi->pkd)
{
for ( i = 0; i < fi->numOfPairs; i++)
2001-05-08 10:46:10 +00:00
{
free (fi->pkd[i].name1);
free (fi->pkd[i].name2);
}
free (fi->pkd);
}
if (fi->ccd)
{
for (i = 0; i < fi->numOfComps; i++)
{
free (fi->ccd[i].ccName);
2010-12-15 08:08:30 +01:00
int j;
2001-05-08 10:46:10 +00:00
for (j = 0; j < fi->ccd[i].numOfPieces; j++)
free (fi->ccd[i].pieces[j].pccName);
free (fi->ccd[i].pieces);
}
free (fi->ccd);
}
free (fi);
}
} // namspace
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */