ft2demos-2.10.1/0000755000175000001440000000000013506426605013166 5ustar00wlusers00000000000000ft2demos-2.10.1/mac/0000755000175000001440000000000013506426605013726 5ustar00wlusers00000000000000ft2demos-2.10.1/mac/codewarrior/0000755000175000001440000000000013506426605016246 5ustar00wlusers00000000000000ft2demos-2.10.1/mac/codewarrior/carbonprefix.h0000644000175000001440000000005313434207203021066 0ustar00wlusers00000000000000#define USING_CARBON #include "ftoption.h"ft2demos-2.10.1/mac/codewarrior/ftlint.prj0000644000175000001440000007637013434207203020267 0ustar00wlusers00000000000000cool(wx03CodeWarrior Projectfreetype:Custom Keywordsfreetype:Access Pathsfreetype:Target Settingsfreetype:File Mappingsfreetype:Build Extrasfreetype:Debugger Targetfreetype:Debugger Runtimefreetype:68K CodeGenfreetype:68K Disassemblerfreetype:68K Global Optimizerfreetype:68K Linkerfreetype:68K Projectfreetype:C/C++ Compilerfreetype:C/C++ Warningsfreetype:CFM68Kfreetype:FTP Panelfreetype:Java Command Linefreetype:Java Languagefreetype:Java MacOS Settingsfreetype:Java Outputfreetype:Java Projectfreetype:JavaDoc Projectfreetype:MacOS Merge Panelfreetype:Pascal Compilerfreetype:Pascal Warningsfreetype:PPC CodeGenfreetype:PPC Disassemblerfreetype:PPC Global Optimizerfreetype:PPC Linkerfreetype:PPC PEFfreetype:PPC Projectfreetype:PPCAsm Panelfreetype:Rez CompilerProject File Listftlint:Custom Keywordsftlint:Access Pathsftlint:Target Settingsftlint:File Mappingsftlint:Build Extrasftlint:Debugger Targetftlint:Debugger Runtimeftlint:68K CodeGenftlint:68K Disassemblerftlint:68K Global Optimizerftlint:68K Linkerftlint:68K Projectftlint:C/C++ Compilerftlint:C/C++ Warningsftlint:CFM68Kftlint:FTP Panelftlint:Java Command Lineftlint:Java Languageftlint:Java MacOS Settingsftlint:Java Outputftlint:Java Projectftlint:JavaDoc Projectftlint:MacOS Merge Panelftlint:Pascal Compilerftlint:Pascal Warningsftlint:PPC CodeGenftlint:PPC Disassemblerftlint:PPC Global Optimizerftlint:PPC Linkerftlint:PPC PEFftlint:PPC Projectftlint:PPCAsm Panelftlint:Rez Compiler/H_u   6N^q8Qf !"#-$A%X&m'()*+,- ./20H1V2g3456789:;5<H=`>|?@ABC EC`C  6789:ABCE  ftoption.h   )*+,-#&./0"('%123456789:;<=>?@AB$!freetypeFirst Segment:a.outLib Import 68KMPW Import 68KBalloon HelpMW C/C++ 68KMW Pascal 68KRezPEF Import 68K:FreeType.libLib Import PPCMW C/C++ PPCMW Pascal PPCPPCAsmXCOFF Import PPCPEF Import PPCMacOS PPC LinkerCustom KeywordsAccess PathsTarget SettingsFile MappingsBuild ExtrasDebugger TargetC/C++ CompilerC/C++ WarningsFTP PanelPascal CompilerPascal WarningsPPC CodeGenPPC DisassemblerPPC Global OptimizerPPC LinkerPPC PEFPPC ProjectPPCAsm PanelRez Compilerftsystem.cftbase.cftbbox.cftcalc.cftdebug.cftextend.cftinit.cftlist.cftobjs.cftoutln.cftraster.cftstream.csfdriver.csfnt.cttcmap.cttload.cttpost.cttsbit.ctruetype.cttdriver.cttgload.cttinterp.cttobjs.cttpload.ct1afm.ct1driver.ct1gload.ct1hinter.ct1load.ct1objs.ct1parse.ct1tokens.ctype1.coltypes.cpsnames.cMSL C.PPC.LibMathLibMSL RuntimePPC.LibInterfaceLibMSL SIOUX.PPC.Libftlint.c:FreeTypeTestAppFreeType.libFreeType_DEBUG.libftlint_mac.c:::bin:FreeTypeTestAppmacgetargv.cftlintmacftlint.rsrc:::bin:ftlintFreeTypeLibftlint.rsrcgetargv.cftview_m.cftlint_m.c -<IVd h w "/?N]gw !"#$%&'()*"+-,6-?.H/R0]1h2s3z456789:;<=>?@AB CD E+F3G=HGIUJ]KpL}MNOPQRSTUVWX*Y6Z@[K\RV NOWP&'()*+TMX[Q,-./0%ZYK USIHJL  F  !"#G$12=>?@ABCD7389:4;<56E ROOTGRUPsrcFILEEFILECGRUP resourcesFILEBGRUP freetypeFILEAGRUPlibFILE6FILE7FILE8FILE9FILE:ntJavaClasses.jarZIP MWZP Merge Out????APPLDLGXckidProjWSPC6K7I8M9L:JAXBYCZE\E\E\:J:J:J:J:J:J:J:J/8!F!F!F!F!F!F!F!F!F!F!F\`V\dErr钀ventModi ΅UW@::::: ::::freetype2:src: ::::freetype2:include: ::::freetype2:obj::@MacOS PPC Linkerftlinte:::bin:NoneMMPr@Java LinkerAPPL`Appl`GIFf.gifJAR Importer@JPEG.jpgJAR Importer@Jjrf.jrfMWCD`RSRC`TEXT.bhBalloon HelpTEXT.htmlTEXT.javaMW JavaTEXT.mfTEXT.rRezdocu`rsrc`.auJAR Importer@.classMW Java.gifJAR Importer@.jpegJAR Importer@.zipMW JavaMacOS 68K LinkerAPPL`Appl`MMLBLib Import 68KMPLFLib Import 68KMWCD`OBJ MPW Import 68KPLob`RSRC`TEXT.bhBalloon HelpTEXT.cMW C/C++ 68KTEXT.c++MW C/C++ 68KTEXT.ccMW C/C++ 68KTEXT.cpMW C/C++ 68KTEXT.cppMW C/C++ 68KTEXT.expTEXT.hMW C/C++ 68KTEXT.pMW Pascal 68KTEXT.pasMW Pascal 68KTEXT.pchMW C/C++ 68KTEXT.pch++MW C/C++ 68KTEXT.ppuMW Pascal 68KTEXT.rRezTEXT.segdocu`rsrc`shlbPEF Import 68KstubPEF Import 68K.docP.oMPW Import 68K.ppob`.rsrc`MacOS MergeAPPL`Appl`RSRC`TEXT.bhBalloon HelpTEXT.rRezrsrc`shlbMacOS PPC LinkerAPPL`Appl`MMLBLib Import PPCMPLFLib Import PPCMWCD`RSRC`TEXT.bhBalloon HelpTEXT.cMW C/C++ PPCTEXT.c++MW C/C++ PPCTEXT.ccMW C/C++ PPCTEXT.cpMW C/C++ PPCTEXT.cppMW C/C++ PPCTEXT.expTEXT.hMW C/C++ PPCTEXT.pMW Pascal PPCTEXT.pasMW Pascal PPCTEXT.pchMW C/C++ PPCTEXT.pch++MW C/C++ PPCTEXT.ppuMW Pascal PPCTEXT.rRezTEXT.sPPCAsmXCOFXCOFF Import PPCdocu`rsrc`shlbPEF Import PPCstubPEF Import PPC.docP.oXCOFF Import PPC.ppob`.rsrc` UPI.prefix a.out????APPLX????U {9:>>  !"#$%__start JBoundApp????WINDnullDFLTMetrowerks JavaInternet ExplorerDFLTMSIEhttp://java.sun.com/products/jdk/1.1/docs/api/__startftlintpeTestAppFTtAPPL@X????P'CODE' 'DATA' 'PICT'(mstr (mstlHmstnmstrmstlHmstn -mtpl |mtps( mtsl mtpit$mtlo%(msti%-,mpsi'Ymtgl (mstiZmall] maplPLstn"pref # #)u ppref ($5 pref .%;npref &U_pref w@'Vfpref `(Xnpref ) pref * pref + pref ,pref m%-Zpref .>pref /pref ?b0]pref $1_2pref 2bpref z3[pref (4gPpref o52pref b6k Ppref 7pZpref A8bpref m9Zr8pref S:  pref 0;\pref t<\ pref '=\ pref >slpref g?t6pref @uNpref _Au.pref Bv$ pref Cft2demos-2.10.1/mac/codewarrior/ftview.prj0000644000175000001440000031554413434207203020272 0ustar00wlusers00000000000000cool(t sCodeWarrior Project/H_u   6N^q8Qf !"#-$A%X&m'()*+,- ./20H1V2g3456789:;5<H=`>|?@ABCDEFG/HCIZJrKLMNOPQ RS)TBUWVrWXYZ[\] ^"_>`Pa_brcdefghi j k /l Im bn {o p q r s t u v 6w Sx ty z { | } ~ ( H g " > [ {  9 ^ y +Jf   )*+,-#&./0"('%123456789:;<=>?@AB$v}z~w{y|uxJKLMNDfGOPQCIHFRSTUhVWXYijZ[g\k]^_lm`abecdEnopqrst!RV[ NrajOWP&'()*g+TMXQ,-./0%ZpYcfbe\]^_d`K USIHJLqh  Fkl  !"#G$12i=>?@ABCDo7389:4;<56EnmSshs[qO  hcK  ftoption.hJavaClasses.jarZIP MWZPPC[freetype:Custom Keywordsfreetype:Access Pathsfreetype:Target Settingsfreetype:File Mappingsfreetype:Build Extrasfreetype:Debugger Targetfreetype:Debugger Runtimefreetype:68K CodeGenfreetype:68K Disassemblerfreetype:68K Global Optimizerfreetype:68K Linkerfreetype:68K Projectfreetype:C/C++ Compilerfreetype:C/C++ Warningsfreetype:CFM68Kfreetype:FTP Panelfreetype:Java Command Linefreetype:Java Languagefreetype:Java MacOS Settingsfreetype:Java Outputfreetype:Java Projectfreetype:JavaDoc Projectfreetype:MacOS Merge Panelfreetype:Pascal Compilerfreetype:Pascal Warningsfreetype:PPC CodeGenfreetype:PPC Disassemblerfreetype:PPC Global Optimizerfreetype:PPC Linkerfreetype:PPC PEFfreetype:PPC Projectfreetype:PPCAsm Panelfreetype:Rez CompilerProject File Listftlint:Custom Keywordsftlint:Access Pathsftlint:Target Settingsftlint:File Mappingsftlint:Build Extrasftlint:Debugger Targetftlint:Debugger Runtimeftlint:68K CodeGenftlint:68K Disassemblerftlint:68K Global Optimizerftlint:68K Linkerftlint:68K Projectftlint:C/C++ Compilerftlint:C/C++ Warningsftlint:CFM68Kftlint:FTP Panelftlint:Java Command Lineftlint:Java Languageftlint:Java MacOS Settingsftlint:Java Outputftlint:Java Projectftlint:JavaDoc Projectftlint:MacOS Merge Panelftlint:Pascal Compilerftlint:Pascal Warningsftlint:PPC CodeGenftlint:PPC Disassemblerftlint:PPC Global Optimizerftlint:PPC Linkerftlint:PPC PEFftlint:PPC Projectftlint:PPCAsm Panelftlint:Rez Compilerftview:Custom Keywordsftview:Access Pathsftview:Target Settingsftview:File Mappingsftview:Build Extrasftview:Debugger Targetftview:Debugger Runtimeftview:68K CodeGenftview:68K Disassemblerftview:68K Global Optimizerftview:68K Linkerftview:68K Projectftview:C/C++ Compilerftview:C/C++ Warningsftview:CFM68Kftview:FTP Panelftview:Java Command Lineftview:Java Languageftview:Java MacOS Settingsftview:Java Outputftview:Java Projectftview:JavaDoc Projectftview:MacOS Merge Panelftview:Pascal Compilerftview:Pascal Warningsftview:PPC CodeGenftview:PPC Disassemblerftview:PPC Global Optimizerftview:PPC Linkerftview:PPC PEFftview:PPC Projectftview:PPCAsm Panelftview:Rez Compilerftview:Source Treesftview:Remote Debugftview:Auto-targetftview:PJavaDebuggingftview:Java MRJAppBuilderftview:Output Flagsftview:Packager Panelftview:PPC CodeGen Mach-Oftview:PPC Mach-O Linkerftview:PPC Mach-O Targetftview:WinRC Compilerftview:x86 CodeGenftview:x86 Disassemblerftview:x86 Exceptions Panelftview:x86 Global Optimizerftview:x86 Linkerftview:x86 Projectftview - carbon:Source Treesftview - carbon:Access Pathsftview - carbon:Debugger Runtimeftview - carbon:Target Settingsftview - carbon:File Mappingsftview - carbon:Build Extrasftview - carbon:Debugger Targetftview - carbon:Remote Debugftview - carbon:Auto-targetftview - carbon:Custom Keywordsftview - carbon:C/C++ Compilerftview - carbon:C/C++ Warningsftview - carbon:FTP Panelftview - carbon:Java Command Lineftview - carbon:PJavaDebuggingftview - carbon:Java Languageftview - carbon:Java MRJAppBuilderftview - carbon:Java Outputftview - carbon:Java Projectftview - carbon:JavaDoc Projectftview - carbon:MacOS Merge Panelftview - carbon:Output Flagsftview - carbon:Packager Panelftview - carbon:PPC CodeGenftview - carbon:PPC CodeGen Mach-Oftview - carbon:PPC Disassemblerftview - carbon:PPC Global Optimizerftview - carbon:PPC Linkerftview - carbon:PPC Mach-O Linkerftview - carbon:PPC Mach-O Targetftview - carbon:PPC PEFftview - carbon:PPC Projectftview - carbon:PPCAsm Panelftview - carbon:Rez Compilerftview - carbon:WinRC Compilerftview - carbon:x86 CodeGenftview - carbon:x86 Disassemblerftview - carbon:x86 Exceptions Panelftview - carbon:x86 Global Optimizerftview - carbon:x86 Linkerftview - carbon:x86 Project UPI.prefixfreetypeFirst Segment:a.outLib Import 68KMPW Import 68KBalloon HelpMW C/C++ 68KMW Pascal 68KRezPEF Import 68K:FreeType.libLib Import PPCMW C/C++ PPCMW Pascal PPCPPCAsmXCOFF Import PPCPEF Import PPCMacOS PPC LinkerCustom KeywordsAccess PathsTarget SettingsFile MappingsBuild ExtrasDebugger TargetC/C++ CompilerC/C++ WarningsFTP PanelPascal CompilerPascal WarningsPPC CodeGenPPC DisassemblerPPC Global OptimizerPPC LinkerPPC PEFPPC ProjectPPCAsm PanelRez Compilerftsystem.cftbase.cftbbox.cftcalc.cftdebug.cftextend.cftinit.cftlist.cftobjs.cftoutln.cftraster.cftstream.csfdriver.csfnt.cttcmap.cttload.cttpost.cttsbit.ctruetype.cttdriver.cttgload.cttinterp.cttobjs.cttpload.ct1afm.ct1driver.ct1gload.ct1hinter.ct1load.ct1objs.ct1parse.ct1tokens.ctype1.coltypes.cpsnames.cMSL C.PPC.LibMathLibMSL RuntimePPC.LibInterfaceLibMSL SIOUX.PPC.Libftlint.c:FreeTypeTestAppFreeType.libFreeType_DEBUG.libftlint_mac.c:::bin:FreeTypeTestAppmacgetargv.cftlintmacftlint.rsrc:::bin:ftlintFreeTypeLibftlint.rsrcftview.cftview:::bin:ftviewgrblit.cgrdevice.cgrfont.cgrinit.cgrobjs.ccommon.cftview_mac.cftview.rsrcgrmac.cgetargv.cftview_m.cftgrays.cMSL_All_PPC.LibSource TreesDebugger RuntimeOutput FlagsPackager PanelUTCUtilsUnicodeConverterTextCommonftview - carbonMSL_All_Carbon.LibCarbonLib6i9L:JAXD]E^F_G`HaIbLdMeNfOgQnRoSpOg:J/8!F!F!F!F!F!F!F!F!F!F!F69:ADEFGHILMNOQRS ( ROOTGRUPsrcFILEOFILENFILEIGRUP graphFILEMFILEDFILEEFILEFFILEGFILEHGRUP resourcesFILELGRUP freetypeFILEAGRUPlibGRUP carbonFILETFILEUGRUP ppcFILE6FILE9FILE:FILEQFILERFILES@cntl@cntlDcntlHcntlL UADEFGHILMNOTUjk lm !"#$%carbonprefix.h JavaClasses.jarZIP MWZP@::::: ::::freetype2:src: ::::freetype2:include: ::::freetype2:obj::MSL:werks Standard Library:MSL C:@:@ MacOS PPC Linkerftview:::bin:main  a.out????APPLX????U {__start`Appl`GIFf.gifJAR Importer@JPEG.jpgJAR mporter@Jjrf.jrfMWCD`RSRC`TEXT.bhBalloon HelpJavaTEXT.htmlJavaTEXT.javaMW JavaJavaTEXT.mfJavaTEXT.rRezRezdocu`rsrc__start startDFLTMetrowerks JavaInternet ExplorerMSIEhttp://java.sun.com/products/jdk/1.1/docs/api/ Merge Out????APPLa.rsrc:DLGXckidProjWSPC` JBoundApp????WINDnullNoneMMPr@Java LinkerAPPL`Appl`GIFf.gifJAR Importer@JPEG.jpgJAR Importer@Jjrf.jrfMWCD`RSRC`TEXT.bhBalloon HelpJavaTEXT.htmlJavaTEXT.javaMW JavaJavaTEXT.mfJavaTEXT.rRezRezdocu`rsrc`.auJAR Importer@.classMW Java.gifJAR Importer@.jpegJAR Importer@.zipMW JavaMacOS 68K LinkerAPPL`Appl`MMLBLib Import 68KMPLFLib Import 68KMWCD`OBJ MPW Import 68KPLob`RSRC`TEXT.bhBalloon HelpTEXT.cMW C/C++ 68KTEXT.c++MW C/C++ 68KTEXT.ccMW C/C++ 68KTEXT.cpMW C/C++ 68KTEXT.cppMW C/C++ 68KTEXT.expTEXT.hMW C/C++ 68KTEXT.pMW Pascal 68KTEXT.pasMW Pascal 68KTEXT.pchMW C/C++ 68KTEXT.pch++MW C/C++ 68KTEXT.ppuMW Pascal 68KTEXT.rRezRezTEXT.segdocu`rsrc`shlbPEF Import 68KstubPEF Import 68K.docP.oMPW Import 68K.ppob`.rsrc`MacOS MergeAPPL`Appl`RSRC`TEXT.bhBalloon HelpTEXT.rRezRezrsrc`shlbMacOS PPC LinkerAPPL`Appl`MMLBLib Import PPCMPLFLib Import PPCMWCD`RSRC`TEXT.bhBalloon HelpTEXT.cMW C/C++ PPCC/C++TEXT.c++MW C/C++ PPCC/C++TEXT.ccMW C/C++ PPCC/C++TEXT.cpMW C/C++ PPCC/C++TEXT.cppMW C/C++ PPCC/C++TEXT.expTEXT.hMW C/C++ PPCC/C++TEXT.pMW Pascal PPCTEXT.pasMW Pascal PPCTEXT.pchMW C/C++ PPCC/C++TEXT.pch++MW C/C++ PPCC/C++TEXT.ppuMW Pascal PPCTEXT.rRezRezTEXT.sPPCAsmXCOFXCOFF Import PPCdocu`rsrc`shlbPEF Import PPCstubPEF Import PPC.docP.oXCOFF Import PPC.ppob`.rsrc`Mach-O PPC LinkerAPPL`Appl`MDYLLib Import Mach-OMLIBLib Import Mach-OMMLBLib Import Mach-OMPLFLib Import Mach-OMWCD`RSRC`TEXT.cMW C/C++ MachPPCC/C++TEXT.c++MW C/C++ MachPPCC/C++TEXT.ccMW C/C++ MachPPCC/C++TEXT.cpMW C/C++ MachPPCC/C++TEXT.cppMW C/C++ MachPPCC/C++TEXT.expTEXT.hMW C/C++ MachPPCC/C++TEXT.pchMW C/C++ MachPPCC/C++TEXT.pch++MW C/C++ MachPPCC/C++TEXT.plistPTEXT.rRezRezdocu`rsrc`.aLib Import Mach-O.docP.dylibLib Import Mach-O.oLib Import Mach-OWin32 x86 LinkerTEXT.cMW C/C++ x86C/C++TEXT.c++MW C/C++ x86C/C++TEXT.ccMW C/C++ x86C/C++TEXT.cpMW C/C++ x86C/C++TEXT.cppMW C/C++ x86C/C++TEXT.defTEXT.hMW C/C++ x86C/C++TEXT.h++MW C/C++ x86C/C++TEXT.hppMW C/C++ x86C/C++TEXT.ordTEXT.pchMW C/C++ x86C/C++TEXT.pch++MW C/C++ x86C/C++TEXT.rcMW WinRCiLIBLib Import x86iOBJObj Import x86.aLib Import x86.docP.libLib Import x86.oObj Import x86.objObj Import x86.resWinRes ImportftviewFTwAPPL@X:????P'CODE' 'DATA' 'PICT'@:@MRJApplicationTEXT.ord????APPL::a.exe????MEXE@a.rsrc:./ noname.exe@ -<IVd h w "/?N]gw !"#$%&'()*"+-,6-?.H/R0]1h2s3z456789:;<=>?@AB CD E+F3G=HGIUJ]KpL}MNOPQRSTUVWX*Y6Z?[F\T]]^h_q`zabcdefghijklmno0p;qKr^s[\lq\7=AXD]E^F_G`HaIbLdMeNfOgTrUsUsUsUsUsUsUs/8!F!F!F!F!F!F!F!F!F!F!F@ ::::: ::::freetype2:src: ::::freetype2:include: ::::freetype2:obj::MSL:werks Standard Library:MSL C:@:MacOS Support:ns:Metrowerks CodeWarrior 7.0:Metrowerks CodeWarrior:MacOS Support:@:@ MacOS PPC Linkerftview - carbon:::bin:NoneMMPr@Java LinkerAPPL`Appl`GIFf.gifJAR Importer@JPEG.jpgJAR Importer@Jjrf.jrfMWCD`RSRC`TEXT.bhBalloon HelpJavaTEXT.htmlJavaTEXT.javaMW JavaJavaTEXT.mfJavaTEXT.rRezRezdocu`rsrc`.auJAR Importer@.classMW Java.gifJAR Importer@.jpegJAR Importer@.zipMW JavaMacOS 68K LinkerAPPL`Appl`MMLBLib Import 68KMPLFLib Import 68KMWCD`OBJ MPW Import 68KPLob`RSRC`TEXT.bhBalloon HelpTEXT.cMW C/C++ 68KTEXT.c++MW C/C++ 68KTEXT.ccMW C/C++ 68KTEXT.cpMW C/C++ 68KTEXT.cppMW C/C++ 68KTEXT.expTEXT.hMW C/C++ 68KTEXT.pMW Pascal 68KTEXT.pasMW Pascal 68KTEXT.pchMW C/C++ 68KTEXT.pch++MW C/C++ 68KTEXT.ppuMW Pascal 68KTEXT.rRezRezTEXT.segdocu`rsrc`shlbPEF Import 68KstubPEF Import 68K.docP.oMPW Import 68K.ppob`.rsrc`MacOS MergeAPPL`Appl`RSRC`TEXT.bhBalloon HelpTEXT.rRezRezrsrc`shlbMacOS PPC LinkerAPPL`Appl`MMLBLib Import PPCMPLFLib Import PPCMWCD`RSRC`TEXT.bhBalloon HelpTEXT.cMW C/C++ PPCC/C++TEXT.c++MW C/C++ PPCC/C++TEXT.ccMW C/C++ PPCC/C++TEXT.cpMW C/C++ PPCC/C++TEXT.cppMW C/C++ PPCC/C++TEXT.expTEXT.hMW C/C++ PPCC/C++TEXT.pMW Pascal PPCTEXT.pasMW Pascal PPCTEXT.pchMW C/C++ PPCC/C++TEXT.pch++MW C/C++ PPCC/C++TEXT.ppuMW Pascal PPCTEXT.rRezRezTEXT.sPPCAsmXCOFXCOFF Import PPCdocu`rsrc`shlbPEF Import PPCstubPEF Import PPC.docP.oXCOFF Import PPC.ppob`.rsrc`Mach-O PPC LinkerAPPL`Appl`MDYLLib Import Mach-OMLIBLib Import Mach-OMMLBLib Import Mach-OMPLFLib Import Mach-OMWCD`RSRC`TEXT.cMW C/C++ MachPPCC/C++TEXT.c++MW C/C++ MachPPCC/C++TEXT.ccMW C/C++ MachPPCC/C++TEXT.cpMW C/C++ MachPPCC/C++TEXT.cppMW C/C++ MachPPCC/C++TEXT.expTEXT.hMW C/C++ MachPPCC/C++TEXT.pchMW C/C++ MachPPCC/C++TEXT.pch++MW C/C++ MachPPCC/C++TEXT.plistPTEXT.rRezRezdocu`rsrc`.aLib Import Mach-O.docP.dylibLib Import Mach-O.oLib Import Mach-OWin32 x86 LinkerTEXT.cMW C/C++ x86C/C++TEXT.c++MW C/C++ x86C/C++TEXT.ccMW C/C++ x86C/C++TEXT.cpMW C/C++ x86C/C++TEXT.cppMW C/C++ x86C/C++TEXT.defTEXT.hMW C/C++ x86C/C++TEXT.h++MW C/C++ x86C/C++TEXT.hppMW C/C++ x86C/C++TEXT.ordTEXT.pchMW C/C++ x86C/C++TEXT.pch++MW C/C++ x86C/C++TEXT.rcMW WinRCiLIBLib Import x86iOBJObj Import x86.aLib Import x86.docP.libLib Import x86.oObj Import x86.objObj Import x86.resWinRes Import`Appl`GIFf.gifJAR Importer@JPEG.jpgJAR mporter@Jjrf.jrfMWCD`RSRC`TEXT.bhBalloon HelpJavaTEXT.htmlJavaTEXT.javaMW JavaJavaTEXT.mfJavaTEXT.rRezRezdocu`rsrcmain@:@MRJApplicationDFLTMetrowerks JavaInternet ExplorerMSIEhttp://java.sun.com/products/jdk/1.1/docs/api/ Merge Out????APPLa.rsrc:DLGXckidProjWSPCTEXT.ord????APPL::__start starta.exe????MEXE@a.rsrc:./ftviewFTwAPPL@X:???? noname.exe@  P'CODE' 'DATA' 'PICT'Hmstr(mstlmstnmstrxmstl (mstn'mtpl |mtps( mtsl (mtpi,XDmtlo L(msti,,mpsix4mtgl2(mstiZmall0mapl.PLstn"prefBD2prefEA`prefFzd7pprefGO# pref(HGt pref IUCprefTJ 8prefK prefcL pref|M prefNLCprefO>prefivP prefQMIprefRZprefS`Epref[fTJprefUwPprefJV2prefWeM prefXnpref)YqprefZH8pref[ prefo\1Dpref]1X pref4^K pref6_YSpref`upref{aprefbK.pref8Uc pref^dpref aXepref Sf pref gKpref Uhpref iϢpref 6jzpref !*kKpref lZbpref Axm֐pref ^nL"pref NoZpref )pZpref Dqvpref @rL2 pref s|pref tjpref qu tmotiZ mtslmtpl|mtps0Hmtpi0X4mtlopref +vpref _whpref wxxpref JOy 7ppref ^zB pref vn{I pref r|L<pref !}zpref E~1bpref N1|>pref 0pref OBpref &Tpref =1pref ]Ypref -Zpref 12pref xj pref otDpref wXpref @zpref o\{pref iD2pref z2pref 22 pref O2< pref pref ibpref ?pref upref Rpref sB2H.pref  pref 2v"pref mvpref <vpref j6vpref M2 pref pref o~jpref ft2demos-2.10.1/mac/Makefile0000644000175000001440000000657213434207203015367 0ustar00wlusers00000000000000################################################################## # # Makefile for MacOS X to build MacOS-specific API test program, # Also targets to setup vanilla source for MPW are included. # This should be executed in this directory, as # "cd ft2demos ; make -C mac". # # most part is taken from ft2demos/Makefile, for UNIX platform. # all: exes empty := space := $(empty) $(empty) TOP_DIR ?= ../../freetype2 OBJ_DIR ?= $(TOP_DIR)/objs TOP_DIR_2 ?= .. OBJ_DIR_2 ?= $(TOP_DIR_2)/objs TOP_DIR_2_MAC ?= $(TOP_DIR_2)/mac ifndef CONFIG_MK PROJECT := freetype CONFIG_MK := $(TOP_DIR)/config.mk endif ifeq ($(wildcard $(CONFIG_MK)),) no_config_mk := 1 endif ifdef no_config_mk exes: @echo Please compile the library before the demo programs! clean distclean: @echo "I need \`$(subst /,$(SEP),$(TOP_DIR)/config.mk)' to do that!" else include $(CONFIG_MK) have_makefile := $(strip $(wildcard Makefile)) TOP_DIR := $(shell cd $(TOP_DIR); pwd) TOP_DIR_2 := $(shell cd $(TOP_DIR_2); pwd) ifneq ($(have_makefile),) BIN_DIR_2 ?= $(TOP_DIR_2)/bin OBJ_DIR_2 ?= $(TOP_DIR_2)/objs else BIN_DIR_2 ?= .. OBJ_DIR_2 ?= .. endif GRAPH_DIR := $(TOP_DIR_2)/graph include $(GRAPH_DIR)/rules.mk ifeq ($(TOP_DIR),..) SRC_DIR := src else SRC_DIR := $(TOP_DIR_2)/src endif FT_INCLUDES := $(OBJ_BUILD) $(BUILD_DIR) $(TOP_DIR)/include $(SRC_DIR) INCLUDES := $(subst /,$(COMPILER_SEP),$(FT_INCLUDES)) COMPILE = $(CC) $(CFLAGS) $(INCLUDES:%=$I%) FTLIB := $(LIB_DIR)/$(LIBRARY).$A ifeq ($(PLATFORM),unix) MATH := -lm endif ifeq ($(PLATFORM),unixdev) MATH := -lm endif LINK_ITEMS = $T$(subst /,$(COMPILER_SEP),$@ $<) CC = $(CCraw) LINK_CMD = $(subst /,$(SEP),$(OBJ_BUILD)/libtool) \ --mode=link $(CC) \ $(subst /,$(COMPILER_SEP),$(LDFLAGS)) ifeq ($(findstring CoreServices,$(LDFLAGS)),) LINK_LIBS = $(subst /,$(COMPILER_SEP),$(FTLIB) $(EFENCE)) $(MATH) \ -Xlinker -framework -Xlinker CoreServices \ -Xlinker -framework -Xlinker ApplicationServices else LINK_LIBS = $(subst /,$(COMPILER_SEP),$(FTLIB) $(EFENCE)) $(MATH) endif LINK_COMMON = $(LINK_CMD) \ $(LINK_ITEMS) $(subst /,$(COMPILER_SEP),$(COMMON_OBJ)) \ $(LINK_LIBS) .PHONY: exes clean distclean E := EXES := ftoldmac exes: $(EXES:%=$(BIN_DIR_2)/%$E) $(BIN_DIR_2)/ftoldmac$E: $(OBJ_DIR_2)/ftoldmac.$(SO) $(FTLIB) $(COMMON_OBJ) $(LINK_COMMON) $(OBJ_DIR_2)/ftoldmac.$(SO): $(TOP_DIR_2_MAC)/ftoldmac.c $(COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) $DFT2_BUILD_LIBRARY COMMON_OBJ := $(OBJ_DIR_2)/common.$(SO) $(COMMON_OBJ): $(SRC_DIR)/common.c $(COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) $DFT2_BUILD_LIBRARY ################################################################ # Targets to setup MPW # clean: rm -f \ $(TOP_DIR_2)/ftoldmac.*.make \ $(OBJ_DIR_2)/*.NJ \ $(OBJ_DIR_2)/*.makeout \ $(OBJ_DIR_2)/*.o $(OBJ_DIR_2)/*.exe makefiles: python $(TOP_DIR_2_MAC)/ascii2mpw.py \ > $(TOP_DIR_2)/ftoldmac.m68k_far.make \ < $(TOP_DIR_2_MAC)/ftoldmac.m68k_far.make.txt python $(TOP_DIR_2_MAC)/ascii2mpw.py \ > $(TOP_DIR_2)/ftoldmac.ppc_classic.make \ < $(TOP_DIR_2_MAC)/ftoldmac.ppc_classic.make.txt find $(TOP_DIR_2) -name '*.make' | \ xargs /Developer/Tools/SetFile -a l -c "MPS " -t TEXT resource: find $(SRC_DIR) $(TOP_DIR_2_MAC) -name '*.[ch]' | \ xargs /Developer/Tools/SetFile -a l -c "MPS " -t TEXT endif ft2demos-2.10.1/mac/ascii2mpw.py0000644000175000001440000000201113434207203016157 0ustar00wlusers00000000000000#!/usr/bin/env python import sys import string if len( sys.argv ) == 1 : for asc_line in sys.stdin.readlines(): mpw_line = string.replace(asc_line, "\\xA5", "\245") mpw_line = string.replace(mpw_line, "\\xB6", "\266") mpw_line = string.replace(mpw_line, "\\xC4", "\304") mpw_line = string.replace(mpw_line, "\\xC5", "\305") mpw_line = string.replace(mpw_line, "\\xFF", "\377") mpw_line = string.replace(mpw_line, "\n", "\r") mpw_line = string.replace(mpw_line, "\\n", "\n") sys.stdout.write(mpw_line) elif sys.argv[1] == "-r" : for mpw_line in sys.stdin.readlines(): asc_line = string.replace(mpw_line, "\n", "\\n") asc_line = string.replace(asc_line, "\r", "\n") asc_line = string.replace(asc_line, "\245", "\\xA5") asc_line = string.replace(asc_line, "\266", "\\xB6") asc_line = string.replace(asc_line, "\304", "\\xC4") asc_line = string.replace(asc_line, "\305", "\\xC5") asc_line = string.replace(asc_line, "\377", "\\xFF") sys.stdout.write(asc_line) ft2demos-2.10.1/mac/ftoldmac.ppc_classic.make.txt0000644000175000001440000000414613434207203021452 0ustar00wlusers00000000000000# File: ftoldmac.ppc_classic.make # Target: ftoldmac.ppc_classic # Created: Thursday, November 24, 2005 10:02:30 AM MAKEFILE = ftoldmac.ppc_classic.make \xA5MondoBuild\xA5 = {MAKEFILE} # Make blank to avoid rebuilds when makefile is modified FT2Dir = ::freetype2: ObjDir = :objs: Includes = \xB6 -i "{FT2Dir}include:" \xB6 -i "{FT2Dir}src:" \xB6 -i :src: \xB6 -i "{FT2Dir}include:freetype:config:" Sym-PPC = -sym off PPCCOptions = \xB6 -d HAVE_FSSPEC=1 \xB6 -d HAVE_FSREF=0 \xB6 -d HAVE_QUICKDRAW_TOOLBOX=1 \xB6 -d HAVE_QUICKDRAW_CARBON=0 \xB6 -d HAVE_ATS=0 \xB6 -d FT2_BUILD_LIBRARY \xB6 -d FT_CONFIG_CONFIG_H="" \xB6 -d FT_CONFIG_MODULES_H="" \xB6 {Includes} {Sym-PPC} -includes unix -ansi strict ### Source Files ### SrcFiles = \xB6 :mac:ftoldmac.c \xB6 :src:common.c ### Object Files ### ObjFiles-PPC = \xB6 "{ObjDir}common.c.x" \xB6 "{ObjDir}ftoldmac.c.x" ### Libraries ### LibFiles-PPC = \xB6 "{FT2Dir}FreeType.ppc_classic.o" \xB6 "{SharedLibraries}InterfaceLib" \xB6 "{SharedLibraries}StdCLib" \xB6 "{SharedLibraries}MathLib" \xB6 "{PPCLibraries}StdCRuntime.o" \xB6 "{PPCLibraries}PPCCRuntime.o" \xB6 "{PPCLibraries}PPCToolLibs.o" ### Default Rules ### .c.x \xC4 .c {\xA5MondoBuild\xA5} {PPCC} {depDir}{default}.c -o {targDir}{default}.c.x {PPCCOptions} ### Build Rules ### ftoldmac.ppc_classic \xC4\xC4 {ObjFiles-PPC} {LibFiles-PPC} {\xA5MondoBuild\xA5} PPCLink \xB6 -o {Targ} \xB6 {ObjFiles-PPC} \xB6 {LibFiles-PPC} \xB6 {Sym-PPC} \xB6 -mf -d \xB6 -t 'MPST' \xB6 -c 'MPS ' ### Required Dependencies ### "{ObjDir}common.c.x" \xC4 :src:common.c "{ObjDir}ftoldmac.c.x" \xC4 :mac:ftoldmac.c ### Optional Dependencies ### ### Build this target to generate "include file" dependencies. ### Dependencies \xC4 $OutOfDate MakeDepend \xB6 -append {MAKEFILE} \xB6 -ignore "{CIncludes}" \xB6 -objdir "{ObjDir}" \xB6 -objext .x \xB6 {Includes} \xB6 {SrcFiles} ft2demos-2.10.1/mac/README0000644000175000001440000000253213434207203014577 0ustar00wlusers00000000000000This folder contains supporting code and CodeWarrior Pro 4 project files to build the FreeType demo programs ftlint and ftview for MacOS. Building To build these apps, you'll first need to build the FreeType library (see config/mac). Be sure to unpack the resource.hqx file; it contains two resource files that are needed for ftlint and ftview. The applications get built in the demos/bin folder. Notes Since the Mac doesn't have the notion of argc/argv, we'll emulate this: each file dropped onto the application will be translated to a command line argument. Both ftlint and ftview take a ppem value as their first command line argument: for the Mac version this has been hard-coded into the source. Also: the additional options for ftview cannot be set. Appendix Makefile, ftoldmac.m68k_far.make.txt, ftoldmac.ppc_classic.make.txt and ftoldmac.c are for commandline program "ftoldmac" to test MacOS specific API, written by suzuki toshiya. On MacOS X, you can build ftoldmac by "make -C mac" in the top directory of ft2demos. Also you can generate MPW makefiles by "make -C mac makefiles", in MacOS X commandline. Have fun with FreeType on the Mac! Just van Rossum, DISCLAIMER: this subdirectory is *not* being maintained by the FreeType team, but by Just van Rossum. It's being released under the same terms as FreeType (see LICENSE.TXT). ft2demos-2.10.1/mac/ftoldmac.m68k_far.make.txt0000644000175000001440000000436313434207203020605 0ustar00wlusers00000000000000# File: ftoldmac.m68k_far.make # Target: ftoldmac.m68k_far # Created: Wednesday, November 23, 2005 04:21:20 PM MAKEFILE = ftoldmac.m68k_far.make \xA5MondoBuild\xA5 = {MAKEFILE} # Make blank to avoid rebuilds when makefile is modified FT2Dir = ::freetype2: ObjDir = :objs: Includes = \xB6 -i "{FT2Dir}include:" \xB6 -i "{FT2Dir}src:" \xB6 -i :src: \xB6 -i "{FT2Dir}include:freetype:config:" Sym-68K = -sym off COptions = \xB6 -d HAVE_FSSPEC=1 \xB6 -d HAVE_FSREF=0 \xB6 -d HAVE_QUICKDRAW_TOOLBOX=1 \xB6 -d HAVE_QUICKDRAW_CARBON=0 \xB6 -d HAVE_ATS=0 \xB6 -d FT2_BUILD_LIBRARY \xB6 -d FT_CONFIG_CONFIG_H="" \xB6 -d FT_CONFIG_MODULES_H="" \xB6 {Includes} {Sym-68K} -model far -includes unix ### Source Files ### SrcFiles = \xB6 :mac:ftoldmac.c \xB6 :src:common.c ### Object Files ### ObjFiles-68K = \xB6 "{ObjDir}ftoldmac.c.o" \xB6 "{ObjDir}common.c.o" ### Libraries ### LibFiles-68K = \xB6 "{FT2Dir}FreeType.m68k_far.o" \xB6 "{Libraries}Stubs.o" \xB6 "{Libraries}MathLib.far.o" \xB6 "{CLibraries}StdCLib.far.o" \xB6 "{Libraries}MacRuntime.o" \xB6 "{Libraries}IntEnv.far.o" \xB6 "{Libraries}ToolLibs.far.o" \xB6 "{Libraries}Interface.o" ### Default Rules ### .c.o \xC4 .c {\xA5MondoBuild\xA5} {C} {depDir}{default}.c -o {targDir}{default}.c.o {COptions} ### Build Rules ### ftoldmac.m68k_far \xC4\xC4 {ObjFiles-68K} {LibFiles-68K} {\xA5MondoBuild\xA5} ILink \xB6 -o {Targ} \xB6 {ObjFiles-68K} \xB6 {LibFiles-68K} \xB6 {Sym-68K} \xB6 -mf -d \xB6 -t 'MPST' \xB6 -c 'MPS ' \xB6 -model far \xB6 -state rewrite \xB6 -compact -pad 0 \xB6 -br on If "{Sym-68K}" =~ /-sym \xC5[nNuU]\xC5/ ILinkToSYM {Targ}.NJ -mf -sym 3.2 -c 'sade' End ### Required Dependencies ### "{ObjDir}ftoldmac.c.o" \xC4 :mac:ftoldmac.c "{ObjDir}common.c.o" \xC4 :src:common.c ### Optional Dependencies ### ### Build this target to generate "include file" dependencies. ### Dependencies \xC4 $OutOfDate MakeDepend \xB6 -append {MAKEFILE} \xB6 -ignore "{CIncludes}" \xB6 -objdir "{ObjDir}" \xB6 -objext .o \xB6 {Includes} \xB6 {SrcFiles} ft2demos-2.10.1/mac/getargv.h0000644000175000001440000000060613434207203015527 0ustar00wlusers00000000000000/* FTMac_GetArgv argc/argv emulation for the Mac. Converts files dropped onto the application to full paths, and stuff them into argv. pargv :: a pointer to an argv array. The array doesn't need to exist before calling this function. The number of files dropped onto the app (ie. argc) */ int FTMac_GetArgv(char ***pargv); ft2demos-2.10.1/mac/getargv.c0000644000175000001440000002013713442124344015526 0ustar00wlusers00000000000000/*********************************************************** Copyright (C) 1991-2019 by Stichting Mathematisch Centrum, Amsterdam, The Netherlands. All Rights Reserved 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, and that the names of Stichting Mathematisch Centrum or CWI not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ /* Construct argc and argv for main() by using Apple Events */ /* From Jack's implementation for STDWIN */ /* Modified for use with FreeType from MacPython's macgetargv.c by Just van Rossum */ #include #include #include "getargv.h" #ifndef USING_CARBON #include #include #include #include #include #include #include #else #include #endif #if defined(GENERATINGCFM) && !defined(USING_CARBON) /* Defined to 0 or 1 in Universal headers */ #define HAVE_UNIVERSAL_HEADERS #endif #if !defined(HAVE_UNIVERSAL_HEADERS) && !defined(USING_CARBON) #define NewAEEventHandlerProc(x) (x) #define AEEventHandlerUPP EventHandlerProcPtr #endif static int arg_count; static char *arg_vector[256]; static char app_name[256]; static int app_name_inited; /* Duplicate a string to the heap. */ static char * strdup(char *src) { char *dst = malloc(strlen(src) + 1); if (dst) strcpy(dst, src); return dst; } /* Given an FSSpec, return the FSSpec of the parent folder */ static OSErr get_folder_parent (FSSpec * fss, FSSpec * parent) { CInfoPBRec rec; short err; * parent = * fss; rec.hFileInfo.ioNamePtr = parent->name; rec.hFileInfo.ioVRefNum = parent->vRefNum; rec.hFileInfo.ioDirID = parent->parID; rec.hFileInfo.ioFDirIndex = -1; rec.hFileInfo.ioFVersNum = 0; if (err = PBGetCatInfoSync (& rec)) return err; parent->parID = rec.dirInfo.ioDrParID; /* parent->name[0] = 0; */ return 0; } /* Given an FSSpec return a full, colon-separated pathname */ static OSErr FTMac_GetFullPath (FSSpec *fss, char *buf) { short err; FSSpec fss_parent, fss_current; char tmpbuf[256]; int plen; fss_current = *fss; plen = fss_current.name[0]; memcpy(buf, &fss_current.name[1], plen); buf[plen] = 0; /* Special case for disk names */ if ( fss_current.parID <= 1 ) { buf[plen++] = ':'; buf[plen] = 0; return 0; } while (fss_current.parID > 1) { /* Get parent folder name */ if (err = get_folder_parent(&fss_current, &fss_parent)) return err; fss_current = fss_parent; /* Prepend path component just found to buf */ plen = fss_current.name[0]; if (strlen(buf) + plen + 1 > 256) { /* Oops... Not enough space (shouldn't happen) */ *buf = 0; return -1; } memcpy(tmpbuf, &fss_current.name[1], plen); tmpbuf[plen] = ':'; strcpy(&tmpbuf[plen+1], buf); strcpy(buf, tmpbuf); } return 0; } /* Initialize name of current application */ static OSErr init_app_name() { ProcessSerialNumber currentPSN; ProcessInfoRec info; OSErr err; FSSpec appSpec; if ( app_name_inited ) return 0; currentPSN.highLongOfPSN = 0; currentPSN.lowLongOfPSN = kCurrentProcess; info.processInfoLength = sizeof(ProcessInfoRec); info.processName = NULL; info.processAppSpec = &appSpec; if ( err=GetProcessInformation(¤tPSN, &info)) return err; strncpy(app_name, (char*)appSpec.name + 1, appSpec.name[0]); app_name[appSpec.name[0]] = '\0'; app_name_inited = 1; return 0; } /* Check that there aren't any args remaining in the event */ static OSErr get_missing_params(const AppleEvent *theAppleEvent) { DescType theType; Size actualSize; OSErr err; err = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard, &theType, nil, 0, &actualSize); if (err == errAEDescNotFound) return noErr; else return errAEEventNotHandled; } static int got_one; /* Flag that we can stop getting events */ /* Handle the Print or Quit events (by failing) */ static pascal OSErr handle_not(const AppleEvent *theAppleEvent, AppleEvent *reply, long refCon) { #pragma unused (reply, refCon) got_one = 1; return errAEEventNotHandled; } /* Handle the Open Application event (by ignoring it) */ static pascal OSErr handle_open_app(const AppleEvent *theAppleEvent, AppleEvent *reply, long refCon) { #pragma unused (reply, refCon) #if 0 /* Test by Jack: would removing this facilitate debugging? */ got_one = 1; #endif return get_missing_params(theAppleEvent); } /* Handle the Open Document event, by adding an argument */ static pascal OSErr handle_open_doc(const AppleEvent *theAppleEvent, AppleEvent *reply, long refCon) { #pragma unused (reply, refCon) OSErr err; AEDescList doclist; AEKeyword keywd; DescType rttype; long i, ndocs, size; FSSpec fss; char path[256]; got_one = 1; if (err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &doclist)) return err; if (err = get_missing_params(theAppleEvent)) return err; if (err = AECountItems(&doclist, &ndocs)) return err; for(i = 1; i <= ndocs; i++) { err = AEGetNthPtr(&doclist, i, typeFSS, &keywd, &rttype, &fss, sizeof(fss), &size); if (err) break; FTMac_GetFullPath(&fss, path); arg_vector[arg_count++] = strdup(path); } return err; } /* Install standard core event handlers */ static AEEventHandlerUPP open_doc_upp; static AEEventHandlerUPP open_app_upp; static AEEventHandlerUPP not_upp; static void set_ae_handlers() { #ifdef USING_CARBON open_doc_upp = NewAEEventHandlerUPP(handle_open_doc); open_app_upp = NewAEEventHandlerUPP(handle_open_app); not_upp = NewAEEventHandlerUPP(handle_not); #else open_doc_upp = NewAEEventHandlerProc(handle_open_doc); open_app_upp = NewAEEventHandlerProc(handle_open_app); not_upp = NewAEEventHandlerProc(handle_not); #endif AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, open_app_upp, 0L, false); AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, open_doc_upp, 0L, false); AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, not_upp, 0L, false); AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, not_upp, 0L, false); } /* Uninstall standard core event handlers */ static void reset_ae_handlers() { AERemoveEventHandler(kCoreEventClass, kAEOpenApplication, open_app_upp, false); AERemoveEventHandler(kCoreEventClass, kAEOpenDocuments, open_doc_upp, false); AERemoveEventHandler(kCoreEventClass, kAEPrintDocuments, not_upp, false); AERemoveEventHandler(kCoreEventClass, kAEQuitApplication, not_upp, false); } /* Wait for events until a core event has been handled */ static void event_loop() { EventRecord event; int n; int ok; got_one = 0; for (n = 0; n < 100 && !got_one; n++) { #ifndef USING_CARBON SystemTask(); #endif ok = GetNextEvent(everyEvent, &event); if (ok && event.what == kHighLevelEvent) { AEProcessAppleEvent(&event); } } } /* Get the argv vector, return argc. See macgetargv.h for more doco. */ int FTMac_GetArgv(pargv) char ***pargv; { arg_count = 0; (void)init_app_name(); arg_vector[arg_count++] = strdup(app_name); set_ae_handlers(); event_loop(); reset_ae_handlers(); arg_vector[arg_count] = NULL; *pargv = arg_vector; return arg_count; } ft2demos-2.10.1/mac/resource.hqx0000644000175000001440000000572613434207203016300 0ustar00wlusers00000000000000(This file must be converted with BinHex 4.0) :$(*PFfpeFQ0P,R0TG!"6594%8dP8)3%!!!!(9!!!!4kE)90*9#%!!J!!"e4b6'& e!J!!!!!@!!!0!!YQG'aTER3ZFR0bB`EK@D!!4J`+!!!!J!!!!!!'k52Z%qJ*KJ! !!!!!!!!!!!!!!!!!!!!!!!'I!!!!!2rrrrpbFh*M8P0&4!%!Y0lZjl6HlcS!!!' C!!!!!!!!!4N!!!!!Pl)!!!!!!!!!!&+E%3!)(#ae#1,@kQ-l3-r1rA-h'clY+LM H9q+m@S[Fj'KEDPD(PRRlbr3)Nck4+9)bfh$4M895H*J+"lDRd-a-6hUrB81a2k& e%)&b(ZXdrYBdI[ZdE)8F9('8dr066MF[CQTkaA%3fiT"m8l2P`!e0ENhlY2j"FL II%YbGc@ph91S4%8'Z5Xc+&ScAr+%DY2QlM5MEm[C1mhS@lHGdf@4$r)jQ+1c[Yf b16K0FP*c0Q[Vq(0e9lNT3"NeFC`c!fd61PVU13*GNpUBBBEDYdiZ2hX`9eAR44H ,BIaH('A$McIF3lH!AZ"TPCcBbG(bCcBTR0P-J9(CPq!SQh,26%f1,GX[-,2KJYL bC2[mR3Fc+V#JQ6c,1D9*!!!0!!YQG(CTCAFZFR0bB`EK@D!!4J`+!!!!J!!!!!! 'k52ZdTd*KJ!!!!!!!!!!!!!!!!!!!"B!!!!!!!!!!2rrrrpbFh*M8P0&4!%!Y0l Zjl@I*fJ!!!R0!!!!!!!!"88!!!!!G63!!!!!!!!!!0H8#eLdNFH9qjfA8IjfVYc V+,IcSPG[%r1Mef"PGRNH2bHC[@GR+aYdP+r9fR9b,hXDfQaLU$)NfG$H6Ma3l!J rb@q#cPhiF`e!5[$!i!F%P!CrjdRIiQ1U8#HUXAqC0ZNE+"#Gi-UPXm`GcPR6d1+ %j@UFd,+C*c(%&qq,LAI(q@TjQmA%0I,iR)F[aK-IRb@fBHY@VQVKj@[iNHP`l[3 r8D8HchTk%V!p1-QjjcVRES%ZEfC'F$,CbRNT829k%*Nh)ZZjkNHPN6Xb0E*fCNE %"EqJB#rq4EhN$`f-A&)XrIQFJU,$rTe68(6*#1FZS5%%1XqmqPYTB@9aET+h5Bi bPCcIjpGGAFkd#f@Z5RE'80"GFffLmqlRVPl4EB0*UP`qXXLr!m[jJH2TNIjAr2f IrFkCEHB6KGq6aiSXMc-8@6-H+E)pHUM)r[#")XH$G%A1p2X+rr[h&!(hlLTHZ(Y (NH[1E8AJl9Z+&frG915qH814jdDD)QrDGF9,ekmTAVjf9C([kK9&rLZA&DpF[U3 SF1QLiY@,&a4"&miVAMYr6[(kZE1+0mkH843mFeVajZP6LVG1R9381RP#i6TaA2( fm@1+`XH1+SSF2D*ijmKKaEZ($bQ#$ae8[(I`J+,SJIf+prI[8hb`EkqLf0ipLZ* lGLXqh,e,%E)V94'DZP04BZF1a8FlYLXqhVj0mFQfVBU5@lFS2Yfb@I(CjNf+ccG Y9(baFB2Lb`hV&DA@Ve0mY@kYS[6D0BSbDeBVbUjHTIKke8T&f-S9L[!9baAPPLp 6P&qf9&&Kk4*&a5@,&Hl&La59&Le84#aFS+LmB,kLb[ajLQrQc998R6Y(8@h1E%A Nl&Q+U&Nc&Gr16&&mPc*$8Ah'G%@0kG-80DG09G5D1N94HdUbi[[NbBSkNbFTITJ d89&hiJ6&Ma2'+hiD2dlamlLaLRTMabMUMaQYL"ip5Y&Je%K&`j%M&$%MKLXD$4q Qm!`EUQJmG)LLbC!!`BUQJ`FTQJdDU2KPi!$&V`2k+f,lpe2meUq[`YZhMb+Z6fp &mpkp&,rhkUR`pHbKL1r4AC(3[CZL4EHZLTCGZbJ5Zh4@r0'jNk*9Tik+eKdl+2l Xd&l4TRdla9rYfLVqETZNq#I*)ZNI3pZr$Hhq-V4[BqM`Tk&MDd1R9SE1IaLk*"U kYM4dDf(SRQ$S%@rSk62dqYh3ZlQK6jbKVpI3lcG$reM$J&m0!hma$'TQ'0c8-+5 *B@KM`c#2BAJM`iJB`mL'KP%0$+1M$@2U'mE@-iclf6$q*m1%(`d6kaSQr@#BA-H 3!2bpB8TY`p4DKQNe$G0V''C80k4mCjMjV@&@P'&fT'&10F2FUSCjhaMQ9c%XU'a B''&B9-Q`f'eB8Y'`Y)*K@AR$mR+'&H''P@''99mE9TFeV#PM@&[DX1iV`rT5KJe I'MCqBGMdZ@(cCiBYRaUfPM4Xqm5`r@2$MSm-1dXB8N-0Zd)-Zcmdl#PZf&[-X%p IX-ihl2lh$3H+'JkqCcJ8E$MmVZ()1iDM43c(#KZ1[fdii6+F,'3ipCEKp*Z'-`8 0Cpm`R([GF2ie`i8J`m9A$CF+'#krBVL5hh!eRq(DbiEV,aR5mKTZj$(Fc'fipD, KGU$K6Ll$h4F-p`)-prd0k6N0$h)B(QBh2-TQb-KUH*c&m-62k-[r[hh!IlZ6J*4 "Cl2AG8i+iL9VZFJ+9Cfc`Xqf#L(2YJbPBQ*E*$M[ET+HEdHHRVQHVdQ+2EYI(ZH e4%$+`06F8BPHMmrPmm6(YA"@,IRF2SqRCU[Q(PGiZ+YjJeK23S,Rrjhb!!!"!!! !!3!!!!!!!!!!(MX0)#!J)#!J)#"'9&p(E(P`D&p0CA4bD@0c+L"YCA4b$A*PFfp eFQ0PFbjcDA4jFe0jFe0jFe0jFfjcC#PdFh-#)&0*9%46593K!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!YD"h%3!!"e3!!!%HGA4XD@jPAe4bB@jcCQpbE5JJ*QGXHA" S,6jbEfpd,QpeG'aTEQ8X$5!J)#!J)#!J)#!J)#!J)#!J)#!J)#!J)#!J)#!J)#C QB@0P,6jdHA"P-5jQEfjdAfeKG(*TH#!T1`d0)#!J)#!J)#"'9&p2GA4XD@jPAdG PG&p$3Qpi+#!QC`!!!3!!!!%!!!!!!!!!!"i!!!!!!!!!!!!F!"lrrf$Z: ft2demos-2.10.1/mac/ftoldmac.c0000644000175000001440000006214313434207203015660 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 1996-2019 by */ /* suzuki toshiya, D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* */ /* ftoldmac - test program for MacOS specific API in ftmac.c */ /* */ /* */ /****************************************************************************/ #if defined(__GNUC__) && defined(__APPLE_CC__) # include # include # include # include #else # include # include # include #endif #include #include FT_FREETYPE_H #include FT_SFNT_NAMES_H #include FT_TRUETYPE_IDS_H /* the following header shouldn't be used in normal programs */ #include FT_INTERNAL_DEBUG_H /* showing driver name */ #include FT_MODULE_H #include FT_INTERNAL_OBJECTS_H #include FT_INTERNAL_DRIVER_H /* FSSpec functions are deprecated since Mac OS X 10.4 */ #ifndef HAVE_FSSPEC #if defined( __LP64__ ) && !TARGET_CPU_68K && !TARGET_CPU_PPC && !TARGET_CPU_PPC64 #define HAVE_FSSPEC 0 typedef void FSSpec; #else #define HAVE_FSSPEC 1 #endif #endif /* most FSRef functions were introduced since Mac OS 9 */ #ifndef HAVE_FSREF #if TARGET_API_MAC_OSX #define HAVE_FSREF 1 #else #define HAVE_FSREF 0 typedef void FSRef; #endif #endif /* QuickDraw is deprecated since Mac OS X 10.4 */ #ifndef HAVE_QUICKDRAW_CARBON #if defined( __LP64__ ) && !TARGET_CPU_68K && !TARGET_CPU_PPC && !TARGET_CPU_PPC64 #define HAVE_QUICKDRAW_CARBON 0 #define HAVE_QUICKDRAW_TOOLBOX 0 #elif TARGET_API_MAC_CARBON || TARGET_API_MAC_OSX #define HAVE_QUICKDRAW_CARBON 1 #define HAVE_QUICKDRAW_TOOLBOX 1 #elif TARGET_API_MAC_OS8 #define HAVE_QUICKDRAW_CARBON 0 #define HAVE_QUICKDRAW_TOOLBOX 1 #endif #endif /* AppleTypeService is available since Mac OS X */ #ifndef HAVE_ATS #if TARGET_API_MAC_OSX #define HAVE_ATS 1 #else #define HAVE_ATS 0 #endif #endif #include FT_MAC_H #undef FT_GetFile_From_Mac_Name #undef FT_GetFile_From_Mac_ATS_Name #undef FT_New_Face_From_FSSpec #include #include #include typedef enum { FT_OldMac_Err_Unimplemented, FT_OldMac_Err_TooLongFileName, FT_OldMac_Err_FileNotFound, FT_OldMac_Err_UnresolvableFontName, FT_OldMac_Err_PseudoFontName, FT_OldMac_Err_UnswappableFontID, FT_OldMac_Err_TooLargeFaceIndex, FT_OldMac_Err_Ok = 0 } FT_OldMac_Err; /* statics of font scanning */ int num_scanned_fonts; int num_opened_fonts; int num_scanned_faces; int num_opened_faces; /* setting for face scanning */ int max_face_number; Boolean force_scan_face; char* font_listing_api; char* font_resolve_api; Boolean auto_suffix; void initParamBlock( CInfoPBRec*, Str255 ); void dumpPBErr( CInfoPBRec* ); void crawlDir( CInfoPBRec*, char* ); void crawlFontFile( char* ); OSErr ftmac_FSPathMakeSpec( const UInt8*, FSSpec*, Boolean ); OSErr ftmac_FSpMakePath( const FSSpec*, UInt8*, UInt32 ); OSErr ftmac_FSpMakePath( const FSSpec* spec_p, UInt8* path, UInt32 maxPathSize ) { OSErr err; FSSpec spec = *spec_p; short vRefNum; long dirID; Str255 parDir_name; FT_MEM_SET( path, 0, maxPathSize ); while ( 1 ) { int child_namelen = ft_strlen( (char *)path ); unsigned char node_namelen = spec.name[0]; unsigned char* node_name = spec.name + 1; if ( node_namelen + child_namelen > maxPathSize ) return errFSNameTooLong; FT_MEM_MOVE( path + node_namelen + 1, path, child_namelen ); FT_MEM_COPY( path, node_name, node_namelen ); if ( child_namelen > 0 ) path[ node_namelen ] = ':'; vRefNum = spec.vRefNum; dirID = spec.parID; parDir_name[0] = '\0'; err = FSMakeFSSpec( vRefNum, dirID, parDir_name, &spec ); if ( noErr != err || dirID == spec.parID ) break; } return noErr; } void dump_face_info( FT_Face face ) { printf( "\t\tface_index=%d, face_flags=0x%08x, num_glyphs=%d\n", (int)face->face_index, (unsigned int)(face->face_flags), (int)face->num_glyphs ); printf( "\t\tnum_fixed_sizes=%d, style_flags=%d%d%d%d%d%d\n", face->num_fixed_sizes, ( (unsigned int)(face->style_flags) >> 5 ) & 1, ( (unsigned int)(face->style_flags) >> 4 ) & 1, ( (unsigned int)(face->style_flags) >> 3 ) & 1, ( (unsigned int)(face->style_flags) >> 2 ) & 1, ( (unsigned int)(face->style_flags) >> 1 ) & 1, ( (unsigned int)(face->style_flags) ) & 1 ); printf("\t\tfamily_name=[%s], style_name=[%s]\n", face->family_name, face->style_name ); } void crawlFontFile( char* font_file_path ) { FT_Library library; FT_Face face; int i, j; FSSpec spec; printf( "*** check font file [%s]\n", font_file_path ); if ( 0 != FT_Init_FreeType( &library ) ) { printf( "\tError: Could not initialize FreeType\n" ); return; } if ( noErr != ftmac_FSPathMakeSpec( (unsigned char const *)font_file_path, &spec, FALSE ) ) { printf( "\tError: Could not open File (MacOS API)\n" ); return; } face = NULL; num_scanned_fonts ++; if ( 0 != FT_New_Face_From_FSSpec( library, &spec, 0, &face ) ) { printf( "\tError: Could not open File (FreeType API)\n" ); return; } num_opened_fonts ++; printf( "\tFont file has %d face\n", (int)face->num_faces ); j = face->num_faces + max_face_number; for ( i = 0; i < j; i++ ) { num_scanned_faces ++; printf( "\tCheck Face #%d...", i ); if ( 0 == FT_New_Face_From_FSSpec( library, &spec, i, &face ) ) { num_opened_faces ++; printf( "Ok\n" ); dump_face_info( face ); FT_Done_Face( face ); } else { printf( "Failed\n" ); if ( !force_scan_face ) goto no_more_face; } } no_more_face: FT_Done_FreeType( library ); } void crawlDir( CInfoPBRec* ci_pb_dir, char* dir_path ) { CInfoPBRec ci_pb; char file_full_path[1024]; int dirname_len; int i; printf( "ioVRefNum = 0x%04x, ioDrDirID = 0x%08x, ioDrParID= 0x%08x\n", ci_pb_dir->dirInfo.ioVRefNum, (unsigned int) ci_pb_dir->dirInfo.ioDrParID, (unsigned int) ci_pb_dir->dirInfo.ioDrDirID ); printf( "files in directory: %d\n", ci_pb_dir->dirInfo.ioDrNmFls ); dirname_len = strlen( dir_path ); strcpy( file_full_path, dir_path ); if ( 0 < dirname_len && ':' != file_full_path[ dirname_len - 1 ] ) dirname_len ++; file_full_path[ dirname_len - 1 ] = ':'; for ( i = 0; i <= ci_pb_dir->dirInfo.ioDrNmFls; i ++ ) { Str255 fileName; memset( &ci_pb, 0, sizeof( CInfoPBRec ) ); fileName[0] = 0; ci_pb.hFileInfo.ioVRefNum = ci_pb_dir->dirInfo.ioVRefNum; ci_pb.hFileInfo.ioDirID = ci_pb_dir->dirInfo.ioDrDirID; ci_pb.hFileInfo.ioNamePtr = fileName; ci_pb.hFileInfo.ioFDirIndex = i; if ( noErr == PBGetCatInfoSync( &ci_pb ) ) { if ( NULL != ci_pb.hFileInfo.ioNamePtr ) { char file_name[256]; strncpy( file_name, (char *)ci_pb.hFileInfo.ioNamePtr + 1, ci_pb.hFileInfo.ioNamePtr[0] ); file_name[ ci_pb.hFileInfo.ioNamePtr[0] ] = '\0'; if ( 0 == strcmp( ".DS_Store", file_name ) ) printf( "*** known non-font filename [%s]\n", file_name ); else if ( 0 == ( ci_pb.hFileInfo.ioFlAttrib & ioDirMask ) ) { file_full_path[ dirname_len ] = '\0'; strncat( file_full_path, file_name, sizeof( file_full_path ) ); crawlFontFile( file_full_path ); } } } } } void initParamBlock( CInfoPBRec* paramBlock, Str255 fileName ) { paramBlock->hFileInfo.ioCompletion = 0; /* synch calls */ paramBlock->hFileInfo.ioNamePtr = fileName; paramBlock->hFileInfo.ioVRefNum = 0; /* alias for default */ paramBlock->hFileInfo.ioFDirIndex = 0; /* XXX */ paramBlock->hFileInfo.ioDirID = 0; /* alias for default */ } void dumpPBErr( CInfoPBRec* paramBlock ) { printf( "[PB access returned after " ); switch ( paramBlock->hFileInfo.ioResult ) { case ioErr: printf( "I/O Error" ); break; case fnOpnErr: printf( "File not Open Error" ); break; case nsvErr: printf( "No such volume Error" ); break; case fnfErr: printf( "File not found Error" ); break; case rfNumErr: printf( "Bad reference number Error" ); break; default: printf( "unexpected err=%d", paramBlock->hFileInfo.ioResult ); break; } printf( "]\n" ); } OSErr ftmac_FSPathMakeSpec( const UInt8* pathname, FSSpec* spec_p, Boolean isDirectory ) { const char *p, *q; short vRefNum; long dirID; Str255 nodeName; OSErr err; FT_UNUSED( isDirectory ); p = q = (const char *)pathname; dirID = 0; vRefNum = 0; while ( 1 ) { q = p + FT_MIN( 255, ft_strlen( (char const *)p ) ); if ( q == p ) return 0; if ( 255 < ft_strlen( (char const *)pathname ) ) { while ( p < q && *q != ':' ) q--; } if ( p < q ) nodeName[0] = q - p; else if ( ft_strlen( (char const *)p ) < 256 ) nodeName[0] = ft_strlen( p ); else return errFSNameTooLong; strncpy( (char *)nodeName + 1, (char *)p, nodeName[0] ); nodeName[ nodeName[0] + 1 ] = '\0'; err = FSMakeFSSpec( vRefNum, dirID, nodeName, spec_p ); if ( err || '\0' == *q ) return err; vRefNum = spec_p->vRefNum; dirID = spec_p->parID; p = q + 1; } } void test_font_files( int argc, char** argv ) { int i; for ( i = 1; i < argc; i++ ) { OSErr status; CInfoPBRec paramBlock; Str255 fileName; /* XXX: should be skipped by better argument handler */ if ( '-' == argv[i][0] && '-' == argv[i][1] ) continue; /* XXX: restrict pathname to legacy HFS limit for simplicity */ if ( 254 < strlen( argv[i] ) ) continue; fileName[0] = strlen( argv[i] ); memcpy( fileName + 1, argv[i], fileName[0] ); initParamBlock( ¶mBlock, fileName ); status = PBGetCatInfoSync( ¶mBlock ); if ( 0 > status ) printf( "[PB access failed] error = %d\n", status ); { FSSpec spec; Str255 volName; int i; strncpy( (char *)volName, (char *)fileName, fileName[0] ); printf( "given file name [%s]", fileName + 1 ); for ( i = 1; i < fileName[0] && ':' != fileName[i + 1]; i ++ ) ; volName[i + 1] = ':'; volName[i + 2] = '\0'; volName[0] = i + 1; printf( "-> volume name [%s]", volName + 1 ); status = FSMakeFSSpec( 0, 0, volName, &spec); if ( noErr != status ) printf( "FSMakeFSSpec(%s) error %d\n", volName, status ); else { printf( "FSMakeFSSpec(%s) return volID = 0x%08x\n", volName + 1, spec.vRefNum ); paramBlock.hFileInfo.ioVRefNum = spec.vRefNum; } } if ( 0 != paramBlock.hFileInfo.ioResult ) dumpPBErr( ¶mBlock ); else if ( 0 != ( paramBlock.hFileInfo.ioFlAttrib & ioDirMask ) ) crawlDir( ¶mBlock, argv[i] ); else crawlFontFile( argv[i] ); } } void print_help_and_exit() { printf("\n" ); printf(" ftoldmac [pathname in HFS syntax]\n" ); printf("\n" ); printf(" e.g. \"Macintosh HD:System Folder:Fonts:\"\n" ); printf(" quotation is required to avoid shell expansion\n" ); printf(" scan directory and open all font files in there\n" ); printf("\n" ); printf(" --max-face-number=N\n" ); printf(" scan face until N instead of face->num_faces\n" ); printf("\n" ); printf(" --force-scan-face\n" ); printf(" ignore the error to open face and continue to max face number\n" ); printf("\n" ); printf(" ftoldmac --font-listing-api=XXX --font-resolve-api=YYY\n" ); printf("\n" ); printf(" --font-listing-api={quickdraw_old|quickdraw|ats}\n" ); printf(" specify API to list system font\n" ); printf("\n" ); printf(" --font-resolve-api={quickdraw|ats}\n" ); printf(" specify API to find fontfile by fontname\n" ); printf("\n" ); printf(" --auto-suffix\n" ); printf(" old QuickDraw API cannot list available style suffixes,\n" ); printf(" this option adds Bold and Italic suffixes automatically.\n" ); printf("\n" ); printf(" available API:" ); #if HAVE_QUICKDRAW_TOOLBOX printf(" quickdraw_old" ); #endif #if HAVE_QUICKDRAW_CARBON printf(" quickdraw" ); #endif #if HAVE_ATS printf(" ats" ); #endif printf("\n" ); printf("\n" ); exit( 0 ); } void verifyFMOutput( FMOutput* fmout ) { OSErr err; Handle font_handle; short rsrcID; ResType rsrcType; Str255 rsrcName; #ifdef VERBOSE printf( "FMOutput.boldPixels 0x%02x\n", fmout->boldPixels ); printf( "FMOutput.italicPixels 0x%02x\n", fmout->italicPixels ); printf( "FMOutput.ulOffset 0x%02x\n", fmout->ulOffset ); printf( "FMOutput.ulShadow 0x%02x\n", fmout->ulShadow ); printf( "FMOutput.ulThick 0x%02x\n", fmout->ulThick ); printf( "FMOutput.shadowPixels 0x%02x\n", fmout->shadowPixels ); printf( "FMOutput.extra 0x%02x\n", fmout->extra ); printf( "FMOutput.curStyle 0x%02x\n", fmout->curStyle ); #else printf( "FMOutput.widMax:%d\n", fmout->widMax ); #endif font_handle = fmout->fontHandle, GetResInfo( font_handle, &rsrcID, &rsrcType, rsrcName ); err = ResError(); if ( 0 != err ) printf( "could not get resource info for handle 0x%08x, err=%d\n", (int)(fmout->fontHandle), err ); else printf( "resource: ID=0x%04x, Type=%c%c%c%c, name=%s\n", rsrcID, (int)MAX( (rsrcType >> 24) & 0xFF, 0x20 ), (int)MAX( (rsrcType >> 16) & 0xFF, 0x20 ), (int)MAX( (rsrcType >> 8) & 0xFF, 0x20 ), (int)MAX( (rsrcType >> 0) & 0xFF, 0x20 ), rsrcName[0] > 0 ? rsrcName + 1 : '\0' ); } FT_OldMac_Err resolveToolBoxQuickDrawFontName( const char* font_name ) { #if !HAVE_QUICKDRAW_TOOLBOX printf( "cannot check [%s] by Toolbox QuickDraw\n", font_name ); return FT_OldMac_Err_Unimplemented; #else Str255 familyName; SInt16 familyID; FMInput lookup_inst; FMOutput* lookup_rslt; ft_strncpy( (char*)familyName + 1, (char*)font_name, 254 ); familyName[0] = strlen( (char *)familyName + 1 ); GetFNum( familyName, &familyID ); if ( 0 > familyID ) { printf( "familyName %s is unresolvable\n", familyName + 1 ); return FT_OldMac_Err_UnresolvableFontName; } else if ( 0 == familyID ) return FT_OldMac_Err_PseudoFontName; printf( "familyName %s:%d -> familyID 0x%04x: -> ", familyName + 1, familyName[0], familyID ); bzero( &lookup_inst, sizeof( FMInput ) ); lookup_inst.family = familyID; lookup_inst.size = 14; lookup_inst.face = 0; lookup_inst.needBits = FALSE; lookup_inst.device = 0; lookup_inst.numer.v = 1; lookup_inst.numer.h = 1; lookup_inst.denom.v = 1; lookup_inst.denom.h = 1; lookup_rslt = FMSwapFont( &lookup_inst ); if ( NULL == lookup_rslt ) { printf( "FMSwapFont returns NULL (unresolved)\n" ); return FT_OldMac_Err_UnswappableFontID; } else verifyFMOutput( lookup_rslt ); return FT_OldMac_Err_Ok; #endif } void test_face_quickdraw( char* face_name, FT_Library library ) { #if !HAVE_QUICKDRAW_CARBON printf( "cannot check [%s] by Carbon QuickDraw\n", face_name ); #else FSSpec spec; UInt8 font_file_path[1024]; FT_Long face_index; FT_Face face; printf( "Lookup [%s]...", face_name ); if ( 0 != FT_GetFile_From_Mac_Name( face_name, &spec, &face_index ) ) { printf( "FreeType could not find font file\n" ); return; } ftmac_FSpMakePath( &spec, font_file_path, 1024 ); printf( "Font file found [%s], face #%d...", font_file_path, (int)face_index ); if ( 0 != FT_New_Face_From_FSSpec( library, &spec, face_index, &face ) ) { printf( "FreeType could not load font file\n" ); return; } printf( "Ok\n" ); num_opened_faces ++; dump_face_info( face ); FT_Done_Face( face ); #endif } void test_face_ats( char* face_name, FT_Library library ) { #if !HAVE_ATS FT_UNUSED( library ); printf( "cannot check [%s] by ATS\n", face_name ); #else UInt8 font_file_path[1024]; FT_Long face_index; FT_Face face; FSSpec spec; printf( "Lookup [%s]...", face_name ); if ( 0 != FT_GetFile_From_Mac_ATS_Name( face_name, &spec, &face_index ) ) { printf( "FreeType could not find font file\n" ); return; } ftmac_FSpMakePath( &spec, font_file_path, 1024 ); printf( "Font file found [%s], face #%d...", font_file_path, (int)face_index ); if ( 0 != FT_New_Face_From_FSSpec( library, &spec, face_index, &face ) ) { printf( "FreeType could not load font file\n" ); return; } printf( "Ok\n" ); num_opened_faces ++; dump_face_info( face ); FT_Done_Face( face ); #endif } void test_face( char* face_name, FT_Library library ) { num_scanned_faces ++; if ( 0 == ft_strcmp( font_resolve_api, "quickdraw" ) ) test_face_quickdraw( face_name, library ); else if ( 0 == ft_strcmp( font_resolve_api, "ats" ) ) test_face_ats( face_name, library ); else { printf( "invalid api name to resolve [%s]\n", font_resolve_api ); exit( -1 ); } } void test_font_list_quickdraw_old( FT_Library library ) { #if !HAVE_QUICKDRAW_TOOLBOX FT_UNUSED( library ); printf( "FreeType2 is configured without quickdraw_old (Toolbox QuickDraw)\n" ); #else Str255 fmo_family_name; char fmo_face_name[1024]; int i; for ( i = 0; i < 0x7FFF; i++ ) { GetFontName( i, fmo_family_name ); if ( 0 < fmo_family_name[0] ) { fmo_family_name[ fmo_family_name[0] + 1 ] = '\0'; ft_strncpy( (char *)fmo_face_name, (char *)fmo_family_name + 1, 1024 ); test_face( fmo_face_name, library ); if ( !auto_suffix ) continue; ft_strncpy( (char *)fmo_face_name, (char *)fmo_family_name + 1, 1024 ); strncat( (char *)fmo_face_name, " Bold", 1024 ); printf( "+ " ); test_face( fmo_face_name, library ); ft_strncpy( (char *)fmo_face_name, (char *)fmo_family_name + 1, 1024 ); strncat( (char *)fmo_face_name, " Italic", 1024 ); printf( "+ " ); test_face( fmo_face_name, library ); ft_strncpy( (char *)fmo_face_name, (char *)fmo_family_name + 1, 1024 ); strncat( (char *)fmo_face_name, " Bold Italic", 1024 ); printf( "+ " ); test_face( fmo_face_name, library ); } } #endif } char* make_style_suffix( char* fm_style_name, FMFontStyle fm_style ) { fm_style_name[0] = ' '; fm_style_name[1] = '\0'; if ( fm_style & bold ) strcat( fm_style_name, "Bold " ); if ( fm_style & italic ) strcat( fm_style_name, "Italic " ); if ( fm_style & underline ) strcat( fm_style_name, "Underline " ); if ( fm_style & outline ) strcat( fm_style_name, "Outline " ); if ( fm_style & shadow ) strcat( fm_style_name, "Shadow " ); if ( fm_style & condense ) strcat( fm_style_name, "Condense " ); if ( fm_style & extend ) strcat( fm_style_name, "Extend " ); if ( ft_strlen( fm_style_name ) > 0 ) fm_style_name[ strlen( fm_style_name) - 1 ] = '\0'; return fm_style_name; } void test_font_list_quickdraw( FT_Library library ) { #if !HAVE_QUICKDRAW_CARBON FT_UNUSED( library ); printf( "FreeType2 is configured without quickdraw (Carbon QuickDraw)\n" ); #else FMFontFamilyIterator fm_family_iter; FMFontFamily fm_family; Str255 fm_family_namestr; char fm_family_name[1024]; FMFontFamilyInstanceIterator fm_font_iter; FMFont fm_font; FMFontStyle fm_style; FMFontSize fm_size; char fm_style_name[1024]; if ( 0 != FMCreateFontFamilyIterator( NULL, NULL, kFMUseGlobalScopeOption, &fm_family_iter ) ) return; get_quickdraw_font_family: if ( 0 == FMGetNextFontFamily( &fm_family_iter, &fm_family ) ) { if ( 0 == FMCreateFontFamilyInstanceIterator( fm_family, &fm_font_iter ) ) { get_quickdraw_font_instance: if ( 0 == FMGetNextFontFamilyInstance( &fm_font_iter, &fm_font, &fm_style, &fm_size ) ) { if ( 0 == fm_size ) { FMGetFontFamilyName( fm_family, fm_family_namestr ); CopyPascalStringToC( fm_family_namestr, fm_family_name ); strcat( fm_family_name, make_style_suffix( fm_style_name, fm_style ) ); test_face( fm_family_name, library ); } goto get_quickdraw_font_instance; } else { FMDisposeFontFamilyInstanceIterator( &fm_font_iter ); goto get_quickdraw_font_family; } } else goto get_quickdraw_font_family; } FMDisposeFontFamilyIterator( &fm_family_iter ); return; #endif } void test_font_list_ats( FT_Library library ) { #if !HAVE_ATS FT_UNUSED( library ); printf( "FreeType2 is configured without ats (AppleTypeService)\n" ); #else ATSFontIterator ats_font_iter; ATSFontRef ats_font_ref; CFStringRef ats_font_name; char face_name[1024]; #ifndef kATSOptionFlagsUnRestrictedScope #define kATSOptionFlagsUnRestrictedScope kATSOptionFlagsDefault #endif if ( noErr != ATSFontIteratorCreate( kATSFontContextGlobal, NULL, NULL, kATSOptionFlagsUnRestrictedScope, &ats_font_iter ) ) return; while ( noErr == ATSFontIteratorNext( ats_font_iter, &ats_font_ref ) ) { if ( 0 != ATSFontGetName( ats_font_ref, kATSOptionFlagsUnRestrictedScope, &ats_font_name ) ) continue; if ( NULL == ats_font_name ) continue; if ( CFStringGetCString( ats_font_name, face_name, 1024, kCFStringEncodingNonLossyASCII ) ) test_face( (char *)face_name, library ); } return; #endif } void test_system_font_list() { FT_Library library; printf( "fontlist is generated by [%s]\n", font_listing_api ); printf( "fontname is resolved by [%s]\n", font_resolve_api ); if ( 0 != FT_Init_FreeType( &library ) ) return; if ( 0 == ft_strcmp( font_listing_api, "quickdraw_old" ) ) test_font_list_quickdraw_old( library ); else if ( 0 == ft_strcmp( font_listing_api, "quickdraw" ) ) test_font_list_quickdraw( library ); else if ( 0 == ft_strcmp( font_listing_api, "ats" ) ) test_font_list_ats( library ); else { printf( "invalid api name to list [%s]\n", font_listing_api ); exit( -1 ); } FT_Done_FreeType( library ); } int main( int argc, char** argv ) { int i; num_scanned_fonts = 0; num_opened_fonts = 0; num_scanned_faces = 0; num_opened_faces = 0; font_listing_api = NULL; font_resolve_api = NULL; auto_suffix = FALSE; max_face_number = 0; force_scan_face = FALSE; if ( 1 == argc ) print_help_and_exit(); else { for ( i = 1; i < argc; i++ ) { if ( 0 == ft_strcmp( "--help", argv[i] ) ) print_help_and_exit(); else if ( 0 == ft_strncmp( "--font-listing-api=", argv[i], 19 ) ) font_listing_api = argv[i] + 19; else if ( 0 == ft_strncmp( "--font-resolve-api=", argv[i], 19 ) ) font_resolve_api = argv[i] + 19; else if ( 0 == ft_strcmp( "--auto-suffix", argv[i] ) ) auto_suffix = TRUE; else if ( 0 == ft_strncmp( "--max-face-number=", argv[i], 18 ) ) max_face_number = atoi( argv[i] + 18 ); else if ( 0 == ft_strcmp( "--force-scan-face", argv[i] ) ) force_scan_face = TRUE; } } if ( NULL == font_listing_api && NULL == font_resolve_api ) test_font_files( argc, argv ); else if ( NULL != font_listing_api && NULL != font_resolve_api ) test_system_font_list( argc, argv ); else if ( NULL == font_listing_api ) printf( "require --font-listing-api to specify how to list system font\n" ); else if ( NULL == font_resolve_api ) printf( "require --font-resolve-api to specify how to find file by fontname\n" ); printf( "\n" ); printf( "---------------------------------\n" ); printf( "Summary\n" ); printf( "Font File opened/scanned = %d/%d\n", num_opened_fonts, num_scanned_fonts ); printf( "Font Face opened/scanned = %d/%d\n", num_opened_faces, num_scanned_faces ); exit( 0 ); } ft2demos-2.10.1/mac/ftview_m.c0000644000175000001440000000224113434207203015700 0ustar00wlusers00000000000000/* minimal Mac wrapper for the ftview.c program */ int original_main( int argc, char** argv ); /* We rename the original main() program to original_main, so we can provide a wrapper around it */ #define main original_main #include "ftview.c" #undef main #define PPEM "24" /* hard-code the ppem size */ #include #include "getargv.h" #ifndef USING_CARBON #include #include #include #include #else #include #endif static void init_toolbox() { #ifndef USING_CARBON InitGraf(&qd.thePort); InitFonts(); InitWindows(); TEInit(); InitDialogs((long)0); InitMenus(); InitCursor(); #endif SIOUXSettings.asktosaveonclose = 0; } int main() { int argc, i; char** argv; init_toolbox(); /* put paths of all files dropped onto the app into argv */ argc = FTMac_GetArgv(&argv); if (argc < 2) { printf("Please drop one or more font files onto the app (but quit first!)\n"); exit(1); } /* move argv[1:] to argv[2:] and fill in the ppem arg */ for (i = argc; i > 1; i--) { argv[i] = argv[i-1]; } argc++; argv[1] = PPEM; /* call the original main() program */ original_main(argc, argv); } ft2demos-2.10.1/mac/ftlint_m.c0000644000175000001440000000211613434207203015675 0ustar00wlusers00000000000000/* minimal Mac wrapper for the ftlint.c program */ int original_main( int argc, char** argv ); /* We rename the original main() program to original_main, so we can provide a wrapper around it */ #define main original_main #include "ftlint.c" #undef main #define PPEM "24" /* hard-code the ppem size */ #include #include "getargv.h" #include #include #include #include static void init_toolbox() { InitGraf(&qd.thePort); InitFonts(); InitWindows(); TEInit(); InitDialogs((long)0); InitMenus(); InitCursor(); SIOUXSettings.asktosaveonclose = 0; } int main() { int argc, i; char** argv; init_toolbox(); /* put paths of all files dropped onto the app into argv */ argc = FTMac_GetArgv(&argv); if (argc < 2) { printf("Please drop one or more font files onto the app (but quit first!)\n"); exit(1); } /* move argv[1:] to argv[2:] and fill in the ppem arg */ for (i = argc; i > 1; i--) { argv[i] = argv[i-1]; } argc++; argv[1] = PPEM; /* call the original main() program */ original_main(argc, argv); } ft2demos-2.10.1/graph/0000755000175000001440000000000013506426605014267 5ustar00wlusers00000000000000ft2demos-2.10.1/graph/os2/0000755000175000001440000000000013506426605014772 5ustar00wlusers00000000000000ft2demos-2.10.1/graph/os2/Jamfile0000644000175000001440000000042513434207203016254 0ustar00wlusers00000000000000# FreeType2 demos graph/os2 Jamfile (c) 2001 David Turner # SubDir FT2DEMO_TOP graph os2 ; SubDirHdrs $(GRAPH_INCLUDE) ; GROS2_PATH = [ FT2_SubDir graph os2 ]; GRAPH_LINKLIBS = $(GROS2_PATH)gros2pm.def ; Library $(GRAPH_LIB) : grxos2.c ; # end of graph/os2 Jamfile ft2demos-2.10.1/graph/os2/gros2pm.h0000644000175000001440000000056713434207203016533 0ustar00wlusers00000000000000#ifndef GROS2PM_H_ #define GROS2PM_H_ #include "grobjs.h" extern grDevice gr_os2pm_device; #ifdef GR_INIT_BUILD static grDeviceChain gr_os2pm_device_chain = { "os2pm", &gr_os2pm_device, GR_INIT_DEVICE_CHAIN }; #undef GR_INIT_DEVICE_CHAIN #define GR_INIT_DEVICE_CHAIN &gr_os2pm_device_chain #endif /* GR_INIT_BUILD */ #endif /* GROS2PM_H_ */ ft2demos-2.10.1/graph/os2/gros2pm.def0000644000175000001440000000013513434207203017031 0ustar00wlusers00000000000000NAME WINDOWCOMPAT DESCRIPTION 'FreeType Graphics' HEAPSIZE 8192 STACKSIZE 40888 ft2demos-2.10.1/graph/os2/gros2pm.c0000644000175000001440000005437213434207203016531 0ustar00wlusers00000000000000#include "grobjs.h" #include "grdevice.h" #define INCL_DOS #define INCL_WIN #define INCL_GPI #define INCL_SUB #include #include #include #include #include #define DEBUGxxx #ifdef DEBUG #define LOG(x) LogMessage##x #else #define LOG(x) /* rien */ #endif #ifdef DEBUG static void LogMessage( const char* fmt, ... ) { va_list ap; va_start( ap, fmt ); vfprintf( stderr, fmt, ap ); va_end( ap ); } #endif typedef struct Translator { ULONG os2key; grKey grkey; } Translator; static Translator key_translators[] = { { VK_BACKSPACE, grKeyBackSpace }, { VK_TAB, grKeyTab }, { VK_ENTER, grKeyReturn }, { VK_ESC, grKeyEsc }, { VK_HOME, grKeyHome }, { VK_LEFT, grKeyLeft }, { VK_UP, grKeyUp }, { VK_RIGHT, grKeyRight }, { VK_DOWN, grKeyDown }, { VK_PAGEUP, grKeyPageUp }, { VK_PAGEDOWN, grKeyPageDown }, { VK_END, grKeyEnd }, { VK_F1, grKeyF1 }, { VK_F2, grKeyF2 }, { VK_F3, grKeyF3 }, { VK_F4, grKeyF4 }, { VK_F5, grKeyF5 }, { VK_F6, grKeyF6 }, { VK_F7, grKeyF7 }, { VK_F8, grKeyF8 }, { VK_F9, grKeyF9 }, { VK_F10, grKeyF10 }, { VK_F11, grKeyF11 }, { VK_F12, grKeyF12 } }; #define MAX_PIXEL_MODES 32 static HAB gr_anchor; /* device anchor block */ typedef POINTL PMBlitPoints[4]; typedef struct grPMSurface_ { grSurface root; grBitmap image; HAB anchor; /* handle to anchor block for surface's window */ HWND frame_window; /* handle to window's frame */ HWND client_window; /* handle to window's client */ HWND title_window; /* handle to window's title bar */ HPS image_ps; /* memory presentation space used to hold */ /* the surface's content under PM */ HDC image_dc; /* memory device context for the image */ HEV event_lock; /* semaphore used in listen_surface */ HMTX image_lock; /* a mutex used to synchronise access */ /* to the memory presentation space */ /* used to hold the surface */ TID message_thread; /* thread used to process this surface's */ /* messages.. */ PBITMAPINFO2 bitmap_header;/* os/2 bitmap descriptor */ HBITMAP os2_bitmap; /* Handle to OS/2 bitmap contained in image */ BOOL ready; /* ??? */ long shades[256]; /* indices of gray levels in pixel_mode_gray */ POINTL surface_blit[4]; /* surface blitting table */ POINTL magnify_blit[4]; /* magnifier blitting table */ int magnification; /* level of magnification */ POINTL magnify_center; SIZEL magnify_size; grEvent event; PMBlitPoints blit_points; } grPMSurface; /* we use a static variable to pass a pointer to the PM Surface */ /* to the client window. This is a bit ugly, but it makes things */ /* a lot more simple.. */ static grPMSurface* the_surface; static void enable_os2_iostreams( void ) { PTIB thread_block; PPIB process_block; /* XXX : This is a very nasty hack, it fools OS/2 and let the program */ /* call PM functions, even though stdin/stdout/stderr are still */ /* directed to the standard i/o streams.. */ /* The program must be compiled with WINDOWCOMPAT */ /* */ /* Credits go to Michal for finding this !! */ /* */ DosGetInfoBlocks( &thread_block, &process_block ); process_block->pib_ultype = 3; } static int init_device( void ) { enable_os2_iostreams(); /* create an anchor block. This will allow this thread (i.e. the */ /* main one) to call Gpi functions.. */ gr_anchor = WinInitialize(0); if (!gr_anchor) { /* could not initialise Presentation Manager */ return -1; } return 0; } static void done_device( void ) { /* Indicates that we do not use the Presentation Manager, this */ /* will also release all associated resources.. */ WinTerminate( gr_anchor ); } /* close a given window */ static void done_surface( grPMSurface* surface ) { LOG(( "Os2PM: done_surface(%08lx)\n", (long)surface )); if ( surface->frame_window ) WinDestroyWindow( surface->frame_window ); WinReleasePS( surface->image_ps ); grDoneBitmap( &surface->image ); grDoneBitmap( &surface->root.bitmap ); } #define LOCK(x) DosRequestMutexSem( x, SEM_INDEFINITE_WAIT ) #define UNLOCK(x) DosReleaseMutexSem( x ) static const int pixel_mode_bit_count[] = { 0, 1, /* mono */ 4, /* pal4 */ 8, /* pal8 */ 8, /* grays */ 15, /* rgb15 */ 16, /* rgb16 */ 24, /* rgb24 */ 32 /* rgb32 */ }; /************************************************************************ * * Technical note : how the OS/2 Presentation Manager driver works * * PM is, in my opinion, a bloated and over-engineered graphics * sub-system, even though it has lots of nice features. Here are * a few tidbits about it : * * * - under PM, a "bitmap" is a device-specific object whose bits are * not directly accessible to the client application. This means * that we must use a scheme like the following to display our * surfaces : * * - hold, for each surface, its own bitmap buffer where the * rest of the graph library writes directly. * * - create a PM bitmap object with the same dimensions (and * possibly format). * * - copy the content of each updated rectangle into the * PM bitmap with the function 'GpiSetBitmapBits'. * * - finally, "blit" the PM bitmap to the screen calling * 'GpiBlitBlt' * * - but there is more : you cannot directly blit a PM bitmap to the * screen with PM. The 'GpiBlitBlt' only works with presentation * spaces. This means that we also need to create, for each surface : * * - a memory presentation space, used to hold the PM bitmap * - a "memory device context" for the presentation space * * The blit is then performed from the memory presentation space * to the screen's presentation space.. * * * - because each surface creates its own event-handling thread, * we must protect the surface's presentation space from concurrent * accesses (i.e. calls to 'GpiSetBitmapBits' when drawing to the * surface, and calls to 'GpiBlitBlt' when drawing it on the screen * are performed in two different threads). * * we use a simple mutex to do this. * * * - we also use a semaphore to perform a rendez-vous between the * main and event-handling threads (needed in "listen_event"). * ************************************************************************/ static void RunPMWindow( grPMSurface* surface ); static void refresh_rectangle( grPMSurface* surface, int x, int y, int w, int h ) { LOG(( "Os2PM: refresh_rectangle( %08lx, %d, %d, %d, %d )\n", (long)surface, x, y, w, h )); (void)x; (void)y; (void)w; (void)h; /* convert_rectangle( surface, x, y, w, h ); */ LOCK( surface->image_lock ); GpiSetBitmapBits( surface->image_ps, 0, surface->root.bitmap.rows, surface->root.bitmap.buffer, surface->bitmap_header ); UNLOCK( surface->image_lock ); WinInvalidateRect( surface->client_window, NULL, FALSE ); WinUpdateWindow( surface->frame_window ); } static void set_title( grPMSurface* surface, const char* title ) { ULONG rc; #if 1 LOG(( "Os2PM: set_title( %08lx == %08lx, %s )\n", (long)surface, surface->client_window, title )); #endif LOG(( " -- frame = %08lx\n", (long)surface->frame_window )); LOG(( " -- client parent = %08lx\n", (long)WinQueryWindow( surface->client_window, QW_PARENT ) )); rc = WinSetWindowText( surface->client_window, (PSZ)title ); LOG(( " -- returned rc = %ld\n",rc )); } static void listen_event( grPMSurface* surface, int event_mask, grEvent* grevent ) { ULONG ulRequestCount; (void) event_mask; /* ignored for now */ /* the listen_event function blocks until there is an event to process */ DosWaitEventSem( surface->event_lock, SEM_INDEFINITE_WAIT ); DosQueryEventSem( surface->event_lock, &ulRequestCount ); *grevent = surface->event; DosResetEventSem( surface->event_lock, &ulRequestCount ); return; } static grPMSurface* init_surface( grPMSurface* surface, grBitmap* bitmap ) { PBITMAPINFO2 bit; SIZEL sizl = { 0, 0 }; LONG palette[256]; LOG(( "Os2PM: init_surface( %08lx, %08lx )\n", (long)surface, (long)bitmap )); LOG(( " -- input bitmap =\n" )); LOG(( " -- mode = %d\n", bitmap->mode )); LOG(( " -- grays = %d\n", bitmap->grays )); LOG(( " -- width = %d\n", bitmap->width )); LOG(( " -- height = %d\n", bitmap->rows )); /* create the bitmap - under OS/2, we support all modes as PM */ /* handles all conversions automatically.. */ if ( grNewBitmap( bitmap->mode, bitmap->grays, bitmap->width, bitmap->rows, bitmap ) ) return 0; LOG(( " -- output bitmap =\n" )); LOG(( " -- mode = %d\n", bitmap->mode )); LOG(( " -- grays = %d\n", bitmap->grays )); LOG(( " -- width = %d\n", bitmap->width )); LOG(( " -- height = %d\n", bitmap->rows )); bitmap->pitch = -bitmap->pitch; surface->root.bitmap = *bitmap; /* create the image and event lock */ DosCreateEventSem( NULL, &surface->event_lock, 0, TRUE ); DosCreateMutexSem( NULL, &surface->image_lock, 0, FALSE ); /* create the image's presentation space */ surface->image_dc = DevOpenDC( gr_anchor, OD_MEMORY, (PSZ)"*", 0L, 0L, 0L ); surface->image_ps = GpiCreatePS( gr_anchor, surface->image_dc, &sizl, PU_PELS | GPIT_MICRO | GPIA_ASSOC | GPIF_DEFAULT ); GpiSetBackMix( surface->image_ps, BM_OVERPAINT ); /* create the image's PM bitmap */ bit = (PBITMAPINFO2)grAlloc( sizeof(BITMAPINFO2) + 256*sizeof(RGB2) ); surface->bitmap_header = bit; bit->cbFix = sizeof( BITMAPINFOHEADER2 ); bit->cx = surface->root.bitmap.width; bit->cy = surface->root.bitmap.rows; bit->cPlanes = 1; bit->argbColor[0].bBlue = 255; bit->argbColor[0].bGreen = 0; bit->argbColor[0].bRed = 0; bit->argbColor[1].bBlue = 0; bit->argbColor[1].bGreen = 255; bit->argbColor[1].bRed = 0; bit->cBitCount = (bitmap->mode == gr_pixel_mode_gray ? 8 : 1 ); if (bitmap->mode == gr_pixel_mode_gray) { RGB2* color = bit->argbColor; int x, count; count = bitmap->grays; for ( x = 0; x < count; x++, color++ ) { color->bBlue = color->bGreen = color->bRed = (((count-x)*255)/count); } } else { RGB2* color = bit->argbColor; color[0].bBlue = color[0].bGreen = color[0].bRed = 0; color[1].bBlue = color[1].bGreen = color[1].bRed = 255; } surface->os2_bitmap = GpiCreateBitmap( surface->image_ps, (PBITMAPINFOHEADER2)bit, 0L, NULL, NULL ); GpiSetBitmap( surface->image_ps, surface->os2_bitmap ); bit->cbFix = sizeof( BITMAPINFOHEADER2 ); GpiQueryBitmapInfoHeader( surface->os2_bitmap, (PBITMAPINFOHEADER2)bit ); surface->bitmap_header = bit; /* for gr_pixel_mode_gray, create a gray-levels logical palette */ if ( bitmap->mode == gr_pixel_mode_gray ) { int x, count; count = bitmap->grays; for ( x = 0; x < count; x++ ) palette[x] = (((count-x)*255)/count) * 0x010101; /* create logical color table */ GpiCreateLogColorTable( surface->image_ps, (ULONG) LCOL_PURECOLOR, (LONG) LCOLF_CONSECRGB, (LONG) 0L, (LONG) count, (PLONG) palette ); /* now, copy the color indexes to surface->shades */ for ( x = 0; x < count; x++ ) surface->shades[x] = GpiQueryColorIndex( surface->image_ps, 0, palette[x] ); } /* set up the blit points array */ surface->blit_points[1].x = surface->root.bitmap.width; surface->blit_points[1].y = surface->root.bitmap.rows; surface->blit_points[3] = surface->blit_points[1]; /* Finally, create the event handling thread for the surface's window */ DosCreateThread( &surface->message_thread, (PFNTHREAD) RunPMWindow, (ULONG) surface, 0UL, 32920 ); /* wait for the window creation */ LOCK(surface->image_lock); UNLOCK(surface->image_lock); surface->root.done = (grDoneSurfaceFunc) done_surface; surface->root.refresh_rect = (grRefreshRectFunc) refresh_rectangle; surface->root.set_title = (grSetTitleFunc) set_title; surface->root.listen_event = (grListenEventFunc) listen_event; /* convert_rectangle( surface, 0, 0, bitmap->width, bitmap->rows ); */ return surface; } MRESULT EXPENTRY Message_Process( HWND handle, ULONG mess, MPARAM parm1, MPARAM parm2 ); static void RunPMWindow( grPMSurface* surface ) { unsigned char class_name[] = "DisplayClass"; ULONG class_flags; static HMQ queue; QMSG message; /* store the current surface pointer in "the_surface". It is a static */ /* variable that is only used to retrieve the pointer in the client */ /* window procedure the first time it is called.. */ the_surface = surface; /* try to prevent the program from going on without the setup of thread 2 */ LOCK( surface->image_lock ); LOG(( "Os2PM: RunPMWindow( %08lx )\n", (long)surface )); /* create an anchor to allow this thread to use PM */ surface->anchor = WinInitialize(0); if (!surface->anchor) { printf( "Error doing WinInitialize()\n" ); return; } /* create a message queue */ queue = WinCreateMsgQueue( surface->anchor, 0 ); if (!queue) { printf( "Error doing WinCreateMsgQueue()\n" ); return; } /* register the window class */ if ( !WinRegisterClass( surface->anchor, (PSZ) class_name, (PFNWP) Message_Process, CS_SIZEREDRAW, 0 ) ) { printf( "Error doing WinRegisterClass()\n" ); return; } /* create the PM window */ class_flags = FCF_TITLEBAR | FCF_MINBUTTON | FCF_DLGBORDER | FCF_TASKLIST | FCF_SYSMENU; LOG(( "Os2PM: RunPMWindow: Creating window\n" )); surface->frame_window = WinCreateStdWindow( HWND_DESKTOP, WS_VISIBLE, &class_flags, (PSZ) class_name, (PSZ) "FreeType Viewer - press F1 for help", WS_VISIBLE, 0, 0, &surface->client_window ); if (!surface->frame_window) { printf( "Error doing WinCreateStdWindow()\n" ); return; } /* find the title window handle */ surface->title_window = WinWindowFromID( surface->frame_window, FID_TITLEBAR ); LOG (( "Os2PM: RunPMWIndow: Creation succeeded\n" )); LOG (( " -- frame = %08lx\n", surface->frame_window )); LOG (( " -- client = %08lx\n", surface->client_window )); /* set Window size and position */ WinSetWindowPos( surface->frame_window, 0L, (SHORT) 60, (SHORT) WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ) - (surface->root.bitmap.rows + 100), (SHORT) WinQuerySysValue( HWND_DESKTOP, SV_CYDLGFRAME )*2 + surface->root.bitmap.width, (SHORT) WinQuerySysValue( HWND_DESKTOP, SV_CYTITLEBAR ) + WinQuerySysValue( HWND_DESKTOP, SV_CYDLGFRAME )*2 + surface->root.bitmap.rows, SWP_SIZE | SWP_MOVE ); #if 0 /* save the handle to the current surface within the window words */ WinSetWindowPtr( surface->client_window,QWL_USER, surface ); #endif /* Announcing window_created */ UNLOCK(surface->image_lock); /* run the message queue till the end */ while ( WinGetMsg( surface->anchor, &message, (HWND)NULL, 0, 0 ) ) { WinDispatchMsg( surface->anchor, &message ); } /* clean-up */ WinDestroyWindow( surface->frame_window ); surface->frame_window = 0; WinDestroyMsgQueue( queue ); WinTerminate( surface->anchor ); /* await death... */ while ( 1 ) DosSleep( 100 ); } /* Message processing for our PM Window class */ MRESULT EXPENTRY Message_Process( HWND handle, ULONG mess, MPARAM parm1, MPARAM parm2 ) { static HDC screen_dc; static HPS screen_ps; static BOOL minimized; SIZEL sizl; SWP swp; grPMSurface* surface; /* get the handle to the window's surface -- note that this */ /* value will be null when the window is created */ surface = (grPMSurface*)WinQueryWindowPtr( handle, QWL_USER ); if (!surface) { surface = the_surface; WinSetWindowPtr( handle, QWL_USER, surface ); } switch( mess ) { case WM_DESTROY: /* warn the main thread to quit if it didn't know */ surface->event.type = gr_event_key; surface->event.key = grKeyEsc; DosPostEventSem( surface->event_lock ); break; case WM_CREATE: /* set original magnification */ minimized = FALSE; /* create Device Context and Presentation Space for screen. */ screen_dc = WinOpenWindowDC( handle ); screen_ps = GpiCreatePS( surface->anchor, screen_dc, &sizl, PU_PELS | GPIT_MICRO | GPIA_ASSOC | GPIF_DEFAULT ); /* take the input focus */ WinFocusChange( HWND_DESKTOP, handle, 0L ); LOG(( "screen_dc and screen_ps have been created\n" )); /* To permit F9, F10 and others to pass through to the application */ if (TRUE != WinSetAccelTable (surface->anchor, 0, surface->frame_window)) { printf( "Error - failed to clear accel table\n"); } break; case WM_MINMAXFRAME: /* to update minimized if changed */ swp = *((PSWP) parm1); if ( swp.fl & SWP_MINIMIZE ) minimized = TRUE; if ( swp.fl & SWP_RESTORE ) minimized = FALSE; return WinDefWindowProc( handle, mess, parm1, parm2 ); break; case WM_ERASEBACKGROUND: case WM_PAINT: /* copy the memory image of the screen out to the real screen */ LOCK( surface->image_lock ); WinBeginPaint( handle, screen_ps, NULL ); /* main image and magnified picture */ GpiBitBlt( screen_ps, surface->image_ps, 4L, surface->blit_points, ROP_SRCCOPY, BBO_AND ); WinEndPaint( screen_ps ); UNLOCK( surface->image_lock ); break; case WM_HELP: /* this really is a F1 Keypress !! */ surface->event.key = grKeyF1; goto Do_Key_Event; case WM_CHAR: if ( CHARMSG( &mess )->fs & KC_KEYUP ) break; /* look for a specific vkey */ { int count = sizeof( key_translators )/sizeof( key_translators[0] ); Translator* trans = key_translators; Translator* limit = trans + count; for ( ; trans < limit; trans++ ) if ( CHARMSG(&mess)->vkey == trans->os2key ) { surface->event.key = trans->grkey; goto Do_Key_Event; } } /* otherwise, simply record the character code */ if ( (CHARMSG( &mess )->fs & KC_CHAR) == 0 ) break; surface->event.key = CHARMSG(&mess)->chr; Do_Key_Event: surface->event.type = gr_event_key; DosPostEventSem( surface->event_lock ); break; default: return WinDefWindowProc( handle, mess, parm1, parm2 ); } return (MRESULT) FALSE; } grDevice gr_os2pm_device = { sizeof( grPMSurface ), "os2pm", init_device, done_device, (grDeviceInitSurfaceFunc) init_surface, 0, 0 }; ft2demos-2.10.1/graph/os2/rules.mk0000644000175000001440000000161713502347420016453 0ustar00wlusers00000000000000#************************************************************************** #* #* OS/2 specific rules file, used to compile the OS/2 graphics driver #* to the graphics subsystem #* #************************************************************************** ifeq ($(PLATFORM),os2) GR_OS2 := $(GRAPH)/os2 # the GRAPH_LINK is expanded each time an executable is linked with the # graphics library. # GRAPH_LINK += $(subst /,$(COMPILER_SEP),$(GR_OS2)/gros2pm.def) # add the OS/2 driver object file to the graphics library `graph.a' # GRAPH_OBJS += $(OBJ_DIR_2)/gros2pm.$O DEVICES += OS2_PM # the rule used to compile the graphics driver # $(OBJ_DIR_2)/gros2pm.$O: $(GR_OS2)/gros2pm.c $(GR_OS2)/gros2pm.h $(GRAPH_H) $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) \ $I$(subst /,$(COMPILER_SEP),$(GR_OS2)) \ $T$(subst /,$(COMPILER_SEP),$@ $<) endif # EOF ft2demos-2.10.1/graph/mac/0000755000175000001440000000000013506426605015027 5ustar00wlusers00000000000000ft2demos-2.10.1/graph/mac/grmac.c0000644000175000001440000002613413434207203016261 0ustar00wlusers00000000000000/******************************************************************* * * grmac.c graphics driver for MacOS platform. * * This is the driver for displaying inside a window under MacOS, * used by the graphics utility of the FreeType test suite. * * Largely written by Just van Rossum, but derived from grwin32.c. * Copyright (C) 1999-2019 by * Just van Rossum, Antoine Leca, * David Turner, Robert Wilhelm, and Werner Lemberg. * * Borrowing liberally from the other FreeType drivers. * * This file is part of the FreeType project, and may only be used * modified and distributed under the terms of the FreeType project * license, LICENSE.TXT. By continuing to use, modify or distribute * this file you indicate that you have read the license and * understand and accept it fully. * ******************************************************************/ /* ANSI C */ #include /* Mac Toolbox */ #include /* FT graphics subsystem */ #include "grobjs.h" #include "grdevice.h" #ifdef __MWERKS__ /* CodeWarrior's poor excuse for a console */ #include #endif /* Mac function key definitions. The 0x100 is a kludge, see listen_event(). */ #define KEY_F1 (0x7A | 0x100) #define KEY_F2 (0x78 | 0x100) #define KEY_F3 (0x63 | 0x100) #define KEY_F4 (0x76 | 0x100) #define KEY_F5 (0x60 | 0x100) #define KEY_F6 (0x61 | 0x100) #define KEY_F7 (0x62 | 0x100) #define KEY_F8 (0x64 | 0x100) #define KEY_F9 (0x65 | 0x100) #define KEY_F10 (0x6D | 0x100) #define KEY_F11 (0x67 | 0x100) #define KEY_F12 (0x6F | 0x100) #define KEY_F13 (0x69 | 0x100) #define KEY_F14 (0x6B | 0x100) #define KEY_F15 (0x71 | 0x100) /* Mac to FT key mapping */ typedef struct Translator_ { short mackey; grKey grkey; } Translator; static Translator key_translators[] = { { kBackspaceCharCode, grKeyBackSpace }, { kTabCharCode, grKeyTab }, { kReturnCharCode, grKeyReturn }, { kEscapeCharCode, grKeyEsc }, { kHomeCharCode, grKeyHome }, { kLeftArrowCharCode, grKeyLeft }, { kUpArrowCharCode, grKeyUp }, { kRightArrowCharCode, grKeyRight }, { kDownArrowCharCode, grKeyDown }, { kPageUpCharCode, grKeyPageUp }, { kPageDownCharCode, grKeyPageDown }, { kEndCharCode, grKeyEnd }, { kHelpCharCode, grKeyF1 }, /* map Help key to F1... */ { KEY_F1, grKeyF1 }, { KEY_F2, grKeyF2 }, { KEY_F3, grKeyF3 }, { KEY_F4, grKeyF4 }, { KEY_F5, grKeyF5 }, { KEY_F6, grKeyF6 }, { KEY_F7, grKeyF7 }, { KEY_F8, grKeyF8 }, { KEY_F9, grKeyF9 }, { KEY_F10, grKeyF10 }, { KEY_F11, grKeyF11 }, { KEY_F12, grKeyF12 } }; /* This is a minimalist driver, it is only able to display */ /* a _single_ window. Moreover, only monochrome and gray */ /* bitmaps are supported.. */ /* pointer to the window. */ static WindowPtr theWindow = NULL; /* the pixmap */ static PixMap thePixMap; /* destroys the window */ static void done_window( ) { if ( theWindow ) { DisposeWindow ( theWindow ); } theWindow = NULL; } /* destroys the surface*/ static void done_surface( grSurface* surface ) { /* ick! this never gets called... */ done_window(); grDoneBitmap( &surface->bitmap ); } static void refresh_rectangle( grSurface* surface, int x, int y, int w, int h ) { Rect bounds; SetRect( &bounds, x, y, x+w, y+h ); if ( theWindow ) { GrafPtr windowPort = GetWindowPort(theWindow); RgnHandle visRgn = GetPortVisibleRegion(windowPort, NewRgn()); SetPort(windowPort); CopyBits( (BitMap*)&thePixMap, GetPortBitMapForCopyBits(windowPort), &bounds, &bounds, srcCopy, visRgn); DisposeRgn(visRgn); } } static void set_title( grSurface* surface, const char* title ) { Str255 pTitle; strcpy( (char*)pTitle+1, title ); pTitle[0] = strlen( title ); if ( theWindow ) SetWTitle( theWindow, pTitle ); } static void listen_event( grSurface* surface, int event_mask, grEvent* grevent ) { grEvent our_grevent; EventRecord mac_event; our_grevent.type = gr_event_none; our_grevent.key = grKeyNone; for ( ;; ) /* The event loop. Sorry, but I'm too lazy to split the various events to proper event handler functions. This whole app is rather ad hoc anyway, so who cares ;-) */ { if ( WaitNextEvent( everyEvent, &mac_event, 10, NULL ) ) { switch ( mac_event.what ) { case autoKey: case keyDown: { int count = sizeof( key_translators ) / sizeof( key_translators[0] ); Translator* trans = key_translators; Translator* limit = trans + count; short char_code; char_code = mac_event.message & charCodeMask; if ( char_code == kFunctionKeyCharCode ) /* Le kluge. Add a flag to differentiate the F-keys from normal keys. */ char_code = 0x100 | ((mac_event.message & keyCodeMask) >> 8); our_grevent.key = char_code; for ( ; trans < limit; trans++ ) /* see if the key maps to a special "gr" key */ if ( char_code == trans->mackey ) { our_grevent.key = trans->grkey; } our_grevent.type = gr_event_key; } if ( our_grevent.key == grKEY('q') || our_grevent.key == grKeyEsc ) /* destroy the window here, since done_surface() doesn't get called */ done_window(); *grevent = our_grevent; return; case updateEvt: if ( theWindow && (WindowPtr)mac_event.message == theWindow ) { SetPortWindowPort( theWindow ); BeginUpdate( theWindow ); refresh_rectangle( surface, 0, 0, thePixMap.bounds.right, thePixMap.bounds.bottom ); EndUpdate( theWindow ); } #ifdef __MWERKS__ else { SIOUXHandleOneEvent( &mac_event ); } #endif break; case mouseDown: { short part; WindowPtr wid; part = FindWindow( mac_event.where, &wid ); if ( wid == theWindow ) { if ( theWindow && part == inDrag) { #if TARGET_API_MAC_CARBON #define screenBounds NULL #else Rect *screenBounds = &qd.screenBits.bounds; #endif DragWindow( wid, mac_event.where, screenBounds); } else if (part == inGoAway) { if ( TrackGoAway( theWindow, mac_event.where ) ) { /* The user clicked the window away, emulate quit event */ done_window(); our_grevent.type = gr_event_key; our_grevent.key = grKeyEsc; *grevent = our_grevent; return; } } else if (part == inContent) { SelectWindow( theWindow ); } } #ifdef __MWERKS__ else { SIOUXHandleOneEvent( &mac_event ); } #endif } break; default: InitCursor(); break; } } } } static grSurface* init_surface( grSurface* surface, grBitmap* bitmap ) { PixMapPtr pixMap = &thePixMap; Rect bounds; SetRect(&bounds, 0, 0, bitmap->width, bitmap->rows); switch (bitmap->mode) { case gr_pixel_mode_rgb24: bitmap->mode = gr_pixel_mode_rgb32; break; default: bitmap->mode = gr_pixel_mode_mono; bitmap->grays = 0; break; } /* create the bitmap - under MacOS, we support all modes as the GDI */ /* handles all conversions automatically.. */ if ( grNewBitmap( bitmap->mode, bitmap->grays, bitmap->width, bitmap->rows, bitmap ) ) return 0; surface->bitmap = *bitmap; /* initialize the PixMap to appropriate values */ pixMap->baseAddr = (char*)bitmap->buffer; pixMap->rowBytes = bitmap->pitch; if (pixMap->rowBytes < 0) pixMap->rowBytes = -pixMap->rowBytes; pixMap->rowBytes |= 0x8000; /* flag indicating it's a PixMap, not a BitMap */ pixMap->bounds = bounds; pixMap->pmVersion = baseAddr32; /* pixmap base address is 32-bit address */ pixMap->packType = 0; pixMap->packSize = 0; pixMap->hRes = 72 << 16; pixMap->vRes = 72 << 16; pixMap->pmTable = 0; #if OLDPIXMAPSTRUCT pixMap->planeBytes = 0; pixMap->pmReserved = 0; #else pixMap->pixelFormat = 0; pixMap->pmExt = 0; #endif switch ( bitmap->mode ) { case gr_pixel_mode_mono: case gr_pixel_mode_gray: pixMap->pixelType = 0; /* indexed color */ pixMap->cmpCount = 1; if (bitmap->mode == gr_pixel_mode_mono) { pixMap->pixelSize = 1; } else { pixMap->pixelSize = 8; pixMap->pmTable = GetCTable(256); /* color palette matching FT's idea */ break; /* of grayscale. See ftview.rsrc */ } pixMap->cmpSize = pixMap->pixelSize; break; case gr_pixel_mode_rgb32: pixMap->pixelSize = 32; pixMap->pixelType = RGBDirect; pixMap->cmpCount = 3; pixMap->cmpSize = 8; pixMap->baseAddr -= 1; /*SHH: goofy hack to reinterpret bitmap's RGBx -> xRGB */ break; default: return 0; /* Unknown mode */ } /* create the window */ OffsetRect(&bounds, 10, 44); /* place it at a decent location */ theWindow = NewCWindow(NULL, &bounds, "\p???", 1, 0, (WindowRef)-1, 1, 0); /* fill in surface interface */ surface->done = (grDoneSurfaceFunc) done_surface; surface->refresh_rect = (grRefreshRectFunc) refresh_rectangle; surface->set_title = (grSetTitleFunc) set_title; surface->listen_event = (grListenEventFunc) listen_event; return surface; } static int init_device( void ) { return 0; } static void done_device( void ) { /* won't get called either :-( */ } grDevice gr_mac_device = { sizeof( grSurface ), "mac", init_device, done_device, (grDeviceInitSurfaceFunc) init_surface, 0, 0 }; /* End */ ft2demos-2.10.1/graph/mac/grmac.h0000644000175000001440000000054713434207203016266 0ustar00wlusers00000000000000#ifndef GRMAC_H_ #define GRMAC_H_ #include "grobjs.h" extern grDevice gr_mac_device; #ifdef GR_INIT_BUILD static grDeviceChain gr_mac_device_chain = { "mac", &gr_mac_device, GR_INIT_DEVICE_CHAIN }; #undef GR_INIT_DEVICE_CHAIN #define GR_INIT_DEVICE_CHAIN &gr_mac_device_chain #endif /* GR_INIT_BUILD */ #endif /* GRMAC_H_ */ ft2demos-2.10.1/graph/win32/0000755000175000001440000000000013506426605015231 5ustar00wlusers00000000000000ft2demos-2.10.1/graph/win32/Jamfile0000644000175000001440000000047613434207203016521 0ustar00wlusers00000000000000# FreeType2 demos graph/win32 Jamfile (c) 2001 David Turner # SubDir FT2DEMO_TOP graph win32 ; SubDirHdrs $(GRAPH_INCLUDE) ; if $(JAM_TOOLSET) = MINGW { GRAPH_LINKLIBS = "-luser32 -lgdi32" ; } else { GRAPH_LINKLIBS = user32.lib gdi32.lib ; } Library $(GRAPH_LIB) : grwin32.c ; # end of graph/win32 Jamfile ft2demos-2.10.1/graph/win32/grwin32.c0000644000175000001440000004323613434207203016667 0ustar00wlusers00000000000000/******************************************************************* * * grwin32.c graphics driver for Win32 platform * * This is the driver for displaying inside a window under Win32, * used by the graphics utility of the FreeType test suite. * * Written by Antoine Leca. * Copyright (C) 1999-2019 by * Antoine Leca, David Turner, Robert Wilhelm, and Werner Lemberg. * * Borrowing liberally from the other FreeType drivers. * * This file is part of the FreeType project, and may only be used * modified and distributed under the terms of the FreeType project * license, LICENSE.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 #include #include /* define to activate OLPC swizzle */ #define xxSWIZZLE #define WIN32_LEAN_AND_MEAN #include #include #include #ifdef SWIZZLE #include #endif /* logging facility */ #include #define DEBUGxxx #ifdef DEBUG #define LOG(x) LogMessage##x #else #define LOG(x) /* rien */ #endif #ifdef DEBUG static void LogMessage( const char* fmt, ... ) { va_list ap; va_start( ap, fmt ); vfprintf( stderr, fmt, ap ); va_end( ap ); } #endif /*-------------------*/ /* Size of the window. */ #define WIN_WIDTH 640u #define WIN_HEIGHT 450u /* These values can be changed, but WIN_WIDTH should remain for now a */ /* multiple of 32 to avoid padding issues. */ typedef struct Translator_ { ULONG winkey; grKey grkey; } Translator; static Translator key_translators[] = { { VK_BACK, grKeyBackSpace }, { VK_TAB, grKeyTab }, { VK_RETURN, grKeyReturn }, { VK_ESCAPE, grKeyEsc }, { VK_HOME, grKeyHome }, { VK_LEFT, grKeyLeft }, { VK_UP, grKeyUp }, { VK_RIGHT, grKeyRight }, { VK_DOWN, grKeyDown }, { VK_PRIOR, grKeyPageUp }, { VK_NEXT, grKeyPageDown }, { VK_END, grKeyEnd }, { VK_F1, grKeyF1 }, { VK_F2, grKeyF2 }, { VK_F3, grKeyF3 }, { VK_F4, grKeyF4 }, { VK_F5, grKeyF5 }, { VK_F6, grKeyF6 }, { VK_F7, grKeyF7 }, { VK_F8, grKeyF8 }, { VK_F9, grKeyF9 }, { VK_F10, grKeyF10 }, { VK_F11, grKeyF11 }, { VK_F12, grKeyF12 } }; static Translator syskey_translators[] = { { VK_F10, grKeyF10 } }; static ATOM ourAtom; typedef struct grWin32SurfaceRec_ { grSurface root; HWND window; int window_width; int window_height; int title_set; const char* the_title; LPBITMAPINFO pbmi; char bmi[ sizeof(BITMAPINFO) + 256*sizeof(RGBQUAD) ]; HBITMAP hbm; grEvent ourevent; int eventToProcess; grBitmap bgrBitmap; /* windows wants data in BGR format !! */ #ifdef SWIZZLE grBitmap swizzle_bitmap; #endif } grWin32Surface; /* destroys the surface*/ static void gr_win32_surface_done( grWin32Surface* surface ) { /* The graphical window has perhaps already destroyed itself */ if ( surface->window ) { DestroyWindow ( surface->window ); PostMessage( surface->window, WM_QUIT, 0, 0 ); } #ifdef SWIZZLE grDoneBitmap( &surface->swizzle_bitmap ); #endif grDoneBitmap( &surface->bgrBitmap ); grDoneBitmap( &surface->root.bitmap ); } static void gr_win32_surface_refresh_rectangle( grWin32Surface* surface, int x, int y, int w, int h ) { HDC hDC; int row_bytes, delta; LPBITMAPINFO pbmi = surface->pbmi; HANDLE window = surface->window; grBitmap* bitmap = &surface->root.bitmap; LOG(( "gr_win32_surface_refresh_rectangle: ( %p, %d, %d, %d, %d )\n", (long)surface, x, y, w, h )); /* clip update rectangle */ if ( x < 0 ) { w += x; x = 0; } delta = x + w - surface->window_width; if ( delta > 0 ) w -= delta; if ( y < 0 ) { h += y; y = 0; } delta = y + h - surface->window_height; if ( delta > 0 ) h -= delta; if ( w <= 0 || h <= 0 ) return; /* now, perform the blit */ row_bytes = surface->root.bitmap.pitch; if ( row_bytes < 0 ) row_bytes = -row_bytes; if ( row_bytes * 8 != pbmi->bmiHeader.biWidth * pbmi->bmiHeader.biBitCount ) pbmi->bmiHeader.biWidth = row_bytes * 8 / pbmi->bmiHeader.biBitCount; #ifdef SWIZZLE { grBitmap* swizzle = &surface->swizzle_bitmap; gr_swizzle_rect_rgb24( bitmap->buffer, bitmap->pitch, swizzle->buffer, swizzle->pitch, bitmap->width, bitmap->rows, 0, 0, bitmap->width, bitmap->rows ); bitmap = swizzle; } #endif /* copy to BGR buffer */ { unsigned char* read_line = (unsigned char*)bitmap->buffer; int read_pitch = bitmap->pitch; unsigned char* write_line = (unsigned char*)surface->bgrBitmap.buffer; int write_pitch = surface->bgrBitmap.pitch; int height = bitmap->rows; int width = bitmap->width; if ( read_pitch < 0 ) read_line -= ( height - 1 ) * read_pitch; if ( write_pitch < 0 ) write_line -= ( height - 1 ) * write_pitch; if ( bitmap->mode == gr_pixel_mode_gray ) { for ( ; height > 0; height-- ) { unsigned char* read = read_line; unsigned char* read_limit = read + width; unsigned char* write = write_line; for ( ; read < read_limit; read++, write++ ) *write = *read; read_line += read_pitch; write_line += write_pitch; } } else { for ( ; height > 0; height-- ) { unsigned char* read = read_line; unsigned char* read_limit = read + 3 * width; unsigned char* write = write_line; for ( ; read < read_limit; read += 3, write += 3 ) { write[0] = read[2]; write[1] = read[1]; write[2] = read[0]; } read_line += read_pitch; write_line += write_pitch; } } } hDC = GetDC ( window ); SetDIBits ( hDC, surface->hbm, 0, bitmap->rows, surface->bgrBitmap.buffer, pbmi, DIB_RGB_COLORS ); ReleaseDC ( window, hDC ); ShowWindow( window, SW_SHOW ); InvalidateRect ( window, NULL, FALSE ); UpdateWindow ( window ); } static void gr_win32_surface_set_title( grWin32Surface* surface, const char* title ) { /* the title will be set on the next listen_event, just */ /* record it there.. */ surface->title_set = 0; surface->the_title = title; } static void gr_win32_surface_listen_event( grWin32Surface* surface, int event_mask, grEvent* grevent ) { MSG msg; HANDLE window = surface->window; event_mask=event_mask; /* unused parameter */ if ( window && !surface->title_set ) { SetWindowText( window, surface->the_title ); surface->title_set = 1; } surface->eventToProcess = 0; while (GetMessage( &msg, 0, 0, 0 )) { TranslateMessage( &msg ); DispatchMessage( &msg ); if (surface->eventToProcess) break; } *grevent = surface->ourevent; } /* * set graphics mode * and create the window class and the message handling. */ static grWin32Surface* gr_win32_surface_init( grWin32Surface* surface, grBitmap* bitmap ) { static RGBQUAD black = { 0, 0, 0, 0 }; static RGBQUAD white = { 0xFF, 0xFF, 0xFF, 0 }; LPBITMAPINFO pbmi; /* find some memory for the bitmap header */ surface->pbmi = pbmi = (LPBITMAPINFO) surface->bmi; LOG(( "Win32: init_surface( %p, %p )\n", surface, bitmap )); LOG(( " -- input bitmap =\n" )); LOG(( " -- mode = %d\n", bitmap->mode )); LOG(( " -- grays = %d\n", bitmap->grays )); LOG(( " -- width = %d\n", bitmap->width )); LOG(( " -- height = %d\n", bitmap->rows )); /* create the bitmap - under Win32, we support all modes as the GDI */ /* handles all conversions automatically.. */ if ( grNewBitmap( bitmap->mode, bitmap->grays, bitmap->width, bitmap->rows, bitmap ) ) return 0; /* allocate the BGR shadow bitmap */ if ( grNewBitmap( bitmap->mode, bitmap->grays, bitmap->width, bitmap->rows, &surface->bgrBitmap ) ) return 0; surface->bgrBitmap.pitch = -surface->bgrBitmap.pitch; #ifdef SWIZZLE if ( bitmap->mode == gr_pixel_mode_rgb24 ) { if ( grNewBitmap( bitmap->mode, bitmap->grays, bitmap->width, bitmap->rows, &surface->swizzle_bitmap ) ) return 0; surface->swizzle_bitmap.pitch = -surface->swizzle_bitmap.pitch; } #endif LOG(( " -- output bitmap =\n" )); LOG(( " -- mode = %d\n", bitmap->mode )); LOG(( " -- grays = %d\n", bitmap->grays )); LOG(( " -- width = %d\n", bitmap->width )); LOG(( " -- height = %d\n", bitmap->rows )); bitmap->pitch = -bitmap->pitch; surface->root.bitmap = *bitmap; /* initialize the header to appropriate values */ memset( pbmi, 0, sizeof ( BITMAPINFO ) + sizeof ( RGBQUAD ) * 256 ); pbmi->bmiHeader.biSize = sizeof ( BITMAPINFOHEADER ); pbmi->bmiHeader.biWidth = bitmap->width; pbmi->bmiHeader.biHeight = bitmap->rows; pbmi->bmiHeader.biPlanes = 1; switch ( bitmap->mode ) { case gr_pixel_mode_mono: pbmi->bmiHeader.biBitCount = 1; pbmi->bmiColors[0] = white; pbmi->bmiColors[1] = black; break; case gr_pixel_mode_rgb24: pbmi->bmiHeader.biBitCount = 24; pbmi->bmiHeader.biCompression = BI_RGB; break; case gr_pixel_mode_gray: pbmi->bmiHeader.biBitCount = 8; pbmi->bmiHeader.biClrUsed = bitmap->grays; { int count = bitmap->grays; int x; RGBQUAD* color = pbmi->bmiColors; for ( x = 0; x < count; x++, color++ ) { color->rgbRed = color->rgbGreen = color->rgbBlue = (unsigned char)(((count-x)*255)/count); color->rgbReserved = 0; } } break; default: return 0; /* Unknown mode */ } surface->window_width = bitmap->width; surface->window_height = bitmap->rows; { DWORD style = WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU; RECT WndRect; WndRect.left = 0; WndRect.top = 0; WndRect.right = bitmap->width; WndRect.bottom = bitmap->rows; AdjustWindowRect( &WndRect, style, FALSE ); surface->window = CreateWindow( /* LPCSTR lpszClassName; */ "FreeTypeTestGraphicDriver", /* LPCSTR lpszWindowName; */ "FreeType Test Graphic Driver", /* DWORD dwStyle; */ style, /* int x; */ CW_USEDEFAULT, /* int y; */ CW_USEDEFAULT, /* int nWidth; */ WndRect.right - WndRect.left, /* int nHeight; */ WndRect.bottom - WndRect.top, /* HWND hwndParent; */ HWND_DESKTOP, /* HMENU hmenu; */ 0, /* HINSTANCE hinst; */ GetModuleHandle( NULL ), /* void FAR* lpvParam; */ surface ); } if ( surface->window == 0 ) return 0; surface->root.done = (grDoneSurfaceFunc) gr_win32_surface_done; surface->root.refresh_rect = (grRefreshRectFunc) gr_win32_surface_refresh_rectangle; surface->root.set_title = (grSetTitleFunc) gr_win32_surface_set_title; surface->root.listen_event = (grListenEventFunc) gr_win32_surface_listen_event; return surface; } /* ---- Windows-specific stuff ------------------------------------------- */ /* Message processing for our Windows class */ LRESULT CALLBACK Message_Process( HWND handle, UINT mess, WPARAM wParam, LPARAM lParam ) { grWin32Surface* surface = NULL; if ( mess == WM_CREATE ) { /* WM_CREATE is the first message sent to this function, and the */ /* surface handle is available from the 'lParam' parameter. We */ /* save its value in a window property.. */ /* */ surface = ((LPCREATESTRUCT)lParam)->lpCreateParams; SetProp( handle, (LPCSTR)(LONG)ourAtom, surface ); } else { /* for other calls, we retrieve the surface handle from the window */ /* property.. ugly, isn't it ?? */ /* */ surface = (grWin32Surface*) GetProp( handle, (LPCSTR)(LONG)ourAtom ); } switch( mess ) { case WM_DESTROY: /* warn the main thread to quit if it didn't know */ surface->ourevent.type = gr_event_key; surface->ourevent.key = grKeyEsc; surface->eventToProcess = 1; surface->window = 0; PostQuitMessage ( 0 ); DeleteObject ( surface->hbm ); return 0; case WM_CREATE: { HDC hDC; LPBITMAPINFO pbmi = surface->pbmi; hDC = GetDC ( handle ); surface->hbm = CreateDIBitmap ( /* HDC hdc; handle of device context */ hDC, /* BITMAPINFOHEADER FAR* lpbmih; addr.of header*/ &pbmi->bmiHeader, /* DWORD dwInit; CBM_INIT to initialize bitmap */ 0, /* const void FAR* lpvBits; address of values */ NULL, /* BITMAPINFO FAR* lpbmi; addr.of bitmap data */ pbmi, /* UINT fnColorUse; RGB or palette indices */ DIB_RGB_COLORS); ReleaseDC ( handle, hDC ); break; } case WM_PAINT: { HDC hDC, memDC; HANDLE oldbm; PAINTSTRUCT ps; hDC = BeginPaint ( handle, &ps ); memDC = CreateCompatibleDC( hDC ); oldbm = SelectObject( memDC, surface->hbm ); BitBlt ( hDC, 0, 0, surface->window_width, surface->window_height, memDC, 0, 0, SRCCOPY); ReleaseDC ( handle, hDC ); SelectObject ( memDC, oldbm ); DeleteObject ( memDC ); EndPaint ( handle, &ps ); return 0; } case WM_SYSKEYDOWN: { int count = sizeof( syskey_translators )/sizeof( syskey_translators[0] ); Translator* trans = syskey_translators; Translator* limit = trans + count; for ( ; trans < limit; trans++ ) if ( wParam == trans->winkey ) { surface->ourevent.key = trans->grkey; goto Do_Key_Event; } return DefWindowProc( handle, mess, wParam, lParam ); } case WM_KEYDOWN: switch ( wParam ) { case VK_ESCAPE: surface->ourevent.type = gr_event_key; surface->ourevent.key = grKeyEsc; surface->eventToProcess = 1; PostQuitMessage ( 0 ); return 0; default: /* lookup list of translated keys */ { int count = sizeof( key_translators )/sizeof( key_translators[0] ); Translator* trans = key_translators; Translator* limit = trans + count; for ( ; trans < limit; trans++ ) if ( wParam == trans->winkey ) { surface->ourevent.key = trans->grkey; goto Do_Key_Event; } } /* the key isn't found, default processing */ /* return DefWindowProc( handle, mess, wParam, lParam ); */ return DefWindowProc( handle, mess, wParam, lParam ); } case WM_CHAR: { surface->ourevent.key = wParam; Do_Key_Event: surface->ourevent.type = gr_event_key; surface->eventToProcess = 1; } break; default: return DefWindowProc( handle, mess, wParam, lParam ); } return 0; } static int gr_win32_device_init( void ) { WNDCLASS ourClass = { /* UINT style */ 0, /* WNDPROC lpfnWndProc */ Message_Process, /* int cbClsExtra */ 0, /* int cbWndExtra */ 0, /* HANDLE hInstance */ 0, /* HICON hIcon */ 0, /* HCURSOR hCursor */ 0, /* HBRUSH hbrBackground*/ 0, /* LPCTSTR lpszMenuName */ NULL, /* LPCTSTR lpszClassName*/ "FreeTypeTestGraphicDriver" }; /* register window class */ ourClass.hInstance = GetModuleHandle( NULL ); ourClass.hIcon = LoadIcon(0, IDI_APPLICATION); ourClass.hCursor = LoadCursor(0, IDC_ARROW); ourClass.hbrBackground= GetStockObject(BLACK_BRUSH); if ( RegisterClass(&ourClass) == 0 ) return -1; /* add global atom */ ourAtom = GlobalAddAtom( "FreeType.Surface" ); return 0; } static void gr_win32_device_done( void ) { GlobalDeleteAtom( ourAtom ); } grDevice gr_win32_device = { sizeof( grWin32Surface ), "win32", gr_win32_device_init, gr_win32_device_done, (grDeviceInitSurfaceFunc) gr_win32_surface_init, 0, 0 }; /* End */ ft2demos-2.10.1/graph/win32/grwin32.h0000644000175000001440000000227013434207203016665 0ustar00wlusers00000000000000/******************************************************************* * * grwin32.h graphics driver for Win32 platform (header) * * This is the driver for displaying inside a window under Win32, * used by the graphics utility of the FreeType test suite. * * Written by Antoine Leca. * Copyright (C) 1999-2019 by * Antoine Leca, David Turner, Robert Wilhelm, and Werner Lemberg. * * Borrowing liberally from the other FreeType drivers. * * This file is part of the FreeType project, and may only be used * modified and distributed under the terms of the FreeType project * license, LICENSE.TXT. By continuing to use, modify or distribute * this file you indicate that you have read the license and * understand and accept it fully. * ******************************************************************/ #ifndef GRWIN32_H_ #define GRWIN32_H_ #include "grobjs.h" extern grDevice gr_win32_device; #ifdef GR_INIT_BUILD static grDeviceChain gr_win32_device_chain = { "win32", &gr_win32_device, GR_INIT_DEVICE_CHAIN }; #undef GR_INIT_DEVICE_CHAIN #define GR_INIT_DEVICE_CHAIN &gr_win32_device_chain #endif /* GR_INIT_BUILD */ #endif /* GRWIN32_H_ */ ft2demos-2.10.1/graph/win32/rules.mk0000644000175000001440000000340713502347420016711 0ustar00wlusers00000000000000#************************************************************************** #* #* Win32 specific rules file, used to compile the Win32 graphics driver #* to the graphics subsystem #* #************************************************************************** ifeq ($(PLATFORM),win32) # directory of the Win32 graphics driver # GR_WIN32 := $(GRAPH)/win32 # add the Win32 driver object file to the graphics library `graph.lib' # GRAPH_OBJS += $(OBJ_DIR_2)/grwin32.$O DEVICES += WIN32 # the rule used to compile the graphics driver # $(OBJ_DIR_2)/grwin32.$O: $(GR_WIN32)/grwin32.c $(GR_WIN32)/grwin32.h \ $(GRAPH_H) $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) \ $I$(subst /,$(COMPILER_SEP),$(GR_WIN32)) \ $T$(subst /,$(COMPILER_SEP),$@ $<) # now update COMPILE_GRAPH_LIB according to the compiler used on Win32 # ifeq ($(firstword $(CC)),gcc) # test for GCC GRAPH_LINK += -luser32 -lgdi32 endif ifeq ($(findstring $(CC),cl icl), $(CC)) # test for Visual C++ & Intel C++ COMPILE_GRAPH_LIB = lib /nologo /out:$(subst /,$(COMPILER_SEP),$(GRAPH_LIB) $(GRAPH_OBJS)) LINK = cl /nologo /MD /Fe$(subst /,$(COMPILER_SEP),$@ $< $(FTLIB)) GRAPH_LINK += user32.lib gdi32.lib endif ifeq ($(CC),lcc) # test for LCC-Win32 COMPILE_GRAPH_LIB = lcclib /out:$(subst /,$(COMPILER_SEP),$(GRAPH_LIB) $(GRAPH_OBJS)) LINK = lcclnk -o $(subst /,$(COMPILER_SEP),$@ $< $(FTLIB)) GRAPH_LINK += user32.lib gdi32.lib endif ifeq ($(CC),bcc32) # test for Borland C++ COMPILE_GRAPH_LIB = tlib /u $(subst /,$(COMPILER_SEP),$(GRAPH_LIB) $(GRAPH_OBJS:%=+%)) LINK = bcc32 -e$(subst /,$(COMPILER_SEP),$@ $< $(FTLIB)) endif endif # EOF ft2demos-2.10.1/graph/x11/0000755000175000001440000000000013506426605014700 5ustar00wlusers00000000000000ft2demos-2.10.1/graph/x11/grx11.h0000644000175000001440000000221013434207203015775 0ustar00wlusers00000000000000/******************************************************************* * * grx11.h graphics driver for X11 (header) * * This is the driver for displaying inside a window under X11, * used by the graphics utility of the FreeType test suite. * * Copyright (C) 1999-2019 by * Antoine Leca, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used * modified and distributed under the terms of the FreeType project * license, LICENSE.TXT. By continuing to use, modify or distribute * this file you indicate that you have read the license and * understand and accept it fully. * ******************************************************************/ #ifndef GRX11_H_ #define GRX11_H_ #ifdef __cplusplus #define class c_class #endif #include "grobjs.h" #include "grdevice.h" extern grDevice gr_x11_device; #ifdef GR_INIT_BUILD static grDeviceChain gr_x11_device_chain = { "x11", &gr_x11_device, GR_INIT_DEVICE_CHAIN }; #undef GR_INIT_DEVICE_CHAIN #define GR_INIT_DEVICE_CHAIN &gr_x11_device_chain #endif /* GR_INIT_BUILD */ #endif /* GRX11_H_ */ ft2demos-2.10.1/graph/x11/Jamfile0000644000175000001440000000034713434207203016165 0ustar00wlusers00000000000000# FreeType2 demos graph/x11 Jamfile (c) 2001 David Turner # SubDir FT2DEMO_TOP graph x11 ; SubDirHdrs $(GRAPH_INCLUDE) ; GRAPH_LINKLIBS = -lX11 -L/usr/X11R6/lib ; Library $(GRAPH_LIB) : grx11.c ; # end of graph/x11 Jamfile ft2demos-2.10.1/graph/x11/grx11.c0000644000175000001440000012563613506414267016024 0ustar00wlusers00000000000000/******************************************************************* * * grx11.c graphics driver for X11. * * This is the driver for displaying inside a window under X11, * used by the graphics utility of the FreeType test suite. * * Copyright (C) 1999-2019 by * Antoine Leca, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used * modified and distributed under the terms of the FreeType project * license, LICENSE.TXT. By continuing to use, modify or distribute * this file you indicate that you have read the license and * understand and accept it fully. * ******************************************************************/ #ifdef __VMS #include #endif #include #include #define xxTEST #ifdef TEST #include "grfont.h" #define LOG(x) printf x #define visualClass(x) ( x == StaticGray ? "StaticGray" : \ x == GrayScale ? "GrayScale" : \ x == StaticColor ? "StaticColor" : \ x == PseudoColor ? "PseudoColor" : \ x == TrueColor ? "TrueColor" : \ x == DirectColor ? "DirectColor" : "unknown" ) #define grAlloc malloc #else #define LOG(x) /* nothing */ #endif #include #include #include #include #include #include #include #include #include #include #include "grx11.h" #if defined( __cplusplus ) || defined( c_plusplus ) #define Class c_class #else #define Class class #endif /* old trick to determine 32-bit integer type */ #include /* The number of bytes in an `int' type. */ #if UINT_MAX == 0xFFFFFFFFUL #define GR_SIZEOF_INT 4 #elif UINT_MAX == 0xFFFFU #define GR_SIZEOF_INT 2 #elif UINT_MAX > 0xFFFFFFFFU && UINT_MAX == 0xFFFFFFFFFFFFFFFFU #define GR_SIZEOF_INT 8 #else #error "Unsupported number of bytes in `int' type!" #endif /* The number of bytes in a `long' type. */ #if ULONG_MAX == 0xFFFFFFFFUL #define GR_SIZEOF_LONG 4 #elif ULONG_MAX > 0xFFFFFFFFU && ULONG_MAX == 0xFFFFFFFFFFFFFFFFU #define GR_SIZEOF_LONG 8 #else #error "Unsupported number of bytes in `long' type!" #endif #if GR_SIZEOF_INT == 4 typedef int int32; typedef unsigned int uint32; #elif GR_SIZEOF_LONG == 4 typedef long int32; typedef unsigned long uint32; #else #error "could not find a 32-bit integer type" #endif typedef struct Translator { KeySym xkey; grKey grkey; } Translator; static Translator key_translators[] = { { XK_BackSpace, grKeyBackSpace }, { XK_Tab, grKeyTab }, { XK_Return, grKeyReturn }, { XK_Escape, grKeyEsc }, { XK_Home, grKeyHome }, { XK_Left, grKeyLeft }, { XK_Up, grKeyUp }, { XK_Right, grKeyRight }, { XK_Down, grKeyDown }, { XK_Page_Up, grKeyPageUp }, { XK_Page_Down, grKeyPageDown }, { XK_End, grKeyEnd }, { XK_Begin, grKeyHome }, { XK_F1, grKeyF1 }, { XK_F2, grKeyF2 }, { XK_F3, grKeyF3 }, { XK_F4, grKeyF4 }, { XK_F5, grKeyF5 }, { XK_F6, grKeyF6 }, { XK_F7, grKeyF7 }, { XK_F8, grKeyF8 }, { XK_F9, grKeyF9 }, { XK_F10, grKeyF10 }, { XK_F11, grKeyF11 }, { XK_F12, grKeyF12 } }; typedef XPixmapFormatValues XDepth; /************************************************************************/ /************************************************************************/ /***** *****/ /***** PIXEL BLITTING SUPPORT *****/ /***** *****/ /************************************************************************/ /************************************************************************/ typedef struct grX11Blitter_ { unsigned char* src_line; int src_pitch; unsigned char* dst_line; int dst_pitch; int x; int y; int width; int height; } grX11Blitter; /* setup blitter; returns 1 if no drawing happens */ static int gr_x11_blitter_reset( grX11Blitter* blit, grBitmap* source, grBitmap* target, int x, int y, int width, int height ) { long pitch; int delta; /* clip rectangle to source bitmap */ if ( x < 0 ) { width += x; x = 0; } delta = x + width - source->width; if ( delta > 0 ) width -= delta; if ( y < 0 ) { height += y; y = 0; } delta = y + height - source->rows; if ( delta > 0 ) height -= delta; /* clip rectangle to target bitmap */ delta = x + width - target->width; if ( delta > 0 ) width -= delta; delta = y + height - target->rows; if ( delta > 0 ) height -= delta; if ( width <= 0 || height <= 0 ) return 1; /* now, setup the blitter */ pitch = blit->src_pitch = source->pitch; blit->src_line = source->buffer + y * pitch; if ( pitch < 0 ) blit->src_line -= ( source->rows - 1 ) * pitch; pitch = blit->dst_pitch = target->pitch; blit->dst_line = target->buffer + y * pitch; if ( pitch < 0 ) blit->dst_line -= ( target->rows - 1 ) * pitch; blit->x = x; blit->y = y; blit->width = width; blit->height = height; return 0; } typedef void (*grX11ConvertFunc)( grX11Blitter* blit ); typedef struct grX11FormatRec_ { int x_depth; int x_bits_per_pixel; unsigned long x_red_mask; unsigned long x_green_mask; unsigned long x_blue_mask; grX11ConvertFunc rgb_convert; grX11ConvertFunc gray_convert; } grX11Format; /************************************************************************/ /************************************************************************/ /***** *****/ /***** BLITTING ROUTINES FOR RGB565 *****/ /***** *****/ /************************************************************************/ /************************************************************************/ static void gr_x11_convert_rgb_to_rgb565( grX11Blitter* blit ) { unsigned char* line_read = blit->src_line + blit->x * 3; unsigned char* line_write = blit->dst_line + blit->x * 2; int h = blit->height; for ( ; h > 0; h-- ) { unsigned char* lread = line_read; unsigned short* lwrite = (unsigned short*)line_write; int x = blit->width; for ( ; x > 0; x--, lread += 3, lwrite++ ) { unsigned int r = lread[0]; unsigned int g = lread[1]; unsigned int b = lread[2]; lwrite[0] = (unsigned short)( ( ( r << 8 ) & 0xF800U ) | ( ( g << 3 ) & 0x07E0 ) | ( ( b >> 3 ) & 0x001F ) ); } line_read += blit->src_pitch; line_write += blit->dst_pitch; } } static void gr_x11_convert_gray_to_rgb565( grX11Blitter* blit ) { unsigned char* line_read = blit->src_line + blit->x; unsigned char* line_write = blit->dst_line + blit->x * 2; int h = blit->height; for ( ; h > 0; h-- ) { unsigned char* lread = line_read; unsigned short* lwrite = (unsigned short*)line_write; int x = blit->width; for ( ; x > 0; x--, lread++, lwrite++ ) { unsigned int p = lread[0]; lwrite[0] = (unsigned short)( ( ( p << 8 ) & 0xF800U ) | ( ( p << 3 ) & 0x07E0 ) | ( ( p >> 3 ) & 0x001F ) ); } line_read += blit->src_pitch; line_write += blit->dst_pitch; } } static const grX11Format gr_x11_format_rgb565 = { 16, 16, 0xF800U, 0x07E0, 0x001F, gr_x11_convert_rgb_to_rgb565, gr_x11_convert_gray_to_rgb565 }; /************************************************************************/ /************************************************************************/ /***** *****/ /***** BLITTING ROUTINES FOR BGR565 *****/ /***** *****/ /************************************************************************/ /************************************************************************/ static void gr_x11_convert_rgb_to_bgr565( grX11Blitter* blit ) { unsigned char* line_read = blit->src_line + blit->x * 3; unsigned char* line_write = blit->dst_line + blit->x * 2; int h = blit->height; for ( ; h > 0; h-- ) { unsigned char* lread = line_read; unsigned short* lwrite = (unsigned short*)line_write; int x = blit->width; for ( ; x > 0; x--, lread += 3, lwrite++ ) { unsigned int r = lread[0]; unsigned int g = lread[1]; unsigned int b = lread[2]; lwrite[0] = (unsigned short)( ( ( b << 8 ) & 0xF800U ) | ( ( g << 3 ) & 0x07E0 ) | ( ( r >> 3 ) & 0x001F ) ); } line_read += blit->src_pitch; line_write += blit->dst_pitch; } } static const grX11Format gr_x11_format_bgr565 = { 16, 16, 0x001F, 0x07E0, 0xF800U, gr_x11_convert_rgb_to_bgr565, gr_x11_convert_gray_to_rgb565 /* the same for bgr565! */ }; /************************************************************************/ /************************************************************************/ /***** *****/ /***** BLITTING ROUTINES FOR RGB555 *****/ /***** *****/ /************************************************************************/ /************************************************************************/ static void gr_x11_convert_rgb_to_rgb555( grX11Blitter* blit ) { unsigned char* line_read = blit->src_line + blit->x * 3; unsigned char* line_write = blit->dst_line + blit->x * 2; int h = blit->height; for ( ; h > 0; h-- ) { unsigned char* lread = line_read; unsigned short* lwrite = (unsigned short*)line_write; int x = blit->width; for ( ; x > 0; x--, lread += 3, lwrite++ ) { unsigned int r = lread[0]; unsigned int g = lread[1]; unsigned int b = lread[2]; lwrite[0] = (unsigned short)( ( ( r << 7 ) & 0x7C00 ) | ( ( g << 2 ) & 0x03E0 ) | ( ( b >> 3 ) & 0x001F ) ); } line_read += blit->src_pitch; line_write += blit->dst_pitch; } } static void gr_x11_convert_gray_to_rgb555( grX11Blitter* blit ) { unsigned char* line_read = blit->src_line + blit->x; unsigned char* line_write = blit->dst_line + blit->x * 2; int h = blit->height; for ( ; h > 0; h-- ) { unsigned char* lread = line_read; unsigned short* lwrite = (unsigned short*)line_write; int x = blit->width; for ( ; x > 0; x--, lread++, lwrite++ ) { unsigned int p = lread[0]; lwrite[0] = (unsigned short)( ( ( p << 7 ) & 0x7C00 ) | ( ( p << 2 ) & 0x03E0 ) | ( ( p >> 3 ) & 0x001F ) ); } line_read += blit->src_pitch; line_write += blit->dst_pitch; } } static const grX11Format gr_x11_format_rgb555 = { 15, 16, 0x7C00, 0x03E0, 0x001F, gr_x11_convert_rgb_to_rgb555, gr_x11_convert_gray_to_rgb555 }; /************************************************************************/ /************************************************************************/ /***** *****/ /***** BLITTING ROUTINES FOR BGR555 *****/ /***** *****/ /************************************************************************/ /************************************************************************/ static void gr_x11_convert_rgb_to_bgr555( grX11Blitter* blit ) { unsigned char* line_read = blit->src_line + blit->x * 3; unsigned char* line_write = blit->dst_line + blit->x * 2; int h = blit->height; for ( ; h > 0; h-- ) { unsigned char* lread = line_read; unsigned short* lwrite = (unsigned short*)line_write; int x = blit->width; for ( ; x > 0; x--, lread += 3, lwrite++ ) { unsigned int r = lread[0]; unsigned int g = lread[1]; unsigned int b = lread[2]; lwrite[0] = (unsigned short)( ( ( b << 7 ) & 0x7C00 ) | ( ( g << 2 ) & 0x03E0 ) | ( ( r >> 3 ) & 0x001F ) ); } line_read += blit->src_pitch; line_write += blit->dst_pitch; } } static const grX11Format gr_x11_format_bgr555 = { 15, 16, 0x001F, 0x03E0, 0x7C00, gr_x11_convert_rgb_to_bgr555, gr_x11_convert_gray_to_rgb555 /* the same for bgr555! */ }; /************************************************************************/ /************************************************************************/ /***** *****/ /***** BLITTING ROUTINES FOR RGB888 *****/ /***** *****/ /************************************************************************/ /************************************************************************/ static void gr_x11_convert_rgb_to_rgb888( grX11Blitter* blit ) { unsigned char* line_read = blit->src_line + blit->x * 3; unsigned char* line_write = blit->dst_line + blit->x * 3; int h = blit->height; for ( ; h > 0; h-- ) { memcpy( line_write, line_read, (unsigned int)( blit->width * 3 ) ); line_read += blit->src_pitch; line_write += blit->dst_pitch; } } static void gr_x11_convert_gray_to_rgb888( grX11Blitter* blit ) { unsigned char* line_read = blit->src_line + blit->x; unsigned char* line_write = blit->dst_line + blit->x * 3; int h = blit->height; for ( ; h > 0; h-- ) { unsigned char* lread = line_read; unsigned char* lwrite = line_write; int x = blit->width; for ( ; x > 0; x--, lread++, lwrite += 3 ) { unsigned char p = lread[0]; lwrite[0] = p; lwrite[1] = p; lwrite[2] = p; } line_read += blit->src_pitch; line_write += blit->dst_pitch; } } static const grX11Format gr_x11_format_rgb888 = { 24, 24, 0xFF0000L, 0x00FF00U, 0x0000FF, gr_x11_convert_rgb_to_rgb888, gr_x11_convert_gray_to_rgb888 }; /************************************************************************/ /************************************************************************/ /***** *****/ /***** BLITTING ROUTINES FOR BGR888 *****/ /***** *****/ /************************************************************************/ /************************************************************************/ static void gr_x11_convert_rgb_to_bgr888( grX11Blitter* blit ) { unsigned char* line_read = blit->src_line + blit->x * 3; unsigned char* line_write = blit->dst_line + blit->x * 3; int h = blit->height; for ( ; h > 0; h-- ) { unsigned char* lread = line_read; unsigned char* lwrite = line_write; int x = blit->width; for ( ; x > 0; x--, lread += 3, lwrite += 3 ) { lwrite[0] = lread[2]; lwrite[1] = lread[1]; lwrite[2] = lread[0]; } line_read += blit->src_pitch; line_write += blit->dst_pitch; } } static const grX11Format gr_x11_format_bgr888 = { 24, 24, 0x0000FF, 0x00FF00U, 0xFF0000L, gr_x11_convert_rgb_to_bgr888, gr_x11_convert_gray_to_rgb888 /* the same for bgr888 */ }; /************************************************************************/ /************************************************************************/ /***** *****/ /***** BLITTING ROUTINES FOR RGB8880 *****/ /***** *****/ /************************************************************************/ /************************************************************************/ static void gr_x11_convert_rgb_to_rgb8880( grX11Blitter* blit ) { unsigned char* line_read = blit->src_line + blit->x * 3; unsigned char* line_write = blit->dst_line + blit->x * 4; int h = blit->height; for ( ; h > 0; h-- ) { unsigned char* lread = line_read; unsigned char* lwrite = line_write; int x = blit->width; for ( ; x > 0; x--, lread += 3, lwrite += 4 ) { uint32 r = lread[0]; uint32 g = lread[1]; uint32 b = lread[2]; *(uint32*)lwrite = ( r << 24 ) | ( g << 16 ) | ( b << 8 ); } line_read += blit->src_pitch; line_write += blit->dst_pitch; } } static void gr_x11_convert_gray_to_rgb8880( grX11Blitter* blit ) { unsigned char* line_read = blit->src_line + blit->x; unsigned char* line_write = blit->dst_line + blit->x*4; int h = blit->height; for ( ; h > 0; h-- ) { unsigned char* lread = line_read; unsigned char* lwrite = line_write; int x = blit->width; for ( ; x > 0; x--, lread ++, lwrite += 4 ) { uint32 p = lread[0]; *(uint32*)lwrite = ( p << 24 ) | ( p << 16 ) | ( p << 8 ); } line_read += blit->src_pitch; line_write += blit->dst_pitch; } } static const grX11Format gr_x11_format_rgb8880 = { 24, 32, 0xFF000000UL, 0x00FF0000L, 0x0000FF00U, gr_x11_convert_rgb_to_rgb8880, gr_x11_convert_gray_to_rgb8880 }; /************************************************************************/ /************************************************************************/ /***** *****/ /***** BLITTING ROUTINES FOR RGB0888 *****/ /***** *****/ /************************************************************************/ /************************************************************************/ static void gr_x11_convert_rgb_to_rgb0888( grX11Blitter* blit ) { unsigned char* line_read = blit->src_line + blit->x * 3; unsigned char* line_write = blit->dst_line + blit->x * 4; int h = blit->height; for ( ; h > 0; h-- ) { unsigned char* lread = line_read; unsigned char* lwrite = line_write; int x = blit->width; for ( ; x > 0; x--, lread += 3, lwrite += 4 ) { uint32 r = lread[0]; uint32 g = lread[1]; uint32 b = lread[2]; *(uint32*)lwrite = ( r << 16 ) | ( g << 8 ) | ( b << 0 ); } line_read += blit->src_pitch; line_write += blit->dst_pitch; } } static void gr_x11_convert_gray_to_rgb0888( grX11Blitter* blit ) { unsigned char* line_read = blit->src_line + blit->x; unsigned char* line_write = blit->dst_line + blit->x * 4; int h = blit->height; for ( ; h > 0; h-- ) { unsigned char* lread = line_read; unsigned char* lwrite = line_write; int x = blit->width; for ( ; x > 0; x--, lread ++, lwrite += 4 ) { uint32 p = lread[0]; *(uint32*)lwrite = ( p << 16 ) | ( p << 8 ) | ( p << 0 ); } line_read += blit->src_pitch; line_write += blit->dst_pitch; } } static const grX11Format gr_x11_format_rgb0888 = { 24, 32, 0x00FF0000L, 0x0000FF00U, 0x000000FF, gr_x11_convert_rgb_to_rgb0888, gr_x11_convert_gray_to_rgb0888 }; /************************************************************************/ /************************************************************************/ /***** *****/ /***** BLITTING ROUTINES FOR BGR8880 *****/ /***** *****/ /************************************************************************/ /************************************************************************/ static void gr_x11_convert_rgb_to_bgr8880( grX11Blitter* blit ) { unsigned char* line_read = blit->src_line + blit->x * 3; unsigned char* line_write = blit->dst_line + blit->x * 4; int h = blit->height; for ( ; h > 0; h-- ) { unsigned char* lread = line_read; unsigned char* lwrite = line_write; int x = blit->width; for ( ; x > 0; x--, lread += 3, lwrite += 4 ) { uint32 r = lread[0]; uint32 g = lread[1]; uint32 b = lread[2]; *(uint32*)lwrite = ( r << 8 ) | ( g << 16 ) | ( b << 24 ); } line_read += blit->src_pitch; line_write += blit->dst_pitch; } } static const grX11Format gr_x11_format_bgr8880 = { 24, 32, 0x0000FF00U, 0x00FF0000L, 0xFF000000UL, gr_x11_convert_rgb_to_bgr8880, gr_x11_convert_gray_to_rgb8880 /* the same for bgr8880 */ }; /************************************************************************/ /************************************************************************/ /***** *****/ /***** BLITTING ROUTINES FOR BGR0888 *****/ /***** *****/ /************************************************************************/ /************************************************************************/ static void gr_x11_convert_rgb_to_bgr0888( grX11Blitter* blit ) { unsigned char* line_read = blit->src_line + blit->x * 3; unsigned char* line_write = blit->dst_line + blit->x * 4; int h = blit->height; for ( ; h > 0; h-- ) { unsigned char* lread = line_read; unsigned char* lwrite = line_write; int x = blit->width; for ( ; x > 0; x--, lread += 3, lwrite += 4 ) { uint32 r = lread[0]; uint32 g = lread[1]; uint32 b = lread[2]; *(uint32*)lwrite = ( r << 0 ) | ( g << 8 ) | ( b << 16 ); } line_read += blit->src_pitch; line_write += blit->dst_pitch; } } static const grX11Format gr_x11_format_bgr0888 = { 24, 32, 0x000000FF, 0x0000FF00U, 0x00FF0000L, gr_x11_convert_rgb_to_bgr0888, gr_x11_convert_gray_to_rgb0888 /* the same for bgr0888 */ }; /************************************************************************/ /************************************************************************/ /***** *****/ /***** X11 DEVICE SUPPORT *****/ /***** *****/ /************************************************************************/ /************************************************************************/ static const grX11Format* gr_x11_formats[] = { &gr_x11_format_rgb565, &gr_x11_format_bgr565, &gr_x11_format_rgb555, &gr_x11_format_bgr555, &gr_x11_format_rgb888, &gr_x11_format_bgr888, &gr_x11_format_rgb0888, &gr_x11_format_bgr0888, &gr_x11_format_rgb8880, &gr_x11_format_bgr8880, NULL }; typedef struct grX11DeviceRec_ { Display* display; Cursor idle; Cursor busy; const grX11Format* format; int scanline_pad; Visual* visual; } grX11Device; static grX11Device x11dev; static void gr_x11_device_done( void ) { if ( x11dev.display ) { XFreeCursor( x11dev.display, x11dev.busy ); XFreeCursor( x11dev.display, x11dev.idle ); XCloseDisplay( x11dev.display ); x11dev.display = NULL; } } static int gr_x11_device_init( void ) { memset( &x11dev, 0, sizeof ( x11dev ) ); XrmInitialize(); x11dev.display = XOpenDisplay( "" ); if ( !x11dev.display ) { fprintf( stderr, "cannot open X11 display\n" ); return -1; } x11dev.idle = XCreateFontCursor( x11dev.display, XC_left_ptr ); x11dev.busy = XCreateFontCursor( x11dev.display, XC_watch ); { int count; XDepth* format; XDepth* formats; XVisualInfo templ; templ.screen = DefaultScreen( x11dev.display ); formats = XListPixmapFormats( x11dev.display, &count ); LOG(( "available pixmap formats\n" )); LOG(( "depth pixbits scanpad\n" )); for ( format = formats; count > 0; count--, format++ ) { LOG(( " %3d %3d %3d\n", format->depth, format->bits_per_pixel, format->scanline_pad )); /* note, the 32-bit modes return a depth of 24, */ /* and 32 bits per pixel */ switch ( format->depth ) { case 16: case 24: case 32: { int count2; XVisualInfo* visual; XVisualInfo* visuals; templ.depth = format->depth; visuals = XGetVisualInfo( x11dev.display, VisualScreenMask | VisualDepthMask, &templ, &count2 ); for ( visual = visuals; count2 > 0; count2--, visual++ ) { LOG(( "> R:G:B %0*lx:%0*lx:%0*lx, colors %3d, bits %2d, %s\n", format->bits_per_pixel/4, visual->red_mask, format->bits_per_pixel/4, visual->green_mask, format->bits_per_pixel/4, visual->blue_mask, visual->colormap_size, visual->bits_per_rgb, visualClass( visual->Class ) )); /* compare to the list of supported formats */ { const grX11Format** pcur_format = gr_x11_formats; const grX11Format* cur_format; for (;;) { cur_format = *pcur_format++; if ( cur_format == NULL ) break; if ( format->depth == cur_format->x_depth && format->bits_per_pixel == cur_format->x_bits_per_pixel && visual->red_mask == cur_format->x_red_mask && visual->green_mask == cur_format->x_green_mask && visual->blue_mask == cur_format->x_blue_mask ) { x11dev.format = cur_format; x11dev.scanline_pad = format->scanline_pad; x11dev.visual = visual->visual; XFree( visuals ); XFree( formats ); return 0; } } } } /* for visuals */ XFree( visuals ); } break; default: ; } /* switch format depth */ } /* for formats */ XFree( formats ); } fprintf( stderr, "unsupported X11 display depth!\n" ); return -1; } /************************************************************************/ /************************************************************************/ /***** *****/ /***** X11 SURFACE SUPPORT *****/ /***** *****/ /************************************************************************/ /************************************************************************/ typedef struct grX11Surface_ { grSurface root; Display* display; Window win; Visual* visual; Colormap colormap; GC gc; int depth; XImage* ximage; grBitmap ximage_bitmap; const grX11Format* format; grX11ConvertFunc convert; char key_buffer[10]; int key_cursor; int key_number; } grX11Surface; /* close a given window */ static void gr_x11_surface_done( grX11Surface* surface ) { Display* display = surface->display; if ( display ) { XFreeGC( display, surface->gc ); if ( surface->ximage ) { XDestroyImage( surface->ximage ); surface->ximage = 0; } if ( surface->win ) { XUnmapWindow( display, surface->win ); surface->win = 0; } } } static void gr_x11_surface_refresh_rect( grX11Surface* surface, int x, int y, int w, int h ) { grX11Blitter blit; if ( !gr_x11_blitter_reset( &blit, &surface->root.bitmap, &surface->ximage_bitmap, x, y, w, h ) ) { surface->convert( &blit ); XPutImage( surface->display, surface->win, surface->gc, surface->ximage, blit.x, blit.y, blit.x, blit.y, (unsigned int)blit.width, (unsigned int)blit.height ); } } static void gr_x11_surface_set_title( grX11Surface* surface, const char* title ) { XStoreName( surface->display, surface->win, title ); } static grKey KeySymTogrKey( KeySym key ) { grKey k; int count = sizeof ( key_translators ) / sizeof( key_translators[0] ); Translator* trans = key_translators; Translator* limit = trans + count; k = grKeyNone; while ( trans < limit ) { if ( trans->xkey == key ) { k = trans->grkey; break; } trans++; } return k; } static void gr_x11_surface_listen_event( grX11Surface* surface, int event_mask, grEvent* grevent ) { XEvent x_event; KeySym key; Display* display = surface->display; int bool_exit; grKey grkey; XComposeStatus compose; /* XXX: for now, ignore the event mask, and only exit when */ /* a key is pressed */ (void)event_mask; bool_exit = surface->key_cursor < surface->key_number; XDefineCursor( display, surface->win, x11dev.idle ); while ( !bool_exit ) { XNextEvent( display, &x_event ); switch ( x_event.type ) { case KeyPress: surface->key_number = XLookupString( &x_event.xkey, surface->key_buffer, sizeof ( surface->key_buffer ), &key, &compose ); surface->key_cursor = 0; if ( surface->key_number == 0 || key > 512 ) { /* this may be a special key like F1, F2, etc. */ grkey = KeySymTogrKey( key ); if ( grkey != grKeyNone ) goto Set_Key; } else bool_exit = 1; break; case MappingNotify: XRefreshKeyboardMapping( &x_event.xmapping ); break; case Expose: #if 1 /* we don't need to convert the bits on each expose! */ XPutImage( surface->display, surface->win, surface->gc, surface->ximage, x_event.xexpose.x, x_event.xexpose.y, x_event.xexpose.x, x_event.xexpose.y, (unsigned int)x_event.xexpose.width, (unsigned int)x_event.xexpose.height ); #else gr_x11_surface_refresh_rect( surface, x_event.xexpose.x, x_event.xexpose.y, x_event.xexpose.width, x_event.xexpose.height ); #endif break; /* You should add more cases to handle mouse events, etc. */ } } XDefineCursor( display, surface->win, x11dev.busy ); XFlush ( display ); /* now, translate the keypress to a grKey; */ /* if this wasn't part of the simple translated keys, */ /* simply get the charcode from the character buffer */ grkey = grKEY( surface->key_buffer[surface->key_cursor++] ); Set_Key: grevent->type = gr_key_down; grevent->key = grkey; } static int gr_x11_surface_init( grX11Surface* surface, grBitmap* bitmap ) { Display* display; int screen; grBitmap* pximage = &surface->ximage_bitmap; const grX11Format* format; surface->key_number = 0; surface->key_cursor = 0; surface->display = display = x11dev.display; screen = DefaultScreen( display ); surface->depth = x11dev.format->x_depth; surface->visual = x11dev.visual; surface->format = format = x11dev.format; surface->root.bitmap = *bitmap; switch ( bitmap->mode ) { case gr_pixel_mode_rgb24: surface->convert = format->rgb_convert; break; case gr_pixel_mode_gray: /* we only support 256-gray level 8-bit pixmaps */ if ( bitmap->grays == 256 ) { surface->convert = format->gray_convert; break; } /* fall through */ default: /* we don't support other modes */ return 0; } /* allocate surface image */ { int bits, over; bits = bitmap->width * format->x_bits_per_pixel; over = bits % x11dev.scanline_pad; if ( over ) bits += x11dev.scanline_pad - over; pximage->pitch = bits >> 3; pximage->width = bitmap->width; pximage->rows = bitmap->rows; } pximage->buffer = (unsigned char*)grAlloc( (unsigned long)( pximage->pitch * pximage->rows ) ); if ( !pximage->buffer ) return 0; /* create the bitmap */ if ( grNewBitmap( bitmap->mode, bitmap->grays, bitmap->width, bitmap->rows, bitmap ) ) return 0; surface->root.bitmap = *bitmap; /* Now create the surface X11 image */ surface->ximage = XCreateImage( display, surface->visual, (unsigned int)format->x_depth, ZPixmap, 0, (char*)pximage->buffer, (unsigned int)pximage->width, (unsigned int)pximage->rows, x11dev.scanline_pad, 0 ); if ( !surface->ximage ) return 0; { XTextProperty xtp = { (unsigned char*)"FreeType", 31, 8, 8 }; XSizeHints xsh = { }; XSetWindowAttributes xswa; unsigned long xswa_mask = CWEventMask | CWCursor; pid_t pid; Atom NET_WM_PID; xswa.cursor = x11dev.busy; xswa.event_mask = KeyPressMask | ExposureMask; if ( surface->visual == DefaultVisual( display, screen ) ) surface->colormap = DefaultColormap( display, screen ); else { xswa_mask |= CWBorderPixel | CWColormap; xswa.border_pixel = BlackPixel( display, screen ); xswa.colormap = XCreateColormap( display, RootWindow( display, screen ), surface->visual, AllocNone ); surface->colormap = xswa.colormap; } surface->win = XCreateWindow( display, RootWindow( display, screen ), 0, 0, (unsigned int)bitmap->width, (unsigned int)bitmap->rows, 10, format->x_depth, InputOutput, surface->visual, xswa_mask, &xswa ); XMapWindow( display, surface->win ); surface->gc = XCreateGC( display, surface->win, 0L, NULL ); XSetForeground( display, surface->gc, xswa.border_pixel ); XSetBackground( display, surface->gc, xswa.background_pixel ); XSetWMProperties( display, surface->win, &xtp, &xtp, NULL, 0, &xsh, NULL, NULL ); pid = getpid(); NET_WM_PID = XInternAtom( display, "_NET_WM_PID", False ); XChangeProperty( display, surface->win, NET_WM_PID, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&pid, 1 ); } surface->root.done = (grDoneSurfaceFunc)gr_x11_surface_done; surface->root.refresh_rect = (grRefreshRectFunc)gr_x11_surface_refresh_rect; surface->root.set_title = (grSetTitleFunc) gr_x11_surface_set_title; surface->root.listen_event = (grListenEventFunc)gr_x11_surface_listen_event; return 1; } grDevice gr_x11_device = { sizeof( grX11Surface ), "x11", gr_x11_device_init, gr_x11_device_done, (grDeviceInitSurfaceFunc) gr_x11_surface_init, 0, 0 }; #ifdef TEST typedef struct grKeyName { grKey key; const char* name; } grKeyName; static const grKeyName key_names[] = { { grKeyF1, "F1" }, { grKeyF2, "F2" }, { grKeyF3, "F3" }, { grKeyF4, "F4" }, { grKeyF5, "F5" }, { grKeyF6, "F6" }, { grKeyF7, "F7" }, { grKeyF8, "F8" }, { grKeyF9, "F9" }, { grKeyF10, "F10" }, { grKeyF11, "F11" }, { grKeyF12, "F12" }, { grKeyEsc, "Esc" }, { grKeyHome, "Home" }, { grKeyEnd, "End" }, { grKeyPageUp, "Page_Up" }, { grKeyPageDown, "Page_Down" }, { grKeyLeft, "Left" }, { grKeyRight, "Right" }, { grKeyUp, "Up" }, { grKeyDown, "Down" }, { grKeyBackSpace, "BackSpace" }, { grKeyReturn, "Return" } }; #if 0 int main( void ) { grSurface* surface; int n; grInit(); surface = grNewScreenSurface( 0, gr_pixel_mode_gray, 320, 400, 128 ); if ( !surface ) Panic( "Could not create window\n" ); else { grColor color; grEvent event; const char* string; int x; grSetSurfaceRefresh( surface, 1 ); grSetTitle( surface, "X11 driver demonstration" ); for ( x = -10; x < 10; x++ ) { for ( n = 0; n < 128; n++ ) { color.value = ( n * 3 ) & 127; grWriteCellChar( surface, x + ( ( n % 60 ) << 3 ), 80 + ( x + 10 ) * 8 * 3 + ( ( n / 60 ) << 3 ), n, color ); } } color.value = 64; grWriteCellString( surface, 0, 0, "just an example", color ); do { listen_event( (grXSurface*)surface, 0, &event ); /* return if ESC was pressed */ if ( event.key == grKeyEsc ) return 0; /* otherwise, display key name */ color.value = ( color.value + 8 ) & 127; { int count = sizeof ( key_names ) / sizeof ( key_names[0] ); grKeyName* name = key_names; grKeyName* limit = name + count; const char* kname = 0; char kname_temp[16]; while ( name < limit ) { if ( name->key == event.key ) { kname = name->name; break; } name++; } if ( !kname ) { sprintf( kname_temp, "char '%c'", (char)event.key ); kname = kname_temp; } grWriteCellString( surface, 30, 30, kname, color ); grRefreshSurface( surface ); paint_rectangle( surface, 0, 0, surface->bitmap.width, surface->bitmap.rows ); } } while ( 1 ); } return 0; } #endif /* O */ #endif /* TEST */ /* END */ ft2demos-2.10.1/graph/x11/rules.mk0000644000175000001440000001010013502347420016344 0ustar00wlusers00000000000000#************************************************************************** #* #* X11-specific rules files, used to compile the X11 graphics driver #* when supported by the current platform #* #************************************************************************** ############################################################################# # # Try to detect an X11 setup. # # The goal is to define variable `X11_PATH', consisting of a list of # directories `A', `B', `C', ..., separated by spaces. While compiling the # demo programs that need X11 support, include file directories `A/include', # `B/include', etc., are passed to the compiler. While linking, directories # `A/lib', `A/lib64', `B/lib', `B/lib64', etc., are passed to the linker. # Note that it doesn't pose a problem to specify both 32bit and 64bit library # directories at the same time since the linker will properly reject the # incorrect ones. # # 1) We try to detect the following directories (in that order) as substrings # in the current path: # # X11/bin (usually a symlink to the current release) # X11R6/bin # X11R5/bin # # From the first hit we derive `X11_PATH' (by removing the `/bin' part). # # 2) If no success, we directly check the directories # # /usr # /usr/X11R6 # /usr/local/X11R6 # # whether they contain `include/X11/Xlib.h'. The first hit sets up # `X11_PATH'. # # 3) If the variable `X11_PATH' is already set (to specify unusual locations # of X11), no other directories are searched. For instance, let us assume # that the X11 header files are located in `/usr/local/X11/R6/include', # and the X11 library files in `/usr/openwin/lib'. Calling # # make X11_PATH="/usr/openwin /usr/local/X11R6" # # should then work. # FT_PATH := $(subst ;, ,$(subst :, ,$(subst $(SEP),/,$(PATH)))) ifndef X11_PATH ifneq ($(findstring X11/bin,$(FT_PATH)),) xversion := X11 else ifneq ($(findstring X11R6/bin,$(FT_PATH)),) xversion := X11R6 else ifneq ($(findstring X11R5/bin,$(FT_PATH)),) xversion := X11R5 endif endif endif ifdef xversion X11_PATH := $(filter %$(xversion)/bin,$(FT_PATH)) X11_PATH := $(X11_PATH:%/bin=%) else X11_DIRS := /usr /usr/X11R6 /usr/local/X11R6 X11_XLIB := include/X11/Xlib.h X11_PATH := $(foreach dir,$(X11_DIRS),$(wildcard $(dir)/$(X11_XLIB))) X11_PATH := $(X11_PATH:%/$(X11_XLIB)=%) endif endif ########################################################################## # # Update some variables to compile the X11 graphics module. Note that # X11 is available on Unix, or on OS/2. However, it only compiles with # gcc on the latter platform, which is why it is safe to use the flags # `-L' and `-l' in GRAPH_LINK. # ifneq ($(X11_PATH),) X11_INCLUDE := $(subst /,$(COMPILER_SEP),$(X11_PATH:%=%/include)) X11_LIB := $(subst /,$(COMPILER_SEP),$(X11_PATH:%=%/lib64) \ $(X11_PATH:%=%/lib)) # The GRAPH_LINK variable is expanded each time an executable is linked # against the graphics library. # ifeq ($(PLATFORM),unix) GRAPH_LINK += $(X11_LIB:%=-R%) endif GRAPH_LINK += $(X11_LIB:%=-L%) -lX11 # Solaris needs a -lsocket in GRAPH_LINK. # UNAME := $(shell uname) ifneq ($(findstring $(UNAME),SunOS Solaris),) GRAPH_LINK += -lsocket endif # Add the X11 driver object file to the graphics library. # GRAPH_OBJS += $(OBJ_DIR_2)/grx11.$(O) GR_X11 := $(GRAPH)/x11 DEVICES += X11 # the rule used to compile the X11 driver # $(OBJ_DIR_2)/grx11.$(O): $(GR_X11)/grx11.c $(GR_X11)/grx11.h $(GRAPH_H) ifneq ($(LIBTOOL),) $(LIBTOOL) --mode=compile $(CC) -static $(CFLAGS) \ $(GRAPH_INCLUDES:%=$I%) \ $I$(subst /,$(COMPILER_SEP),$(GR_X11)) \ $(X11_INCLUDE:%=$I%) \ $T$(subst /,$(COMPILER_SEP),$@ $<) else $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) \ $I$(subst /,$(COMPILER_SEP),$(GR_X11)) \ $(X11_INCLUDE:%=$I%) \ $T$(subst /,$(COMPILER_SEP),$@ $<) endif endif # EOF ft2demos-2.10.1/graph/allegro/0000755000175000001440000000000013506426605015714 5ustar00wlusers00000000000000ft2demos-2.10.1/graph/allegro/gralleg.h0000644000175000001440000000057113434207203017474 0ustar00wlusers00000000000000#ifndef GRALLEG_H_ #define GRALLEG_H_ #include "grobjs.h" extern grDevice gr_alleg_device; #ifdef GR_INIT_BUILD static grDeviceChain gr_alleg_device_chain = { "Allegro", &gr_alleg_device, GR_INIT_DEVICE_CHAIN }; #undef GR_INIT_DEVICE_CHAIN #define GR_INIT_DEVICE_CHAIN &gr_alleg_device_chain #endif /* GR_INIT_BUILD */ #endif /* GRALLEG_H_ */ ft2demos-2.10.1/graph/allegro/gralleg.c0000644000175000001440000001077513501434334017500 0ustar00wlusers00000000000000/******************************************************************* * * ft2demos/graph/allegro/gralleg.c * * Allegro driver for MiGS (minimalist graphics subsystem). Allegro * (Allegro Low LEvel Gaming ROutines) is a library for sound, * graphics, timers, etc., and is available on 32-bit DOS, Windows, * UNIX (X11, DGA, DGA2), Linux (svgalib, framebuffer) and BeOS. * * http://liballeg.org/ * https://github.com/liballeg * ******************************************************************/ /* FT graphics subsystem */ #include "grobjs.h" #include "grdevice.h" /* Allegro header */ #include static void set_graypalette() { PALETTE pal; int i = 0; for(; i < 256; i++) { pal[i].r = i >> 2; pal[i].g = i >> 2; pal[i].b = i >> 2; } set_palette(pal); } static int almodes[] = { 32, 24, 16, 15, 8, 0 }; static int gray[256]; static int init_device(void) { int* almode = almodes; if(allegro_init()) return -1; if(install_keyboard()) return -1; while(*almode) { set_color_depth(*almode); if(*almode == 8) set_graypalette(); if(set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) == 0) { int i = 0; for(; i < 256; i++) gray[i] = makecol(i, i, i); clear(screen); return 0; } almode++; } return -1; } static void done_device(void) { allegro_exit(); } static void alset_title(grSurface* surface, const char* title_string) { set_window_title(title_string); } static void alrefresh_rect(grSurface* surface, int x, int y, int width, int height) { unsigned char* bufptr = surface->bitmap.buffer; int cx = 0, cy = 0; switch(surface->bitmap.mode) { case gr_pixel_mode_mono: for(; cy < height; cy++) { for(cx = 0; cx < width; cx++) { putpixel(screen, cx + x, cy + y, (*bufptr++ ? gray[255] : gray[0])); } } break; case gr_pixel_mode_gray: for(; cy < height; cy++) { for(cx = 0; cx < width; cx++) { putpixel(screen, cx + x, cy + y, gray[*bufptr++]); } } break; default: break; } } static void aldone(grSurface* surface) { grDoneBitmap(&(surface->bitmap)); } static int key_translator[] = { KEY_F1, grKeyF1, KEY_F2, grKeyF2, KEY_F3, grKeyF3, KEY_F4, grKeyF4, KEY_F5, grKeyF5, KEY_F6, grKeyF6, KEY_F7, grKeyF7, KEY_F8, grKeyF8, KEY_F9, grKeyF9, KEY_F10, grKeyF10, KEY_F11, grKeyF11, KEY_F12, grKeyF12, KEY_LEFT, grKeyLeft, KEY_RIGHT, grKeyRight, KEY_UP, grKeyUp, KEY_DOWN, grKeyDown, KEY_INSERT, grKeyIns, KEY_DEL, grKeyDel, KEY_HOME, grKeyHome, KEY_END, grKeyEnd, KEY_PGUP, grKeyPageUp, KEY_PGDN, grKeyPageDown, KEY_ESC, grKeyEsc, KEY_TAB, grKeyTab, KEY_BACKSPACE, grKeyBackSpace, KEY_ENTER, grKeyReturn, 0, 0 }; static int translateKey(int scancode) { int* trans = key_translator; while(*trans) { if(scancode == *trans++) { return *trans; } trans++; } return 0; } static int allisten_event(grSurface* surface, int event_mode, grEvent* event) { int ch = 0, ascii = 0, scancode = 0, shifts = 0; event->type = gr_event_key; while(1) { ch = readkey(); shifts = 0; if(key_shifts & KB_SHIFT_FLAG) shifts |= grKeyShift; if(key_shifts & KB_CTRL_FLAG) shifts |= grKeyCtrl; if(key_shifts & KB_ALT_FLAG) shifts |= grKeyAlt; ascii = ch & 0xFF; scancode = ch >> 8; if(ascii > 31 && ascii < 127) { event->key = ascii | shifts; return 1; } if( (ch = translateKey(scancode)) ) { event->key = ch | shifts; return 1; } } return 0; } static int init_surface(grSurface* surface, grBitmap* bitmap) { if(grNewBitmap(bitmap->mode, bitmap->grays, bitmap->width, bitmap->rows, bitmap)) return 0; surface->bitmap = *bitmap; surface->refresh = 0; surface->owner = 0; surface->saturation = 0; surface->blit_mono = 0; surface->refresh_rect = alrefresh_rect; surface->set_title = alset_title; surface->listen_event = allisten_event; surface->done = aldone; return 1; } grDevice gr_alleg_device = { sizeof(grSurface), "Allegro", init_device, done_device, init_surface, 0, 0 }; ft2demos-2.10.1/graph/allegro/rules.mk0000644000175000001440000000155713502347420017400 0ustar00wlusers00000000000000#************************************************************************** #* #* Allegro driver makefile #* #************************************************************************** # test for the `ALLEGRO' environment variable. This is non-optimal. # ifdef ALLEGRO # directory of Allegro driver # GR_ALLEG := $(GRAPH)/allegro # add Allegro driver to lib objects # GRAPH_OBJS += $(OBJ_DIR_2)/gralleg.$O # add Allegro driver to list of devices # DEVICES += ALLEGRO # our compilation rule # $(OBJ_DIR_2)/gralleg.$O : $(GR_ALLEG)/gralleg.c $(GR_ALLEG)/gralleg.h \ $(GRAPH_H) $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) \ $I$(subst /,$(COMPILER_SEP),$(GR_ALLEG)) \ $T$(subst /,$(COMPILER_SEP),$@ $<) # we need to link with Allegro # GRAPH_LINK += -lalleg endif # test ALLEGRO # EOF ft2demos-2.10.1/graph/beos/0000755000175000001440000000000013506426605015217 5ustar00wlusers00000000000000ft2demos-2.10.1/graph/beos/grbeos.h0000644000175000001440000000056013434207203016641 0ustar00wlusers00000000000000#ifndef GRBEOS_H_ #define GRBEOS_H_ #include "grobjs.h" extern grDevice gr_beos_device; #ifdef GR_INIT_BUILD static grDeviceChain gr_beos_device_chain = { "beos", &gr_beos_device, GR_INIT_DEVICE_CHAIN }; #undef GR_INIT_DEVICE_CHAIN #define GR_INIT_DEVICE_CHAIN &gr_beos_device_chain #endif /* GR_INIT_BUILD */ #endif /* GRBEOS_H_ */ ft2demos-2.10.1/graph/beos/Jamfile0000644000175000001440000000034713434207203016504 0ustar00wlusers00000000000000# FreeType2 demos graph/beos Jamfile (c) 2002 David Turner # SubDir FT2DEMO_TOP graph beos ; SubDirHdrs $(GRAPH_INCLUDE) ; GRAPH_LINKLIBS = -lbe -lstdc++.r4 ; Library $(GRAPH_LIB) : grbeos.cpp ; # end of graph/beos Jamfile ft2demos-2.10.1/graph/beos/grbeos.cpp0000644000175000001440000002155513434207270017207 0ustar00wlusers00000000000000/******************************************************************* * * grbeos.c graphics driver for BeOS platform. 0.1 * * This is the driver for displaying inside a window under BeOS, * used by the graphics utility of the FreeType test suite. * * Written by Michael Pfeiffer. * Copyright (C) 2001-2019 by * Michael Pfeiffer * * This file is part of the FreeType project, and may only be used * modified and distributed under the terms of the FreeType project * license, LICENSE.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 #include #include #include #include #include #include #include #include #include #include #include "grbeos.h" /* logging facility */ #include #define DEBUG #ifdef DEBUG #define LOG(x) LogMessage##x #else #define LOG(x) /* empty */ #endif #ifdef DEBUG static void LogMessage( const char* fmt, ... ) { va_list ap; va_start( ap, fmt ); vfprintf( stderr, fmt, ap ); va_end( ap ); } #endif typedef struct Translator_ { int32 beoskey; grKey grkey; } Translator; static Translator key_translators[] = { { B_BACKSPACE, grKeyBackSpace }, { B_TAB, grKeyTab }, { B_ENTER, grKeyReturn }, { B_ESCAPE, grKeyEsc }, { B_HOME, grKeyHome }, { B_LEFT_ARROW, grKeyLeft }, { B_UP_ARROW, grKeyUp }, { B_RIGHT_ARROW, grKeyRight }, { B_DOWN_ARROW, grKeyDown }, { B_PAGE_UP, grKeyPageUp }, { B_PAGE_DOWN, grKeyPageDown }, { B_END, grKeyEnd } }; static Translator fkey_translators[] = { { B_F1_KEY, grKeyF1 }, { B_F2_KEY, grKeyF2 }, { B_F3_KEY, grKeyF3 }, { B_F4_KEY, grKeyF4 }, { B_F5_KEY, grKeyF5 }, { B_F6_KEY, grKeyF6 }, { B_F7_KEY, grKeyF7 }, { B_F8_KEY, grKeyF8 }, { B_F9_KEY, grKeyF9 }, { B_F10_KEY, grKeyF10 }, { B_F11_KEY, grKeyF11 }, { B_F12_KEY, grKeyF12 } }; static Translator* find_key(int32 key, Translator t[], int size) { for (int i = 0; i < size; i++) { if (t[i].beoskey == key) { return &t[i]; } } return NULL; } static const grPixelMode pixel_modes[] = { gr_pixel_mode_mono, gr_pixel_mode_gray // gr_pixel_mode_rgb565, // gr_pixel_mode_rgb32, }; class Window; typedef struct grBeOSSurface_ { grSurface root; Window* window; } grBeOSSurface; class Window : public BWindow { private: grBeOSSurface* _surface; BBitmap* _offscreen; BBitmap* _bitmap; BMessageQueue _event_queue; sem_id _locker; class View : public BView { BBitmap* _offscreen; BMessageQueue* _event_queue; sem_id _locker; public: View(BBitmap* offscreen, BMessageQueue* event_queue, sem_id locker, BRect r); void Draw(BRect r); void KeyDown(const char *bytes, int32 numBytes); }; View* _view; public: Window(grBeOSSurface* surface, grBitmap* bitmap); ~Window(); void Refresh(int x, int y, int w, int h); int listen_event(int event_mask, grEvent* grevent); static grSurface* init_surface(grSurface* surface, grBitmap* bitmap); static void done_surface(grSurface* surface); static void refresh_rectangle(grSurface* surface, int x, int y, int w, int h); static void set_title(grSurface* surface, const char* title); static int listen_event(grSurface* surface, int event_mask, grEvent* grevent); }; static int init_device(); static void done_device(void); grDevice gr_beos_device = { sizeof( grBeOSSurface ), "beos", init_device, done_device, (grDeviceInitSurfaceFunc) Window::init_surface, 0, 0 }; static int init_device() { gr_beos_device.num_pixel_modes = 2; gr_beos_device.pixel_modes = (grPixelMode*) pixel_modes; new BApplication("application/x.mp.freetype.test"); return 0; } static void done_device(void) { if (be_app) { delete be_app; be_app = NULL; } } Window::View::View(BBitmap* offscreen, BMessageQueue* event_queue, sem_id locker, BRect r) : BView(r, "", B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW), _offscreen(offscreen), _event_queue(event_queue), _locker(locker) { SetViewColor(B_TRANSPARENT_COLOR); } void Window::View::Draw(BRect r) { DrawBitmap(_offscreen); } void Window::View::KeyDown(const char *bytes, int32 numBytes) { BMessage* m = Window()->CurrentMessage(); int32 key; if (B_OK == m->FindInt32("key", &key)) { Translator* t = NULL; if (numBytes == 1) { if (*bytes == B_FUNCTION_KEY) { t = find_key(key, fkey_translators, sizeof(fkey_translators)/sizeof(Translator)); } else { t = find_key(*bytes, key_translators, sizeof(key_translators)/sizeof(Translator)); } } if (t || numBytes == 1) { _event_queue->Lock(); if (_event_queue->IsEmpty()) release_sem(_locker); _event_queue->AddMessage(new BMessage(t ? t->grkey : *bytes)); _event_queue->Unlock(); return; } } BView::KeyDown(bytes, numBytes); } int Window::listen_event(int event_mask, grEvent* grevent) { acquire_sem(_locker); _event_queue.Lock(); BMessage* m = _event_queue.NextMessage(); if (!_event_queue.IsEmpty()) release_sem(_locker); _event_queue.Unlock(); grevent->type = gr_key_down; grevent->key = (grKey)m->what; delete m; return 0; } Window::Window(grBeOSSurface* surface, grBitmap* bitmap) : BWindow(BRect(20, 20, 100, 100), "", B_TITLED_WINDOW, B_NOT_CLOSABLE | B_NOT_RESIZABLE | B_NOT_ZOOMABLE) { _locker = create_sem(0, "event_locker"); _surface = surface; surface->root.done = done_surface; surface->root.refresh_rect = refresh_rectangle; surface->root.set_title = set_title; surface->root.listen_event = listen_event; surface->window = this; int w = bitmap->width; int h = bitmap->rows; BRect r(0, 0, w, h); switch (bitmap->mode) { case gr_pixel_mode_mono: _bitmap = new BBitmap(r, B_GRAY1); break; case gr_pixel_mode_gray: _bitmap = new BBitmap(r, B_CMAP8); break; case gr_pixel_mode_rgb565: _bitmap = new BBitmap(r, B_RGB16); break; case gr_pixel_mode_rgb32: _bitmap = new BBitmap(r, B_RGB32); break; default: LOG(("unsupported mode")); exit(-1); } bitmap->buffer = (unsigned char*)_bitmap->Bits(); bitmap->pitch = _bitmap->BytesPerRow(); _surface->root.bitmap = *bitmap; _offscreen = new BBitmap(r, B_RGB32); _view = new View(_offscreen, &_event_queue, _locker, r); AddChild(_view); _view->MakeFocus(true); ResizeTo(w, h); Show(); } Window::~Window() { delete_sem(_locker); delete _offscreen; delete _bitmap; } void Window::Refresh(int x, int y, int w, int h) { int32* d = (int32*)_offscreen->Bits(); int32* dl = d; uint8* s = (uint8*)_bitmap->Bits(); uint8* sl = s; if (Lock()) { switch(_surface->root.bitmap.mode) { case gr_pixel_mode_mono: for (y = 0; y < _surface->root.bitmap.rows; y++) { sl = s; dl = d; for (x = 0; x < _surface->root.bitmap.width; x++) { *dl = *sl ? -1 : 0; sl++; dl++; } s += _bitmap->BytesPerRow(); d = (int32*)(((char*)d) + _offscreen->BytesPerRow()); } break; case gr_pixel_mode_gray: for (y = 0; y < _surface->root.bitmap.rows; y++) { sl = s; int8* dx = (int8*)d; for (x = 0; x < _surface->root.bitmap.width; x++) { *dx = *sl; dx++; *dx = *sl; dx++; *dx = *sl; dx++; *dx = *sl; dx++; sl++; } s += _bitmap->BytesPerRow(); d = (int32*)(((char*)d) + _offscreen->BytesPerRow()); } break; default: fprintf(stderr, "unsupported mode: %d\n", _surface->root.bitmap.mode); break; } _view->Invalidate(); Unlock(); } } grSurface* Window::init_surface( grSurface* surface, grBitmap* bitmap) { new Window((grBeOSSurface*) surface, bitmap); return surface; } void Window::done_surface(grSurface* surface) { Window* w = ((grBeOSSurface*)surface)->window; if (w->Lock()) { w->PostMessage(B_QUIT_REQUESTED); w->Unlock(); } } void Window::refresh_rectangle(grSurface* surface, int x, int y, int w, int h) { Window* win = ((grBeOSSurface*)surface)->window; win->Refresh(x, y, w, h); } void Window::set_title(grSurface* surface, const char* title) { Window* win = ((grBeOSSurface*)surface)->window; if (win->Lock()) { win->SetTitle(title); win->Unlock(); } } int Window::listen_event(grSurface* surface, int event_mask, grEvent* grevent) { Window* win = ((grBeOSSurface*)surface)->window; return win->listen_event(event_mask, grevent); } /* End */ ft2demos-2.10.1/graph/beos/rules.mk0000644000175000001440000000243213502347420016674 0ustar00wlusers00000000000000#************************************************************************** #* #* BeOS specific rules file, used to compile the BeOS graphics driver #* to the graphics subsystem #* #************************************************************************** ifeq ($(PLATFORM),beos) # directory of the BeOS graphics driver # GR_BEOS := $(GRAPH)/beos # add the BeOS driver object file to the graphics library `graph.a' # GRAPH_OBJS += $(OBJ_DIR_2)/grbeos.$(O) DEVICES += BEOS DEVICE_INCLUDES += $(GR_BEOS) # the rule used to compile the graphics driver # $(OBJ_DIR_2)/grbeos.$(O): $(GR_BEOS)/grbeos.cpp $(GR_BEOS)/grbeos.h \ $(GRAPH_H) ifneq ($(LIBTOOL),) $(LIBTOOL) --mode=compile $(CC) -static $(CFLAGS) \ $(GRAPH_INCLUDES:%=$I%) \ $I$(subst /,$(COMPILER_SEP),$(GR_BEOS)) \ $(X11_INCLUDE:%=$I%) \ $T$(subst /,$(COMPILER_SEP),$@ $<) else $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) \ $I$(subst /,$(COMPILER_SEP),$(GR_BEOS)) \ $(X11_INCLUDE:%=$I%) \ $T$(subst /,$(COMPILER_SEP),$@ $<) endif # Now update GRAPH_LINK according to the compiler used on BeOS GRAPH_LINK += -lbe -lstdc++.r4 endif # EOF ft2demos-2.10.1/graph/batch/0000755000175000001440000000000013506426605015350 5ustar00wlusers00000000000000ft2demos-2.10.1/graph/batch/grbatch.h0000644000175000001440000000056713501434334017134 0ustar00wlusers00000000000000#ifndef GRBATCH_H_ #define GRBATCH_H_ #include "grobjs.h" extern grDevice gr_batch_device; #ifdef GR_INIT_BUILD static grDeviceChain gr_batch_device_chain = { "batch", &gr_batch_device, GR_INIT_DEVICE_CHAIN }; #undef GR_INIT_DEVICE_CHAIN #define GR_INIT_DEVICE_CHAIN &gr_batch_device_chain #endif /* GR_INIT_BUILD */ #endif /* GRBATCH_H_ */ ft2demos-2.10.1/graph/batch/grbatch.c0000644000175000001440000000466313501434350017126 0ustar00wlusers00000000000000/******************************************************************* * * grbatch.c Batch processing driver. * * This driver maintains the image in memory without displaying it, * used by the graphics utility of the FreeType test suite. * * Copyright (C) 1999-2019 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used * modified and distributed under the terms of the FreeType project * license, LICENSE.TXT. By continuing to use, modify or distribute * this file you indicate that you have read the license and * understand and accept it fully. * ******************************************************************/ #include /* FT graphics subsystem */ #include "grobjs.h" #include "grdevice.h" static int gr_batch_device_init( void ) { return 0; /* success */ } static void gr_batch_device_done( void ) { /* nothing to do */ } static void gr_batch_surface_set_title( grSurface* surface, const char* title_string ) { (void)surface; /* unused */ printf( "%s\n", title_string ); /* prompt */ } static void gr_batch_surface_done( grSurface* surface ) { grDoneBitmap( &(surface->bitmap) ); } static int gr_batch_surface_listen_event( grSurface* surface, int event_mode, grEvent* event ) { (void)surface; /* unused */ (void)event_mode; event->type = gr_event_key; event->key = grKEY( getchar() ); return 1; } static int gr_batch_surface_init( grSurface* surface, grBitmap* bitmap ) { if ( grNewBitmap( bitmap->mode, bitmap->grays, bitmap->width, bitmap->rows, bitmap ) ) return 0; surface->bitmap = *bitmap; surface->refresh = 0; surface->owner = 0; surface->saturation = 0; surface->blit_mono = 0; surface->refresh_rect = (grRefreshRectFunc)NULL; /* nothing to refresh */ surface->set_title = gr_batch_surface_set_title; surface->listen_event = gr_batch_surface_listen_event; surface->done = gr_batch_surface_done; return 1; } grDevice gr_batch_device = { sizeof( grSurface ), "batch", gr_batch_device_init, gr_batch_device_done, gr_batch_surface_init, 0, 0 }; /* END */ ft2demos-2.10.1/graph/batch/rules.mk0000644000175000001440000000163613502347420017032 0ustar00wlusers00000000000000#************************************************************************** #* #* Batch processing driver makefile #* #************************************************************************** # directory of batch driver # GR_BATCH := $(GRAPH)/batch # add batch driver to lib objects # GRAPH_OBJS += $(OBJ_DIR_2)/grbatch.$O # add batch driver to list of devices # DEVICES += BATCH # batch driver compilation rule # $(OBJ_DIR_2)/grbatch.$O : $(GR_BATCH)/grbatch.c $(GR_BATCH)/grbatch.h \ $(GRAPH_H) ifneq ($(LIBTOOL),) $(LIBTOOL) --mode=compile $(CC) -static $(CFLAGS) \ $(GRAPH_INCLUDES:%=$I%) \ $I$(subst /,$(COMPILER_SEP),$(GR_BATCH)) \ $T$(subst /,$(COMPILER_SEP),$@ $<) else $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) \ $I$(subst /,$(COMPILER_SEP),$(GR_BATCH)) \ $T$(subst /,$(COMPILER_SEP),$@ $<) endif # EOF ft2demos-2.10.1/graph/grswizzle.h0000644000175000001440000000313113434207203016465 0ustar00wlusers00000000000000#ifndef GRSWIZZLE_H_ #define GRSWIZZLE_H_ void gr_swizzle_rect_rgb24( unsigned char* read_buff, int read_pitch, unsigned char* write_buff, int write_pitch, int buff_width, int buff_height, int x, int y, int width, int height ); void gr_swizzle_rect_rgb565( unsigned char* read_buff, int read_pitch, unsigned char* write_buff, int write_pitch, int buff_width, int buff_height, int x, int y, int width, int height ); void gr_swizzle_rect_xrgb32( unsigned char* read_buff, int read_pitch, unsigned char* write_buff, int write_pitch, int buff_width, int buff_height, int x, int y, int width, int height ); #endif /* GRSWIZZLE_H_ */ ft2demos-2.10.1/graph/migs.html0000644000175000001440000002733213434207203016112 0ustar00wlusers00000000000000
MiGS Overview
A Minimalist Graphics Subsystem


Introduction

This document details the design and implementation of MiGS, the minimalist graphics subsystem used by the FreeType 2 demonstration programs. Its purpose is mainly to help writers of new demo programs, as well as developers who would like port the subsystem to other platforms.

I - Design goals

MiGS is a tiny graphics subsystem used to demo text rendering through the FreeType library. It was mainly written to provide the abilities to :
    • draw a monochrome glyph bitmap to many kinds of target surfaces (i.e. really bitmaps/pixmaps)
    • draw an anti-aliased glyph bitmap, with any level of grays, to many kinds of target surfaces
    • display a simple window on many systems like X11, OS/2 and Windows
    • accept simple events (keypresses and mouse buttons) in this window.
    • to be portable and present a unified API on all running systems


    MiGS uses system-specific "drivers" in order to perform display and event handling. The blitting functions are not device-specific. MiGS can be built and/or used with no system-specific features, like for example, to generate simple GIF, PNG, TIFF, etc.. images without ever needing to display them.


II - Surfaces, bitmaps and windows

A surface in MiGS models a drawable region where glyph images can be rendered, a surface always contains a bitmap descriptor as well as a few other things that will be described later in this section.

Some surfaces can be displayed, they are then either called windowed surfaces or screen surfaces depending on the nature of the device used to display them. Each device is implemented by a very simple driver in the MiGS code. Here are a few example devices that are or could be written to display surfaces :

- an X11 device
- a Win 32 GDI device
- an OS/2 Presentation Manager device
- a fullscreen SVGALib device on Linux
- a GGI visual device
- an OS/2 "Dive" device, or the equivalent Win32 "DirectX" device

etc..

NOTE: For now, only the X11 device was written and tested.. More devices should come later

Before explaining how to create a surface, we need to explain how MiGS manages bitmaps and renders glyph images to them.

1. Bitmaps :

A bitmap in MiGS features the following things :
  • a width in pixels
  • a height in pixels
  • a pixel mode, which indicates how the pixels are stored in the surface's buffer
  • a pitch, whose absolute values is the number of bytes taken by each surface row
  • a number of valid gray levels (see below)
  • a buffer, holding the surface's pixels


MiGS uses the "Y downwards" convention, which means that increasing Y coordinates correspond to lower rows of the bitmap. Hence, the coordinate (0,0) always corresponds to the bitmap's top-left pixel.

The bitmap's rows can be stored either "downwards" or "upwards" in the pixel buffer.

In the first case (downwards), increasing memory addresses in the pixel buffer correspond to lower rows of the bitmap(e.g. PC video modes), and the pitch should be equal to the number of bytes taken by each row. The first pixel buffer byte corresponds to the upper row.

In the second case (upwards), increasing memory addresses in the pixel buffer correspond to upper rows of the bitmap and the pitch should be equal to the opposite of the number of bytes taken by each row. The first pixel buffer byte corresponds to the lower row.

In all cases, the pitch is the increment to be used to go from one bitmap row to the one below it.

The supported pixel modes are :

  • 1-bit monochrome bitmaps. With "0" as the background, and "1" as the foreground.
  • 4-bit color bitmaps, using an arbitrary palette.
  • 8-bit color bitmaps, using an arbitrary palette.
  • 8-bit gray bitmaps, using a given N number of gray levels in the range 0..N-1.
  • 15-bit color bitmaps, also known as RGB555
  • 16-bit color bitmaps, also known as RGB565
  • 24-bit color bitmaps, also known as RGB
  • 32-bit color bitmaps, also known as RGBA (though the A is ignored by MiGS)
The bitmap's number of gray levels is only relevant for 8-bit gray bitmaps, and indicates the range of gray levels that can be found in the bitmap. If a bitmap as N gray levels, it is said to be N-grayscales, and the pixels within it must all have values between 0, considered as the background color, and N-1, considered as the foreground color.

N-grayscale bitmaps are crucial for the rendering of anti-aliased text.
 

2. Glyph images :

The glyph images that can be drawn on bitmaps through MiGS are bitmaps themselves, though limited to the following pixel modes :

1-bit monochrome glyph bitmaps

These can be drawn on any kind of bitmap. Note that only the "lit" pixels (i.e. the bits set to 1) are effectively drawn to the target, as opaque blitting isn't supported (remember, it's a minimalist library !)


N-grayscales glyph images (with any value of N >= 2)

These can be drawn to all RGB bitmaps (15, 16, 24 & 32 bits/pixel), as well as any other M-grayscales bitmaps. In the latter case, the values of N and M need not be equal, as the library is able to perform automatic conversions on the fly.

For example, it is possible to render a 5-grayscales glyph image into a 128-grayscales bitmap. Moreover, it is also possible to render a 17-grayscales glyph image into a 5-grayscales bitmap, even if this will result in a loss of quality. This feature is crucial in order to experiment easily with other anti-aliasing algorithms for FreeType
 

Note that you can only draw monochrome bitmaps to the following pixel modes : monochrome, 4-bit color and 8-bit color.

3. Windows and Screens:

In order to debug FreeType, displaying a surface in a window or in full-screen mode, is required. MiGS thus makes a difference between simple surfaces, which only contain a bitmap, windowed surfaces, which are used to display their content in a window, and screen surfaces, which are used to display their content in a full-screen mode (SVGAlib, DirectX, GGI or whatever).

A few important things must be said about non-simple surfaces.
 

  • First, they might contain some system-specific data which is used to manage the display in a window or on the screen. This must be completely hidden to MiGS clients. Indeed, rendering to any kind of surface is achieved through exactly the same function calls.
  • Second, they may contain a bitmap whose pixel mode doesn't correspond to the screen's depth used to display it. For example, the surface might contain an 128-grayscale bitmap, while the screen is in RGB24 mode. Some conversion must be performed to display the surface. This can either happen in the system-specific graphics library (e.g. on OS/2, a single Presentation Manager call is used to blit a N-grayscale image to any kind of window) or in the system-specific part of MiGS (e.g. the X11 MiGS driver must convert the surface's bitmap into the appropriate X11 image each time a repaint is requested). Again this must be completely hidden to MiGS clients
Surfaces have also a few fields that are only used when displaying them in Windows :

a title string

This is simply a text string that is displayed on the title bar of the surface's window. It can also appear at the top or bottom of full-screen surfaces if the MiGS driver supports it. The title string can be changed with a call to grSetTitle, and is ignored for simple surfaces.


a refresh flag

This boolean flag is only used for window surfaces, and some fullscreen ones (depending on the driver implementation). When set, it indicates that each glyph image blit must be displayed immediately. By default, this flag is set to False, which means that demo programs must call the grRefreshSurface(surface) function to display the whole contents of a surface one it has been updated.

The refresh flag can be set with grSetSurfaceRefresh(surface,flag). Note that a single surface rectangle can be forced to be displayed with a call to grRefreshRectangle(surface,x,y,w,h) at any time.

4. Devices :

As said before, each device is in charge of displaying a surface in a given window or screen. Each device is managed through a very simple driver, described to MiGS through a very simple "grDevice" structure.

A grDevice contains, among other things, pointers to the functions used to:

- refresh/display a given rectangle of the surface to the window/screen
- listen events (key presses and mouse) and send them back to client apps.
- for windowed devices, update the title bar.

As said before, this is a highly minimalist system..
 


III - Important implementation issues :

1. Display surface negotiation :

A display surface is created with the function grNewScreenSurface which takes parameters indicating which device should be used, the pixel dimensions of the requested surface, as well as its pixel mode.

Because of some device-specific limitations, the resulting surface's properties might not match exactly those requested for the call. Hence, a developer should always take care of reading a new display surface's bitmap descriptor in order to get its real dimensions, pixel mode and eventually number of grays.

The function grNewSurface will create a memory surface with the corresponding bitmap.
The function grNewBitmapSurface will create a surface from a pre-existing bitmap. This is useful to draw text on loaded images, for example.

Any surface (display or not) is destroyed with grDoneSurface.

2. Supporting 8-bit grayscale mode :

It is important, for the debugging of FreeType anti-aliased renderer(s), that _all_ devices should support the 8-bit gray mode. The number of gray levels can be fixed or negotiated as required by implementation-specific issues.

As most existing devices do not provide direct support for such a mode, each 8-bit surface must thus contain :

- an internal N-grayscale bitmap, used as the target of all glyph drawings
- its own device-specific "image", which matches the display depth.

Each time the device's "refresh_rect" function is called, it should then :
- convert the grayscales within the bitmap's rectangle into the image's buffer and format.
- display the corresponding image rectangle.

This scheme is used, for example, by the X11 device.

ft2demos-2.10.1/graph/grevents.h0000644000175000001440000000645113434207203016272 0ustar00wlusers00000000000000#ifndef GREVENTS_H_ #define GREVENTS_H_ #define gr_event_none 0 #define gr_event_wait 1 #define gr_event_poll 2 #define gr_event_flush 3 #define gr_mouse_down 0x04 #define gr_mouse_move 0x08 #define gr_mouse_up 0x10 #define gr_mouse_drag 0x20 #define gr_key_down 0x40 #define gr_key_up 0x80 #define gr_event_mouse 0x3C #define gr_event_key 0xC0 #define gr_event_type ( gr_event_mouse | gr_event_key ) typedef enum grKey_ { grKeyNone = 0, grKeySpace = ' ', grKey0 = '0', grKey1 = '1', grKey2 = '2', grKey3 = '3', grKey4 = '4', grKey5 = '5', grKey6 = '6', grKey7 = '7', grKey8 = '8', grKey9 = '9', grKeyPlus = '+', grKeyLess = '-', grKeyEqual = '=', grKeyMult = '*', grKeyDollar = '$', grKeySmaller = '<', grKeyGreater = '>', grKeyQuestion = '?', grKeyComma = ',', grKeyDot = '.', grKeySemiColon = ';', grKeyColon = ':', grKeyDiv = '/', grKeyExclam = '!', grKeyPercent = '%', grKeyLeftParen = '(', grKeyRightParen = ')', grKeyAt = '@', grKey_A = 'A', grKey_B = 'B', grKey_C = 'C', grKey_D = 'D', grKey_E = 'E', grKey_F = 'F', grKey_G = 'G', grKey_H = 'H', grKey_I = 'I', grKey_J = 'J', grKey_K = 'K', grKey_L = 'L', grKey_M = 'M', grKey_N = 'N', grKey_O = 'O', grKey_P = 'P', grKey_Q = 'Q', grKey_R = 'R', grKey_S = 'S', grKey_T = 'T', grKey_U = 'U', grKey_V = 'V', grKey_W = 'W', grKey_X = 'X', grKey_Y = 'Y', grKey_Z = 'Z', grKeyLeftB = '[', grKeyBackSlash = '\\', grKeyRightB = ']', grKeyCircumflex = '^', grKeyUnder = '_', grKeyBackTick = '`', grKey_a = 'a', grKey_b = 'b', grKey_c = 'c', grKey_d = 'd', grKey_e = 'e', grKey_f = 'f', grKey_g = 'g', grKey_h = 'h', grKey_i = 'i', grKey_j = 'j', grKey_k = 'k', grKey_l = 'l', grKey_m = 'm', grKey_n = 'n', grKey_o = 'o', grKey_p = 'p', grKey_q = 'q', grKey_r = 'r', grKey_s = 's', grKey_t = 't', grKey_u = 'u', grKey_v = 'v', grKey_w = 'w', grKey_x = 'x', grKey_y = 'y', grKey_z = 'z', grKeyBackSpace = 0x100, grKeyTab, grKeyReturn, grKeyEsc, grKeyIns, grKeyDel, grKeyHome, grKeyEnd, grKeyPageUp, grKeyPageDown, grKeyF1, grKeyF2, grKeyF3, grKeyF4, grKeyF5, grKeyF6, grKeyF7, grKeyF8, grKeyF9, grKeyF10, grKeyF11, grKeyF12, grKeyLeft, grKeyRight, grKeyUp, grKeyDown, grKeyForceShort = 0x7FFF, /* this forces the grKey to be stored */ /* on at least one short */ grKeyMax } grKey; #define grKEY( c ) ( (grKey)( c ) ) /* masks - to be used as enums they would have to be included */ /* in the grKey enum */ #define grKeyAlt ( (grKey)0x8000 ) #define grKeyCtrl ( (grKey)0x4000 ) #define grKeyShift ( (grKey)0x2000 ) #define grKeyModifiers ( (grKey)0xE000 ) typedef struct grEvent_ { int type; grKey key; int x, y; } grEvent; #endif /* GREVENTS_H_ */ ft2demos-2.10.1/graph/grfont.c0000644000175000001440000003721013434207203015724 0ustar00wlusers00000000000000/* grfont.c */ #include "grfont.h" #include /* internal CP437 8x8 font characters */ const unsigned char font_8x8[2048] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E, 0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E, 0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x38, 0x7C, 0x38, 0xFE, 0xFE, 0x92, 0x10, 0x7C, 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x7C, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF, 0x0F, 0x07, 0x0F, 0x7D, 0xCC, 0xCC, 0xCC, 0x78, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x70, 0xF0, 0xE0, 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x67, 0xE6, 0xC0, 0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99, 0x80, 0xE0, 0xF8, 0xFE, 0xF8, 0xE0, 0x80, 0x00, 0x02, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x02, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, 0x7F, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x00, 0x3E, 0x63, 0x38, 0x6C, 0x6C, 0x38, 0x86, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x7E, 0x3C, 0x18, 0xFF, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00, 0x18, 0x7E, 0xC0, 0x7C, 0x06, 0xFC, 0x18, 0x00, 0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00, 0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, 0x7C, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0x7C, 0x00, 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xFC, 0x00, 0x78, 0xCC, 0x0C, 0x38, 0x60, 0xCC, 0xFC, 0x00, 0x78, 0xCC, 0x0C, 0x38, 0x0C, 0xCC, 0x78, 0x00, 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x1E, 0x00, 0xFC, 0xC0, 0xF8, 0x0C, 0x0C, 0xCC, 0x78, 0x00, 0x38, 0x60, 0xC0, 0xF8, 0xCC, 0xCC, 0x78, 0x00, 0xFC, 0xCC, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0xCC, 0xCC, 0x78, 0x00, 0x78, 0xCC, 0xCC, 0x7C, 0x0C, 0x18, 0x70, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, 0x18, 0x30, 0x60, 0xC0, 0x60, 0x30, 0x18, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x3C, 0x66, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00, 0x7C, 0xC6, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00, 0x30, 0x78, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0x00, 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x3C, 0x66, 0xC0, 0xC0, 0xC0, 0x66, 0x3C, 0x00, 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00, 0xFE, 0x62, 0x68, 0x78, 0x68, 0x62, 0xFE, 0x00, 0xFE, 0x62, 0x68, 0x78, 0x68, 0x60, 0xF0, 0x00, 0x3C, 0x66, 0xC0, 0xC0, 0xCE, 0x66, 0x3A, 0x00, 0xCC, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0xCC, 0x00, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0x00, 0xE6, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00, 0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0xFC, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xD6, 0x7C, 0x0E, 0x00, 0xFC, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0xE6, 0x00, 0x7C, 0xC6, 0xE0, 0x78, 0x0E, 0xC6, 0x7C, 0x00, 0xFC, 0xB4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xFC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00, 0xC6, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0xC6, 0x00, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x30, 0x78, 0x00, 0xFE, 0xC6, 0x8C, 0x18, 0x32, 0x66, 0xFE, 0x00, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, 0xE0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xDC, 0x00, 0x00, 0x00, 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x00, 0x1C, 0x0C, 0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, 0x38, 0x6C, 0x64, 0xF0, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8, 0xE0, 0x60, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00, 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, 0x0C, 0x00, 0x1C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0xE0, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0xE6, 0x00, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0xCC, 0xFE, 0xFE, 0xD6, 0xD6, 0x00, 0x00, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, 0x78, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x7C, 0x60, 0xF0, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0x1E, 0x00, 0x00, 0xDC, 0x76, 0x62, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x7C, 0xC0, 0x70, 0x1C, 0xF8, 0x00, 0x10, 0x30, 0xFC, 0x30, 0x30, 0x34, 0x18, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8, 0x00, 0x00, 0xFC, 0x98, 0x30, 0x64, 0xFC, 0x00, 0x1C, 0x30, 0x30, 0xE0, 0x30, 0x30, 0x1C, 0x00, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0xE0, 0x30, 0x30, 0x1C, 0x30, 0x30, 0xE0, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00, 0x7C, 0xC6, 0xC0, 0xC6, 0x7C, 0x0C, 0x06, 0x7C, 0x00, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x1C, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, 0x7E, 0x81, 0x3C, 0x06, 0x3E, 0x66, 0x3B, 0x00, 0xCC, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, 0xE0, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, 0x30, 0x30, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0x78, 0x0C, 0x38, 0x7E, 0x81, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00, 0xCC, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, 0xE0, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, 0xCC, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, 0x7C, 0x82, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00, 0xE0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, 0xC6, 0x10, 0x7C, 0xC6, 0xFE, 0xC6, 0xC6, 0x00, 0x30, 0x30, 0x00, 0x78, 0xCC, 0xFC, 0xCC, 0x00, 0x1C, 0x00, 0xFC, 0x60, 0x78, 0x60, 0xFC, 0x00, 0x00, 0x00, 0x7F, 0x0C, 0x7F, 0xCC, 0x7F, 0x00, 0x3E, 0x6C, 0xCC, 0xFE, 0xCC, 0xCC, 0xCE, 0x00, 0x78, 0x84, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0xCC, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0xE0, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, 0x78, 0x84, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0xE0, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0xCC, 0x00, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8, 0xC3, 0x18, 0x3C, 0x66, 0x66, 0x3C, 0x18, 0x00, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x18, 0x18, 0x7E, 0xC0, 0xC0, 0x7E, 0x18, 0x18, 0x38, 0x6C, 0x64, 0xF0, 0x60, 0xE6, 0xFC, 0x00, 0xCC, 0xCC, 0x78, 0x30, 0xFC, 0x30, 0xFC, 0x30, 0xF8, 0xCC, 0xCC, 0xFA, 0xC6, 0xCF, 0xC6, 0xC3, 0x0E, 0x1B, 0x18, 0x3C, 0x18, 0x18, 0xD8, 0x70, 0x1C, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x1C, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x1C, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0xF8, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0x00, 0xFC, 0x00, 0xCC, 0xEC, 0xFC, 0xDC, 0xCC, 0x00, 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00, 0x00, 0x18, 0x00, 0x18, 0x18, 0x30, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0C, 0x0C, 0x00, 0x00, 0xC6, 0xCC, 0xD8, 0x36, 0x6B, 0xC2, 0x84, 0x0F, 0xC3, 0xC6, 0xCC, 0xDB, 0x37, 0x6D, 0xCF, 0x03, 0x18, 0x00, 0x18, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00, 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0xDB, 0xF6, 0xDB, 0x6F, 0xDB, 0x7E, 0xD7, 0xED, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36, 0x00, 0x00, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x36, 0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0xFE, 0x06, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xFE, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0xFE, 0x00, 0x00, 0x00, 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x36, 0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x18, 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3F, 0x00, 0x00, 0x00, 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, 0x36, 0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0xC8, 0xDC, 0x76, 0x00, 0x00, 0x78, 0xCC, 0xF8, 0xCC, 0xF8, 0xC0, 0xC0, 0x00, 0xFC, 0xCC, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0xFE, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0xFC, 0xCC, 0x60, 0x30, 0x60, 0xCC, 0xFC, 0x00, 0x00, 0x00, 0x7E, 0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0xC0, 0x00, 0x76, 0xDC, 0x18, 0x18, 0x18, 0x18, 0x00, 0xFC, 0x30, 0x78, 0xCC, 0xCC, 0x78, 0x30, 0xFC, 0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0x6C, 0x38, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x6C, 0xEE, 0x00, 0x1C, 0x30, 0x18, 0x7C, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0x7E, 0x00, 0x00, 0x06, 0x0C, 0x7E, 0xDB, 0xDB, 0x7E, 0x60, 0xC0, 0x38, 0x60, 0xC0, 0xF8, 0xC0, 0x60, 0x38, 0x00, 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x7E, 0x00, 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xFC, 0x00, 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xFC, 0x00, 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, 0x70, 0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00, 0x00, 0x76, 0xDC, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0F, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C, 0x58, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x70, 0x98, 0x30, 0x60, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static grBitmap gr_charcell = { 8, /* rows */ 8, /* width */ 1, /* pitch */ gr_pixel_mode_mono, /* mode */ 0, /* grays */ 0 /* buffer */ }; void grWriteCellChar( grBitmap* target, int x, int y, int charcode, grColor color ) { if ( charcode < 0 || charcode > 255 ) return; gr_charcell.buffer = (unsigned char*)font_8x8 + 8 * charcode; grBlitGlyphToBitmap( target, &gr_charcell, x, y, color ); } void grWriteCellString( grBitmap* target, int x, int y, const char* string, grColor color ) { while ( *string ) { gr_charcell.buffer = (unsigned char *)font_8x8 + 8 * (int)(unsigned char) * string++; grBlitGlyphToBitmap( target, &gr_charcell, x, y, color ); x += 8; } } static int gr_cursor_x = 0; static int gr_cursor_y = 0; static int gr_line_height = 8; static grBitmap* gr_text_bitmap = 0; static grColor gr_color = { 0 }; static int gr_margin_right = 0; static int gr_margin_top = 0; void grGotobitmap( grBitmap* bitmap ) { gr_text_bitmap = bitmap; gr_color = grFindColor( bitmap, 100, 100, 100, 255 ); } void grSetMargin( int right, int top ) { gr_margin_top = top << 3; gr_margin_right = right << 3; } void grSetPixelMargin( int right, int top ) { gr_margin_top = top; gr_margin_right = right; } void grSetLineHeight( int height ) { gr_line_height = height; } void grGotoxy( int x, int y ) { gr_cursor_x = x; gr_cursor_y = y; } void grWrite( const char* string ) { if ( string ) { grWriteCellString( gr_text_bitmap, gr_margin_right + ( gr_cursor_x << 3 ), gr_margin_top + gr_cursor_y * gr_line_height, string, gr_color ); gr_cursor_x += strlen( string ); } } void grLn( void ) { gr_cursor_y++; gr_cursor_x = 0; } void grWriteln( const char* string ) { grWrite( string ); grLn(); } /* eof */ ft2demos-2.10.1/graph/grblit.h0000644000175000001440000000207113434207203015712 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 1996-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* blitter.h: Support for blitting of bitmaps with various depth. */ /* */ /****************************************************************************/ #ifndef GRBLIT_H_ #define GRBLIT_H_ #include "grobjs.h" int grBlitMono( grBitmap* target, grBitmap* source, int x_offset, int y_offset, grColor color ); #endif /* GRBLIT_H_ */ /* End */ ft2demos-2.10.1/graph/gblvbgr.h0000644000175000001440000000352513434207203016061 0ustar00wlusers00000000000000 GBLENDER_CHANNEL_VARS; int h = blit->height; const unsigned char* src_line = blit->src_line; int src_pitch = blit->src_pitch; unsigned char* dst_line = blit->dst_line; gblender_use_channels( blender, 1 ); GBLENDER_CHANNEL_VARS_SET(blender,r,g,b); do { const unsigned char* src = src_line + blit->src_x; unsigned char* dst = dst_line + blit->dst_x*GDST_INCR; int w = blit->width; do { unsigned int ab = GBLENDER_SHADE_INDEX(src[0]); unsigned int ag = GBLENDER_SHADE_INDEX(src[src_pitch]); unsigned int ar = GBLENDER_SHADE_INDEX(src[src_pitch << 1]); GBlenderPixel aa = ((GBlenderPixel)ar << 16) | (ag << 8) | ab; if ( aa == 0 ) { /* nothing */ } else if ( aa == (((GBLENDER_SHADE_COUNT-1) << 16) | ((GBLENDER_SHADE_COUNT-1) << 8) | (GBLENDER_SHADE_COUNT-1) ) ) { GDST_COPY(dst); } else { GBlenderPixel back; int pix_r, pix_g, pix_b; GDST_READ(dst,back); { unsigned int back_r = (back >> 16) & 255; GBLENDER_LOOKUP_R( blender, back_r ); pix_r = _grcells[ar]; } { unsigned int back_g = (back >> 8) & 255; GBLENDER_LOOKUP_G( blender, back_g ); pix_g = _ggcells[ag]; } { unsigned int back_b = (back) & 255; GBLENDER_LOOKUP_B( blender, back_b ); pix_b = _gbcells[ab]; } GDST_STOREC(dst,pix_r,pix_g,pix_b); } src += 1; dst += GDST_INCR; } while (--w > 0); src_line += blit->src_pitch*3; dst_line += blit->dst_pitch; } while (--h > 0); GBLENDER_CHANNEL_CLOSE(blender); ft2demos-2.10.1/graph/Jamfile0000644000175000001440000000172613434207203015556 0ustar00wlusers00000000000000# FreeType2 demo graph Jamfile (c) 2001 David Turner # SubDir FT2DEMO_TOP graph ; GRAPH_INCLUDE = $(FT2DEMO_GRAPH) ; GRAPH_LIB = $(LIBPREFIX)graph$(SUFLIB) ; graph_sources = grblit grobjs grfont grdevice grinit gblender gblblit grfill grswizzle ; if $(OS) = BEOS { DEVICE_DEFINE = -DDEVICE_BEOS ; } else if $(UNIX) { DEVICE_DEFINE = -DDEVICE_X11 ; } else if $(NT) { DEVICE_DEFINE = -DDEVICE_WIN32 ; } else if $(OS2) { DEVICE_DEFINE = -DDEVICE_OS2 ; } CCFLAGS on grinit$(SUFOBJ) = $(CCFLAGS) $(DEVICE_DEFINE) ; Library $(GRAPH_LIB) : $(graph_sources).c ; if $(OS) = BEOS { SubInclude FT2DEMO_TOP graph beos ; } else if $(UNIX) { SubInclude FT2DEMO_TOP graph x11 ; } else if $(NT) { SubInclude FT2DEMO_TOP graph win32 ; } else if $(OS2) { SubInclude FT2DEMO_TOP graph os2 ; } # end of graph Jamfile ft2demos-2.10.1/graph/gblender.h0000644000175000001440000002053613434207665016233 0ustar00wlusers00000000000000/**************************************************************************** * * Gamma-correct alpha blending of text * * Copyright (C) 2004-2019 by * David Turner * */ #ifndef GBLENDER_H_ #define GBLENDER_H_ #ifndef GBLENDER_API #define GBLENDER_API(x) extern x #endif #ifndef GBLENDER_APIDEF #define GBLENDER_APIDEF(x) x #endif #define GBLENDER_SHADE_BITS 4 /* must be <= 7 !! */ #define GBLENDER_SHADE_COUNT ( 1 << GBLENDER_SHADE_BITS ) #define GBLENDER_SHADE_INDEX(n) (((n) * (GBLENDER_SHADE_COUNT-1) + 128) >> 8) #define GBLENDER_KEY_COUNT 256 /* must be a power of 2 */ #define GBLENDER_GAMMA_SHIFT 2 #define xGBLENDER_STORE_BYTES /* define this to store (R,G,B) values on 3 * bytes, instead of a single 32-bit integer. * surprisingly, this can speed up * the blender on certain machines. * Go figure what's really happening though :-) */ #define xGBLENDER_STATS /* define this to collect statistics in the * blender */ typedef unsigned int GBlenderPixel; /* needs 32-bits here !! */ #ifdef GBLENDER_STORE_BYTES typedef unsigned char GBlenderCell; # define GBLENDER_CELL_SIZE 3 #else typedef GBlenderPixel GBlenderCell; # define GBLENDER_CELL_SIZE 1 #endif typedef struct { GBlenderPixel background; GBlenderPixel foreground; GBlenderCell* cells; } GBlenderKeyRec, *GBlenderKey; typedef struct { unsigned short backfore; /* (fore << 8) | back */ signed short index; /* offset in (unsigned char*)cells */ } GBlenderChanKeyRec, *GBlenderChanKey; typedef struct GBlenderRec_ { GBlenderKeyRec keys [ GBLENDER_KEY_COUNT ]; GBlenderCell cells[ GBLENDER_KEY_COUNT*GBLENDER_SHADE_COUNT*GBLENDER_CELL_SIZE ]; /* a small cache for normal modes */ GBlenderPixel cache_back; GBlenderPixel cache_fore; GBlenderCell* cache_cells; /* a small cache for RGB channels modes */ unsigned int cache_r_back; unsigned int cache_r_fore; unsigned char* cache_r_cells; unsigned int cache_g_back; unsigned int cache_g_fore; unsigned char* cache_g_cells; unsigned int cache_b_back; unsigned int cache_b_fore; unsigned char* cache_b_cells; /* are we in color or channel mode ? */ int channels; /* the gamma table */ unsigned short gamma_ramp[256]; /* voltage to linear */ unsigned char gamma_ramp_inv[256 << GBLENDER_GAMMA_SHIFT]; /* linear to voltage */ #ifdef GBLENDER_STATS long stat_hits; /* number of direct hits */ long stat_lookups; /* number of table lookups */ long stat_keys; /* number of table key recomputation */ long stat_clears; /* number of table clears */ #endif } GBlenderRec, *GBlender; /* initialize with a given gamma */ GBLENDER_API( void ) gblender_init( GBlender blender, double gamma ); /* clear blender, and reset stats */ GBLENDER_API( void ) gblender_reset( GBlender blender ); GBLENDER_API( void ) gblender_use_channels( GBlender blender, int channels ); /* lookup a cell range for a given (background,foreground) pair */ GBLENDER_API( GBlenderCell* ) gblender_lookup( GBlender blender, GBlenderPixel background, GBlenderPixel foreground ); GBLENDER_API( unsigned char* ) gblender_lookup_channel( GBlender blender, unsigned int background, unsigned int foreground ); #ifdef GBLENDER_STATS GBLENDER_API( void ) gblender_dump_stats( GBlender blender ); #else # define gblender_dump_stats(b) do { } while (0); #endif #ifdef GBLENDER_STATS #define GBLENDER_STAT_HIT(gb) (gb)->stat_hits++ #else #define GBLENDER_STAT_HIT(gb) /* nothing */ #endif /* no final `;'! */ #define GBLENDER_VARS \ GBlenderPixel _gback; \ GBlenderCell* _gcells; \ GBlenderPixel _gfore #define GBLENDER_VARS_SET(_gb,_fore) \ _gback = (_gb)->cache_back; \ _gcells = ( (_fore) == (_gb)->cache_fore ? (_gb)->cache_cells : gblender_lookup( (_gb), _gback, _fore ) ); \ _gfore = (_fore) #define GBLENDER_LOOKUP(gb,back) \ GBLENDER_STAT_HIT(gb); \ if ( _gback != (GBlenderPixel)(back) ) \ { \ _gback = (GBlenderPixel)(back); \ _gcells = gblender_lookup( (gb), _gback, _gfore ); \ } #define GBLENDER_CLOSE(_gb) \ (_gb)->cache_back = _gback; \ (_gb)->cache_fore = _gfore; \ (_gb)->cache_cells = _gcells; /* no final `;'! */ #define GBLENDER_CHANNEL_VARS \ unsigned int _grback; \ unsigned char* _grcells; \ unsigned int _grfore; \ unsigned int _ggback; \ unsigned char* _ggcells; \ unsigned int _ggfore; \ unsigned int _gbback; \ unsigned char* _gbcells; \ unsigned int _gbfore #define GBLENDER_CHANNEL_VARS_SET(_gb,_rfore,_gfore,_bfore) \ _grback = (_gb)->cache_r_back; \ _grcells = ( (_rfore) == (_gb)->cache_r_fore ? (_gb)->cache_r_cells : gblender_lookup_channel( (_gb), _grback, _rfore )); \ _grfore = (_rfore); \ _ggback = (_gb)->cache_g_back; \ _ggcells = ( (_gfore) == (_gb)->cache_g_fore ? (_gb)->cache_g_cells : gblender_lookup_channel( (_gb), _ggback, _gfore )); \ _ggfore = (_gfore); \ _gbback = (_gb)->cache_b_back; \ _gbcells = ( (_bfore) == (_gb)->cache_b_fore ? (_gb)->cache_b_cells : gblender_lookup_channel( (_gb), _gbback, _bfore )); \ _gbfore = (_bfore); #define GBLENDER_CHANNEL_CLOSE(_gb) \ (_gb)->cache_r_back = _grback; \ (_gb)->cache_r_fore = _grfore; \ (_gb)->cache_r_cells = _grcells; \ (_gb)->cache_g_back = _ggback; \ (_gb)->cache_g_fore = _ggfore; \ (_gb)->cache_g_cells = _ggcells; \ (_gb)->cache_b_back = _gbback; \ (_gb)->cache_b_fore = _gbfore; \ (_gb)->cache_b_cells = _gbcells; #define GBLENDER_LOOKUP_R(gb,back) \ GBLENDER_STAT_HIT(gb); \ if ( _grback != (back) ) \ { \ _grback = (GBlenderPixel)(back); \ _grcells = gblender_lookup_channel( (gb), _grback, _grfore ); \ } #define GBLENDER_LOOKUP_G(gb,back) \ GBLENDER_STAT_HIT(gb); \ if ( _ggback != (back) ) \ { \ _ggback = (GBlenderPixel)(back); \ _ggcells = gblender_lookup_channel( (gb), _ggback, _ggfore ); \ } #define GBLENDER_LOOKUP_B(gb,back) \ GBLENDER_STAT_HIT(gb); \ if ( _gbback != (back) ) \ { \ _gbback = (GBlenderPixel)(back); \ _gbcells = gblender_lookup_channel( (gb), _gbback, _gbfore ); \ } #endif /* GBLENDER_H_ */ ft2demos-2.10.1/graph/grfont.h0000644000175000001440000000103013434207203015720 0ustar00wlusers00000000000000/* grfont.h */ #ifndef GRFONT_H_ #define GRFONT_H_ #include "graph.h" extern const unsigned char font_8x8[]; void grGotobitmap( grBitmap* bitmap ); void grSetMargin( int right, int top ); void grSetPixelMargin( int right, int top ); void grSetLineHeight( int height ); void grGotoxy ( int x, int y ); void grWrite( const char* string ); void grWriteln( const char* string ); void grLn( void ); #endif /* GRFONT_H_ */ /* eof */ ft2demos-2.10.1/graph/gblcolor.h0000644000175000001440000000214713434207203016236 0ustar00wlusers00000000000000 GBLENDER_VARS; int h = blit->height; const unsigned char* src_line = blit->src_line; unsigned char* dst_line = blit->dst_line; gblender_use_channels( blender, 0 ); GBLENDER_VARS_SET(blender,color); /* make compiler happy */ (void)(r); (void)(g); (void)(b); do { const unsigned char* src = src_line + (blit->src_x); unsigned char* dst = dst_line + blit->dst_x*GDST_INCR; int w = blit->width; do { int a = GBLENDER_SHADE_INDEX(src[0]); if ( a == 0 ) { /* nothing */ } else if ( a == GBLENDER_SHADE_COUNT-1 ) { GDST_COPY(dst); } else { GBlenderPixel back; GDST_READ(dst,back); GBLENDER_LOOKUP( blender, back ); #ifdef GBLENDER_STORE_BYTES GDST_STOREB(dst,_gcells,a); #else GDST_STOREP(dst,_gcells,a); #endif } src += 1; dst += GDST_INCR; } while (--w > 0); src_line += blit->src_pitch; dst_line += blit->dst_pitch; } while (--h > 0); GBLENDER_CLOSE(blender); ft2demos-2.10.1/graph/xtest.c0000644000175000001440000000512213434207203015571 0ustar00wlusers00000000000000#include "graph.h" #include "grfont.h" /* dispara^itra bientot */ #include static void Panic( const char* message ) { fprintf( stderr, "PANIC: %s\n", message ); exit(1); } typedef struct grKeyName { grKey key; const char* name; } grKeyName; static const grKeyName key_names[] = { { grKeyF1, "F1" }, { grKeyF2, "F2" }, { grKeyF3, "F3" }, { grKeyF4, "F4" }, { grKeyF5, "F5" }, { grKeyF6, "F6" }, { grKeyF7, "F7" }, { grKeyF8, "F8" }, { grKeyF9, "F9" }, { grKeyF10, "F10" }, { grKeyF11, "F11" }, { grKeyF12, "F12" }, { grKeyEsc, "Esc" }, { grKeyHome, "Home" }, { grKeyEnd, "End" }, { grKeyPageUp, "Page_Up" }, { grKeyPageDown, "Page_Down" }, { grKeyLeft, "Left" }, { grKeyRight, "Right" }, { grKeyUp, "Up" }, { grKeyDown, "Down" }, { grKeyBackSpace, "BackSpace" }, { grKeyReturn, "Return" } }; int main( void ) { grSurface* surface; int n; grInit(); surface = grNewScreenSurface( 0, gr_pixel_mode_gray, 320, 400, 128 ); if (!surface) Panic("Could not create window\n" ); else { grColor color; grEvent event; const char* string; int x; grSetSurfaceRefresh( surface, 1 ); grSetTitle(surface,"X11 driver demonstration" ); for ( x = -10; x < 10; x++ ) { for ( n = 0; n < 128; n++ ) { color.value = (n*3) & 127; grWriteCellChar( surface, x + ((n % 60) << 3), 80 + (x+10)*8*3 + ((n/60) << 3), n, color ); } } color.value = 64; grWriteCellString( surface, 0, 0, "just an example", color ); do { grListenSurface( surface, 0, &event); /* return if ESC was pressed */ if ( event.key == grKeyEsc ) return 0; /* otherwise, display key string */ color.value = (color.value + 8) & 127; { int count = sizeof(key_names)/sizeof(key_names[0]); grKeyName* name = (grKeyName*)key_names; grKeyName* limit = name + count; const char* kname = 0; char kname_temp[16]; while (name < limit) { if ( name->key == event.key ) { kname = (const char*)name->name; break; } name++; } if (!kname) { sprintf( kname_temp, "char '%c'", (char)event.key ); kname = kname_temp; } grWriteCellString( surface, 30, 30, kname, color ); grRefreshSurface(surface); } } while (1); } return 0; } ft2demos-2.10.1/graph/grobjs.c0000644000175000001440000001220013434207203015703 0ustar00wlusers00000000000000#include "grobjs.h" #include #include int grError = 0; /* values must be in 0..255 range */ grColor grFindColor( grBitmap* target, int red, int green, int blue, int alpha ) { grColor color; color.value = 0; switch (target->mode) { case gr_pixel_mode_mono: if ( (red|green|blue) ) color.value = 1; break; case gr_pixel_mode_gray: color.value = (3*red + 6*green + blue)/10; break; case gr_pixel_mode_rgb555: color.value = ((red & 0xF8) << 7) | ((green & 0xF8) << 2) | ((blue & 0xF8) >> 3); break; case gr_pixel_mode_rgb565: color.value = ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | ((blue & 0xF8) >> 3); break; case gr_pixel_mode_rgb24: color.chroma[0] = (unsigned char)red; color.chroma[1] = (unsigned char)green; color.chroma[2] = (unsigned char)blue; break; case gr_pixel_mode_rgb32: color.chroma[0] = (unsigned char)red; color.chroma[1] = (unsigned char)green; color.chroma[2] = (unsigned char)blue; color.chroma[3] = (unsigned char)alpha; break; default: ; } return color; } /******************************************************************** * * * grAlloc * * * Simple memory allocation. The returned block is always zero-ed * * * size :: size in bytes of the requested block * * * the memory block address. 0 in case of error * ********************************************************************/ unsigned char* grAlloc( unsigned long size ) { unsigned char* p; p = (unsigned char*)malloc(size); if (!p && size > 0) { grError = gr_err_memory; } if (p) memset( p, 0, size ); return p; } /******************************************************************** * * * grFree * * * Simple memory release * * * block :: target block * ********************************************************************/ void grFree( const void* block ) { if (block) free( (void *)block ); } static int check_mode( grPixelMode pixel_mode, int num_grays ) { if ( pixel_mode <= gr_pixel_mode_none || pixel_mode >= gr_pixel_mode_max ) goto Fail; if ( pixel_mode != gr_pixel_mode_gray || ( num_grays >= 2 && num_grays <= 256 ) ) return 0; Fail: grError = gr_err_bad_argument; return grError; } /********************************************************************** * * * grNewBitmap * * * creates a new bitmap * * * pixel_mode :: the target surface's pixel_mode * num_grays :: number of grays levels for PAL8 pixel mode * width :: width in pixels * height :: height in pixels * * * bit :: descriptor of the new bitmap * * * Error code. 0 means success. * **********************************************************************/ extern int grNewBitmap( grPixelMode pixel_mode, int num_grays, int width, int height, grBitmap *bit ) { int pitch; /* check mode */ if (check_mode(pixel_mode,num_grays)) goto Fail; /* check dimensions */ if (width < 0 || height < 0) { grError = gr_err_bad_argument; goto Fail; } bit->width = width; bit->rows = height; bit->mode = pixel_mode; bit->grays = num_grays; pitch = width; switch (pixel_mode) { case gr_pixel_mode_mono : pitch = (width+7) >> 3; break; case gr_pixel_mode_pal4 : pitch = (width+3) >> 2; break; case gr_pixel_mode_pal8 : case gr_pixel_mode_gray : pitch = width; break; case gr_pixel_mode_rgb555: case gr_pixel_mode_rgb565: pitch = width*2; break; case gr_pixel_mode_rgb24 : pitch = width*3; break; case gr_pixel_mode_rgb32 : pitch = width*4; break; default: grError = gr_err_bad_target_depth; return 0; } bit->pitch = pitch; bit->buffer = grAlloc( (unsigned long)( bit->pitch * bit->rows ) ); if (!bit->buffer) goto Fail; return 0; Fail: return grError; } /********************************************************************** * * * grDoneBitmap * * * destroys a bitmap * * * bitmap :: handle to bitmap descriptor * * * This function does NOT release the bitmap descriptor, only * the pixel buffer. * **********************************************************************/ extern void grDoneBitmap( grBitmap* bit ) { grFree( bit->buffer ); bit->buffer = 0; } ft2demos-2.10.1/graph/gblhrgb.h0000644000175000001440000000336513434207203016045 0ustar00wlusers00000000000000 GBLENDER_CHANNEL_VARS; int h = blit->height; const unsigned char* src_line = blit->src_line; unsigned char* dst_line = blit->dst_line; gblender_use_channels( blender, 1 ); GBLENDER_CHANNEL_VARS_SET(blender,r,g,b); do { const unsigned char* src = src_line + blit->src_x*3; unsigned char* dst = dst_line + blit->dst_x*GDST_INCR; int w = blit->width; do { unsigned int ar = GBLENDER_SHADE_INDEX(src[0]); unsigned int ag = GBLENDER_SHADE_INDEX(src[1]); unsigned int ab = GBLENDER_SHADE_INDEX(src[2]); unsigned int aa = (ar << 16) | (ag << 8) | ab; if ( aa == 0 ) { /* nothing */ } else if ( aa == (((GBLENDER_SHADE_COUNT-1) << 16) | ((GBLENDER_SHADE_COUNT-1) << 8) | (GBLENDER_SHADE_COUNT-1) ) ) { GDST_COPY(dst); } else { GBlenderPixel back; int pix_r, pix_g, pix_b; GDST_READ(dst,back); { unsigned int back_r = (back >> 16) & 255; GBLENDER_LOOKUP_R( blender, back_r ); pix_r = _grcells[ar]; } { unsigned int back_g = (back >> 8) & 255; GBLENDER_LOOKUP_G( blender, back_g ); pix_g = _ggcells[ag]; } { unsigned int back_b = (back) & 255; GBLENDER_LOOKUP_B( blender, back_b ); pix_b = _gbcells[ab]; } GDST_STOREC(dst,pix_r,pix_g,pix_b); } src += 3; dst += GDST_INCR; } while (--w > 0); src_line += blit->src_pitch; dst_line += blit->dst_pitch; } while (--h > 0); GBLENDER_CHANNEL_CLOSE(blender); ft2demos-2.10.1/graph/gblhbgr.h0000644000175000001440000000336513434207203016045 0ustar00wlusers00000000000000 GBLENDER_CHANNEL_VARS; int h = blit->height; const unsigned char* src_line = blit->src_line; unsigned char* dst_line = blit->dst_line; gblender_use_channels( blender, 1 ); GBLENDER_CHANNEL_VARS_SET(blender,r,g,b); do { const unsigned char* src = src_line + blit->src_x*3; unsigned char* dst = dst_line + blit->dst_x*GDST_INCR; int w = blit->width; do { unsigned int ab = GBLENDER_SHADE_INDEX(src[0]); unsigned int ag = GBLENDER_SHADE_INDEX(src[1]); unsigned int ar = GBLENDER_SHADE_INDEX(src[2]); unsigned int aa = (ar << 16) | (ag << 8) | ab; if ( aa == 0 ) { /* nothing */ } else if ( aa == (((GBLENDER_SHADE_COUNT-1) << 16) | ((GBLENDER_SHADE_COUNT-1) << 8) | (GBLENDER_SHADE_COUNT-1) ) ) { GDST_COPY(dst); } else { GBlenderPixel back; int pix_r, pix_g, pix_b; GDST_READ(dst,back); { unsigned int back_r = (back >> 16) & 255; GBLENDER_LOOKUP_R( blender, back_r ); pix_r = _grcells[ar]; } { unsigned int back_g = (back >> 8) & 255; GBLENDER_LOOKUP_G( blender, back_g ); pix_g = _ggcells[ag]; } { unsigned int back_b = (back) & 255; GBLENDER_LOOKUP_B( blender, back_b ); pix_b = _gbcells[ab]; } GDST_STOREC(dst,pix_r,pix_g,pix_b); } src += 3; dst += GDST_INCR; } while (--w > 0); src_line += blit->src_pitch; dst_line += blit->dst_pitch; } while (--h > 0); GBLENDER_CHANNEL_CLOSE(blender); ft2demos-2.10.1/graph/gblvrgb.h0000644000175000001440000000352513434207203016061 0ustar00wlusers00000000000000 GBLENDER_CHANNEL_VARS; int h = blit->height; const unsigned char* src_line = blit->src_line; int src_pitch = blit->src_pitch; unsigned char* dst_line = blit->dst_line; gblender_use_channels( blender, 1 ); GBLENDER_CHANNEL_VARS_SET(blender,r,g,b); do { const unsigned char* src = src_line + blit->src_x; unsigned char* dst = dst_line + blit->dst_x*GDST_INCR; int w = blit->width; do { unsigned int ar = GBLENDER_SHADE_INDEX(src[0]); unsigned int ag = GBLENDER_SHADE_INDEX(src[src_pitch]); unsigned int ab = GBLENDER_SHADE_INDEX(src[src_pitch << 1]); GBlenderPixel aa = ((GBlenderPixel)ar << 16) | (ag << 8) | ab; if ( aa == 0 ) { /* nothing */ } else if ( aa == (((GBLENDER_SHADE_COUNT-1) << 16) | ((GBLENDER_SHADE_COUNT-1) << 8) | (GBLENDER_SHADE_COUNT-1) ) ) { GDST_COPY(dst); } else { GBlenderPixel back; int pix_r, pix_g, pix_b; GDST_READ(dst,back); { unsigned int back_r = (back >> 16) & 255; GBLENDER_LOOKUP_R( blender, back_r ); pix_r = _grcells[ar]; } { unsigned int back_g = (back >> 8) & 255; GBLENDER_LOOKUP_G( blender, back_g ); pix_g = _ggcells[ag]; } { unsigned int back_b = (back) & 255; GBLENDER_LOOKUP_B( blender, back_b ); pix_b = _gbcells[ab]; } GDST_STOREC(dst,pix_r,pix_g,pix_b); } src += 1; dst += GDST_INCR; } while (--w > 0); src_line += blit->src_pitch*3; dst_line += blit->dst_pitch; } while (--h > 0); GBLENDER_CHANNEL_CLOSE(blender); ft2demos-2.10.1/graph/gblbgra.h0000644000175000001440000000402613434207203016031 0ustar00wlusers00000000000000 int h = blit->height; const unsigned char* src_line = blit->src_line; unsigned char* dst_line = blit->dst_line; do { const unsigned char* src = src_line + blit->src_x * 4; unsigned char* dst = dst_line + blit->dst_x * GDST_INCR; int w = blit->width; do { unsigned int pix_b = src[0]; unsigned int pix_g = src[1]; unsigned int pix_r = src[2]; unsigned int a = src[3]; if ( a == 0 ) { /* nothing */ } else if ( a == 255 ) { GDST_STOREC(dst,pix_r,pix_g,pix_b); } else { GBlenderPixel back; GDST_READ(dst,back); { unsigned int ba = 255 - a; unsigned int back_r = (back >> 16) & 255; unsigned int back_g = (back >> 8) & 255; unsigned int back_b = (back) & 255; #if 1 /* premultiplied blending without gamma correction */ pix_r = (back_r * ba / 255 + pix_r); pix_g = (back_g * ba / 255 + pix_g); pix_b = (back_b * ba / 255 + pix_b); #else /* gamma-corrected blending */ const unsigned char* gamma_ramp_inv = blit->blender->gamma_ramp_inv; const unsigned short* gamma_ramp = blit->blender->gamma_ramp; back_r = gamma_ramp[back_r]; back_g = gamma_ramp[back_g]; back_b = gamma_ramp[back_b]; /* premultiplication undone */ pix_r = gamma_ramp[pix_r * 255 / a]; pix_g = gamma_ramp[pix_g * 255 / a]; pix_b = gamma_ramp[pix_b * 255 / a]; pix_r = gamma_ramp_inv[(back_r * ba + pix_r * a + 127) / 255]; pix_g = gamma_ramp_inv[(back_g * ba + pix_g * a + 127) / 255]; pix_b = gamma_ramp_inv[(back_b * ba + pix_b * a + 127) / 255]; #endif } GDST_STOREC(dst,pix_r,pix_g,pix_b); } src += 4; dst += GDST_INCR; } while ( --w > 0 ); src_line += blit->src_pitch; dst_line += blit->dst_pitch; } while ( --h > 0 ); ft2demos-2.10.1/graph/grswizzle.c0000644000175000001440000005202613434207203016467 0ustar00wlusers00000000000000#include /* Author: David Turner * * this filtering code is explicitly placed in the public domain !! */ #include #include #include "grswizzle.h" /* technical note: * * the following code is used to simulate the color display of an * OLPC screen on a traditional LCD or CRT screen. First, here's more or * less how the laptop's hardware works: * * when in color mode, the screen uses the following colored pixels * arrangement, where each pixel is square and can have its luminosity * set between 0 and 255: * * R G B R G B .... * G B R G B R * B R G B R G * R G B R G B * G B R G B R * B R G B R G * : * : * * in its normal mode of operation, the laptop's graphics chip gets its * data from a normal frame buffer (where each pixel has three * components: R, G and B) but only selects the red signal for the first * pixel, the green signal for the second pixel, etc... * * in other words, it ignores 2/3rd of the frame buffer data ! * * there is also another interesting mode of operation, so-called * "anti-aliasing mode" where the value of displayed pixel is obtained * by performing a simple 3x3 linear filter on the frame-buffer data. * the filter's matrix being: * * 0 1/8 0 * * 1/8 1/2 1/8 * * 0 1/8 0 * * note that this filtering is per-color, so the *displayed* intensity of * a given red pixel corresponds to an average of the pixel's red value and * its four neighboring pixels' red values. * * note that the code below uses a 3-lines work buffer, where each line * in the buffer holds a copy of the source frame buffer. * * more exactly, each line has 'width+2' pixels, where the first and last * pixels are always set to 0. this allows us to ignore edge cases in the * filtering code. * * similarly, we artificially extend the source buffer with zero-ed lines * above and below. */ /* define ANTIALIAS to perform anti-alias filtering before swizzling */ #define ANTIALIAS /* define POSTPROCESS to enhance the output for traditional displays, * otherwise, you'll get those ugly diagonals everywhere */ #define POSTPROCESS /************************************************************************/ /************************************************************************/ /***** *****/ /***** G E N E R I C F I L T E R I N G *****/ /***** *****/ /************************************************************************/ /************************************************************************/ /* the type of a line filtering function, see below for usage */ typedef void (*filter_func_t)( unsigned char** lines, unsigned char* write, int width, int offset ); static void copy_line_generic( unsigned char* from, unsigned char* to, int x, int width, int buff_width, int pix_bytes ) { if (x > 0) { width += 1; from -= pix_bytes; } else to += pix_bytes; if (x+width < buff_width) width += 1; memcpy( to, from, (unsigned int)( width * pix_bytes ) ); } /* a generic function to perform 3x3 filtering of a given rectangle, * from a source bitmap into a destination one, the source *can* be * equal to the destination. * * IMPORTANT: this will read the rectangle (x-1,y-1,width+2,height+2) * from the source (clipping and edge cases are handled). * * read_buff :: first byte of source buffer * read_pitch :: source buffer bytes per row * write_buff :: first byte of target buffer * write_pitch :: target buffer bytes per row * buff_width :: width in pixels of both buffers * buff_height :: height in pixels of both buffers * x :: rectangle's left-most horizontal coordinate * y :: rectangle's top-most vertical coordinate * width :: rectangle width in pixels * height :: rectangle height in pixels * pix_bytes :: number of bytes per pixels in both buffer * filter_func :: line filtering function * temp_lines :: a work buffer of at least '3*(width+2)*pix_bytes' bytes */ static void filter_rect_generic( unsigned char* read_buff, int read_pitch, unsigned char* write_buff, int write_pitch, int buff_width, int buff_height, int x, int y, int width, int height, int pix_bytes, filter_func_t filter_func, unsigned char* temp_lines ) { unsigned char* lines[3]; int offset = (x+y) % 3; int delta, height2; /* clip rectangle, just to be sure */ if (x < 0) { width += x; x = 0; } delta = x+width - buff_width; if (delta > 0) width -= delta; if (y < 0) { height += y; y = 0; } delta = y+height - buff_height; if (delta > 0) height -= delta; if (width <= 0 || height <= 0) /* nothing to do */ return; /* now setup the three work lines */ read_buff += y*read_pitch + pix_bytes*x; write_buff += y*write_pitch + pix_bytes*x; memset( temp_lines, 0, (unsigned int)(3 * pix_bytes * ( width + 2 ) ) ); lines[0] = (unsigned char*) temp_lines; lines[1] = lines[0] + pix_bytes*(width+2); lines[2] = lines[1] + pix_bytes*(width+2); /* lines[0] correspond to the pixels of the line above */ if (y > 0) copy_line_generic( read_buff - read_pitch, lines[0], x, width, buff_width, pix_bytes ); /* lines[1] correspond to the pixels of the current line */ copy_line_generic( read_buff, lines[1], x, width, buff_width, pix_bytes ); /* process all lines, except the last one */ for ( height2 = height; height2 > 1; height2-- ) { unsigned char* tmp; /* lines[2] correspond to the pixels of the line below */ copy_line_generic( read_buff + read_pitch, lines[2], x, width, buff_width, pix_bytes ); filter_func( lines, write_buff, width, offset ); if (++offset == 3) offset = 0; /* scroll the work lines */ tmp = lines[0]; lines[0] = lines[1]; lines[1] = lines[2]; lines[2] = tmp; read_buff += read_pitch; write_buff += write_pitch; } /* process last line */ if (y+height == buff_height) memset( lines[2], 0, (unsigned int)( ( width + 2 ) * pix_bytes ) ); else copy_line_generic( read_buff + read_pitch, lines[2], x, width, buff_width, pix_bytes ); filter_func ( lines, write_buff, width, offset ); } /************************************************************************/ /************************************************************************/ /***** *****/ /***** R G B 2 4 S U P P O R T *****/ /***** *****/ /************************************************************************/ /************************************************************************/ /* this function performs AA+swizzling of a given line from/to RGB24 buffers */ static void swizzle_line_rgb24( unsigned char** lines, unsigned char* write, int width, int offset ) { unsigned char* above = lines[0] + 3; unsigned char* current = lines[1] + 3; unsigned char* below = lines[2] + 3; int nn; width *= 3; for ( nn = 0; nn < width; nn += 3 ) { unsigned int sum; int off = nn + offset; #ifdef ANTIALIAS sum = (unsigned int)current[off] << 2; sum += current[off-3] + current[off+3] + above [off] + below [off] ; /* performance trick: use shifts to avoid jumps */ sum = (sum >> 3) << (offset*8); #else /* !ANTIALIAS */ sum = current[off] << (offset*8); #endif write[nn] = (unsigned char) sum; write[nn+1] = (unsigned char)(sum >> 8); write[nn+2] = (unsigned char)(sum >> 16); if ( ++offset == 3 ) offset = 0; } } /* the following function is used to post-process the result of the * swizzling algorithm to provide a more pleasant output on normal * (LCD and CRT) display screens. * * that's because the normal processing creates images that are not * relevant to the display's true nature. For example, consider a 3x3 * white square on the original frame buffer, after simple swizzling, this * will generate the following picture (represented by RGB triplets): * * (255,0,0)(0,255,0)(0,0,255) * (0,255,0)(0,0,255)(255,0,0) * (0,0,255)(255,0,0)(0,255,0) * * the laptop's DCON chip ignores all the 0s above, and will essentially * display a *bright* white square * * a traditional display will not, and this will result in an image that * will be much darker (due to all the zeroes). * * moreover, on an typical LCD screen, this creates very visible * black diagonals. On a CRT, some thinner diagonals are also visible, but * this is mostly due to the fact that the human eye is much more sensitive * to green than red and blue */ /* in this algorithm we steal the green and blue components from each pixel's * neighbours. For example, for a red pixel, we compute the average of the * green pixels on its right and below it, and the average of the blue pixels * on its left and above it. */ static void postprocess_line_rgb24( unsigned char** lines, unsigned char* write, int width, int offset ) { unsigned char* above = lines[0] + 3; unsigned char* current = lines[1] + 3; unsigned char* below = lines[2] + 3; int nn; width *= 3; for ( nn = 0; nn < width; nn += 3 ) { if (offset == 0) /* red */ { write[nn] = current[nn]; write[nn+1] = (unsigned char)((current[nn+4] + below[nn+1]) >> 1); write[nn+2] = (unsigned char)((current[nn-1] + above[nn+2]) >> 1); offset = 1; } else if (offset == 1) /* green */ { write[nn] = (unsigned char)((current[nn-3] + above[nn]) >> 1); write[nn+1] = current[nn+1]; write[nn+2] = (unsigned char)((current[nn+5] + below[nn+2]) >> 1); offset = 2; } else /* blue */ { write[nn] = (unsigned char)((current[nn+3] + below[nn]) >> 1); write[nn+1] = (unsigned char)((current[nn-2] + above[nn+1]) >> 1); write[nn+2] = current[nn+2]; offset = 0; } } } /************************************************************************/ /************************************************************************/ /***** *****/ /***** R G B 5 6 5 S U P P O R T *****/ /***** *****/ /************************************************************************/ /************************************************************************/ /* this function performs AA+swizzling of a given line from/to RGB565 buffers */ static void swizzle_line_rgb565( unsigned char** lines, unsigned char* _write, int width, int offset ) { unsigned short* above = (unsigned short*) lines[0] + 1; unsigned short* current = (unsigned short*) lines[1] + 1; unsigned short* below = (unsigned short*) lines[2] + 1; unsigned short* write = (unsigned short*) _write; int nn; static const unsigned int masks[3] = { 0xf800, 0x07e0, 0x001f }; for (nn = 0; nn < width; nn++) { unsigned int mask = masks[offset]; #ifdef ANTIALIAS unsigned int sum; sum = ((unsigned int)current[nn] & mask) << 2; sum += ((unsigned int)current[nn-1] & mask) + ((unsigned int)current[nn+1] & mask) + ((unsigned int)above[nn] & mask) + ((unsigned int)below[nn] & mask); write[nn] = (unsigned short)( (sum >> 3) & mask ); #else write[nn] = (unsigned short)( current[nn] & mask ); #endif if (++offset == 3) offset = 0; } } static void postprocess_line_rgb565( unsigned char** lines, unsigned char* _write, int width, int offset ) { unsigned short* above = (unsigned short*) lines[0] + 1; unsigned short* current = (unsigned short*) lines[1] + 1; unsigned short* below = (unsigned short*) lines[2] + 1; unsigned short* write = (unsigned short*) _write; int nn; static const unsigned int masks[5] = { 0xf800, 0x07e0, 0x001f, 0xf800, 0x07e0 }; unsigned int l_mask, r_mask, c_mask; l_mask = masks[offset]; c_mask = masks[offset+1]; r_mask = masks[offset+2]; for ( nn = 0; nn < width; nn += 1 ) { unsigned int left, right, center, tmp; center = current[nn]; left = ((current[nn-1] & l_mask) + (above[nn] & l_mask)) >> 1; right = ((current[nn+1] & r_mask) + (below[nn] & r_mask)) >> 1; write[nn] = (unsigned short)( (left & l_mask) | (right & r_mask) | (center & c_mask) ); tmp = l_mask; l_mask = c_mask; c_mask = r_mask; r_mask = tmp; } } /************************************************************************/ /************************************************************************/ /***** *****/ /***** X R G B 3 2 S U P P O R T *****/ /***** *****/ /************************************************************************/ /************************************************************************/ /* this function performs AA+swizzling of a given line from/to 32-bit ARGB or RGB * buffers */ static void swizzle_line_xrgb32( unsigned char** lines, unsigned char* _write, int width, int offset ) { unsigned int* above = (unsigned int*) lines[0] + 1; unsigned int* current = (unsigned int*) lines[1] + 1; unsigned int* below = (unsigned int*) lines[2] + 1; unsigned int* write = (unsigned int*) _write; int nn; unsigned int mask = (0xff0000) >> (offset*8); for (nn = 0; nn < width; nn++) { #ifdef ANTIALIAS unsigned int sum; sum = (current[nn] & mask) << 2; sum += (current[nn-1] & mask) + (current[nn+1] & mask) + (above[nn] & mask) + (below[nn] & mask); write[nn] = (sum >> 3) & mask; /* should we set ALPHA to 0xFF ? */ #else write[nn] = current[nn] & mask; #endif mask >>= 8; if (mask == 0) mask = 0x00ff0000; } } static void postprocess_line_xrgb32( unsigned char** lines, unsigned char* _write, int width, int offset ) { unsigned int* above = (unsigned int*) lines[0] + 1; unsigned int* current = (unsigned int*) lines[1] + 1; unsigned int* below = (unsigned int*) lines[2] + 1; unsigned int* write = (unsigned int*) _write; int nn; static const unsigned int masks[5] = { 0xff0000, 0x00ff00, 0x0000ff, 0xff0000, 0x00ff00 }; unsigned int l_mask, r_mask, c_mask; l_mask = masks[offset]; c_mask = masks[offset+1]; r_mask = masks[offset+2]; for ( nn = 0; nn < width; nn += 1 ) { unsigned int left, right, center, tmp; center = current[nn]; left = ((current[nn-1] & l_mask) + (above[nn] & l_mask)) >> 1; right = ((current[nn+1] & r_mask) + (below[nn] & r_mask)) >> 1; write[nn] = (unsigned int)( (left & l_mask) | (right & r_mask) | (center & c_mask) ); tmp = l_mask; l_mask = c_mask; c_mask = r_mask; r_mask = tmp; } } static void gr_swizzle_generic( unsigned char* read_buff, int read_pitch, unsigned char* write_buff, int write_pitch, int buff_width, int buff_height, int x, int y, int width, int height, int pixbytes, filter_func_t swizzle_func, filter_func_t postprocess_func ) { unsigned char* temp_lines; unsigned char temp_local[ 2048 ]; unsigned int temp_size; if ( height <= 0 || width <= 0 ) return; if ( read_pitch < 0 ) read_buff -= (buff_height-1)*read_pitch; if ( write_pitch < 0 ) write_buff -= (buff_height-1)*write_pitch; /* we allocate a work buffer that will be used to hold three * working 'lines', each of them having width+2 pixels. the first * and last pixels being always 0 */ temp_size = (unsigned int)( ( width + 2 ) * 3 * pixbytes ); if ( temp_size <= sizeof ( temp_local ) ) { /* try to use stack allocation, which is a lot faster than malloc */ temp_lines = temp_local; } else { temp_lines = (unsigned char*)malloc( temp_size ); if ( temp_lines == NULL ) return; } filter_rect_generic( read_buff, read_pitch, write_buff, write_pitch, buff_width, buff_height, x, y, width, height, pixbytes, swizzle_func, temp_lines ); #ifdef POSTPROCESS /* perform darkness correction */ if ( postprocess_func ) filter_rect_generic( write_buff, write_pitch, write_buff, write_pitch, buff_width, buff_height, x, y, width, height, pixbytes, postprocess_func, temp_lines ); #endif /* free work buffer if needed */ if (temp_lines != temp_local) free( temp_lines ); } extern void gr_swizzle_rect_rgb24( unsigned char* read_buff, int read_pitch, unsigned char* write_buff, int write_pitch, int buff_width, int buff_height, int x, int y, int width, int height ) { gr_swizzle_generic( read_buff, read_pitch, write_buff, write_pitch, buff_width, buff_height, x, y, width, height, 3, swizzle_line_rgb24, postprocess_line_rgb24 ); } extern void gr_swizzle_rect_rgb565( unsigned char* read_buff, int read_pitch, unsigned char* write_buff, int write_pitch, int buff_width, int buff_height, int x, int y, int width, int height ) { gr_swizzle_generic( read_buff, read_pitch, write_buff, write_pitch, buff_width, buff_height, x, y, width, height, 2, swizzle_line_rgb565, postprocess_line_rgb565 ); } extern void gr_swizzle_rect_xrgb32( unsigned char* read_buff, int read_pitch, unsigned char* write_buff, int write_pitch, int buff_width, int buff_height, int x, int y, int width, int height ) { gr_swizzle_generic( read_buff, read_pitch, write_buff, write_pitch, buff_width, buff_height, x, y, width, height, 4, swizzle_line_xrgb32, postprocess_line_xrgb32 ); } ft2demos-2.10.1/graph/grtypes.h0000644000175000001440000000213713434207761016140 0ustar00wlusers00000000000000/*************************************************************************** * * grtypes.h * * basic type definitions * * Copyright (C) 1999-2019 by * The FreeType Development Team - www.freetype.org * * * * ***************************************************************************/ #ifndef GRTYPES_H_ #define GRTYPES_H_ typedef unsigned char byte; #if 0 typedef signed char uchar; typedef unsigned long ulong; typedef unsigned short ushort; typedef unsigned int uint; #endif typedef struct grDimension_ { int x; int y; } grDimension; #define gr_err_ok 0 #define gr_err_memory -1 #define gr_err_bad_argument -2 #define gr_err_bad_target_depth -3 #define gr_err_bad_source_depth -4 #define gr_err_saturation_overflow -5 #define gr_err_conversion_overflow -6 #define gr_err_invalid_device -7 #ifdef GR_MAKE_OPTION_SINGLE_OBJECT #define GR_LOCAL_DECL static #define GR_LOCAL_FUNC static #else #define GR_LOCAL_DECL extern #define GR_LOCAL_FUNC /* void */ #endif #endif /* GRTYPES_H_ */ ft2demos-2.10.1/graph/grfill.c0000644000175000001440000001417613501434274015717 0ustar00wlusers00000000000000#include "graph.h" #include #include static void gr_fill_hline_mono( unsigned char* line, int x, int width, grColor color ) { int c1 = (x >> 3); int lmask = 0xFF >> (x & 7); int c2 = ((x+width-1) >> 3); int rmask = 0x7F8 >> ((x+width-1) & 7); if ( color.value != 0 ) { if ( c1 == c2 ) line[c1] = (unsigned char)( line[c1] | (lmask & rmask)); else { line[c1] = (unsigned char)(line[c1] | lmask); for ( ++c1; c1 < c2; c1++ ) line[c1] = 0xFF; line[c2] = (unsigned char)(line[c2] | rmask); } } else { if ( c1 == c2 ) line[c1] = (unsigned char)( line[c1] & ~(lmask & rmask) ); else { line[c1] = (unsigned char)(line[c1] & ~lmask); for (++c1; c1 < c2; c1++) line[c1] = 0; line[c2] = (unsigned char)(line[c2] & ~rmask); } } } static void gr_fill_hline_4( unsigned char* line, int x, int width, grColor color ) { int col = color.value | (color.value << 4); line += (x >> 1); if ( x & 1 ) { line[0] = (unsigned char)((line[0] & 0xF0) | (col & 0x0F)); line++; width--; } for ( ; width >= 2; width -= 2 ) { line[0] = (unsigned char)col; line++; } if ( width > 0 ) line[0] = (unsigned char)((line[0] & 0x0F) | (col & 0xF0)); } static void gr_fill_hline_8( unsigned char* line, int x, int width, grColor color ) { memset( line+x, color.value, (unsigned int)width ); } static void gr_fill_hline_16( unsigned char* _line, int x, int width, grColor color ) { unsigned short* line = (unsigned short*)_line + x; for ( ; width > 0; width-- ) *line++ = (unsigned short)color.value; } static void gr_fill_hline_24( unsigned char* line, int x, int width, grColor color ) { int r = color.chroma[0]; int g = color.chroma[1]; int b = color.chroma[2]; line += 3*x; if (r == g && g == b) memset( line, r, (unsigned int)(width*3) ); else { for ( ; width > 0; width--, line += 3 ) { line[0] = (unsigned char)r; line[1] = (unsigned char)g; line[2] = (unsigned char)b; } } } static void gr_fill_hline_32( unsigned char* line, int x, int width, grColor color ) { line += 4*x; /* clearly slow */ for (; width > 0; width--, line += 4) { line[0] = color.chroma[0]; line[1] = color.chroma[1]; line[2] = color.chroma[2]; line[3] = color.chroma[3]; } } typedef void (*grFillHLineFunc)( unsigned char* line, int x, int width, grColor color ); static const grFillHLineFunc gr_fill_hline_funcs[gr_pixel_mode_max] = { NULL, gr_fill_hline_mono, gr_fill_hline_4, gr_fill_hline_8, gr_fill_hline_8, gr_fill_hline_16, gr_fill_hline_16, gr_fill_hline_24, gr_fill_hline_32, NULL, NULL, NULL, NULL }; extern void grFillHLine( grBitmap* target, int x, int y, int width, grColor color ) { int delta; unsigned char* line; grFillHLineFunc hline_func = gr_fill_hline_funcs[target->mode]; if ( x < 0 ) { width += x; x = 0; } delta = x + width - target->width; if ( delta > 0 ) width -= delta; if ( y < 0 || y >= target->rows || width <= 0 || hline_func == NULL ) return; line = target->buffer + y*target->pitch; if ( target->pitch < 0 ) line -= target->pitch*(target->rows-1); hline_func( line, x, width, color ); } extern void grFillVLine( grBitmap* target, int x, int y, int height, grColor color ) { int delta; unsigned char* line; grFillHLineFunc hline_func = gr_fill_hline_funcs[ target->mode ]; if ( y < 0 ) { height += y; y = 0; } delta = y + height - target->rows; if ( delta > 0 ) height -= delta; if ( x < 0 || x >= target->width || height <= 0 || hline_func == NULL ) return; line = target->buffer + y*target->pitch; if ( target->pitch < 0 ) line -= target->pitch*(target->rows-1); for ( ; height > 0; height--, line += target->pitch ) hline_func( line, x, 1, color ); } extern void grFillRect( grBitmap* target, int x, int y, int width, int height, grColor color ) { int delta; unsigned char* line; grFillHLineFunc hline_func; int size = 0; if ( x < 0 ) { width -= x; x = 0; } delta = x + width - target->width; if ( delta > 0 ) width -= delta; if ( y < 0 ) { height += y; y = 0; } delta = y + height - target->rows; if ( delta > 0 ) height -= delta; if ( width <= 0 || height <= 0 ) return; line = target->buffer + y*target->pitch; if ( target->pitch < 0 ) line -= target->pitch*(target->rows-1); hline_func = gr_fill_hline_funcs[ target->mode ]; switch ( target->mode ) { case gr_pixel_mode_rgb32: size++; /* fall through */ case gr_pixel_mode_rgb24: size++; /* fall through */ case gr_pixel_mode_rgb565: case gr_pixel_mode_rgb555: size += 2; hline_func( line, x, width, color ); for ( line += size * x; --height > 0; line += target->pitch ) memcpy( line + target->pitch, line, (size_t)size * (size_t)width ); break; case gr_pixel_mode_gray: case gr_pixel_mode_pal8: case gr_pixel_mode_pal4: case gr_pixel_mode_mono: for ( ; height-- > 0; line += target->pitch ) hline_func( line, x, width, color ); break; default: break; } } ft2demos-2.10.1/graph/grconfig.h0000644000175000001440000000020013501434334016217 0ustar00wlusers00000000000000#ifndef GRCONFIG_H_ #define GRCONFIG_H_ #define GR_MAX_SATURATIONS 8 #define GR_MAX_CONVERSIONS 16 #endif /* GRCONFIG_H_ */ ft2demos-2.10.1/graph/grdevice.h0000644000175000001440000000706713501434334016233 0ustar00wlusers00000000000000/*************************************************************************** * * grdevice.h * * Graphics device interface * * Copyright (C) 1999-2019 by * The FreeType Development Team - www.freetype.org * * ***************************************************************************/ #ifndef GRDEVICE_H_ #define GRDEVICE_H_ #include "graph.h" /******************************************************************** * * * grDeviceInitFunc * * * Simple device initialiser function * * * error code. 0 means success * ********************************************************************/ typedef int (*grDeviceInitFunc)( void ); /******************************************************************** * * * grDeviceDoneFunc * * * Simple device finaliser function * * * error code. 0 means success * ********************************************************************/ typedef void (*grDeviceDoneFunc)( void ); /******************************************************************** * * * grDeviceInitSurfaceFunc * * * initializes a new surface for the device. This may be a window * or a video screen, depending on the device. * * * surface :: handle to target surface * * * bitmap :: handle to bitmap descriptor * ********************************************************************/ typedef int (*grDeviceInitSurfaceFunc)( grSurface* surface, grBitmap* bitmap ); /******************************************************************** * * * grDevice * * * Simple device interface structure * * * surface_objsize :: size in bytes of a single surface object for * this device. * * device_name :: name of device, e.g. "x11", "os2pm", "directx" etc.. * init :: device initialisation routine * done :: device finalisation * new_surface :: function used to create a new surface (screen or * window) from the device * * num_pixel_modes :: the number of pixel modes supported by this * device. This value _must_ be set to -1 * default, unless the device provides a * static set of pixel modes (fullscreen). * * pixel_modes :: an array of pixel modes supported by this * device * * * the fields "num_pixel_modes" and "pixel_modes" must be * set by the "init" function. * * This allows windowed devices to "discover" at run-time the * available pixel modes they can provide depending on the * current screen depth. * ********************************************************************/ struct grDevice_ { unsigned int surface_objsize; const char* device_name; /* name of device */ grDeviceInitFunc init; grDeviceDoneFunc done; grDeviceInitSurfaceFunc init_surface; int num_pixel_modes; grPixelMode* pixel_modes; }; extern grDeviceChain* gr_device_chain; extern void gr_swizzle_rgb24( unsigned char* read_buff, int read_pitch, unsigned char* write_buff, int write_pitch, int width, int height ); #endif /* GRDEVICE_H_ */ ft2demos-2.10.1/graph/grinit.c0000644000175000001440000000411113501434334015715 0ustar00wlusers00000000000000#include "grobjs.h" #include "grdevice.h" #include #define GR_INIT_DEVICE_CHAIN ((grDeviceChain*)0) #define GR_INIT_BUILD #ifdef DEVICE_BATCH #include "batch/grbatch.h" #endif #ifdef DEVICE_X11 #ifndef VMS #include "x11/grx11.h" #else #include "grx11.h" #endif #endif #ifdef DEVICE_OS2_PM #include "os2/gros2pm.h" #endif #ifdef DEVICE_WIN32 #include "win32/grwin32.h" #endif #ifdef macintosh #include "mac/grmac.h" #endif #ifdef DEVICE_ALLEGRO #include "allegro/gralleg.h" #endif #ifdef DEVICE_BEOS #include "beos/grbeos.h" #endif /********************************************************************** * * * grInitDevices * * * This function is in charge of initialising all system-specific * devices. A device is responsible for creating and managing one * or more "surfaces". A surface is either a window or a screen, * depending on the system. * * * a pointer to the first element of a device chain. The chain can * be parsed to find the available devices on the current system * * * If a device cannot be initialised correctly, it is not part of * the device chain returned by this function. For example, if an * X11 device was compiled in the library, it will be part of * the returned device chain only if a connection to the display * could be established * * If no driver could be initialised, this function returns NULL. * **********************************************************************/ extern grDeviceChain* grInitDevices( void ) { grDeviceChain* chain; grDeviceChain** chptr; chain = gr_device_chain = GR_INIT_DEVICE_CHAIN; chptr = &gr_device_chain; while (chain) { if ( chain->device->init() != 0 ) *chptr = chain->next; chptr = &chain->next; chain = chain->next; } return gr_device_chain; } extern void grDoneDevices( void ) { grDeviceChain* chain = gr_device_chain; while (chain) { chain->device->done(); chain = chain->next; } } ft2demos-2.10.1/graph/graph.h0000644000175000001440000005213513502347420015540 0ustar00wlusers00000000000000/*************************************************************************** * * graph.h * * Graphics Subsystem interface * * Copyright (C) 1999-2019 by * - The FreeType Development Team - www.freetype.org * ***************************************************************************/ #ifndef GRAPH_H_ #define GRAPH_H_ #include "grevents.h" /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /******** ********/ /******** GENERAL DEFINITIONS AND BLITTING ROUTINES ********/ /******** ********/ /******** ********/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* define the global error variable */ extern int grError; /* pixel mode constants */ typedef enum grPixelMode { gr_pixel_mode_none = 0, gr_pixel_mode_mono, /* monochrome bitmaps */ gr_pixel_mode_pal4, /* 4-bit paletted - 16 colors */ gr_pixel_mode_pal8, /* 8-bit paletted - 256 colors */ gr_pixel_mode_gray, /* 8-bit gray levels */ gr_pixel_mode_rgb555, /* 15-bits mode - 32768 colors */ gr_pixel_mode_rgb565, /* 16-bits mode - 65536 colors */ gr_pixel_mode_rgb24, /* 24-bits mode - 16 million colors */ gr_pixel_mode_rgb32, /* 32-bits mode - 16 million colors */ gr_pixel_mode_lcd, /* horizontal RGB-decimated */ gr_pixel_mode_lcdv, /* vertical RGB-decimated */ gr_pixel_mode_lcd2, /* horizontal BGR-decimated */ gr_pixel_mode_lcdv2, /* vertical BGR-decimated */ gr_pixel_mode_bgra, /* premultiplied BGRA colors */ gr_pixel_mode_max /* don't remove */ } grPixelMode; /* forward declaration of the surface class */ typedef struct grSurface_ grSurface; /********************************************************************* * * * grBitmap * * * a simple bitmap descriptor * * * rows :: height in pixels * width :: width in pixels * pitch :: + or - the number of bytes per row * mode :: pixel mode of bitmap buffer * grays :: number of grays in palette for PAL8 mode. 0 otherwise * buffer :: pointer to pixel buffer * * * the 'pitch' is positive for downward flows, and negative otherwise * Its absolute value is always the number of bytes taken by each * bitmap row. * * All drawing operations will be performed within the first * "width" pixels of each row (clipping is always performed). * ********************************************************************/ typedef struct grBitmap_ { int rows; int width; int pitch; grPixelMode mode; int grays; unsigned char* buffer; } grBitmap; typedef long grPos; typedef char grBool; typedef struct grVector_ { grPos x; grPos y; } grVector; typedef union grColor_ { long value; unsigned char chroma[4]; } grColor; /********************************************************************** * * * grNewBitmap * * * creates a new bitmap * * * pixel_mode :: the target surface's pixel_mode * num_grays :: number of grays levels for PAL8 pixel mode * width :: width in pixels * height :: height in pixels * * * bit :: descriptor of the new bitmap * * * Error code. 0 means success. * * * This function really allocates a pixel buffer, zero it, then * returns a descriptor for it. * * Call grDoneBitmap when you're done with it.. * **********************************************************************/ extern int grNewBitmap( grPixelMode pixel_mode, int num_grays, int width, int height, grBitmap *bit ); /********************************************************************** * * * grBlitGlyphToBitmap * * * writes a given glyph bitmap to a target surface. * * * target :: handle to target bitmap that belongs to surface * glyph :: handle to source glyph bitmap * x :: position of left-most pixel of glyph image in target surface * y :: position of top-most pixel of glyph image in target surface * color :: color to be used to draw a monochrome glyph * * * Error code. 0 means success * * * There are only two supported source pixel modes : monochrome * and gray. The 8-bit images can have any number of grays between * 2 and 128, and conversions to the target surface is handled * _automatically_. * * Note however that you should avoid blitting a gray glyph to a gray * bitmap with fewer levels of grays, as this would much probably * give unpleasant results.. * * This function performs clipping * **********************************************************************/ extern int grBlitGlyphToBitmap( grBitmap* target, grBitmap* glyph, grPos x, grPos y, grColor color ); /* values must be in 0..255 range */ extern grColor grFindColor( grBitmap* target, int red, int green, int blue, int alpha ); /********************************************************************** * * * grWriteCellChar * * * The graphics sub-system contains an internal CP437 8x8 font * which can be used to display simple strings of text without * using FreeType. * * This function writes a single 8x8 character on the target bitmap. * * * target :: handle to target surface * x :: x pixel position of character cell's top left corner * y :: y pixel position of character cell's top left corner * charcode :: Latin-1 character code * color :: color to be used to draw the character * **********************************************************************/ extern void grWriteCellChar( grBitmap* target, int x, int y, int charcode, grColor color ); /********************************************************************** * * * grWriteCellString * * * The graphics sub-system contains an internal CP437 8x8 font * which can be used to display simple strings of text without * using FreeType. * * This function writes a string with the internal font * * * target :: handle to target bitmap * x :: x pixel position of string's top left corner * y :: y pixel position of string's top left corner * string :: Latin-1 text string * color :: color to be used to draw the character * **********************************************************************/ extern void grWriteCellString( grBitmap* target, int x, int y, const char* string, grColor color ); /********************************************************************** * * * grDoneBitmap * * * destroys a bitmap * * * bitmap :: handle to bitmap descriptor * * * This function does NOT release the bitmap descriptor, only * the pixel buffer. * **********************************************************************/ extern void grDoneBitmap( grBitmap* bit ); /********************************************************************** * * * grFillRect * * * this function is used to fill a given rectangle on a surface * * * target :: handle to target surface * x :: x coordinate of the top-left corner of the rectangle * y :: y coordinate of the top-left corner of the rectangle * width :: rectangle width in pixels * height :: rectangle height in pixels * color :: fill color * **********************************************************************/ extern void grFillHLine( grBitmap* target, int x, int y, int width, grColor color ); extern void grFillVLine( grBitmap* target, int x, int y, int height, grColor color ); extern void grFillRect( grBitmap* target, int x, int y, int width, int height, grColor color ); /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /******** ********/ /******** DEVICE-SPECIFIC DEFINITIONS AND ROUTINES ********/ /******** ********/ /******** ********/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* forward declaration - the definition of grDevice is not visible */ /* to clients.. */ typedef struct grDevice_ grDevice; /********************************************************************** * * * grDeviceChain * * * a simple structure used to implement a linked list of * graphics device descriptors. The list is called a * "device chain" * * * name :: ASCII name of the device, e.g. "x11", "os2pm", etc.. * device :: handle to the device descriptor. * next :: next element in chain * * * the 'device' field is a blind pointer; it is thus unusable by * client applications.. * **********************************************************************/ typedef struct grDeviceChain_ grDeviceChain; struct grDeviceChain_ { const char* name; grDevice* device; grDeviceChain* next; }; /********************************************************************** * * * grInitDevices * * * This function is in charge of initialising all system-specific * devices. A device is responsible for creating and managing one * or more "surfaces". A surface is either a window or a screen, * depending on the system. * * * a pointer to the first element of a device chain. The chain can * be parsed to find the available devices on the current system * * * If a device cannot be initialised correctly, it is not part of * the device chain returned by this function. For example, if an * X11 device was compiled in the library, it will be part of * the returned device chain only if a connection to the display * could be established * * If no driver could be initialised, this function returns NULL. * **********************************************************************/ extern grDeviceChain* grInitDevices( void ); /********************************************************************** * * * grDoneDevices * * * Finalize all devices activated with grInitDevices. * **********************************************************************/ extern void grDoneDevices( void ); /********************************************************************** * * * grGetDeviceModes * * * queries the available pixel modes for a device. * * * device_name :: name of device to be used. 0 for the default * device. For a list of available devices, see * grInitDevices. * * * num_modes :: number of available modes. 0 in case of error, * which really is an invalid device name. * * pixel_modes :: array of available pixel modes for this device * this table is internal to the device and should * not be freed by client applications. * * * error code. 0 means success. invalid device name otherwise * * * All drivers are _required_ to support at least the following * pixel formats : * * - gr_pixel_mode_mono : i.e. monochrome bitmaps * - gr_pixel_mode_gray : with any number of gray levels between * 2 and 256. * * the pixel modes do not provide the number of grays in the case * of "gray" devices. You should try to create a surface with the * maximal number (256, that is) and see the value returned in * the bitmap descriptor. * **********************************************************************/ extern void grGetDeviceModes( const char* device_name, int *num_modes, grPixelMode* *pixel_modes ); /********************************************************************** * * * grNewSurface * * * creates a new device-specific surface. A surface is either * a window or a screen, depending on the device. * * * device :: name of the device to use. A value of NULL means * the default device (which depends on the system). * for a list of available devices, see grInitDevices. * * * bitmap :: handle to a bitmap descriptor containing the * requested pixel mode, number of grays and dimensions * for the surface. the bitmap's 'pitch' and 'buffer' * fields are ignored on input. * * * handle to the corresponding surface object. 0 in case of error * * * All drivers are _required_ to support at least the following * pixel formats : * * - gr_pixel_mode_mono : i.e. monochrome bitmaps * - gr_pixel_mode_gray : with any number of gray levels between * 2 and 256. * * This function might change the bitmap descriptor's fields. For * example, when displaying a full-screen surface, the bitmap's * dimensions will be set to those of the screen (e.g. 640x480 * or 800x600); also, the bitmap's 'buffer' field might point to * the Video Ram depending on the mode requested.. * * The surface contains a copy of the returned bitmap descriptor, * you can thus discard the 'bitmap' parameter after the call. * **********************************************************************/ extern grSurface* grNewSurface( const char* device, grBitmap* bitmap ); extern void grDoneSurface( grSurface* surface ); /********************************************************************** * * * grRefreshRectangle * * * this function is used to indicate that a given surface rectangle * was modified and thus needs re-painting. It really is useful for * windowed or gray surfaces. * * * surface :: handle to target surface * x :: x coordinate of the top-left corner of the rectangle * y :: y coordinate of the top-left corner of the rectangle * width :: rectangle width in pixels * height :: rectangle height in pixels * **********************************************************************/ extern void grRefreshRectangle( grSurface* surface, grPos x, grPos y, grPos width, grPos height ); /********************************************************************** * * * grRefreshSurface * * * a variation of grRefreshRectangle which repaints the whole surface * to the screen. * * * surface :: handle to target surface * **********************************************************************/ extern void grRefreshSurface( grSurface* surface ); /********************************************************************** * * * grWriteSurfaceChar * * * This function is equivalent to calling grWriteCellChar on the * surface's bitmap, then invoking grRefreshRectangle. * * The graphics sub-system contains an internal CP437 8x8 font * which can be used to display simple strings of text without * using FreeType. * * This function writes a single 8x8 character on the target bitmap. * * * target :: handle to target surface * x :: x pixel position of character cell's top left corner * y :: y pixel position of character cell's top left corner * charcode :: Latin-1 character code * color :: color to be used to draw the character * **********************************************************************/ extern void grWriteSurfaceChar( grSurface* target, int x, int y, int charcode, grColor color ); /********************************************************************** * * * grWriteSurfaceString * * * This function is equivalent to calling grWriteCellString on the * surface's bitmap, then invoking grRefreshRectangle. * * The graphics sub-system contains an internal CP437 8x8 font * which can be used to display simple strings of text without * using FreeType. * * This function writes a string with the internal font * * * target :: handle to target bitmap * x :: x pixel position of string's top left corner * y :: y pixel position of string's top left corner * string :: Latin-1 text string * color :: color to be used to draw the character * **********************************************************************/ extern void grWriteSurfaceString( grSurface* target, int x, int y, const char* string, grColor color ); /********************************************************************** * * * grSetTitle * * * set the window title of a given windowed surface. * * * surface :: handle to target surface * title_string :: the new title * **********************************************************************/ extern void grSetTitle( grSurface* surface, const char* title_string ); /********************************************************************** * * * grListenSurface * * * listen the events for a given surface * * * surface :: handle to target surface * event_mask :: the event mask (mode) * * * event :: the returned event * * * XXX : For now, only keypresses are supported. * **********************************************************************/ extern int grListenSurface( grSurface* surface, int event_mask, grEvent *event ); /********************************************************************** * * * grSetTargetGamma * * * set the gamma-correction coefficient. This is only used to * blit glyphs * * * gamma :: gamma value. <= 0 to select sRGB transfer function * **********************************************************************/ extern void grSetTargetGamma( grBitmap* target, double gamma_value ); /* */ #endif /* GRAPH_H_ */ ft2demos-2.10.1/graph/grdevice.c0000644000175000001440000002455413502347420016226 0ustar00wlusers00000000000000#include "grobjs.h" #include "grdevice.h" #include #include grDeviceChain* gr_device_chain; static grDevice* find_device( const char* device_name ) { grDeviceChain* chain = gr_device_chain; grDevice* device = NULL; if (device_name) while (chain) { if ( strcmp( device_name, chain->name ) == 0 ) { device = chain->device; break; } chain = chain->next; } else if (chain) device = chain->device; if (!device) grError = gr_err_invalid_device; return device; } /********************************************************************** * * * grGetDeviceModes * * * queries the available pixel modes for a device. * * * device_name :: name of device to be used. 0 for the default * device. For a list of available devices, see * grInitDevices. * * * num_modes :: number of available modes. 0 in case of error, * which really is an invalid device name. * * pixel_modes :: array of available pixel modes for this device * this table is internal to the device and should * not be freed by client applications. * * * error code. 0 means success. invalid device name otherwise * * * All drivers are _required_ to support at least the following * pixel formats : * * - gr_pixel_mode_mono : i.e. monochrome bitmaps * - gr_pixel_mode_gray : with any number of gray levels between * 2 and 256. * * the pixel modes do not provide the number of grays in the case * of "gray" devices. You should try to create a surface with the * maximal number (256, that is) and see the value returned in * the bitmap descriptor. * **********************************************************************/ extern void grGetDeviceModes( const char* device_name, int *num_modes, grPixelMode* *pixel_modes ) { grDevice* device; *num_modes = 0; *pixel_modes = 0; device = find_device( device_name ); if (device) { *num_modes = device->num_pixel_modes; *pixel_modes = device->pixel_modes; } } /********************************************************************** * * * grNewSurface * * * creates a new device-specific surface. A surface is either * a window or a screen, depending on the device. * * * device :: name of the device to use. A value of NULL means * the default device (which depends on the system). * for a list of available devices, see grInitDevices. * * * bitmap :: handle to a bitmap descriptor containing the * requested pixel mode, number of grays and dimensions * for the surface. the bitmap's 'pitch' and 'buffer' * fields are ignored on input. * * * handle to the corresponding surface object. 0 in case of error * * * All drivers are _required_ to support at least the following * pixel formats : * * - gr_pixel_mode_mono : i.e. monochrome bitmaps * - gr_pixel_mode_gray : with any number of gray levels between * 2 and 256. * * This function might change the bitmap descriptor's fields. For * example, when displaying a full-screen surface, the bitmap's * dimensions will be set to those of the screen (e.g. 640x480 * or 800x600); also, the bitmap's 'buffer' field might point to * the Video Ram depending on the mode requested.. * * The surface contains a copy of the returned bitmap descriptor, * you can thus discard the 'bitmap' parameter after the call. * **********************************************************************/ grSurface* grNewSurface( const char* device_name, grBitmap* bitmap ) { grDevice* device; grSurface* surface; /* Now find the device */ device = find_device( device_name ); if (!device) return 0; surface = (grSurface*)grAlloc( device->surface_objsize ); if (!surface) return 0; if ( !device->init_surface( surface, bitmap ) ) { grFree( (void *)surface ); surface = 0; } else grSetTargetGamma( (grBitmap*)surface, 1.8 ); return surface; } extern void grDoneSurface( grSurface* surface ) { if (surface) { /* first of all, call the device-specific destructor */ surface->done(surface); /* then remove the bitmap if we're owner */ if (surface->owner) grFree( surface->bitmap.buffer ); surface->owner = 0; surface->bitmap.buffer = 0; grFree( surface ); } } /********************************************************************** * * * grRefreshRectangle * * * this function is used to indicate that a given surface rectangle * was modified and thus needs re-painting. It really is useful for * windowed or gray surfaces. * * * surface :: handle to target surface * x :: x coordinate of the top-left corner of the rectangle * y :: y coordinate of the top-left corner of the rectangle * width :: rectangle width in pixels * height :: rectangle height in pixels * **********************************************************************/ extern void grRefreshRectangle( grSurface* surface, grPos x, grPos y, grPos width, grPos height ) { if (surface->refresh_rect) surface->refresh_rect( surface, x, y, width, height ); } /********************************************************************** * * * grWriteSurfaceChar * * * This function is equivalent to calling grWriteCellChar on the * surface's bitmap, then invoking grRefreshRectangle. * * The graphics sub-system contains an internal CP437 8x8 font * which can be used to display simple strings of text without * using FreeType. * * This function writes a single 8x8 character on the target bitmap. * * * target :: handle to target surface * x :: x pixel position of character cell's top left corner * y :: y pixel position of character cell's top left corner * charcode :: Latin-1 character code * color :: color to be used to draw the character * **********************************************************************/ extern void grWriteSurfaceChar( grSurface* target, int x, int y, int charcode, grColor color ) { grWriteCellChar( &target->bitmap, x, y, charcode, color ); if (target->refresh_rect) target->refresh_rect( target, x, y, 8, 8 ); } /********************************************************************** * * * grWriteSurfaceString * * * This function is equivalent to calling grWriteCellString on the * surface's bitmap, then invoking grRefreshRectangle. * * The graphics sub-system contains an internal CP437 8x8 font * which can be used to display simple strings of text without * using FreeType. * * This function writes a string with the internal font * * * target :: handle to target bitmap * x :: x pixel position of string's top left corner * y :: y pixel position of string's top left corner * string :: Latin-1 text string * color :: color to be used to draw the character * **********************************************************************/ extern void grWriteSurfaceString( grSurface* target, int x, int y, const char* string, grColor color ) { int len; len = (int)strlen(string); grWriteCellString( &target->bitmap, x, y, string, color ); if (target->refresh_rect) target->refresh_rect( target, x, y, 8*len, 8 ); } /********************************************************************** * * * grRefreshSurface * * * a variation of grRefreshRectangle which repaints the whole surface * to the screen. * * * surface :: handle to target surface * **********************************************************************/ extern void grRefreshSurface( grSurface* surface ) { if (surface->refresh_rect) surface->refresh_rect( surface, 0, 0, surface->bitmap.width, surface->bitmap.rows ); } /********************************************************************** * * * grSetTitle * * * set the window title of a given windowed surface. * * * surface :: handle to target surface * title_string :: the new title * **********************************************************************/ extern void grSetTitle( grSurface* surface, const char* title_string ) { if (surface->set_title) surface->set_title( surface, title_string ); } /********************************************************************** * * * grListenSurface * * * listen the events for a given surface * * * surface :: handle to target surface * event_mask :: the event mask (mode) * * * event :: the returned event * * * XXX : For now, only keypresses are supported. * **********************************************************************/ extern int grListenSurface( grSurface* surface, int event_mask, grEvent *event ) { return surface->listen_event( surface, event_mask, event ); } ft2demos-2.10.1/graph/gblblit.h0000644000175000001440000000277213503605615016064 0ustar00wlusers00000000000000#ifndef GBLBLIT_H_ #define GBLBLIT_H_ #include "grobjs.h" #include "gblender.h" /* * blitting interface * */ typedef enum { GBLENDER_SOURCE_GRAY8 = 0, GBLENDER_SOURCE_HRGB, GBLENDER_SOURCE_HBGR, GBLENDER_SOURCE_VRGB, GBLENDER_SOURCE_VBGR, GBLENDER_SOURCE_BGRA, GBLENDER_SOURCE_MAX } GBlenderSourceFormat; typedef enum { GBLENDER_TARGET_GRAY8 = 0, GBLENDER_TARGET_RGB32, GBLENDER_TARGET_RGB24, GBLENDER_TARGET_RGB565, GBLENDER_TARGET_BGR565, GBLENDER_TARGET_MAX } GBlenderTargetFormat; typedef struct GBlenderBlitRec_* GBlenderBlit; typedef void (*GBlenderBlitFunc)( GBlenderBlit blit, GBlenderPixel color ); typedef struct GBlenderBlitRec_ { int width; int height; const unsigned char* src_line; int src_pitch; int src_x; int src_y; unsigned char* dst_line; int dst_pitch; int dst_x; int dst_y; GBlenderSourceFormat src_format; GBlenderTargetFormat dst_format; GBlender blender; GBlenderBlitFunc blit_func; } GBlenderBlitRec; #define gblender_blit_run(b,color) (b)->blit_func( (b), (color) ) GBLENDER_API( int ) grBlitGlyphToSurface( grSurface* surface, grBitmap* glyph, grPos x, grPos y, grColor color ); #endif /* GBLBLIT_H_ */ ft2demos-2.10.1/graph/gblender.c0000644000175000001440000002577113503605615016226 0ustar00wlusers00000000000000#include "gblender.h" #include #if 0 /* using slow power functions */ #include static void gblender_set_gamma_table( double gamma_value, unsigned short* gamma_ramp, unsigned char* gamma_ramp_inv ) { const int gmax = (256 << GBLENDER_GAMMA_SHIFT)-1; if ( gamma_value <= 0 ) /* special case for sRGB */ { int ii; for ( ii = 0; ii < 256; ii++ ) { double x = (double)ii / 255.0; if ( x <= 0.039285714 ) x /= 12.92321; else x = pow( (x+0.055)/ 1.055, 2.4 ); gamma_ramp[ii] = (unsigned short)(gmax*x + 0.5); } for ( ii = 0; ii <= gmax; ii++ ) { double x = (double)ii / gmax; if ( x <= 0.0030399346 ) x *= 12.92321; else x = 1.055*pow(x,1/2.4) - 0.055; gamma_ramp_inv[ii] = (unsigned char)(255.*x + 0.5); } } else { int ii; double gamma_inv = 1. / gamma_value; /* voltage to linear */ for ( ii = 0; ii < 256; ii++ ) gamma_ramp[ii] = (unsigned short)( gmax*pow( (double)ii/255., gamma_value ) + 0.5 ); /* linear to voltage */ for ( ii = 0; ii <= gmax; ii++ ) gamma_ramp_inv[ii] = (unsigned char)( 255.*pow( (double)ii/gmax, gamma_inv ) + 0.5 ); } } #else /* using fast finite differences */ static void gblender_set_gamma_table( double gamma_value, unsigned short* gamma_ramp, unsigned char* gamma_ramp_inv ) { const int gmax = (256 << GBLENDER_GAMMA_SHIFT)-1; double p; if ( gamma_value <= 0 ) /* special case for sRGB */ { int ii; /* voltage to linear; power function using finite differences */ for ( p = 1.0, ii = 255; ii > (int)(255.*0.039285714); ii-- ) { gamma_ramp[ii] = (unsigned short)( gmax*p + 0.5 ); p -= 2.4 * p / ( ii + 255. * 0.055 ); } for ( ; ii >= 0; ii-- ) gamma_ramp[ii] = (unsigned short)( gmax*ii/(255.*12.92321) + 0.5 ); /* linear to voltage; power function using finite differences */ for ( p = 1.0, ii = gmax; ii > (int)(gmax*0.0030399346); ii-- ) { gamma_ramp_inv[ii] = (unsigned char)( 255.*p + 0.5 ); p -= ( p + 0.055 ) / ( 2.4 * ii ); } for ( ; ii >= 0; ii-- ) gamma_ramp_inv[ii] = (unsigned char)( 255.*12.92321*ii/gmax + 0.5 ); } else { int ii; double gamma_inv = 1. / gamma_value; /* voltage to linear; power function using finite differences */ for ( p = 1.0, ii = 255; ii > 0; ii-- ) { gamma_ramp[ii] = (unsigned short)( gmax*p + 0.5 ); p -= gamma_value * p / ii; } gamma_ramp[ii] = 0; /* linear to voltage; power function using finite differences */ for ( p = 1.0, ii = gmax; ii > 0; ii-- ) { gamma_ramp_inv[ii] = (unsigned char)( 255.*p + 0.5 ); p -= gamma_inv * p / ii; } gamma_ramp[ii] = 0; } } #endif /* clear the cache */ static void gblender_clear( GBlender blender ) { int nn; GBlenderKey keys = blender->keys; if ( blender->channels ) { GBlenderChanKey chan_keys = (GBlenderChanKey) blender->keys; for ( nn = 0; nn < GBLENDER_KEY_COUNT; nn++ ) chan_keys[nn].index = -1; blender->cache_r_back = ~0U; blender->cache_r_fore = ~0U; blender->cache_r_cells = NULL; blender->cache_g_back = ~0U; blender->cache_g_fore = ~0U; blender->cache_g_cells = NULL; blender->cache_b_back = ~0U; blender->cache_b_fore = ~0U; blender->cache_b_cells = NULL; } else { for ( nn = 0; nn < GBLENDER_KEY_COUNT; nn++ ) keys[nn].cells = NULL; blender->cache_back = ~0U; blender->cache_fore = ~0U; blender->cache_cells = NULL; } } GBLENDER_APIDEF( void ) gblender_reset( GBlender blender ) { gblender_clear( blender ); if ( blender->channels ) { blender->cache_r_back = 0; blender->cache_r_fore = 0xFFFFFF; blender->cache_r_cells = gblender_lookup_channel( blender, blender->cache_r_back, blender->cache_r_fore ); blender->cache_g_back = 0; blender->cache_g_fore = 0xFFFFFF; blender->cache_g_cells = gblender_lookup_channel( blender, blender->cache_g_back, blender->cache_g_fore ); blender->cache_b_back = 0; blender->cache_b_fore = 0xFFFFFF; blender->cache_b_cells = gblender_lookup_channel( blender, blender->cache_b_back, blender->cache_b_fore ); } else { blender->cache_back = 0; blender->cache_fore = 0xFFFFFF; blender->cache_cells = gblender_lookup( blender, blender->cache_back, blender->cache_fore ); } #ifdef GBLENDER_STATS blender->stat_hits = 0; blender->stat_lookups = 0; blender->stat_keys = 0; blender->stat_clears = 0; #endif } GBLENDER_APIDEF( void ) gblender_init( GBlender blender, double gamma_value ) { blender->channels = 0; gblender_set_gamma_table ( gamma_value, blender->gamma_ramp, blender->gamma_ramp_inv ); gblender_reset( blender ); } GBLENDER_APIDEF( void ) gblender_use_channels( GBlender blender, int channels ) { channels = (channels != 0); if ( blender->channels != channels ) { blender->channels = channels; gblender_reset( blender ); } } /* recompute the grade levels of a given key */ static void gblender_reset_key( GBlender blender, GBlenderKey key ) { GBlenderPixel back = key->background; GBlenderPixel fore = key->foreground; GBlenderCell* gr = key->cells; unsigned int nn; const unsigned char* gamma_ramp_inv = blender->gamma_ramp_inv; const unsigned short* gamma_ramp = blender->gamma_ramp; unsigned int r1,g1,b1,r2,g2,b2; r1 = ( back >> 16 ) & 255; g1 = ( back >> 8 ) & 255; b1 = ( back ) & 255; r2 = ( fore >> 16 ) & 255; g2 = ( fore >> 8 ) & 255; b2 = ( fore ) & 255; #ifdef GBLENDER_STORE_BYTES gr[0] = (unsigned char)r1; gr[1] = (unsigned char)g1; gr[2] = (unsigned char)b1; gr += 3; #else gr[0] = back; gr += 1; #endif r1 = gamma_ramp[r1]; g1 = gamma_ramp[g1]; b1 = gamma_ramp[b1]; r2 = gamma_ramp[r2]; g2 = gamma_ramp[g2]; b2 = gamma_ramp[b2]; for ( nn = 1; nn < GBLENDER_SHADE_COUNT; nn++ ) { unsigned int a = 255 * nn / ( GBLENDER_SHADE_COUNT - 1 ); unsigned int r, g, b; r = ( r2 * a + r1 * ( 255 - a ) + 127 ) / 255; g = ( g2 * a + g1 * ( 255 - a ) + 127 ) / 255; b = ( b2 * a + b1 * ( 255 - a ) + 127 ) / 255; r = gamma_ramp_inv[r]; g = gamma_ramp_inv[g]; b = gamma_ramp_inv[b]; #ifdef GBLENDER_STORE_BYTES gr[0] = (unsigned char)r; gr[1] = (unsigned char)g; gr[2] = (unsigned char)b; gr += 3; #else gr[0] = (( r & 255 ) << 16) | (( g & 255 ) << 8 ) | (( b & 255 ) ) ; gr ++; #endif } } /* lookup the grades of a given (background,foreground) couple */ GBLENDER_APIDEF( GBlenderCell* ) gblender_lookup( GBlender blender, GBlenderPixel background, GBlenderPixel foreground ) { int idx, idx0; GBlenderKey key; #ifdef GBLENDER_STATS blender->stat_hits--; blender->stat_lookups++; #endif #if 0 if ( blender->channels ) { /* set to normal mode */ blender->channels = 0; gblender_reset( blender ); } #endif idx0 = ( background + foreground*63 ) & (GBLENDER_KEY_COUNT-1); idx = idx0; do { key = blender->keys + idx; if ( key->cells == NULL ) goto NewNode; if ( key->background == background && key->foreground == foreground ) goto Exit; idx = (idx+1) & (GBLENDER_KEY_COUNT-1); } while ( idx != idx0 ); /* the cache is full, clear it completely */ #ifdef GBLENDER_STATS blender->stat_clears++; #endif gblender_clear( blender ); NewNode: key->background = background; key->foreground = foreground; key->cells = blender->cells + idx*(GBLENDER_SHADE_COUNT*GBLENDER_CELL_SIZE); gblender_reset_key( blender, key ); #ifdef GBLENDER_STATS blender->stat_keys++; #endif Exit: return key->cells; } static void gblender_reset_channel_key( GBlender blender, GBlenderChanKey key ) { unsigned int back = key->backfore & 255; unsigned int fore = (key->backfore >> 8) & 255; unsigned char* gr = (unsigned char*)blender->cells + key->index; unsigned int nn; const unsigned char* gamma_ramp_inv = blender->gamma_ramp_inv; const unsigned short* gamma_ramp = blender->gamma_ramp; unsigned int r1,r2; r1 = back; r2 = fore; gr[0] = (unsigned char)r1; gr++; r1 = gamma_ramp[r1]; r2 = gamma_ramp[r2]; for ( nn = 1; nn < GBLENDER_SHADE_COUNT; nn++ ) { unsigned int a = 255 * nn / ( GBLENDER_SHADE_COUNT - 1 ); unsigned int r; r = ( r2 * a + r1 * ( 255 - a ) + 127 ) / 255; r = gamma_ramp_inv[r]; gr[0] = (unsigned char)r; gr++; } } GBLENDER_APIDEF( unsigned char* ) gblender_lookup_channel( GBlender blender, unsigned int background, unsigned int foreground ) { int idx, idx0; unsigned short backfore = (unsigned short)((foreground << 8) | background); GBlenderChanKey key; #ifdef GBLENDER_STATS blender->stat_hits--; blender->stat_lookups++; #endif #if 0 if ( !blender->channels ) { /* set to normal mode */ blender->channels = 1; gblender_reset( blender ); } #endif idx0 = ( background + foreground*17 ) & (GBLENDER_KEY_COUNT-1); idx = idx0; do { key = (GBlenderChanKey)blender->keys + idx; if ( key->index < 0 ) goto NewNode; if ( key->backfore == backfore ) goto Exit; idx = (idx+1) & (GBLENDER_KEY_COUNT-1); } while ( idx != idx0 ); /* the cache is full, clear it completely */ #ifdef GBLENDER_STATS blender->stat_clears++; #endif gblender_clear( blender ); NewNode: key->backfore = backfore; key->index = (signed short)( idx * GBLENDER_SHADE_COUNT ); gblender_reset_channel_key( blender, key ); #ifdef GBLENDER_STATS blender->stat_keys++; #endif Exit: return (unsigned char*)blender->cells + key->index; } #ifdef GBLENDER_STATS #include GBLENDER_APIDEF( void ) gblender_dump_stats( GBlender blender ) { printf( "hits = %ld, miss1 = %ld, miss2 = %ld, rate1=%.2f%%, rate2=%.2f%%\n", blender->stat_hits, blender->stat_lookups, blender->stat_keys, (100.0*blender->stat_hits) / (double)(blender->stat_hits + blender->stat_lookups), (100.0*blender->stat_lookups) / (double)( blender->stat_lookups + blender->stat_keys) ); } #endif ft2demos-2.10.1/graph/grblit.c0000644000175000001440000013763713503605615015734 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 1996-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* grblit.c: Support for blitting of bitmaps with various depth. */ /* */ /****************************************************************************/ #include "grblit.h" #include "gblblit.h" #define GRAY8 static int compute_clips( grBlitter* blit, int x_offset, int y_offset ) { int xmin, ymin, xmax, ymax, width, height, target_width; /* perform clipping and setup variables */ width = blit->source.width; height = blit->source.rows; switch ( blit->source.mode ) { case gr_pixel_mode_mono: width = (width + 7) & -8; break; case gr_pixel_mode_pal4: width = (width + 1) & -2; break; case gr_pixel_mode_lcd: case gr_pixel_mode_lcd2: width /= 3; break; case gr_pixel_mode_lcdv: case gr_pixel_mode_lcdv2: height /= 3; break; default: ; } xmin = x_offset; ymin = y_offset; xmax = xmin + width-1; ymax = ymin + height-1; /* clip if necessary */ if ( width == 0 || height == 0 || xmax < 0 || xmin >= blit->target.width || ymax < 0 || ymin >= blit->target.rows ) return 1; /* set up clipping and cursors */ blit->yread = 0; if ( ymin < 0 ) { blit->yread -= ymin; height += ymin; blit->ywrite = 0; } else blit->ywrite = ymin; if ( ymax >= blit->target.rows ) height -= ymax - blit->target.rows + 1; blit->xread = 0; if ( xmin < 0 ) { blit->xread -= xmin; width += xmin; blit->xwrite = 0; } else blit->xwrite = xmin; target_width = blit->target.width; switch ( blit->target.mode ) { case gr_pixel_mode_mono: target_width = (target_width + 7) & -8; break; case gr_pixel_mode_pal4: target_width = (target_width + 1) & -2; break; default: ; } blit->right_clip = xmax - target_width + 1; if ( blit->right_clip > 0 ) width -= blit->right_clip; else blit->right_clip = 0; blit->width = width; blit->height = height; /* set read and write to the top-left corner of the read */ /* and write areas before clipping. */ blit->read = blit->source.buffer; blit->write = blit->target.buffer; blit->read_line = blit->source.pitch; blit->write_line = blit->target.pitch; if ( blit->read_line < 0 ) blit->read -= (blit->source.rows-1) * blit->read_line; if ( blit->write_line < 0 ) blit->write -= (blit->target.rows-1) * blit->write_line; /* now go to the start line. Note that we do not move the */ /* x position yet, as this is dependent on the pixel format */ blit->read += blit->yread * blit->read_line; blit->write += blit->ywrite * blit->write_line; return 0; } /**************************************************************************/ /* */ /* blit_mono_to_mono */ /* */ /**************************************************************************/ static void blit_mono_to_mono( grBlitter* blit, grColor color ) { unsigned int shift; int left_clip, x, y; byte* read; byte* write; (void)color; /* unused argument */ left_clip = ( blit->xread > 0 ); shift = (unsigned int)( blit->xwrite - blit->xread ) & 7; read = blit->read + (blit->xread >> 3); write = blit->write + (blit->xwrite >> 3); if ( shift == 0 ) { y = blit->height; do { byte* _read = read; byte* _write = write; x = blit->width; do { *_write++ |= *_read++; x -= 8; } while ( x > 0 ); read += blit->read_line; write += blit->write_line; y--; } while ( y > 0 ); } else { int first, last, count; first = blit->xwrite >> 3; last = (blit->xwrite + blit->width-1) >> 3; count = last - first; if ( blit->right_clip ) count++; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; unsigned int old; unsigned int shift2 = (8-shift); if ( left_clip ) old = (unsigned int)(*_read++) << shift2; else old = 0; x = count; while ( x > 0 ) { unsigned char val; val = *_read++; *_write++ |= (unsigned char)( (val >> shift) | old ); old = (unsigned int)val << shift2; x--; } if ( !blit->right_clip ) *_write |= (unsigned char)old; read += blit->read_line; write += blit->write_line; y--; } while ( y > 0 ); } } /**************************************************************************/ /* */ /* blit_mono_to_pal8 */ /* */ /**************************************************************************/ static void blit_mono_to_pal8( grBlitter* blit, grColor color ) { int x, y; unsigned int shift; unsigned char* read; unsigned char* write; read = blit->read + (blit->xread >> 3); write = blit->write + blit->xwrite; shift = blit->xread & 7; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; unsigned long val = ((unsigned long)*_read++ | 0x100) << shift; x = blit->width; do { if (val & 0x10000) val = *_read++ | 0x100; if ( val & 0x80 ) *_write = (unsigned char)color.value; val <<= 1; _write++; } while ( --x > 0 ); read += blit->read_line; write += blit->write_line; y--; } while ( y > 0 ); } /**************************************************************************/ /* */ /* blit_mono_to_pal4 */ /* */ /**************************************************************************/ static void blit_mono_to_pal4( grBlitter* blit, grColor color ) { int x, y, phase; unsigned int shift; unsigned char* read; unsigned char* write; unsigned int col; col = color.value & 15; read = blit->read + (blit->xread >> 3); write = blit->write + (blit->xwrite >> 1); /* now begin blit */ shift = blit->xread & 7; phase = blit->xwrite & 1; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; int _phase = phase; unsigned long val = ((unsigned long)*_read++ | 0x100) << shift; x = blit->width; do { if (val & 0x10000) val = *_read++ | 0x100; if ( val & 0x80 ) { if ( _phase ) *_write = (unsigned char)((*_write & 0xF0) | col); else *_write = (unsigned char)((*_write & 0x0F) | (col << 4)); } val <<= 1; _write += _phase; _phase ^= 1; x--; } while ( x > 0 ); read += blit->read_line; write += blit->write_line; y--; } while ( y > 0 ); } /**************************************************************************/ /* */ /* blit_mono_to_rgb16 */ /* */ /**************************************************************************/ static void blit_mono_to_rgb16( grBlitter* blit, grColor color ) { int x, y; unsigned int shift; unsigned char* read; unsigned char* write; read = blit->read + (blit->xread >> 3); write = blit->write + blit->xwrite*2; shift = blit->xread & 7; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; unsigned long val = ((unsigned long)*_read++ | 0x100) << shift; x = blit->width; do { if (val & 0x10000) val = *_read++ | 0x100; if ( val & 0x80 ) *(short*)_write = (short)color.value; val <<= 1; _write +=2; x--; } while ( x > 0 ); read += blit->read_line; write += blit->write_line; y--; } while ( y > 0 ); } /**************************************************************************/ /* */ /* blit_mono_to_rgb24 */ /* */ /**************************************************************************/ static void blit_mono_to_rgb24( grBlitter* blit, grColor color ) { int x, y; unsigned int shift; unsigned char* read; unsigned char* write; read = blit->read + (blit->xread >> 3); write = blit->write + blit->xwrite*3; shift = blit->xread & 7; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; unsigned long val = ((unsigned long)*_read++ | 0x100) << shift; x = blit->width; do { if (val & 0x10000) val = *_read++ | 0x100; if ( val & 0x80 ) { _write[0] = color.chroma[0]; _write[1] = color.chroma[1]; _write[2] = color.chroma[2]; } val <<= 1; _write += 3; x--; } while ( x > 0 ); read += blit->read_line; write += blit->write_line; y--; } while ( y > 0 ); } /**************************************************************************/ /* */ /* blit_mono_to_rgb32 */ /* */ /**************************************************************************/ static void blit_mono_to_rgb32( grBlitter* blit, grColor color ) { int x, y; unsigned int shift; unsigned char* read; unsigned char* write; read = blit->read + ( blit->xread >> 3 ); write = blit->write + blit->xwrite*4; shift = blit->xread & 7; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; unsigned long val = ((unsigned long)*_read++ | 0x100L ) << shift; x = blit->width; do { if ( val & 0x10000 ) val = *_read++ | 0x100L; if ( val & 0x80 ) { /* this could be greatly optimized as */ /* */ /* *(long*)_write = color.value */ /* */ /* but it wouldn't work on 64-bits systems... stupid C types! */ _write[0] = color.chroma[0]; _write[1] = color.chroma[1]; _write[2] = color.chroma[2]; _write[3] = color.chroma[3]; } val <<= 1; _write += 4; x--; } while ( x > 0 ); read += blit->read_line; write += blit->write_line; y--; } while ( y > 0 ); } static const grBlitterFunc gr_mono_blitters[gr_pixel_mode_max] = { 0, blit_mono_to_mono, blit_mono_to_pal4, blit_mono_to_pal8, blit_mono_to_pal8, blit_mono_to_rgb16, blit_mono_to_rgb16, blit_mono_to_rgb24, blit_mono_to_rgb32 }; /*******************************************************************/ /* */ /* Saturation tables */ /* */ /*******************************************************************/ typedef struct grSaturation_ { int count; const byte* table; } grSaturation; static const byte gr_saturation_5[8] = { 0, 1, 2, 3, 4, 4, 4, 4 }; static const byte gr_saturation_17[32] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, }; static grSaturation gr_saturations[ GR_MAX_SATURATIONS ] = { { 5, gr_saturation_5 }, { 17, gr_saturation_17 } }; static int gr_num_saturations = 2; static grSaturation* gr_last_saturation = gr_saturations; static const byte* grGetSaturation( int num_grays ) { /* first of all, scan the current saturations table */ grSaturation* sat = gr_saturations; grSaturation* limit = sat + gr_num_saturations; if ( num_grays < 2 ) { grError = gr_err_bad_argument; return 0; } for ( ; sat < limit; sat++ ) { if ( sat->count == num_grays ) { gr_last_saturation = sat; return sat->table; } } /* not found, simply create a new entry if there is room */ if (gr_num_saturations < GR_MAX_SATURATIONS) { int i; const byte* table; table = (const byte*)grAlloc( (unsigned long)( 3 * num_grays - 1 ) * sizeof ( byte ) ); if (!table) return 0; sat->count = num_grays; sat->table = table; for ( i = 0; i < num_grays; i++, table++ ) *(unsigned char*)table = (unsigned char)i; for ( i = 2*num_grays-1; i > 0; i--, table++ ) *(unsigned char*)table = (unsigned char)(num_grays-1); gr_num_saturations++; gr_last_saturation = sat; return sat->table; } grError = gr_err_saturation_overflow; return 0; } /*******************************************************************/ /* */ /* conversion tables */ /* */ /*******************************************************************/ typedef struct grConversion_ { int target_grays; int source_grays; const byte* table; } grConversion; static const byte gr_gray5_to_gray17[5] = { 0, 4, 8, 12, 16 }; static const byte gr_gray5_to_gray128[5] = { 0, 32, 64, 96, 127 }; static const unsigned char gr_gray17_to_gray128[17] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 127 }; static grConversion gr_conversions[ GR_MAX_CONVERSIONS ] = { { 17, 5, gr_gray5_to_gray17 }, { 128, 5, gr_gray5_to_gray128 }, { 128, 17, gr_gray17_to_gray128 } }; static int gr_num_conversions = 3; static grConversion* gr_last_conversion = gr_conversions; static const byte* grGetConversion( int target_grays, int source_grays ) { grConversion* conv = gr_conversions; grConversion* limit = conv + gr_num_conversions; if ( target_grays < 2 || source_grays < 2 ) { grError = gr_err_bad_argument; return 0; } /* otherwise, scan table */ for ( ; conv < limit; conv++ ) { if ( conv->target_grays == target_grays && conv->source_grays == source_grays ) { gr_last_conversion = conv; return conv->table; } } /* not found, add a new conversion to the table */ if (gr_num_conversions < GR_MAX_CONVERSIONS) { const byte* table; int n; table = (const byte*)grAlloc( (unsigned long)source_grays * sizeof ( byte ) ); if (!table) return 0; conv->target_grays = target_grays; conv->source_grays = source_grays; conv->table = table; for ( n = 0; n < source_grays; n++ ) ((unsigned char*)table)[n] = (unsigned char)(n*(target_grays-1) / (source_grays-1)); gr_num_conversions++; gr_last_conversion = conv; return table; } grError = gr_err_conversion_overflow; return 0; } /**************************************************************************/ /* */ /* blit_gray_to_gray */ /* */ /**************************************************************************/ static void blit_gray_to_gray( grBlitter* blit, const byte* saturation, const byte* conversion ) { int y; unsigned char* read; unsigned char* write; read = blit->read + blit->xread; write = blit->write + blit->xwrite; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; int x = blit->width; while (x > 0) { #ifdef GR_CONFIG_GRAY_SKIP_WHITE unsigned char val = *_read; if (val) { if (val == max) *_write = max2; else *_write = saturation[ (int)*_write + conversion[ *_read ] ]; } #else *_write = saturation[ (int)*_write + conversion[ *_read ] ]; #endif _write++; _read++; x--; } read += blit->read_line; write += blit->write_line; y--; } while (y > 0); } /**************************************************************************/ /* */ /* blit_gray_to_gray_simple */ /* */ /**************************************************************************/ static void blit_gray_to_gray_simple( grBlitter* blit, const byte* saturation ) { int y; unsigned char* read; unsigned char* write; #ifdef GR_CONFIG_GRAY_SKIP_WHITE unsigned char max; max = (unsigned char)( blit->source.grays - 1 ); #endif read = blit->read + blit->xread; write = blit->write + blit->xwrite; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; int x = blit->width; while (x > 0) { #ifdef GR_CONFIG_GRAY_SKIP_WHITE unsigned char val = *_read; if (val) { if (val == max) *_write = val; else *_write = saturation[ (int)*_write + *_read ]; } #else *_write = saturation[ (int)*_write + *_read ]; #endif _write++; _read++; x--; } read += blit->read_line; write += blit->write_line; y--; } while (y > 0); } #define compose_pixel_full( a, b, n0, n1, n2, max ) \ { \ int d, half = max >> 1; \ \ \ d = (int)b.chroma[0] - a.chroma[0]; \ a.chroma[0] += (unsigned char)((n0*d + half)/max); \ \ d = (int)b.chroma[1] - a.chroma[1]; \ a.chroma[1] += (unsigned char)((n1*d + half)/max); \ \ d = (int)b.chroma[2] - a.chroma[2]; \ a.chroma[2] += (unsigned char)((n2*d + half)/max); \ } #define compose_pixel( a, b, n, max ) \ compose_pixel_full( a, b, n, n, n, max ) #define extract555( pixel, color ) \ color.chroma[0] = (unsigned char)((pixel >> 10) & 0x1F); \ color.chroma[1] = (unsigned char)((pixel >> 5) & 0x1F); \ color.chroma[2] = (unsigned char)((pixel ) & 0x1F); #define extract565( pixel, color ) \ color.chroma[0] = (unsigned char)((pixel >> 11) & 0x1F); \ color.chroma[1] = (unsigned char)((pixel >> 5) & 0x3F); \ color.chroma[2] = (unsigned char)((pixel ) & 0x1F); #define inject555( color ) \ ( ( (unsigned short)color.chroma[0] << 10 ) | \ ( (unsigned short)color.chroma[1] << 5 ) | \ color.chroma[2] ) #define inject565( color ) \ ( ( (unsigned short)color.chroma[0] << 11 ) | \ ( (unsigned short)color.chroma[1] << 5 ) | \ color.chroma[2] ) /**************************************************************************/ /* */ /* blit_gray_to_555 */ /* */ /**************************************************************************/ #ifdef GRAY8 static void blit_gray8_to_555( grBlitter* blit, grColor color ) { int y; int sr = (color.chroma[0] << 7) & 0x7C00; int sg = (color.chroma[1] << 2) & 0x03E0; int sb = (color.chroma[2] >> 3) & 0x001F; unsigned char* read; unsigned char* write; read = blit->read + blit->xread; write = blit->write + 2*blit->xwrite; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; int x = blit->width; while (x > 0) { unsigned char val; val = *_read; if (val) { unsigned short* pixel = (unsigned short*)_write; if (val >= 254 ) *pixel = (unsigned short)( sr | sg | sb ); else if ( val >= 2 ) { /* compose gray value */ int pix = (int)*pixel; int dr = pix & 0x7C00; int dg = pix & 0x03E0; int db = pix & 0x001F; dr += ((sr-dr)*val) >> 8; dr &= 0x7C00; dg += ((sg-dg)*val) >> 8; dg &= 0x03E0; db += ((sb-db)*val) >> 8; db &= 0x001F; *pixel = (unsigned short)( dr | dg | db ); } } _write +=2; _read ++; x--; } read += blit->read_line; write += blit->write_line; y--; } while (y > 0); } #endif /* GRAY8 */ static void blit_gray_to_555( grBlitter* blit, grColor color, int max ) { int y; unsigned char* read; unsigned char* write; read = blit->read + blit->xread; write = blit->write + 2*blit->xwrite; /* scale down R:G:B triplet */ color.chroma[0] >>= 3; color.chroma[1] >>= 3; color.chroma[2] >>= 3; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; int x = blit->width; while (x > 0) { unsigned char val; val = *_read; if (val) { unsigned short* pixel = (unsigned short*)_write; if (val == max) *pixel = (unsigned short)(inject555( color )); else { /* compose gray value */ unsigned short pix16 = *pixel; grColor pix; extract555( pix16, pix ); compose_pixel( pix, color, val, max ); *pixel = (unsigned short)(inject555( pix )); } } _write += 2; _read ++; x--; } read += blit->read_line; write += blit->write_line; y--; } while (y > 0); } /**************************************************************************/ /* */ /* blit_gray_to_565 */ /* */ /**************************************************************************/ #ifdef GRAY8 static void blit_gray8_to_565( grBlitter* blit, grColor color ) { int y; int sr = (color.chroma[0] << 8) & 0xF800; int sg = (color.chroma[1] << 3) & 0x07E0; int sb = (color.chroma[2] >> 3) & 0x001F; unsigned char* read; unsigned char* write; read = blit->read + blit->xread; write = blit->write + 2*blit->xwrite; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; int x = blit->width; while (x > 0) { unsigned char val; val = *_read; if (val) { unsigned short* pixel = (unsigned short*)_write; if (val >= 254 ) *pixel = (unsigned short)( sr | sg | sb ); else if ( val >= 2 ) { /* compose gray value */ int pix = (int)*pixel; int dr = pix & 0xF800; int dg = pix & 0x07E0; int db = pix & 0x001F; dr += ((sr-dr)*val) >> 8; dr &= 0xF800; dg += ((sg-dg)*val) >> 8; dg &= 0x07E0; db += ((sb-db)*val) >> 8; db &= 0x001F; *pixel = (unsigned short)( dr | dg | db ); } } _write +=2; _read ++; x--; } read += blit->read_line; write += blit->write_line; y--; } while (y > 0); } #endif static void blit_gray_to_565( grBlitter* blit, grColor color, int max ) { int y; unsigned char* read; unsigned char* write; read = blit->read + blit->xread; write = blit->write + 2*blit->xwrite; /* scale down R:G:B triplet */ color.chroma[0] >>= 3; color.chroma[1] >>= 2; color.chroma[2] >>= 3; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; int x = blit->width; while (x > 0) { unsigned char val; val = *_read; if (val) { unsigned short* pixel = (unsigned short*)_write; if (val == max) *pixel = (unsigned short)inject565( color ); else { /* compose gray value */ unsigned short pix16 = *pixel; grColor pix; extract565( pix16, pix ); compose_pixel( pix, color, val, max ); *pixel = (unsigned short)inject565( pix ); } } _write +=2; _read ++; x--; } read += blit->read_line; write += blit->write_line; y--; } while (y > 0); } /**************************************************************************/ /* */ /* blit_gray_to_24 */ /* */ /**************************************************************************/ #ifdef GRAY8 static void blit_gray8_to_24( grBlitter* blit, grColor color ) { int y; int sr = color.chroma[0]; int sg = color.chroma[1]; int sb = color.chroma[2]; unsigned char* read; unsigned char* write; read = blit->read + blit->xread; write = blit->write + 3*blit->xwrite; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; int x = blit->width; while (x > 0) { unsigned char val; val = *_read; if (val) { if (val >= 254) { _write[0] = (unsigned char)sr; _write[1] = (unsigned char)sg; _write[2] = (unsigned char)sb; } else if ( val >= 2 ) { int dr = _write[0]; int dg = _write[1]; int db = _write[2]; dr += ((sr-dr)*val) >> 8; dg += ((sg-dg)*val) >> 8; db += ((sb-db)*val) >> 8; _write[0] = (unsigned char)dr; _write[1] = (unsigned char)dg, _write[2] = (unsigned char)db; } } _write += 3; _read ++; x--; } read += blit->read_line; write += blit->write_line; y--; } while (y > 0); } #endif /* GRAY8 */ static void blit_gray_to_24( grBlitter* blit, grColor color, int max ) { int y; unsigned char* read; unsigned char* write; read = blit->read + blit->xread; write = blit->write + 3*blit->xwrite; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; int x = blit->width; while (x > 0) { unsigned char val; val = *_read; if (val) { if (val == max) { _write[0] = color.chroma[0]; _write[1] = color.chroma[1]; _write[2] = color.chroma[2]; } else { /* compose gray value */ grColor pix; pix.chroma[0] = _write[0]; pix.chroma[1] = _write[1]; pix.chroma[2] = _write[2]; compose_pixel( pix, color, val, max ); _write[0] = pix.chroma[0]; _write[1] = pix.chroma[1]; _write[2] = pix.chroma[2]; } } _write += 3; _read ++; x--; } read += blit->read_line; write += blit->write_line; y--; } while (y > 0); } /**************************************************************************/ /* */ /* blit_gray_to_32 */ /* */ /**************************************************************************/ static void blit_gray_to_32( grBlitter* blit, grColor color, int max ) { int y; unsigned char* read; unsigned char* write; read = blit->read + blit->xread; write = blit->write + 4*blit->xwrite; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; int x = blit->width; while (x > 0) { unsigned char val; val = *_read; if (val) { if (val == max) { _write[0] = color.chroma[0]; _write[1] = color.chroma[1]; _write[2] = color.chroma[2]; _write[3] = color.chroma[3]; } else { /* compose gray value */ grColor pix; pix.chroma[0] = _write[0]; pix.chroma[1] = _write[1]; pix.chroma[2] = _write[2]; compose_pixel( pix, color, val, max ); _write[0] = pix.chroma[0]; _write[1] = pix.chroma[1]; _write[2] = pix.chroma[2]; } } _write += 4; _read ++; x--; } read += blit->read_line; write += blit->write_line; y--; } while (y > 0); } static void blit_gray8_to_32( grBlitter* blit, grColor color ) { blit_gray_to_32( blit, color, 255 ); } /**************************************************************************/ /* */ /* blit_lcd_to_24 */ /* */ /**************************************************************************/ #ifdef GRAY8 static void blit_lcd8_to_24( grBlitter* blit, grColor color ) { int y; int sr = color.chroma[0]; int sg = color.chroma[1]; int sb = color.chroma[2]; unsigned char* read; unsigned char* write; read = blit->read + 3*blit->xread; write = blit->write + 3*blit->xwrite; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; int x = blit->width; while (x > 0) { int val0, val1, val2; val0 = _read[0]; val1 = _read[1]; val2 = _read[2]; if ( val0 | val1 | val2 ) { if ( val0 == val1 && val0 == val2 && val0 == 255 ) { _write[0] = (unsigned char)sr; _write[1] = (unsigned char)sg; _write[2] = (unsigned char)sb; } else { /* compose gray value */ int dr, dg, db; dr = _write[0]; dr += (sr-dr)*val0 >> 8; dg = _write[1]; dg += (sg-dg)*val1 >> 8; db = _write[2]; db += (sb-db)*val2 >> 8; _write[0] = (unsigned char)dr; _write[1] = (unsigned char)dg; _write[2] = (unsigned char)db; } } _write += 3; _read += 3; x--; } read += blit->read_line; write += blit->write_line; y--; } while (y > 0); } #endif /* GRAY8 */ static void blit_lcd_to_24( grBlitter* blit, grColor color, int max ) { int y; unsigned char* read; unsigned char* write; read = blit->read + 3*blit->xread; write = blit->write + 3*blit->xwrite; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; int x = blit->width; while (x > 0) { int val0, val1, val2; val0 = _read[0]; val1 = _read[1]; val2 = _read[2]; if ( val0 | val1 | val2 ) { if ( val0 == val1 && val0 == val2 && val0 == max ) { _write[0] = color.chroma[0]; _write[1] = color.chroma[1]; _write[2] = color.chroma[2]; } else { /* compose gray value */ grColor pix; pix.chroma[0] = _write[0]; pix.chroma[1] = _write[1]; pix.chroma[2] = _write[2]; compose_pixel_full( pix, color, val0, val1, val2, max ); _write[0] = pix.chroma[0]; _write[1] = pix.chroma[1]; _write[2] = pix.chroma[2]; } } _write += 3; _read += 3; x--; } read += blit->read_line; write += blit->write_line; y--; } while (y > 0); } #ifdef GRAY8 static void blit_lcd28_to_24( grBlitter* blit, grColor color ) { int y; int sr = color.chroma[0]; int sg = color.chroma[1]; int sb = color.chroma[2]; unsigned char* read; unsigned char* write; read = blit->read + 3*blit->xread; write = blit->write + 3*blit->xwrite; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; int x = blit->width; while (x > 0) { int val0, val1, val2; val0 = _read[2]; val1 = _read[1]; val2 = _read[0]; if ( val0 | val1 | val2 ) { if ( val0 == val1 && val0 == val2 && val0 == 255 ) { _write[0] = (unsigned char)sr; _write[1] = (unsigned char)sg; _write[2] = (unsigned char)sb; } else { /* compose gray value */ int dr, dg, db; dr = _write[0]; dr += (sr-dr)*val0 >> 8; dg = _write[1]; dg += (sg-dg)*val1 >> 8; db = _write[2]; db += (sb-db)*val2 >> 8; _write[0] = (unsigned char)dr; _write[1] = (unsigned char)dg; _write[2] = (unsigned char)db; } } _write += 3; _read += 3; x--; } read += blit->read_line; write += blit->write_line; y--; } while (y > 0); } #endif /* GRAY8 */ static void blit_lcd2_to_24( grBlitter* blit, grColor color, int max ) { int y; unsigned char* read; unsigned char* write; read = blit->read + 3*blit->xread; write = blit->write + 3*blit->xwrite; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; int x = blit->width; while (x > 0) { int val0, val1, val2; val0 = _read[2]; val1 = _read[1]; val2 = _read[0]; if ( val0 | val1 | val2 ) { if ( val0 == val1 && val0 == val2 && val0 == max ) { _write[0] = color.chroma[0]; _write[1] = color.chroma[1]; _write[2] = color.chroma[2]; } else { /* compose gray value */ grColor pix; pix.chroma[0] = _write[0]; pix.chroma[1] = _write[1]; pix.chroma[2] = _write[2]; compose_pixel_full( pix, color, val0, val1, val2, max ); _write[0] = pix.chroma[0]; _write[1] = pix.chroma[1]; _write[2] = pix.chroma[2]; } } _write += 3; _read += 3; x--; } read += blit->read_line; write += blit->write_line; y--; } while (y > 0); } /**************************************************************************/ /* */ /* blit_lcdv_to_24 */ /* */ /**************************************************************************/ static void blit_lcdv_to_24( grBlitter* blit, grColor color, int max ) { int y; unsigned char* read; unsigned char* write; long line; read = blit->read + blit->xread; write = blit->write + 3*blit->xwrite; line = blit->read_line; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; int x = blit->width; while (x > 0) { unsigned char val0, val1, val2; val0 = _read[0*line]; val1 = _read[1*line]; val2 = _read[2*line]; if ( val0 | val1 | val2 ) { if ( val0 == val1 && val0 == val2 && val0 == max ) { _write[0] = color.chroma[0]; _write[1] = color.chroma[1]; _write[2] = color.chroma[2]; } else { /* compose gray value */ grColor pix; pix.chroma[0] = _write[0]; pix.chroma[1] = _write[1]; pix.chroma[2] = _write[2]; compose_pixel_full( pix, color, val0, val1, val2, max ); _write[0] = pix.chroma[0]; _write[1] = pix.chroma[1]; _write[2] = pix.chroma[2]; } } _write += 3; _read += 1; x--; } read += 3*line; write += blit->write_line; y--; } while (y > 0); } static void blit_lcdv2_to_24( grBlitter* blit, grColor color, int max ) { int y; unsigned char* read; unsigned char* write; long line; read = blit->read + blit->xread; write = blit->write + 3*blit->xwrite; line = blit->read_line; y = blit->height; do { unsigned char* _read = read; unsigned char* _write = write; int x = blit->width; while (x > 0) { unsigned char val0, val1, val2; val0 = _read[2*line]; val1 = _read[1*line]; val2 = _read[0*line]; if ( val0 | val1 | val2 ) { if ( val0 == val1 && val0 == val2 && val0 == max ) { _write[0] = color.chroma[0]; _write[1] = color.chroma[1]; _write[2] = color.chroma[2]; } else { /* compose gray value */ grColor pix; pix.chroma[0] = _write[0]; pix.chroma[1] = _write[1]; pix.chroma[2] = _write[2]; compose_pixel_full( pix, color, val0, val1, val2, max ); _write[0] = pix.chroma[0]; _write[1] = pix.chroma[1]; _write[2] = pix.chroma[2]; } } _write += 3; _read += 1; x--; } read += 3*line; write += blit->write_line; y--; } while (y > 0); } typedef void (*grColorGlyphBlitter)( grBlitter* blit, grColor color, int max_gray ); static const grColorGlyphBlitter gr_color_blitters[gr_pixel_mode_max] = { 0, 0, 0, 0, 0, blit_gray_to_555, blit_gray_to_565, blit_gray_to_24, blit_gray_to_32 }; #ifdef GRAY8 typedef void (*grGray8GlyphBlitter)( grBlitter* blit, grColor color ); static const grGray8GlyphBlitter gr_gray8_blitters[gr_pixel_mode_max] = { 0, 0, 0, 0, 0, blit_gray8_to_555, blit_gray8_to_565, blit_gray8_to_24, blit_gray8_to_32 }; #endif int grBlitGlyphToBitmap( grBitmap* target, grBitmap* glyph, grPos x, grPos y, grColor color ) { grBlitter blit; grPixelMode mode; /* check arguments */ if ( !target || !glyph ) { grError = gr_err_bad_argument; return -1; } if ( !glyph->rows || !glyph->width ) { /* nothing to do */ return 0; } /* short cut to alpha blender for certain glyph types */ switch ( grBlitGlyphToSurface( (grSurface*)target, glyph, x, y, color ) ) { case 1: return 1; case 0: return 0; } /* set up blitter and compute clipping. Return immediately if needed */ blit.source = *glyph; blit.target = *target; mode = target->mode; if ( compute_clips( &blit, x, y ) ) return 0; switch ( glyph->mode ) { case gr_pixel_mode_mono: /* handle monochrome bitmap blitting */ if ( mode <= gr_pixel_mode_none || mode >= gr_pixel_mode_max ) { grError = gr_err_bad_source_depth; return -1; } gr_mono_blitters[mode]( &blit, color ); break; case gr_pixel_mode_gray: if ( glyph->grays > 1 ) { int target_grays = target->grays; int source_grays = glyph->grays; const byte* saturation; if ( mode == gr_pixel_mode_gray && target_grays > 1 ) { /* rendering into a gray target - use special composition */ /* routines.. */ if ( gr_last_saturation->count == target_grays ) saturation = gr_last_saturation->table; else { saturation = grGetSaturation( target_grays ); if ( !saturation ) return -3; } if ( target_grays == source_grays ) blit_gray_to_gray_simple( &blit, saturation ); else { const byte* conversion; if ( gr_last_conversion->target_grays == target_grays && gr_last_conversion->source_grays == source_grays ) conversion = gr_last_conversion->table; else { conversion = grGetConversion( target_grays, source_grays ); if ( !conversion ) return -3; } blit_gray_to_gray( &blit, saturation, conversion ); } } else { /* rendering into a color target */ if ( mode <= gr_pixel_mode_gray || mode >= gr_pixel_mode_max ) { grError = gr_err_bad_target_depth; return -1; } #ifdef GRAY8 if ( source_grays == 256 ) gr_gray8_blitters[mode]( &blit, color ); else #endif /* GRAY8 */ gr_color_blitters[mode]( &blit, color, source_grays - 1 ); } } break; case gr_pixel_mode_lcd: if ( mode == gr_pixel_mode_rgb24 ) { #ifdef GRAY8 if ( glyph->grays == 256 ) blit_lcd8_to_24( &blit, color ); else #endif if ( glyph->grays > 1 ) blit_lcd_to_24( &blit, color, glyph->grays-1 ); } break; case gr_pixel_mode_lcdv: if ( glyph->grays > 1 && mode == gr_pixel_mode_rgb24 ) { blit_lcdv_to_24( &blit, color, glyph->grays-1 ); break; } /* fall through */ case gr_pixel_mode_lcd2: if ( mode == gr_pixel_mode_rgb24 ) { #ifdef GRAY8 if ( glyph->grays == 256 ) blit_lcd28_to_24( &blit, color ); else #endif if ( glyph->grays > 1 ) blit_lcd2_to_24( &blit, color, glyph->grays-1 ); } break; case gr_pixel_mode_lcdv2: if ( mode == gr_pixel_mode_rgb24 ) { if ( glyph->grays > 1 ) blit_lcdv2_to_24( &blit, color, glyph->grays-1 ); } break; default: /* we don't support the blitting of bitmaps of the following */ /* types : pal4, pal8, rgb555, rgb565, rgb24, rgb32 */ /* */ grError = gr_err_bad_source_depth; return -2; } return 0; } /* End */ ft2demos-2.10.1/graph/gblany.h0000644000175000001440000000750613503605624015721 0ustar00wlusers00000000000000/* check that all macros are correctly set */ #ifndef GDST_INCR #error "GDST_INCR not defined" #endif #ifndef GDST_TYPE #error "GDST_TYPE not defined" #endif #ifndef GDST_READ #error "GDST_READ not defined" #endif #ifdef GBLENDER_STORE_BYTES # ifndef GDST_STOREB # error "GDST_STOREB not defined" # endif #else # ifndef GDST_STOREP # error "GDST_STOREP not defined" # endif #endif /* !STORE_BYTES */ #ifndef GDST_STOREC #error "GDST_STOREC not defined" #endif #ifndef GDST_COPY #error "GDST_COPY not defined" #endif #ifndef GDST_COPY_VAR #error "GDST_COPY_VAR not defined" #endif #undef GCONCAT #undef GCONCATX #define GCONCAT(x,y) GCONCATX(x,y) #define GCONCATX(x,y) x ## y static void GCONCAT( _gblender_spans_, GDST_TYPE )( int y, int count, const grSpan* spans, grSurface* surface ) { GBlenderPixel color = surface->gcolor; GBlender blender = surface->gblender; unsigned int r = (color >> 16) & 255; unsigned int g = (color >> 8) & 255; unsigned int b = (color) & 255; GDST_COPY_VAR #include "gblspans.h" } static void GCONCAT( _gblender_blit_gray8_, GDST_TYPE )( GBlenderBlit blit, GBlenderPixel color ) { GBlender blender = blit->blender; unsigned int r = (color >> 16) & 255; unsigned int g = (color >> 8) & 255; unsigned int b = (color) & 255; GDST_COPY_VAR #include "gblcolor.h" } static void GCONCAT( _gblender_blit_hrgb_, GDST_TYPE )( GBlenderBlit blit, GBlenderPixel color ) { GBlender blender = blit->blender; unsigned int r = (color >> 16) & 255; unsigned int g = (color >> 8) & 255; unsigned int b = (color) & 255; GDST_COPY_VAR #include "gblhrgb.h" } static void GCONCAT( _gblender_blit_hbgr_, GDST_TYPE )( GBlenderBlit blit, GBlenderPixel color ) { GBlender blender = blit->blender; unsigned int r = (color >> 16) & 255; unsigned int g = (color >> 8) & 255; unsigned int b = (color) & 255; GDST_COPY_VAR #include "gblhbgr.h" } static void GCONCAT( _gblender_blit_vrgb_, GDST_TYPE )( GBlenderBlit blit, GBlenderPixel color ) { GBlender blender = blit->blender; unsigned int r = (color >> 16) & 255; unsigned int g = (color >> 8) & 255; unsigned int b = (color) & 255; GDST_COPY_VAR #include "gblvrgb.h" } static void GCONCAT( _gblender_blit_vbgr_, GDST_TYPE )( GBlenderBlit blit, GBlenderPixel color ) { GBlender blender = blit->blender; unsigned int r = (color >> 16) & 255; unsigned int g = (color >> 8) & 255; unsigned int b = (color) & 255; GDST_COPY_VAR #include "gblvbgr.h" } static void GCONCAT( _gblender_blit_bgra_, GDST_TYPE )( GBlenderBlit blit, GBlenderPixel color ) { (void)color; /* unused */ #include "gblbgra.h" } static const GBlenderBlitFunc GCONCAT( blit_funcs_, GDST_TYPE )[GBLENDER_SOURCE_MAX] = { GCONCAT( _gblender_blit_gray8_, GDST_TYPE ), GCONCAT( _gblender_blit_hrgb_, GDST_TYPE ), GCONCAT( _gblender_blit_hbgr_, GDST_TYPE ), GCONCAT( _gblender_blit_vrgb_, GDST_TYPE ), GCONCAT( _gblender_blit_vbgr_, GDST_TYPE ), GCONCAT( _gblender_blit_bgra_, GDST_TYPE ) }; /* unset the macros, to prevent accidental re-use */ #undef GCONCATX #undef GCONCAT #undef GDST_TYPE #undef GDST_INCR #undef GDST_READ #undef GDST_COPY #undef GDST_STOREB #undef GDST_STOREP #undef GDST_STOREC #undef GDST_COPY_VAR /* EOF */ ft2demos-2.10.1/graph/gblblit.c0000644000175000001440000003156013503605624016054 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 1996-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* grblit.c: Support for alpha blending with gamma correction and caching. */ /* */ /****************************************************************************/ #include "grobjs.h" #include "gblblit.h" /* blitting gray glyphs */ /* generic macros */ #define GRGB_PACK(r,g,b) ( ((GBlenderPixel)(r) << 16) | \ ((GBlenderPixel)(g) << 8) | \ (GBlenderPixel)(b) ) #define GDST_STORE3(d,r,g,b) (d)[0] = (unsigned char)(r); \ (d)[1] = (unsigned char)(g); \ (d)[2] = (unsigned char)(b) /* */ #define GRGB_TO_RGB565(r,g,b) ((unsigned short)( (((r) << 8) & 0xF800) | \ (((g) << 3) & 0x07E0) | \ (((b) >> 3) & 0x001F) ) ) #define GRGB565_TO_RGB24(p) ( ( ((p) << 8) & 0xF80000 ) | \ ( ((p) << 3) & 0x0700F8 ) | \ ( ((p) << 5) & 0x00FC00 ) | \ ( ((p) >> 1) & 0x000300 ) | \ ( ((p) >> 2) & 0x000007 ) ) #define GRGB24_TO_RGB565(p) ( (unsigned short)( (((p) >> 8) & 0xF800 ) | \ (((p) >> 5) & 0x07E0 ) | \ (((p) >> 3) & 0x001F ) ) ) /* */ #define GRGB_TO_BGR565(r,g,b) GRGB_TO_RGB565(b,g,r) #define GBGR565_TO_RGB24(p) ( ( ((p) << 19) & 0xF80000 ) | \ ( ((p) << 12) & 0x070000 ) | \ ( ((p) << 5) & 0x00FC00 ) | \ ( ((p) >> 1) & 0x000300 ) | \ ( ((p) >> 8) & 0x0000F8 ) | \ ( ((p) >> 13) & 0x000007 ) ) #define GRGB24_TO_BGR565(p) ( (unsigned short)( (((p) << 8) & 0xF800 ) | \ (((p) >> 5) & 0x07E0 ) | \ (((p) >> 19) & 0x001F ) ) ) /* */ #define GRGB_TO_GRAY8(r,g,b) ( (unsigned char)( ( 2*(r) + 7*(g) + (b) ) / 10 ) ) #define GRGB24_TO_GRAY8(p) ( (unsigned char)( ( 2*( ((p) >> 16) & 0xFF ) + \ 7*( ((p) >> 8) & 0xFF ) + \ ( ((p)) & 0xFF ) ) / 10 ) ) /* */ /* Rgb32 blitting routines */ #define GDST_TYPE rgb32 #define GDST_INCR 4 #define GDST_READ(d,p) (p) = *(GBlenderPixel*)(d) & 0xFFFFFF #define GDST_COPY(d) *(GBlenderPixel*)(d) = color #define GDST_STOREP(d,cells,a) *(GBlenderPixel*)(d) = (cells)[(a)] #define GDST_STOREB(d,cells,a) \ { \ GBlenderCell* _g = (cells) + (a)*3; \ \ GDST_STOREC(d,_g[0],_g[1],_g[2]); \ } #define GDST_STOREC(d,r,g,b) *(GBlenderPixel*)(d) = GRGB_PACK(r,g,b) #define GDST_COPY_VAR /* nothing */ #include "gblany.h" /* Rgb24 blitting routines */ #define GDST_TYPE rgb24 #define GDST_INCR 3 #define GDST_READ(d,p) (p) = GRGB_PACK((d)[0],(d)[1],(d)[2]) #define GDST_COPY(d) GDST_STORE3(d,r,g,b) #define GDST_STOREC(d,r,g,b) GDST_STORE3(d,r,g,b) #define GDST_STOREB(d,cells,a) \ { \ GBlenderCell* _g = (cells) + (a)*3; \ \ (d)[0] = _g[0]; \ (d)[1] = _g[1]; \ (d)[2] = _g[2]; \ } #define GDST_STOREP(d,cells,a) \ { \ GBlenderPixel _pix = (cells)[(a)]; \ \ GDST_STORE3(d,_pix >> 16,_pix >> 8,_pix); \ } #define GDST_COPY_VAR /* nothing */ #include "gblany.h" /* Rgb565 blitting routines */ #define GDST_TYPE rgb565 #define GDST_INCR 2 #define GDST_READ(d,p) p = (GBlenderPixel)*(unsigned short*)(d); \ p = GRGB565_TO_RGB24(p) #define GDST_COPY_VAR unsigned short pix = GRGB_TO_RGB565(r,g,b); #define GDST_COPY(d) *(unsigned short*)(d) = pix #define GDST_STOREB(d,cells,a) \ { \ GBlenderCell* _g = (cells) + (a)*3; \ \ *(unsigned short*)(d) = GRGB_TO_RGB565(_g[0],_g[1],_g[2]); \ } #define GDST_STOREP(d,cells,a) \ { \ GBlenderPixel _pix = (cells)[(a)]; \ \ *(unsigned short*)(d) = GRGB24_TO_RGB565(_pix); \ } #define GDST_STOREC(d,r,g,b) *(unsigned short*)(d) = GRGB_TO_RGB565(r,g,b) #include "gblany.h" /* Bgr565 blitting routines */ #define GDST_TYPE bgr565 #define GDST_INCR 2 #define GDST_READ(d,p) p = (GBlenderPixel)*(unsigned short*)(d); \ p = GBGR565_TO_RGB24(p) #define GDST_COPY_VAR unsigned short pix = GRGB_TO_BGR565(r,g,b); #define GDST_COPY(d) *(d) = (unsigned char)pix #define GDST_STOREB(d,cells,a) \ { \ GBlenderCell* _g = (cells) + (a)*3; \ \ *(unsigned short*)(d) = GRGB_TO_BGR565(_g[0],_g[1],_g[2]); \ } #define GDST_STOREP(d,cells,a) \ { \ GBlenderPixel _pix = (cells)[(a)]; \ \ *(unsigned short*)(d) = GRGB24_TO_BGR565(_pix); \ } #define GDST_STOREC(d,r,g,b) *(unsigned short*)(d) = GRGB_TO_BGR565(r,g,b) #include "gblany.h" /* Gray8 blitting routines */ #define GDST_TYPE gray8 #define GDST_INCR 1 #define GDST_READ(d,p) (p) = GRGB_PACK((d)[0],(d)[0],(d)[0]) #define GDST_COPY_VAR /* nothing */ #define GDST_COPY(d) *(d) = GRGB_TO_GRAY8(r,g,b) #define GDST_STOREB(d,cells,a) \ { \ GBlenderCell* _g = (cells) + (a)*3; \ \ *(d) = GRGB_TO_GRAY8(_g[0],_g[1],_g[2]); \ } #define GDST_STOREP(d,cells,a) \ { \ GBlenderPixel _pix = (cells)[(a)]; \ \ *(d) = GRGB24_TO_GRAY8(_pix); \ } #define GDST_STOREC(d,r,g,b) *(d) = GRGB_TO_GRAY8(r,g,b) #include "gblany.h" /* */ static const GBlenderBlitFunc* blit_funcs[GBLENDER_TARGET_MAX] = { blit_funcs_gray8, blit_funcs_rgb32, blit_funcs_rgb24, blit_funcs_rgb565, blit_funcs_bgr565 }; static void _gblender_blit_dummy( GBlenderBlit blit, GBlenderPixel color ) { (void)blit; (void)color; } static int gblender_blit_init( GBlenderBlit blit, int dst_x, int dst_y, grSurface* surface, grBitmap* glyph ) { int src_x = 0; int src_y = 0; int delta; grBitmap* target = (grBitmap*)surface; GBlenderSourceFormat src_format; const unsigned char* src_buffer = glyph->buffer; int src_pitch = glyph->pitch; int src_width = glyph->width; int src_height = glyph->rows; GBlenderTargetFormat dst_format; unsigned char* dst_buffer = target->buffer; int dst_pitch = target->pitch; int dst_width = target->width; int dst_height = target->rows; if ( glyph->grays != 256 ) return -2; switch ( glyph->mode ) { case gr_pixel_mode_gray: src_format = GBLENDER_SOURCE_GRAY8; break; case gr_pixel_mode_lcd: src_format = GBLENDER_SOURCE_HRGB; break; case gr_pixel_mode_lcdv: src_format = GBLENDER_SOURCE_VRGB; break; case gr_pixel_mode_lcd2: src_format = GBLENDER_SOURCE_HBGR; break; case gr_pixel_mode_lcdv2: src_format = GBLENDER_SOURCE_VBGR; break; case gr_pixel_mode_bgra: src_format = GBLENDER_SOURCE_BGRA; break; default: return -2; } switch ( target->mode ) { case gr_pixel_mode_gray: dst_format = GBLENDER_TARGET_GRAY8; break; case gr_pixel_mode_rgb32: dst_format = GBLENDER_TARGET_RGB32; break; case gr_pixel_mode_rgb24: dst_format = GBLENDER_TARGET_RGB24; break; case gr_pixel_mode_rgb565: dst_format = GBLENDER_TARGET_RGB565; break; default: return -2; } blit->blender = surface->gblender; blit->blit_func = blit_funcs[dst_format][src_format]; if ( blit->blit_func == 0 ) { /* unsupported blit mode */ blit->blit_func = _gblender_blit_dummy; return -2; } if ( glyph->mode == gr_pixel_mode_lcd || glyph->mode == gr_pixel_mode_lcd2 ) src_width /= 3; if ( glyph->mode == gr_pixel_mode_lcdv || glyph->mode == gr_pixel_mode_lcdv2 ) src_height /= 3; if ( dst_x < 0 ) { src_width += dst_x; src_x -= dst_x; dst_x = 0; } delta = dst_x + src_width - dst_width; if ( delta > 0 ) src_width -= delta; if ( dst_y < 0 ) { src_height += dst_y; src_y -= dst_y; dst_y = 0; } delta = dst_y + src_height - dst_height; if ( delta > 0 ) src_height -= delta; /* nothing to blit */ if ( src_width <= 0 || src_height <= 0 ) { blit->blit_func = _gblender_blit_dummy; return -1; } blit->width = src_width; blit->height = src_height; blit->src_format = src_format; blit->dst_format = dst_format; blit->src_x = src_x; blit->src_y = src_y; blit->src_line = src_buffer + src_pitch*src_y; blit->src_pitch = src_pitch; if ( src_pitch < 0 ) blit->src_line -= (src_height-1)*src_pitch; blit->dst_x = dst_x; blit->dst_y = dst_y; blit->dst_line = dst_buffer + dst_pitch*dst_y; blit->dst_pitch = dst_pitch; if ( dst_pitch < 0 ) blit->dst_line -= (dst_height-1)*dst_pitch; return 0; } GBLENDER_APIDEF( int ) grBlitGlyphToSurface( grSurface* surface, grBitmap* glyph, grPos x, grPos y, grColor color ) { GBlenderBlitRec gblit[1]; GBlenderPixel gcolor; /* check arguments */ if ( !surface || !glyph ) { grError = gr_err_bad_argument; return -1; } if ( !glyph->rows || !glyph->width ) { /* nothing to do */ return 0; } switch ( gblender_blit_init( gblit, x, y, surface, glyph ) ) { case -1: /* nothing to do */ return 0; case -2: return -1; } gcolor = ((GBlenderPixel)color.chroma[0] << 16) | ((GBlenderPixel)color.chroma[1] << 8 ) | ((GBlenderPixel)color.chroma[2] ) ; gblender_blit_run( gblit, gcolor ); return 1; } GBLENDER_APIDEF( void ) grSetTargetGamma( grBitmap* target, double gamma ) { grSurface* surface = (grSurface*)target; gblender_init( surface->gblender, gamma ); /* not related to gamma but needs to be set */ switch ( target->mode ) { case gr_pixel_mode_gray: surface->gray_spans = _gblender_spans_gray8; break; case gr_pixel_mode_rgb32: surface->gray_spans = _gblender_spans_rgb32; break; case gr_pixel_mode_rgb24: surface->gray_spans = _gblender_spans_rgb24; break; case gr_pixel_mode_rgb565: surface->gray_spans = _gblender_spans_rgb565; break; default: (void)_gblender_spans_bgr565; /* unused */ surface->gray_spans = (grSpanFunc)0; } } ft2demos-2.10.1/graph/gblspans.h0000644000175000001440000000156013503605624016250 0ustar00wlusers00000000000000 GBLENDER_VARS; unsigned char* dst_origin = surface->origin - y * surface->bitmap.pitch; gblender_use_channels( blender, 0 ); GBLENDER_VARS_SET(blender,color); /* make compiler happy */ (void)(r); (void)(g); (void)(b); for ( ; count--; spans++ ) { unsigned char* dst = dst_origin + spans->x * GDST_INCR; unsigned short w = spans->len; int a = GBLENDER_SHADE_INDEX( spans->coverage ); if ( a == GBLENDER_SHADE_COUNT-1 ) for ( ; w-- ; dst += GDST_INCR ) { GDST_COPY(dst); } else if ( a ) for ( ; w-- ; dst += GDST_INCR ) { GBlenderPixel back; GDST_READ(dst,back); GBLENDER_LOOKUP( blender, back ); #ifdef GBLENDER_STORE_BYTES GDST_STOREB(dst,_gcells,a); #else GDST_STOREP(dst,_gcells,a); #endif } } GBLENDER_CLOSE(blender); ft2demos-2.10.1/graph/grobjs.h0000644000175000001440000001173313503605624015730 0ustar00wlusers00000000000000/*************************************************************************** * * grobjs.h * * basic object classes definitions * * Copyright (C) 1999 by * The FreeType Development Team - www.freetype.org * * * * ***************************************************************************/ #ifndef GROBJS_H_ #define GROBJS_H_ #include "graph.h" #include "grconfig.h" #include "grtypes.h" #include "gblender.h" typedef struct grBiColor_ { grColor foreground; grColor background; int num_levels; int max_levels; grColor* levels; } grBiColor; /********************************************************************** * * Technical note : explaining how the blitter works. * * The blitter is used to "draw" a given source bitmap into * a given target bitmap. * * The function called 'compute_clips' is used to compute clipping * constraints. These lead us to compute two areas : * * - the read area : is the rectangle, within the source bitmap, * which will be effectively "drawn" in the * target bitmap. * * - the write area : is the rectangle, within the target bitmap, * which will effectively "receive" the pixels * from the read area * * Note that both areas have the same dimensions, but are * located in distinct surfaces. * * These areas are computed by 'compute_clips' which is called * by each blitting function. * * Note that we use the Y-downwards convention within the blitter * **********************************************************************/ typedef struct grBlitter_ { int width; /* width in pixels of the areas */ int height; /* height in pixels of the areas */ int xread; /* x position of start point in read area */ int yread; /* y position of start point in read area */ int xwrite; /* x position of start point in write area */ int ywrite; /* y position of start point in write area */ int right_clip; /* amount of right clip */ unsigned char* read; /* top left corner of read area in source map */ unsigned char* write; /* top left corner of write area in target map */ int read_line; /* byte increment to go down one row in read area */ int write_line; /* byte increment to go down one row in write area */ grBitmap source; /* source bitmap descriptor */ grBitmap target; /* target bitmap descriptor */ } grBlitter; typedef void (*grBlitterFunc)( grBlitter* blitter, grColor color ); typedef void (*grSetTitleFunc)( grSurface* surface, const char* title_string ); typedef void (*grRefreshRectFunc)( grSurface* surface, int x, int y, int width, int height ); typedef void (*grDoneSurfaceFunc)( grSurface* surface ); typedef int (*grListenEventFunc)( grSurface* surface, int event_mode, grEvent *event ); typedef struct grSpan_ { short x; unsigned short len; unsigned char coverage; } grSpan; typedef void (*grSpanFunc)( int y, int count, const grSpan* spans, grSurface* surface ); struct grSurface_ { grBitmap bitmap; GBlenderRec gblender[1]; unsigned char* origin; /* span origin */ GBlenderPixel gcolor; /* span color */ grSpanFunc gray_spans; /* span function */ grDevice* device; grBool refresh; grBool owner; const byte* saturation; /* used for gray surfaces only */ grBlitterFunc blit_mono; /* 0 by default, set by grBlit.. */ grRefreshRectFunc refresh_rect; grSetTitleFunc set_title; grListenEventFunc listen_event; grDoneSurfaceFunc done; }; /******************************************************************** * * * grAlloc * * * Simple memory allocation. The returned block is always zero-ed * * * size :: size in bytes of the requested block * * * the memory block address. 0 in case of error * ********************************************************************/ extern unsigned char* grAlloc( unsigned long size ); /******************************************************************** * * * grFree * * * Simple memory release * * * block :: target block * ********************************************************************/ extern void grFree( const void* block ); #endif /* GROBJS_H_ */ ft2demos-2.10.1/graph/rules.mk0000644000175000001440000000637013503605624015755 0ustar00wlusers00000000000000#************************************************************************** #* #* FreeType demo utilities sub-Makefile #* #* This Makefile is to be included by `../Makefile'. Its #* purpose is to compile MiGS (the Minimalist Graphics Subsystem). #* #* It is written for GNU Make. Other make utilities are not #* supported! #* #************************************************************************** GRAPH_INCLUDES := $(subst /,$(COMPILER_SEP),$(TOP_DIR_2)/graph) GRAPH_LIB := $(OBJ_DIR_2)/graph.$(SA) GRAPH := $(TOP_DIR_2)/graph GRAPH_H := $(GRAPH)/gblany.h \ $(GRAPH)/gblbgra.h \ $(GRAPH)/gblblit.h \ $(GRAPH)/gblspans.h \ $(GRAPH)/gblcolor.h \ $(GRAPH)/gblhbgr.h \ $(GRAPH)/gblhrgb.h \ $(GRAPH)/gblvbgr.h \ $(GRAPH)/gblvrgb.h \ $(GRAPH)/gblender.h \ $(GRAPH)/graph.h \ $(GRAPH)/grblit.h \ $(GRAPH)/grconfig.h \ $(GRAPH)/grdevice.h \ $(GRAPH)/grevents.h \ $(GRAPH)/grfont.h \ $(GRAPH)/grobjs.h \ $(GRAPH)/grswizzle.h \ $(GRAPH)/grtypes.h GRAPH_OBJS := $(OBJ_DIR_2)/gblblit.$(O) \ $(OBJ_DIR_2)/gblender.$(O) \ $(OBJ_DIR_2)/grblit.$(O) \ $(OBJ_DIR_2)/grdevice.$(O) \ $(OBJ_DIR_2)/grfill.$(O) \ $(OBJ_DIR_2)/grfont.$(O) \ $(OBJ_DIR_2)/grinit.$(O) \ $(OBJ_DIR_2)/grobjs.$(O) \ $(OBJ_DIR_2)/grswizzle.$(O) # Default value for COMPILE_GRAPH_LIB; # this value can be modified by the system-specific graphics drivers. # ifneq ($(LIBTOOL),) COMPILE_GRAPH_LIB = $(LIBTOOL) --mode=link $(CCraw) -static \ -o $(subst /,$(COMPILER_SEP),$@ $(GRAPH_OBJS)) else COMPILE_GRAPH_LIB = ar -r $(subst /,$(COMPILER_SEP),$@ $(GRAPH_OBJS)) endif # Add the rules used to detect and compile graphics driver depending # on the current platform. # include $(wildcard $(TOP_DIR_2)/graph/*/rules.mk) ######################################################################### # # Build the `graph' library from its objects. This should be changed # in the future in order to support more systems. Probably something # like a `config/' hierarchy with a system-specific rules file # to indicate how to make a library file, but for now, I'll stick to # unix, Win32, and OS/2-gcc. # # $(GRAPH_LIB): $(GRAPH_OBJS) $(COMPILE_GRAPH_LIB) # pattern rule for normal sources # $(OBJ_DIR_2)/%.$(O): $(GRAPH)/%.c $(GRAPH_H) ifneq ($(LIBTOOL),) $(LIBTOOL) --mode=compile $(CC) -static $(CFLAGS) \ $(GRAPH_INCLUDES:%=$I%) $T$@ $< else $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) $T$@ $< endif # a special rule is used for 'grinit.o' as it needs the definition # of some macros like "-DDEVICE_X11" or "-DDEVICE_OS2_PM" # $(OBJ_DIR_2)/grinit.$(O): $(GRAPH)/grinit.c $(GRAPH_H) ifneq ($(LIBTOOL),) $(LIBTOOL) --mode=compile $(CC) -static \ $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) \ $(DEVICES:%=$DDEVICE_%) $T$(subst /,$(COMPILER_SEP),$@ $<) else $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) \ $(DEVICES:%=$DDEVICE_%) $T$(subst /,$(COMPILER_SEP),$@ $<) endif # EOF ft2demos-2.10.1/objs/0000755000175000001440000000000013506426605014123 5ustar00wlusers00000000000000ft2demos-2.10.1/objs/README0000644000175000001440000000012613434207203014771 0ustar00wlusers00000000000000This directory contains all the object files generated for the demonstration programs ft2demos-2.10.1/src/0000755000175000001440000000000013506426605013755 5ustar00wlusers00000000000000ft2demos-2.10.1/src/ftinspect/0000755000175000001440000000000013506426605015754 5ustar00wlusers00000000000000ft2demos-2.10.1/src/ftinspect/widgets/0000755000175000001440000000000013506426605017422 5ustar00wlusers00000000000000ft2demos-2.10.1/src/ftinspect/widgets/qpushbuttonx.cpp0000644000175000001440000000140613434207203022702 0ustar00wlusers00000000000000// qpushbuttonx.cpp // Copyright (C) 2016-2019 by Werner Lemberg. #include "qpushbuttonx.hpp" #include // code derived from Qt 4.8.7, function `QPushButton::sizeHint', // file `src/gui/widgets/qpushbutton.cpp' QPushButtonx::QPushButtonx(const QString &text, QWidget *parent) : QPushButton(text, parent) { QStyleOptionButton opt; opt.initFrom(this); QString s(this->text()); QFontMetrics fm = fontMetrics(); QSize sz = fm.size(Qt::TextShowMnemonic, s); opt.rect.setSize(sz); sz = style()->sizeFromContents(QStyle::CT_PushButton, &opt, sz, this); setFixedWidth(sz.width()); } // end of qpushbuttonx.cpp ft2demos-2.10.1/src/ftinspect/widgets/qspinboxx.cpp0000644000175000001440000000306613434207203022155 0ustar00wlusers00000000000000// qspinboxx.cpp // Copyright (C) 2016-2019 by Werner Lemberg. #include "qspinboxx.hpp" // we want to mark the center of a pixel square with a single dot or a small // cross; starting with a certain magnification we thus only use even values // so that we can do that symmetrically int QSpinBoxx::valueFromText(const QString& text) const { int val = QSpinBox::valueFromText(text); if (val > 640) val = val - (val % 64); else if (val > 320) val = val - (val % 32); else if (val > 160) val = val - (val % 16); else if (val > 80) val = val - (val % 8); else if (val > 40) val = val - (val % 4); else if (val > 20) val = val - (val % 2); return val; } void QSpinBoxx::stepBy(int steps) { int val = value(); if (steps > 0) { for (int i = 0; i < steps; i++) { if (val >= 640) val = val + 64; else if (val >= 320) val = val + 32; else if (val >= 160) val = val + 16; else if (val >= 80) val = val + 8; else if (val >= 40) val = val + 4; else if (val >= 20) val = val + 2; else val++; } } else if (steps < 0) { for (int i = 0; i < -steps; i++) { if (val > 640) val = val - 64; else if (val > 320) val = val - 32; else if (val > 160) val = val - 16; else if (val > 80) val = val - 8; else if (val > 40) val = val - 4; else if (val > 20) val = val - 2; else val--; } } setValue(val); } // end of qspinboxx.cpp ft2demos-2.10.1/src/ftinspect/widgets/qcomboboxx.cpp0000644000175000001440000000152513434207203022301 0ustar00wlusers00000000000000// qcomboboxx.cpp // Copyright (C) 2016-2019 by Werner Lemberg. #include "qcomboboxx.hpp" #include void QComboBoxx::setItemEnabled(int index, bool enable) { const QStandardItemModel* itemModel = qobject_cast(model()); QStandardItem* item = itemModel->item(index); if (enable) { item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); item->setData(QVariant(), Qt::TextColorRole); } else { item->setFlags(item->flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsEnabled)); // clear item data in order to use default color; // this visually greys out the item item->setData(palette().color(QPalette::Disabled, QPalette::Text), Qt::TextColorRole); } } // end of qcomboboxx.cpp ft2demos-2.10.1/src/ftinspect/widgets/qpushbuttonx.hpp0000644000175000001440000000054613434207203022713 0ustar00wlusers00000000000000// qpushbuttonx.hpp // Copyright (C) 2016-2019 by Werner Lemberg. #pragma once #include // we want buttons that are horizontally as small as possible class QPushButtonx : public QPushButton { Q_OBJECT public: QPushButtonx(const QString& text, QWidget* = 0); virtual ~QPushButtonx(){} }; // end of qpushbuttonx.hpp ft2demos-2.10.1/src/ftinspect/widgets/qspinboxx.hpp0000644000175000001440000000052213434207203022154 0ustar00wlusers00000000000000// qspinboxx.hpp // Copyright (C) 2016-2019 by Werner Lemberg. #pragma once #include #include // we want to have our own `stepBy' function for the zoom spin box class QSpinBoxx : public QSpinBox { Q_OBJECT public: void stepBy(int val); int valueFromText(const QString& text) const; }; // qspinboxx.hpp ft2demos-2.10.1/src/ftinspect/widgets/qcomboboxx.hpp0000644000175000001440000000056413434207203022310 0ustar00wlusers00000000000000// qcomboboxx.hpp // Copyright (C) 2016-2019 by Werner Lemberg. #pragma once #include // we want to grey out items in a combo box; // since Qt doesn't provide a function for this we derive a class class QComboBoxx : public QComboBox { Q_OBJECT public: void setItemEnabled(int index, bool enable); }; // end of qcomboboxx.hpp ft2demos-2.10.1/src/ftinspect/widgets/qgraphicsviewx.hpp0000644000175000001440000000101013434207203023156 0ustar00wlusers00000000000000// qgraphicsviewx.hpp // Copyright (C) 2016-2019 by Werner Lemberg. #pragma once #include // we want to anchor the view at the bottom left corner // while the windows gets resized class QGraphicsViewx : public QGraphicsView { Q_OBJECT public: QGraphicsViewx(); protected: void resizeEvent(QResizeEvent* event); void scrollContentsBy(int dx, int dy); private: QPointF lastBottomLeftPoint; bool lastBottomLeftPointInitialized; }; // end of qgraphicsviewx.hpp ft2demos-2.10.1/src/ftinspect/widgets/qgraphicsviewx.cpp0000644000175000001440000000216613434207203023166 0ustar00wlusers00000000000000// qgraphicsviewx.hpp // Copyright (C) 2016-2019 by Werner Lemberg. #include "qgraphicsviewx.hpp" #include QGraphicsViewx::QGraphicsViewx() : lastBottomLeftPointInitialized(false) { // empty } void QGraphicsViewx::scrollContentsBy(int dx, int dy) { QGraphicsView::scrollContentsBy(dx, dy); lastBottomLeftPoint = viewport()->rect().bottomLeft(); } void QGraphicsViewx::resizeEvent(QResizeEvent* event) { QGraphicsView::resizeEvent(event); // XXX I don't know how to properly initialize this value, // thus the hack with the boolean if (!lastBottomLeftPointInitialized) { lastBottomLeftPoint = viewport()->rect().bottomLeft(); lastBottomLeftPointInitialized = true; } QPointF currentBottomLeftPoint = viewport()->rect().bottomLeft(); int verticalPosition = verticalScrollBar()->value(); verticalScrollBar()->setValue(static_cast( verticalPosition - (currentBottomLeftPoint.y() - lastBottomLeftPoint.y()))); } // end of qgraphicsviewx.cpp ft2demos-2.10.1/src/ftinspect/engine/0000755000175000001440000000000013506426605017221 5ustar00wlusers00000000000000ft2demos-2.10.1/src/ftinspect/engine/engine.cpp0000644000175000001440000003637713503605615021207 0ustar00wlusers00000000000000// engine.cpp // Copyright (C) 2016-2019 by Werner Lemberg. #include "engine.hpp" #include "../maingui.hpp" #include #include #include FT_DRIVER_H #include FT_LCD_FILTER_H // internal FreeType header files; only available in the source code bundle #include FT_INTERNAL_DRIVER_H #include FT_INTERNAL_OBJECTS_H ///////////////////////////////////////////////////////////////////////////// // // FaceID // ///////////////////////////////////////////////////////////////////////////// FaceID::FaceID() : fontIndex(-1), faceIndex(-1), namedInstanceIndex(-1) { // empty } FaceID::FaceID(int fontIdx, long faceIdx, int namedInstanceIdx) : fontIndex(fontIdx), faceIndex(faceIdx), namedInstanceIndex(namedInstanceIdx) { // empty } bool FaceID::operator<(const FaceID& other) const { bool ret = false; if (fontIndex < other.fontIndex) ret = true; else if (fontIndex == other.fontIndex) { if (faceIndex < other.faceIndex) ret = true; else if (faceIndex == other.faceIndex) { if (namedInstanceIndex < other.namedInstanceIndex) ret = true; } } return ret; } // The face requester is a function provided by the client application to // the cache manager to translate an `abstract' face ID into a real // `FT_Face' object. // // We use a map: `faceID' is the value, and its associated key gives the // font, face, and named instance indices. Getting a key from a value is // slow, but this must be done only once, since `faceRequester' is only // called if the font is not yet in the cache. FT_Error faceRequester(FTC_FaceID ftcFaceID, FT_Library library, FT_Pointer requestData, FT_Face* faceP) { MainGUI* gui = static_cast(requestData); // `ftcFaceID' is actually an integer // -> first convert pointer to same-width integer, then discard superfluous // bits (e.g., on x86_64 where pointers are wider than int) int val = static_cast(reinterpret_cast(ftcFaceID)); // make sure this does not cause information loss Q_ASSERT_X(sizeof(void*) >= sizeof(int), "faceRequester", "Pointer size must be at least the size of int" " in order to treat FTC_FaceID correctly"); const FaceID& faceID = gui->engine->faceIDMap.key(val); // this is the only place where we have to check the validity of the font // index; note that the validity of both the face and named instance index // is checked by FreeType itself if (faceID.fontIndex < 0 || faceID.fontIndex >= gui->fontList.size()) return FT_Err_Invalid_Argument; QString& font = gui->fontList[faceID.fontIndex]; long faceIndex = faceID.faceIndex; if (faceID.namedInstanceIndex > 0) faceIndex += faceID.namedInstanceIndex << 16; return FT_New_Face(library, qPrintable(font), faceIndex, faceP); } ///////////////////////////////////////////////////////////////////////////// // // Engine // ///////////////////////////////////////////////////////////////////////////// Engine::Engine(MainGUI* g) { gui = g; ftSize = NULL; // we reserve value 0 for the `invalid face ID' faceCounter = 1; FT_Error error; error = FT_Init_FreeType(&library); if (error) { // XXX error handling } error = FTC_Manager_New(library, 0, 0, 0, faceRequester, gui, &cacheManager); if (error) { // XXX error handling } error = FTC_SBitCache_New(cacheManager, &sbitsCache); if (error) { // XXX error handling } error = FTC_ImageCache_New(cacheManager, &imageCache); if (error) { // XXX error handling } // query engines and check for alternatives // CFF error = FT_Property_Get(library, "cff", "hinting-engine", &cffHintingEngineDefault); if (error) { // no CFF engine cffHintingEngineDefault = -1; cffHintingEngineOther = -1; } else { int engines[] = { FT_HINTING_FREETYPE, FT_HINTING_ADOBE }; int i; for (i = 0; i < 2; i++) if (cffHintingEngineDefault == engines[i]) break; cffHintingEngineOther = engines[(i + 1) % 2]; error = FT_Property_Set(library, "cff", "hinting-engine", &cffHintingEngineOther); if (error) cffHintingEngineOther = -1; // reset FT_Property_Set(library, "cff", "hinting-engine", &cffHintingEngineDefault); } // TrueType error = FT_Property_Get(library, "truetype", "interpreter-version", &ttInterpreterVersionDefault); if (error) { // no TrueType engine ttInterpreterVersionDefault = -1; ttInterpreterVersionOther = -1; ttInterpreterVersionOther1 = -1; } else { int interpreters[] = { TT_INTERPRETER_VERSION_35, TT_INTERPRETER_VERSION_38, TT_INTERPRETER_VERSION_40 }; int i; for (i = 0; i < 3; i++) if (ttInterpreterVersionDefault == interpreters[i]) break; ttInterpreterVersionOther = interpreters[(i + 1) % 3]; error = FT_Property_Set(library, "truetype", "interpreter-version", &ttInterpreterVersionOther); if (error) ttInterpreterVersionOther = -1; ttInterpreterVersionOther1 = interpreters[(i + 2) % 3]; error = FT_Property_Set(library, "truetype", "interpreter-version", &ttInterpreterVersionOther1); if (error) ttInterpreterVersionOther1 = -1; // reset FT_Property_Set(library, "truetype", "interpreter-version", &ttInterpreterVersionDefault); } // auto-hinter error = FT_Property_Get(library, "autofitter", "warping", &doWarping); if (error) { // no warping haveWarping = 0; doWarping = 0; } else { haveWarping = 1; doWarping = 0; // we don't do warping by default FT_Property_Set(library, "autofitter", "warping", &doWarping); } } Engine::~Engine() { FTC_Manager_Done(cacheManager); FT_Done_FreeType(library); } long Engine::numberOfFaces(int fontIndex) { FT_Face face; long numFaces = -1; // search triplet (fontIndex, 0, 0) FTC_FaceID ftcFaceID = reinterpret_cast (faceIDMap.value(FaceID(fontIndex, 0, 0))); if (ftcFaceID) { // found if (!FTC_Manager_LookupFace(cacheManager, ftcFaceID, &face)) numFaces = face->num_faces; } else { // not found; try to load triplet (fontIndex, 0, 0) ftcFaceID = reinterpret_cast(faceCounter); faceIDMap.insert(FaceID(fontIndex, 0, 0), faceCounter++); if (!FTC_Manager_LookupFace(cacheManager, ftcFaceID, &face)) numFaces = face->num_faces; else { faceIDMap.remove(FaceID(fontIndex, 0, 0)); faceCounter--; } } return numFaces; } int Engine::numberOfNamedInstances(int fontIndex, long faceIndex) { FT_Face face; // we return `n' named instances plus one; // instance index 0 represents a face without a named instance selected int numNamedInstances = -1; // search triplet (fontIndex, faceIndex, 0) FTC_FaceID ftcFaceID = reinterpret_cast (faceIDMap.value(FaceID(fontIndex, faceIndex, 0))); if (ftcFaceID) { // found if (!FTC_Manager_LookupFace(cacheManager, ftcFaceID, &face)) numNamedInstances = static_cast((face->style_flags >> 16) + 1); } else { // not found; try to load triplet (fontIndex, faceIndex, 0) ftcFaceID = reinterpret_cast(faceCounter); faceIDMap.insert(FaceID(fontIndex, faceIndex, 0), faceCounter++); if (!FTC_Manager_LookupFace(cacheManager, ftcFaceID, &face)) numNamedInstances = static_cast((face->style_flags >> 16) + 1); else { faceIDMap.remove(FaceID(fontIndex, faceIndex, 0)); faceCounter--; } } return numNamedInstances; } int Engine::loadFont(int fontIndex, long faceIndex, int namedInstanceIndex) { int numGlyphs = -1; fontType = FontType_Other; update(); // search triplet (fontIndex, faceIndex, namedInstanceIndex) scaler.face_id = reinterpret_cast (faceIDMap.value(FaceID(fontIndex, faceIndex, namedInstanceIndex))); if (scaler.face_id) { // found if (!FTC_Manager_LookupSize(cacheManager, &scaler, &ftSize)) numGlyphs = ftSize->face->num_glyphs; } else { // not found; try to load triplet // (fontIndex, faceIndex, namedInstanceIndex) scaler.face_id = reinterpret_cast(faceCounter); faceIDMap.insert(FaceID(fontIndex, faceIndex, namedInstanceIndex), faceCounter++); if (!FTC_Manager_LookupSize(cacheManager, &scaler, &ftSize)) numGlyphs = ftSize->face->num_glyphs; else { faceIDMap.remove(FaceID(fontIndex, faceIndex, namedInstanceIndex)); faceCounter--; } } if (numGlyphs < 0) { ftSize = NULL; curFamilyName = QString(); curStyleName = QString(); } else { curFamilyName = QString(ftSize->face->family_name); curStyleName = QString(ftSize->face->style_name); FT_Module module = &ftSize->face->driver->root; const char* moduleName = module->clazz->module_name; // XXX cover all available modules if (!strcmp(moduleName, "cff")) fontType = FontType_CFF; else if (!strcmp(moduleName, "truetype")) fontType = FontType_TrueType; } return numGlyphs; } void Engine::removeFont(int fontIndex) { // we iterate over all triplets that contain the given font index // and remove them QMap::iterator iter = faceIDMap.lowerBound(FaceID(fontIndex, 0, 0)); for (;;) { if (iter == faceIDMap.end()) break; FaceID faceID = iter.key(); if (faceID.fontIndex != fontIndex) break; FTC_FaceID ftcFaceID = reinterpret_cast(iter.value()); FTC_Manager_RemoveFaceID(cacheManager, ftcFaceID); iter = faceIDMap.erase(iter); } } const QString& Engine::currentFamilyName() { return curFamilyName; } const QString& Engine::currentStyleName() { return curStyleName; } QString Engine::glyphName(int index) { QString name; if (index < 0) throw std::runtime_error("Invalid glyph index"); if (ftSize && FT_HAS_GLYPH_NAMES(ftSize->face)) { char buffer[256]; if (!FT_Get_Glyph_Name(ftSize->face, static_cast(index), buffer, sizeof(buffer))) name = QString(buffer); } return name; } FT_Outline* Engine::loadOutline(int glyphIndex) { update(); if (glyphIndex < 0) throw std::runtime_error("Invalid glyph index"); FT_Glyph glyph; // XXX handle bitmap fonts // the `scaler' object is set up by the // `update' and `loadFont' methods if (FTC_ImageCache_LookupScaler(imageCache, &scaler, loadFlags | FT_LOAD_NO_BITMAP, static_cast(glyphIndex), &glyph, NULL)) { // XXX error handling? return NULL; } if (glyph->format != FT_GLYPH_FORMAT_OUTLINE) return NULL; FT_OutlineGlyph outlineGlyph = reinterpret_cast(glyph); return &outlineGlyph->outline; } void Engine::setCFFHintingMode(int mode) { int index = gui->hintingModesCFFHash.key(mode); FT_Error error = FT_Property_Set(library, "cff", "hinting-engine", &index); if (!error) { // reset the cache FTC_Manager_Reset(cacheManager); } } void Engine::setTTInterpreterVersion(int mode) { int index = gui->hintingModesTrueTypeHash.key(mode); FT_Error error = FT_Property_Set(library, "truetype", "interpreter-version", &index); if (!error) { // reset the cache FTC_Manager_Reset(cacheManager); } } void Engine::update() { // Spinbox value cannot become negative dpi = static_cast(gui->dpiSpinBox->value()); if (gui->unitsComboBox->currentIndex() == MainGUI::Units_px) { pixelSize = gui->sizeDoubleSpinBox->value(); pointSize = pixelSize * 72.0 / dpi; } else { pointSize = gui->sizeDoubleSpinBox->value(); pixelSize = pointSize * dpi / 72.0; } doHinting = gui->hintingCheckBox->isChecked(); doAutoHinting = gui->autoHintingCheckBox->isChecked(); doHorizontalHinting = gui->horizontalHintingCheckBox->isChecked(); doVerticalHinting = gui->verticalHintingCheckBox->isChecked(); doBlueZoneHinting = gui->blueZoneHintingCheckBox->isChecked(); showSegments = gui->segmentDrawingCheckBox->isChecked(); doWarping = gui->warpingCheckBox->isChecked(); gamma = gui->gammaSlider->value(); loadFlags = FT_LOAD_DEFAULT; if (doAutoHinting) loadFlags |= FT_LOAD_FORCE_AUTOHINT; loadFlags |= FT_LOAD_NO_BITMAP; // XXX handle bitmap fonts also int index = gui->antiAliasingComboBoxx->currentIndex(); if (doHinting) { unsigned long target; if (index == MainGUI::AntiAliasing_None) target = FT_LOAD_TARGET_MONO; else { switch (index) { case MainGUI::AntiAliasing_Light: target = FT_LOAD_TARGET_LIGHT; break; case MainGUI::AntiAliasing_LCD: case MainGUI::AntiAliasing_LCD_BGR: target = FT_LOAD_TARGET_LCD; break; case MainGUI::AntiAliasing_LCD_Vertical: case MainGUI::AntiAliasing_LCD_Vertical_BGR: target = FT_LOAD_TARGET_LCD_V; break; default: target = FT_LOAD_TARGET_NORMAL; } } loadFlags |= target; } else { loadFlags |= FT_LOAD_NO_HINTING; if (index == MainGUI::AntiAliasing_None) loadFlags |= FT_LOAD_MONOCHROME; } // XXX handle color fonts also scaler.pixel = 0; // use 26.6 format if (gui->unitsComboBox->currentIndex() == MainGUI::Units_px) { scaler.width = static_cast(pixelSize * 64.0); scaler.height = static_cast(pixelSize * 64.0); scaler.x_res = 0; scaler.y_res = 0; } else { scaler.width = static_cast(pointSize * 64.0); scaler.height = static_cast(pointSize * 64.0); scaler.x_res = dpi; scaler.y_res = dpi; } } // end of engine.cpp ft2demos-2.10.1/src/ftinspect/engine/engine.hpp0000644000175000001440000000461313503605615021200 0ustar00wlusers00000000000000// engine.hpp // Copyright (C) 2016-2019 by Werner Lemberg. #pragma once #include #include #include #include FT_FREETYPE_H #include FT_OUTLINE_H #include FT_CACHE_H // This structure maps the (font, face, instance) index triplet to abstract // IDs (generated by a running number stored in MainGUI's `faceCounter' // member). // // Qt's `QMap' class needs an implementation of the `<' operator. struct FaceID { int fontIndex; long faceIndex; int namedInstanceIndex; FaceID(); FaceID(int fontIndex, long faceIndex, int namedInstanceIndex); bool operator<(const FaceID& other) const; }; class MainGUI; // FreeType specific data. class Engine { public: Engine(MainGUI*); ~Engine(); const QString& currentFamilyName(); const QString& currentStyleName(); QString glyphName(int glyphIndex); long numberOfFaces(int fontIndex); int numberOfNamedInstances(int fontIndex, long faceIndex); int loadFont(int fontIndex, long faceIndex, int namedInstanceIndex); // return number of glyphs FT_Outline* loadOutline(int glyphIndex); void removeFont(int fontIndex); void setCFFHintingMode(int mode); void setTTInterpreterVersion(int version); void update(); friend class MainGUI; friend FT_Error faceRequester(FTC_FaceID, FT_Library, FT_Pointer, FT_Face*); // XXX cover all available modules enum FontType { FontType_CFF, FontType_TrueType, FontType_Other }; private: MainGUI* gui; int faceCounter; // a running number used to initialize `faceIDMap' QMap faceIDMap; QString curFamilyName; QString curStyleName; FT_Library library; FTC_Manager cacheManager; FTC_ImageCache imageCache; FTC_SBitCache sbitsCache; FTC_ScalerRec scaler; FT_Size ftSize; int cffHintingEngineDefault; int cffHintingEngineOther; int ttInterpreterVersionDefault; int ttInterpreterVersionOther; int ttInterpreterVersionOther1; int fontType; int haveWarping; double pointSize; double pixelSize; unsigned int dpi; bool doHinting; bool doAutoHinting; bool doHorizontalHinting; bool doVerticalHinting; bool doBlueZoneHinting; bool showSegments; bool doWarping; double gamma; unsigned long loadFlags; }; // end of engine.hpp ft2demos-2.10.1/src/ftinspect/rendering/0000755000175000001440000000000013506426605017731 5ustar00wlusers00000000000000ft2demos-2.10.1/src/ftinspect/rendering/glyphoutline.cpp0000644000175000001440000000445613434207203023160 0ustar00wlusers00000000000000// glyphoutline.cpp // Copyright (C) 2016-2019 by Werner Lemberg. #include "glyphoutline.hpp" #include extern "C" { // vertical font coordinates are bottom-up, // while Qt uses top-down static int moveTo(const FT_Vector* to, void* user) { QPainterPath* path = static_cast(user); path->moveTo(qreal(to->x) / 64, -qreal(to->y) / 64); return 0; } static int lineTo(const FT_Vector* to, void* user) { QPainterPath* path = static_cast(user); path->lineTo(qreal(to->x) / 64, -qreal(to->y) / 64); return 0; } static int conicTo(const FT_Vector* control, const FT_Vector* to, void* user) { QPainterPath* path = static_cast(user); path->quadTo(qreal(control->x) / 64, -qreal(control->y) / 64, qreal(to->x) / 64, -qreal(to->y) / 64); return 0; } static int cubicTo(const FT_Vector* control1, const FT_Vector* control2, const FT_Vector* to, void* user) { QPainterPath* path = static_cast(user); path->cubicTo(qreal(control1->x) / 64, -qreal(control1->y) / 64, qreal(control2->x) / 64, -qreal(control2->y) / 64, qreal(to->x) / 64, -qreal(to->y) / 64); return 0; } static FT_Outline_Funcs outlineFuncs = { moveTo, lineTo, conicTo, cubicTo, 0, // no shift 0 // no delta }; } // extern "C" GlyphOutline::GlyphOutline(const QPen& outlineP, FT_Outline* outln) : outlinePen(outlineP), outline(outln) { FT_BBox cbox; qreal halfPenWidth = outlinePen.widthF(); FT_Outline_Get_CBox(outline, &cbox); bRect.setCoords(qreal(cbox.xMin) / 64 - halfPenWidth, -qreal(cbox.yMax) / 64 - halfPenWidth, qreal(cbox.xMax) / 64 + halfPenWidth, -qreal(cbox.yMin) / 64 + halfPenWidth); } QRectF GlyphOutline::boundingRect() const { return bRect; } void GlyphOutline::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*) { painter->setPen(outlinePen); QPainterPath path; FT_Outline_Decompose(outline, &outlineFuncs, &path); painter->drawPath(path); } // end of glyphoutline.cpp ft2demos-2.10.1/src/ftinspect/rendering/grid.cpp0000644000175000001440000000371413434207203021356 0ustar00wlusers00000000000000// grid.cpp // Copyright (C) 2016-2019 by Werner Lemberg. #include "grid.hpp" #include #include Grid::Grid(const QPen& gridP, const QPen& axisP) : gridPen(gridP), axisPen(axisP) { // empty } QRectF Grid::boundingRect() const { // XXX fix size // no need to take care of pen width return QRectF(-100, -100, 200, 200); } // XXX call this in a `myQDraphicsView::drawBackground' derived method // to always fill the complete viewport void Grid::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget*) { const qreal lod = option->levelOfDetailFromTransform( painter->worldTransform()); painter->setPen(gridPen); // don't mark pixel center with a cross if magnification is too small if (lod > 20) { int halfLength = 1; // cf. QSpinBoxx if (lod > 640) halfLength = 6; else if (lod > 320) halfLength = 5; else if (lod > 160) halfLength = 4; else if (lod > 80) halfLength = 3; else if (lod > 40) halfLength = 2; for (qreal x = -100; x < 100; x++) for (qreal y = -100; y < 100; y++) { painter->drawLine(QLineF(x + 0.5, y + 0.5 - halfLength / lod, x + 0.5, y + 0.5 + halfLength / lod)); painter->drawLine(QLineF(x + 0.5 - halfLength / lod, y + 0.5, x + 0.5 + halfLength / lod, y + 0.5)); } } // don't draw grid if magnification is too small if (lod >= 5) { // XXX fix size for (int x = -100; x <= 100; x++) painter->drawLine(x, -100, x, 100); for (int y = -100; y <= 100; y++) painter->drawLine(-100, y, 100, y); } painter->setPen(axisPen); painter->drawLine(0, -100, 0, 100); painter->drawLine(-100, 0, 100, 0); } // end of grid.cpp ft2demos-2.10.1/src/ftinspect/rendering/glyphpointnumbers.hpp0000644000175000001440000000117713434207203024230 0ustar00wlusers00000000000000// glyphpointnumbers.hpp // Copyright (C) 2016-2019 by Werner Lemberg. #pragma once #include #include #include #include FT_FREETYPE_H #include FT_OUTLINE_H class GlyphPointNumbers : public QGraphicsItem { public: GlyphPointNumbers(const QPen& onPen, const QPen& offPen, FT_Outline* outline); QRectF boundingRect() const; void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget); private: QPen onPen; QPen offPen; FT_Outline* outline; QRectF bRect; }; // end of glyphpointnumbers.hpp ft2demos-2.10.1/src/ftinspect/rendering/glyphbitmap.cpp0000644000175000001440000000655713434207203022761 0ustar00wlusers00000000000000// glyphbitmap.cpp // Copyright (C) 2016-2019 by Werner Lemberg. #include "glyphbitmap.hpp" #include #include #include GlyphBitmap::GlyphBitmap(FT_Outline* outline, FT_Library lib, FT_Pixel_Mode pxlMode, const QVector& monoColorTbl, const QVector& grayColorTbl) : library(lib), pixelMode(pxlMode), monoColorTable(monoColorTbl), grayColorTable(grayColorTbl) { // make a copy of the outline since we are going to manipulate it FT_Outline_New(library, static_cast(outline->n_points), outline->n_contours, &transformed); FT_Outline_Copy(outline, &transformed); FT_BBox cbox; FT_Outline_Get_CBox(outline, &cbox); cbox.xMin &= ~63; cbox.yMin &= ~63; cbox.xMax = (cbox.xMax + 63) & ~63; cbox.yMax = (cbox.yMax + 63) & ~63; // we shift the outline to the origin for rendering later on FT_Outline_Translate(&transformed, -cbox.xMin, -cbox.yMin); bRect.setCoords(cbox.xMin / 64, -cbox.yMax / 64, cbox.xMax / 64, -cbox.yMin / 64); } GlyphBitmap::~GlyphBitmap() { FT_Outline_Done(library, &transformed); } QRectF GlyphBitmap::boundingRect() const { return bRect; } void GlyphBitmap::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget*) { FT_Bitmap bitmap; int height = static_cast(ceil(bRect.height())); int width = static_cast(ceil(bRect.width())); QImage::Format format = QImage::Format_Indexed8; // XXX cover LCD and color if (pixelMode == FT_PIXEL_MODE_MONO) format = QImage::Format_Mono; QImage image(QSize(width, height), format); if (pixelMode == FT_PIXEL_MODE_MONO) image.setColorTable(monoColorTable); else image.setColorTable(grayColorTable); image.fill(0); bitmap.rows = static_cast(height); bitmap.width = static_cast(width); bitmap.buffer = image.bits(); bitmap.pitch = image.bytesPerLine(); bitmap.pixel_mode = pixelMode; FT_Error error = FT_Outline_Get_Bitmap(library, &transformed, &bitmap); if (error) { // XXX error handling return; } // `drawImage' doesn't work as expected: // the larger the zoom, the more the pixel rectangle positions // deviate from the grid lines #if 0 painter->drawImage(QPoint(bRect.left(), bRect.top()), image.convertToFormat( QImage::Format_ARGB32_Premultiplied)); #else const qreal lod = option->levelOfDetailFromTransform( painter->worldTransform()); painter->setPen(Qt::NoPen); for (int x = 0; x < image.width(); x++) for (int y = 0; y < image.height(); y++) { // be careful not to lose the alpha channel QRgb p = image.pixel(x, y); painter->fillRect(QRectF(x + bRect.left() - 1 / lod / 2, y + bRect.top() - 1 / lod / 2, 1 + 1 / lod, 1 + 1 / lod), QColor(qRed(p), qGreen(p), qBlue(p), qAlpha(p))); } #endif } // end of glyphbitmap.cpp ft2demos-2.10.1/src/ftinspect/rendering/glyphpoints.cpp0000644000175000001440000000543113434207203023007 0ustar00wlusers00000000000000// glyphpoints.cpp // Copyright (C) 2016-2019 by Werner Lemberg. #include "glyphpoints.hpp" #include #include GlyphPoints::GlyphPoints(const QPen& onP, const QPen& offP, FT_Outline* outln) : onPen(onP), offPen(offP), outline(outln) { FT_BBox cbox; qreal halfPenWidth = qMax(onPen.widthF(), offPen.widthF()) / 2; FT_Outline_Get_CBox(outline, &cbox); bRect.setCoords(qreal(cbox.xMin) / 64 - halfPenWidth, -qreal(cbox.yMax) / 64 - halfPenWidth, qreal(cbox.xMax) / 64 + halfPenWidth, -qreal(cbox.yMin) / 64 + halfPenWidth); } QRectF GlyphPoints::boundingRect() const { return bRect; } void GlyphPoints::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget*) { const qreal lod = option->levelOfDetailFromTransform( painter->worldTransform()); // don't draw points if magnification is too small if (lod >= 5) { // we want the same dot size regardless of the scaling; // for good optical results, the pen widths should be uneven integers // interestingly, using `drawPoint' doesn't work as expected: // the larger the zoom, the more horizontally stretched the dot appears #if 0 qreal origOnPenWidth = onPen.widthF(); qreal origOffPenWidth = offPen.widthF(); onPen.setWidthF(origOnPenWidth / lod); offPen.setWidthF(origOffPenWidth / lod); for (int i = 0; i < outline->n_points; i++) { if (outline->tags[i] & FT_CURVE_TAG_ON) painter->setPen(onPen); else painter->setPen(offPen); painter->drawPoint(QPointF(qreal(outline->points[i].x) / 64, -qreal(outline->points[i].y) / 64)); } onPen.setWidthF(origOnPenWidth); offPen.setWidthF(origOffPenWidth); #else QBrush onBrush(onPen.color()); QBrush offBrush(offPen.color()); painter->setPen(Qt::NoPen); qreal onRadius = onPen.widthF() / lod; qreal offRadius = offPen.widthF() / lod; for (int i = 0; i < outline->n_points; i++) { if (outline->tags[i] & FT_CURVE_TAG_ON) { painter->setBrush(onBrush); painter->drawEllipse(QPointF(qreal(outline->points[i].x) / 64, -qreal(outline->points[i].y) / 64), onRadius, onRadius); } else { painter->setBrush(offBrush); painter->drawEllipse(QPointF(qreal(outline->points[i].x) / 64, -qreal(outline->points[i].y) / 64), offRadius, offRadius); } } #endif } } // end of glyphpoints.cpp ft2demos-2.10.1/src/ftinspect/rendering/grid.hpp0000644000175000001440000000066013434207203021360 0ustar00wlusers00000000000000// grid.hpp // Copyright (C) 2016-2019 by Werner Lemberg. #pragma once #include #include class Grid : public QGraphicsItem { public: Grid(const QPen& gridPen, const QPen& axisPen); QRectF boundingRect() const; void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget); private: QPen gridPen; QPen axisPen; }; // end of grid.hpp ft2demos-2.10.1/src/ftinspect/rendering/glyphoutline.hpp0000644000175000001440000000106213434207203023153 0ustar00wlusers00000000000000// glyphoutline.hpp // Copyright (C) 2016-2019 by Werner Lemberg. #pragma once #include #include #include #include FT_FREETYPE_H #include FT_OUTLINE_H class GlyphOutline : public QGraphicsItem { public: GlyphOutline(const QPen& pen, FT_Outline* outline); QRectF boundingRect() const; void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget); private: QPen outlinePen; FT_Outline* outline; QRectF bRect; }; // end of glyphoutline.hpp ft2demos-2.10.1/src/ftinspect/rendering/glyphpointnumbers.cpp0000644000175000001440000001434213434207203024221 0ustar00wlusers00000000000000// glyphpointnumbers.cpp // Copyright (C) 2016-2019 by Werner Lemberg. #include "glyphpointnumbers.hpp" #include #include #include GlyphPointNumbers::GlyphPointNumbers(const QPen& onP, const QPen& offP, FT_Outline* outln) : onPen(onP), offPen(offP), outline(outln) { FT_BBox cbox; FT_Outline_Get_CBox(outline, &cbox); // XXX fix bRect size bRect.setCoords(qreal(cbox.xMin) / 64, -qreal(cbox.yMax) / 64, qreal(cbox.xMax) / 64, -qreal(cbox.yMin) / 64); } QRectF GlyphPointNumbers::boundingRect() const { return bRect; } void GlyphPointNumbers::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget*) { const qreal lod = option->levelOfDetailFromTransform( painter->worldTransform()); // don't draw point numbers if magnification is too small if (lod >= 10) { QFont font = painter->font(); // the following doesn't work correctly with scaling; // it seems that Qt doesn't allow arbitrarily small font sizes // that get magnified later on #if 0 // we want the same text size regardless of the scaling font.setPointSizeF(font.pointSizeF() / lod); painter->setFont(font); #else font.setPointSizeF(font.pointSizeF() * 3 / 4); painter->setFont(font); QBrush onBrush(onPen.color()); QBrush offBrush(offPen.color()); painter->scale(1 / lod, 1 / lod); #endif FT_Vector* points = outline->points; FT_Short* contours = outline->contours; char* tags = outline->tags; QVector2D octants[8] = { QVector2D(1, 0), QVector2D(0.707f, -0.707f), QVector2D(0, -1), QVector2D(-0.707f, -0.707f), QVector2D(-1, 0), QVector2D(-0.707f, 0.707f), QVector2D(0, 1), QVector2D(0.707f, 0.707f) }; short ptIdx = 0; for (int contIdx = 0; contIdx < outline->n_contours; contIdx++ ) { for (;;) { short prevIdx, nextIdx; // find previous and next point in outline if (contIdx == 0) { if (contours[contIdx] == 0) { prevIdx = 0; nextIdx = 0; } else { prevIdx = ptIdx > 0 ? ptIdx - 1 : contours[contIdx]; nextIdx = ptIdx < contours[contIdx] ? ptIdx + 1 : 0; } } else { prevIdx = ptIdx > (contours[contIdx - 1] + 1) ? ptIdx - 1 : contours[contIdx]; nextIdx = ptIdx < contours[contIdx] ? ptIdx + 1 : contours[contIdx - 1] + 1; } // get vectors to previous and next point and normalize them; QVector2D in(static_cast(points[prevIdx].x - points[ptIdx].x) / 64, -static_cast(points[prevIdx].y - points[ptIdx].y) / 64); QVector2D out(static_cast(points[nextIdx].x - points[ptIdx].x) / 64, -static_cast(points[nextIdx].y - points[ptIdx].y) / 64); in = in.normalized(); out = out.normalized(); QVector2D middle = in + out; // check whether vector is very small, using a threshold of 1/8px if (qAbs(middle.x()) < 1.0f / 8 && qAbs(middle.y()) < 1.0f / 8) { // in case of vectors in almost exactly opposite directions, // use a vector orthogonal to them middle.setX(out.y()); middle.setY(-out.x()); if (qAbs(middle.x()) < 1.0f / 8 && qAbs(middle.y()) < 1.0f / 8) { // use direction based on point index for the offset // if we still don't have a good value middle = octants[ptIdx % 8]; } } // normalize `middle' vector (which is never zero), // then multiply by 8 to get some distance between // the point and the number middle = middle.normalized() * 8; // we now position the point number in the opposite // direction of the `middle' vector, QString number = QString::number(ptIdx); #if 0 // this fails, see comment above int size = 10000; qreal x = qreal(points[ptIdx].x) / 64 - middle.x() / lod; qreal y = -qreal(points[ptIdx].y) / 64 - middle.y() / lod; QPointF corner(x, y); int flags = middle.x() > 0 ? Qt::AlignRight : Qt::AlignLeft; if (flags == Qt::AlignRight) corner.rx() -= size; QRectF posRect(corner, QSizeF(size, size)); if (tags[ptIdx] & FT_CURVE_TAG_ON) painter->setPen(onPen); else painter->setPen(offPen); painter->drawText(posRect, flags, number); #else // convert text string to a path object QPainterPath path; path.addText(QPointF(0, 0), font, number); QRectF ctrlPtRect = path.controlPointRect(); qreal x = static_cast(points[ptIdx].x) / 64 * lod - static_cast(middle.x()); qreal y = -static_cast(points[ptIdx].y) / 64 * lod - static_cast(middle.y()); qreal heuristicOffset = 2; if (middle.x() > 0) path.translate(x - ctrlPtRect.width() - heuristicOffset, y + ctrlPtRect.height() / 2); else path.translate(x, y + ctrlPtRect.height() / 2); painter->fillPath(path, tags[ptIdx] & FT_CURVE_TAG_ON ? onBrush : offBrush); #endif ptIdx++; if (ptIdx > contours[contIdx]) break; } } } } // end of glyphpointnumbers.cpp ft2demos-2.10.1/src/ftinspect/rendering/glyphbitmap.hpp0000644000175000001440000000147613434207203022761 0ustar00wlusers00000000000000// glyphbitmap.hpp // Copyright (C) 2016-2019 by Werner Lemberg. #pragma once #include #include #include #include FT_FREETYPE_H #include FT_OUTLINE_H class GlyphBitmap : public QGraphicsItem { public: GlyphBitmap(FT_Outline* outline, FT_Library library, FT_Pixel_Mode pixelMode, const QVector& monoColorTable, const QVector& grayColorTable); ~GlyphBitmap(); QRectF boundingRect() const; void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget); private: FT_Outline transformed; FT_Library library; unsigned char pixelMode; const QVector& monoColorTable; const QVector& grayColorTable; QRectF bRect; }; // end of glyphbitmap.hpp ft2demos-2.10.1/src/ftinspect/rendering/glyphpoints.hpp0000644000175000001440000000113313434207203023007 0ustar00wlusers00000000000000// glyphpoints.hpp // Copyright (C) 2016-2019 by Werner Lemberg. #pragma once #include #include #include #include FT_FREETYPE_H #include FT_OUTLINE_H class GlyphPoints : public QGraphicsItem { public: GlyphPoints(const QPen& onPen, const QPen& offPen, FT_Outline* outline); QRectF boundingRect() const; void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget); private: QPen onPen; QPen offPen; FT_Outline* outline; QRectF bRect; }; // end of glyphpoints.hpp ft2demos-2.10.1/src/ftinspect/ftinspect.cpp0000644000175000001440000000104713434207203020450 0ustar00wlusers00000000000000// ftinspect.cpp // Copyright (C) 2016-2019 by Werner Lemberg. #include "maingui.hpp" #include "engine/engine.hpp" #include #define VERSION "X.Y.Z" int main(int argc, char** argv) { QApplication app(argc, argv); app.setApplicationName("ftinspect"); app.setApplicationVersion(VERSION); app.setOrganizationName("FreeType"); app.setOrganizationDomain("freetype.org"); MainGUI gui; Engine engine(&gui); gui.update(&engine); gui.setDefaults(); gui.show(); return app.exec(); } // end of ftinspect.cpp ft2demos-2.10.1/src/ftinspect/maingui.cpp0000644000175000001440000010744113503605615020115 0ustar00wlusers00000000000000// maingui.cpp // Copyright (C) 2016-2019 by Werner Lemberg. #include "maingui.hpp" #include "rendering/grid.hpp" #include #include #include #include #include #include FT_DRIVER_H MainGUI::MainGUI() { engine = NULL; fontWatcher = new QFileSystemWatcher; // if the current input file is invalid we retry once a second to load it timer = new QTimer; timer->setInterval(1000); setGraphicsDefaults(); createLayout(); createConnections(); createActions(); createMenus(); createStatusBar(); readSettings(); setUnifiedTitleAndToolBarOnMac(true); } MainGUI::~MainGUI() { // empty } void MainGUI::update(Engine* e) { engine = e; } // overloading void MainGUI::closeEvent(QCloseEvent* event) { writeSettings(); event->accept(); } void MainGUI::about() { QMessageBox::about( this, tr("About ftinspect"), tr("

This is ftinspect version %1
" " Copyright %2 2016-2019
" " by Werner Lemberg <wl@gnu.org>

" "" "

ftinspect shows how a font gets rendered" " by FreeType, allowing control over virtually" " all rendering parameters.

" "" "

License:" " FreeType" " License (FTL) or" " GNU" " GPLv2

") .arg(QApplication::applicationVersion()) .arg(QChar(0xA9))); } void MainGUI::aboutQt() { QApplication::aboutQt(); } void MainGUI::loadFonts() { int oldSize = fontList.size(); QStringList files = QFileDialog::getOpenFileNames( this, tr("Load one or more fonts"), QDir::homePath(), "", NULL, QFileDialog::ReadOnly); // XXX sort data, uniquify elements fontList.append(files); // if we have new fonts, set the current index to the first new one if (oldSize < fontList.size()) currentFontIndex = oldSize; showFont(); } void MainGUI::closeFont() { if (currentFontIndex < fontList.size()) { engine->removeFont(currentFontIndex); fontWatcher->removePath(fontList[currentFontIndex]); fontList.removeAt(currentFontIndex); } // show next font after deletion, i.e., retain index if possible if (fontList.size()) { if (currentFontIndex >= fontList.size()) currentFontIndex = fontList.size() - 1; } else currentFontIndex = 0; showFont(); } void MainGUI::watchCurrentFont() { timer->stop(); showFont(); } void MainGUI::showFont() { // we do lazy computation of FT_Face objects if (currentFontIndex < fontList.size()) { QString& font = fontList[currentFontIndex]; QFileInfo fileInfo(font); QString fontName = fileInfo.fileName(); if (fileInfo.exists()) { // Qt's file watcher doesn't handle symlinks; // we thus fall back to polling if (fileInfo.isSymLink()) { fontName.prepend(""); fontName.append(""); timer->start(); } else fontWatcher->addPath(font); } else { // On Unix-like systems, the symlink's target gets opened; this // implies that deletion of a symlink doesn't make `engine->loadFont' // fail since it operates on a file handle pointing to the target. // For this reason, we remove the font to enforce a reload. engine->removeFont(currentFontIndex); } fontFilenameLabel->setText(fontName); } else fontFilenameLabel->clear(); currentNumberOfFaces = engine->numberOfFaces(currentFontIndex); currentNumberOfNamedInstances = engine->numberOfNamedInstances(currentFontIndex, currentFaceIndex); currentNumberOfGlyphs = engine->loadFont(currentFontIndex, currentFaceIndex, currentNamedInstanceIndex); if (currentNumberOfGlyphs < 0) { // there might be various reasons why the current // (file, face, instance) triplet is invalid or missing; // we thus start our timer to periodically test // whether the font starts working if (currentFontIndex < fontList.size()) timer->start(); } fontNameLabel->setText(QString("%1 %2") .arg(engine->currentFamilyName()) .arg(engine->currentStyleName())); checkCurrentFontIndex(); checkCurrentFaceIndex(); checkCurrentNamedInstanceIndex(); checkHinting(); adjustGlyphIndex(0); drawGlyph(); } void MainGUI::checkHinting() { if (hintingCheckBox->isChecked()) { if (engine->fontType == Engine::FontType_CFF) { for (int i = 0; i < hintingModeComboBoxx->count(); i++) { if (hintingModesCFFHash.key(i, -1) != -1) hintingModeComboBoxx->setItemEnabled(i, true); else hintingModeComboBoxx->setItemEnabled(i, false); } hintingModeComboBoxx->setCurrentIndex(currentCFFHintingMode); } else if (engine->fontType == Engine::FontType_TrueType) { for (int i = 0; i < hintingModeComboBoxx->count(); i++) { if (hintingModesTrueTypeHash.key(i, -1) != -1) hintingModeComboBoxx->setItemEnabled(i, true); else hintingModeComboBoxx->setItemEnabled(i, false); } hintingModeComboBoxx->setCurrentIndex(currentTTInterpreterVersion); } else { hintingModeLabel->setEnabled(false); hintingModeComboBoxx->setEnabled(false); } for (int i = 0; i < hintingModesAlwaysDisabled.size(); i++) hintingModeComboBoxx->setItemEnabled(hintingModesAlwaysDisabled[i], false); autoHintingCheckBox->setEnabled(true); checkAutoHinting(); } else { hintingModeLabel->setEnabled(false); hintingModeComboBoxx->setEnabled(false); autoHintingCheckBox->setEnabled(false); horizontalHintingCheckBox->setEnabled(false); verticalHintingCheckBox->setEnabled(false); blueZoneHintingCheckBox->setEnabled(false); segmentDrawingCheckBox->setEnabled(false); warpingCheckBox->setEnabled(false); antiAliasingComboBoxx->setItemEnabled(AntiAliasing_Light, false); } drawGlyph(); } void MainGUI::checkHintingMode() { int index = hintingModeComboBoxx->currentIndex(); if (engine->fontType == Engine::FontType_CFF) { engine->setCFFHintingMode(index); currentCFFHintingMode = index; } else if (engine->fontType == Engine::FontType_TrueType) { engine->setTTInterpreterVersion(index); currentTTInterpreterVersion = index; } // this enforces reloading of the font showFont(); } void MainGUI::checkAutoHinting() { if (autoHintingCheckBox->isChecked()) { hintingModeLabel->setEnabled(false); hintingModeComboBoxx->setEnabled(false); horizontalHintingCheckBox->setEnabled(true); verticalHintingCheckBox->setEnabled(true); blueZoneHintingCheckBox->setEnabled(true); segmentDrawingCheckBox->setEnabled(true); if (engine->haveWarping) warpingCheckBox->setEnabled(true); antiAliasingComboBoxx->setItemEnabled(AntiAliasing_Light, true); } else { if (engine->fontType == Engine::FontType_CFF || engine->fontType == Engine::FontType_TrueType) { hintingModeLabel->setEnabled(true); hintingModeComboBoxx->setEnabled(true); } horizontalHintingCheckBox->setEnabled(false); verticalHintingCheckBox->setEnabled(false); blueZoneHintingCheckBox->setEnabled(false); segmentDrawingCheckBox->setEnabled(false); warpingCheckBox->setEnabled(false); antiAliasingComboBoxx->setItemEnabled(AntiAliasing_Light, false); if (antiAliasingComboBoxx->currentIndex() == AntiAliasing_Light) antiAliasingComboBoxx->setCurrentIndex(AntiAliasing_Normal); } drawGlyph(); } void MainGUI::checkAntiAliasing() { int index = antiAliasingComboBoxx->currentIndex(); if (index == AntiAliasing_None || index == AntiAliasing_Normal || index == AntiAliasing_Light) { lcdFilterLabel->setEnabled(false); lcdFilterComboBox->setEnabled(false); } else { lcdFilterLabel->setEnabled(true); lcdFilterComboBox->setEnabled(true); } drawGlyph(); } void MainGUI::checkLcdFilter() { int index = lcdFilterComboBox->currentIndex(); FT_Library_SetLcdFilter(engine->library, lcdFilterHash.key(index)); } void MainGUI::checkShowPoints() { if (showPointsCheckBox->isChecked()) showPointNumbersCheckBox->setEnabled(true); else showPointNumbersCheckBox->setEnabled(false); drawGlyph(); } void MainGUI::checkUnits() { int index = unitsComboBox->currentIndex(); if (index == Units_px) { dpiLabel->setEnabled(false); dpiSpinBox->setEnabled(false); sizeDoubleSpinBox->setSingleStep(1); sizeDoubleSpinBox->setValue(qRound(sizeDoubleSpinBox->value())); } else { dpiLabel->setEnabled(true); dpiSpinBox->setEnabled(true); sizeDoubleSpinBox->setSingleStep(0.5); } drawGlyph(); } void MainGUI::adjustGlyphIndex(int delta) { // only adjust current glyph index if we have a valid font if (currentNumberOfGlyphs > 0) { currentGlyphIndex += delta; currentGlyphIndex = qBound(0, currentGlyphIndex, currentNumberOfGlyphs - 1); } QString upperHex = QString::number(currentGlyphIndex, 16).toUpper(); glyphIndexLabel->setText(QString("%1 (0x%2)") .arg(currentGlyphIndex) .arg(upperHex)); glyphNameLabel->setText(engine->glyphName(currentGlyphIndex)); drawGlyph(); } void MainGUI::checkCurrentFontIndex() { if (fontList.size() < 2) { previousFontButton->setEnabled(false); nextFontButton->setEnabled(false); } else if (currentFontIndex == 0) { previousFontButton->setEnabled(false); nextFontButton->setEnabled(true); } else if (currentFontIndex >= fontList.size() - 1) { previousFontButton->setEnabled(true); nextFontButton->setEnabled(false); } else { previousFontButton->setEnabled(true); nextFontButton->setEnabled(true); } } void MainGUI::checkCurrentFaceIndex() { if (currentNumberOfFaces < 2) { previousFaceButton->setEnabled(false); nextFaceButton->setEnabled(false); } else if (currentFaceIndex == 0) { previousFaceButton->setEnabled(false); nextFaceButton->setEnabled(true); } else if (currentFaceIndex >= currentNumberOfFaces - 1) { previousFaceButton->setEnabled(true); nextFaceButton->setEnabled(false); } else { previousFaceButton->setEnabled(true); nextFaceButton->setEnabled(true); } } void MainGUI::checkCurrentNamedInstanceIndex() { if (currentNumberOfNamedInstances < 2) { previousNamedInstanceButton->setEnabled(false); nextNamedInstanceButton->setEnabled(false); } else if (currentNamedInstanceIndex == 0) { previousNamedInstanceButton->setEnabled(false); nextNamedInstanceButton->setEnabled(true); } else if (currentNamedInstanceIndex >= currentNumberOfNamedInstances - 1) { previousNamedInstanceButton->setEnabled(true); nextNamedInstanceButton->setEnabled(false); } else { previousNamedInstanceButton->setEnabled(true); nextNamedInstanceButton->setEnabled(true); } } void MainGUI::previousFont() { if (currentFontIndex > 0) { currentFontIndex--; currentFaceIndex = 0; currentNamedInstanceIndex = 0; showFont(); } } void MainGUI::nextFont() { if (currentFontIndex < fontList.size() - 1) { currentFontIndex++; currentFaceIndex = 0; currentNamedInstanceIndex = 0; showFont(); } } void MainGUI::previousFace() { if (currentFaceIndex > 0) { currentFaceIndex--; currentNamedInstanceIndex = 0; showFont(); } } void MainGUI::nextFace() { if (currentFaceIndex < currentNumberOfFaces - 1) { currentFaceIndex++; currentNamedInstanceIndex = 0; showFont(); } } void MainGUI::previousNamedInstance() { if (currentNamedInstanceIndex > 0) { currentNamedInstanceIndex--; showFont(); } } void MainGUI::nextNamedInstance() { if (currentNamedInstanceIndex < currentNumberOfNamedInstances - 1) { currentNamedInstanceIndex++; showFont(); } } void MainGUI::zoom() { int scale = zoomSpinBox->value(); QTransform transform; transform.scale(scale, scale); // we want horizontal and vertical 1px lines displayed with full pixels; // we thus have to shift the coordinate system accordingly, using a value // that represents 0.5px (i.e., half the 1px line width) after the scaling qreal shift = 0.5 / scale; transform.translate(shift, shift); glyphView->setTransform(transform); } void MainGUI::setGraphicsDefaults() { // color tables (with suitable opacity values) for converting // FreeType's pixmaps to something Qt understands monoColorTable.append(QColor(Qt::transparent).rgba()); monoColorTable.append(QColor(Qt::black).rgba()); for (int i = 0xFF; i >= 0; i--) grayColorTable.append(qRgba(i, i, i, 0xFF - i)); // XXX make this user-configurable axisPen.setColor(Qt::black); axisPen.setWidth(0); blueZonePen.setColor(QColor(64, 64, 255, 64)); // light blue blueZonePen.setWidth(0); gridPen.setColor(Qt::lightGray); gridPen.setWidth(0); offPen.setColor(Qt::darkGreen); offPen.setWidth(3); onPen.setColor(Qt::red); onPen.setWidth(3); outlinePen.setColor(Qt::red); outlinePen.setWidth(0); segmentPen.setColor(QColor(64, 255, 128, 64)); // light green segmentPen.setWidth(0); } void MainGUI::drawGlyph() { // the call to `engine->loadOutline' updates FreeType's load flags if (!engine) return; if (currentGlyphBitmapItem) { glyphScene->removeItem(currentGlyphBitmapItem); delete currentGlyphBitmapItem; currentGlyphBitmapItem = NULL; } if (currentGlyphOutlineItem) { glyphScene->removeItem(currentGlyphOutlineItem); delete currentGlyphOutlineItem; currentGlyphOutlineItem = NULL; } if (currentGlyphPointsItem) { glyphScene->removeItem(currentGlyphPointsItem); delete currentGlyphPointsItem; currentGlyphPointsItem = NULL; } if (currentGlyphPointNumbersItem) { glyphScene->removeItem(currentGlyphPointNumbersItem); delete currentGlyphPointNumbersItem; currentGlyphPointNumbersItem = NULL; } FT_Outline* outline = engine->loadOutline(currentGlyphIndex); if (outline) { if (showBitmapCheckBox->isChecked()) { // XXX support LCD FT_Pixel_Mode pixelMode = FT_PIXEL_MODE_GRAY; if (antiAliasingComboBoxx->currentIndex() == AntiAliasing_None) pixelMode = FT_PIXEL_MODE_MONO; currentGlyphBitmapItem = new GlyphBitmap(outline, engine->library, pixelMode, monoColorTable, grayColorTable); glyphScene->addItem(currentGlyphBitmapItem); } if (showOutlinesCheckBox->isChecked()) { currentGlyphOutlineItem = new GlyphOutline(outlinePen, outline); glyphScene->addItem(currentGlyphOutlineItem); } if (showPointsCheckBox->isChecked()) { currentGlyphPointsItem = new GlyphPoints(onPen, offPen, outline); glyphScene->addItem(currentGlyphPointsItem); if (showPointNumbersCheckBox->isChecked()) { currentGlyphPointNumbersItem = new GlyphPointNumbers(onPen, offPen, outline); glyphScene->addItem(currentGlyphPointNumbersItem); } } } glyphScene->update(); } // XXX distances are specified in pixels, // making the layout dependent on the output device resolution void MainGUI::createLayout() { // left side fontFilenameLabel = new QLabel; hintingCheckBox = new QCheckBox(tr("Hinting")); hintingModeLabel = new QLabel(tr("Hinting Mode")); hintingModeLabel->setAlignment(Qt::AlignRight); hintingModeComboBoxx = new QComboBoxx; hintingModeComboBoxx->insertItem(HintingMode_TrueType_v35, tr("TrueType v35")); hintingModeComboBoxx->insertItem(HintingMode_TrueType_v38, tr("TrueType v38")); hintingModeComboBoxx->insertItem(HintingMode_TrueType_v40, tr("TrueType v40")); hintingModeComboBoxx->insertItem(HintingMode_CFF_FreeType, tr("CFF (FreeType)")); hintingModeComboBoxx->insertItem(HintingMode_CFF_Adobe, tr("CFF (Adobe)")); hintingModeLabel->setBuddy(hintingModeComboBoxx); autoHintingCheckBox = new QCheckBox(tr("Auto-Hinting")); horizontalHintingCheckBox = new QCheckBox(tr("Horizontal Hinting")); verticalHintingCheckBox = new QCheckBox(tr("Vertical Hinting")); blueZoneHintingCheckBox = new QCheckBox(tr("Blue-Zone Hinting")); segmentDrawingCheckBox = new QCheckBox(tr("Segment Drawing")); warpingCheckBox = new QCheckBox(tr("Warping")); antiAliasingLabel = new QLabel(tr("Anti-Aliasing")); antiAliasingLabel->setAlignment(Qt::AlignRight); antiAliasingComboBoxx = new QComboBoxx; antiAliasingComboBoxx->insertItem(AntiAliasing_None, tr("None")); antiAliasingComboBoxx->insertItem(AntiAliasing_Normal, tr("Normal")); antiAliasingComboBoxx->insertItem(AntiAliasing_Light, tr("Light")); antiAliasingComboBoxx->insertItem(AntiAliasing_LCD, tr("LCD (RGB)")); antiAliasingComboBoxx->insertItem(AntiAliasing_LCD_BGR, tr("LCD (BGR)")); antiAliasingComboBoxx->insertItem(AntiAliasing_LCD_Vertical, tr("LCD (vert. RGB)")); antiAliasingComboBoxx->insertItem(AntiAliasing_LCD_Vertical_BGR, tr("LCD (vert. BGR)")); antiAliasingLabel->setBuddy(antiAliasingComboBoxx); lcdFilterLabel = new QLabel(tr("LCD Filter")); lcdFilterLabel->setAlignment(Qt::AlignRight); lcdFilterComboBox = new QComboBox; lcdFilterComboBox->insertItem(LCDFilter_Default, tr("Default")); lcdFilterComboBox->insertItem(LCDFilter_Light, tr("Light")); lcdFilterComboBox->insertItem(LCDFilter_None, tr("None")); lcdFilterComboBox->insertItem(LCDFilter_Legacy, tr("Legacy")); lcdFilterLabel->setBuddy(lcdFilterComboBox); int width; // make all labels have the same width width = hintingModeLabel->minimumSizeHint().width(); width = qMax(antiAliasingLabel->minimumSizeHint().width(), width); width = qMax(lcdFilterLabel->minimumSizeHint().width(), width); hintingModeLabel->setMinimumWidth(width); antiAliasingLabel->setMinimumWidth(width); lcdFilterLabel->setMinimumWidth(width); // ensure that all items in combo boxes fit completely; // also make all combo boxes have the same width width = hintingModeComboBoxx->minimumSizeHint().width(); width = qMax(antiAliasingComboBoxx->minimumSizeHint().width(), width); width = qMax(lcdFilterComboBox->minimumSizeHint().width(), width); hintingModeComboBoxx->setMinimumWidth(width); antiAliasingComboBoxx->setMinimumWidth(width); lcdFilterComboBox->setMinimumWidth(width); gammaLabel = new QLabel(tr("Gamma")); gammaLabel->setAlignment(Qt::AlignRight); gammaSlider = new QSlider(Qt::Horizontal); gammaSlider->setRange(0, 30); // in 1/10th gammaSlider->setTickPosition(QSlider::TicksBelow); gammaSlider->setTickInterval(5); gammaLabel->setBuddy(gammaSlider); showBitmapCheckBox = new QCheckBox(tr("Show Bitmap")); showPointsCheckBox = new QCheckBox(tr("Show Points")); showPointNumbersCheckBox = new QCheckBox(tr("Show Point Numbers")); showOutlinesCheckBox = new QCheckBox(tr("Show Outlines")); infoLeftLayout = new QHBoxLayout; infoLeftLayout->addWidget(fontFilenameLabel); hintingModeLayout = new QHBoxLayout; hintingModeLayout->addWidget(hintingModeLabel); hintingModeLayout->addWidget(hintingModeComboBoxx); horizontalHintingLayout = new QHBoxLayout; horizontalHintingLayout->addSpacing(20); // XXX px horizontalHintingLayout->addWidget(horizontalHintingCheckBox); verticalHintingLayout = new QHBoxLayout; verticalHintingLayout->addSpacing(20); // XXX px verticalHintingLayout->addWidget(verticalHintingCheckBox); blueZoneHintingLayout = new QHBoxLayout; blueZoneHintingLayout->addSpacing(20); // XXX px blueZoneHintingLayout->addWidget(blueZoneHintingCheckBox); segmentDrawingLayout = new QHBoxLayout; segmentDrawingLayout->addSpacing(20); // XXX px segmentDrawingLayout->addWidget(segmentDrawingCheckBox); warpingLayout = new QHBoxLayout; warpingLayout->addSpacing(20); // XXX px warpingLayout->addWidget(warpingCheckBox); antiAliasingLayout = new QHBoxLayout; antiAliasingLayout->addWidget(antiAliasingLabel); antiAliasingLayout->addWidget(antiAliasingComboBoxx); lcdFilterLayout = new QHBoxLayout; lcdFilterLayout->addWidget(lcdFilterLabel); lcdFilterLayout->addWidget(lcdFilterComboBox); gammaLayout = new QHBoxLayout; gammaLayout->addWidget(gammaLabel); gammaLayout->addWidget(gammaSlider); pointNumbersLayout = new QHBoxLayout; pointNumbersLayout->addSpacing(20); // XXX px pointNumbersLayout->addWidget(showPointNumbersCheckBox); generalTabLayout = new QVBoxLayout; generalTabLayout->addWidget(hintingCheckBox); generalTabLayout->addLayout(hintingModeLayout); generalTabLayout->addWidget(autoHintingCheckBox); generalTabLayout->addLayout(horizontalHintingLayout); generalTabLayout->addLayout(verticalHintingLayout); generalTabLayout->addLayout(blueZoneHintingLayout); generalTabLayout->addLayout(segmentDrawingLayout); generalTabLayout->addLayout(warpingLayout); generalTabLayout->addSpacing(20); // XXX px generalTabLayout->addStretch(1); generalTabLayout->addLayout(antiAliasingLayout); generalTabLayout->addLayout(lcdFilterLayout); generalTabLayout->addSpacing(20); // XXX px generalTabLayout->addStretch(1); generalTabLayout->addLayout(gammaLayout); generalTabLayout->addSpacing(20); // XXX px generalTabLayout->addStretch(1); generalTabLayout->addWidget(showBitmapCheckBox); generalTabLayout->addWidget(showPointsCheckBox); generalTabLayout->addLayout(pointNumbersLayout); generalTabLayout->addWidget(showOutlinesCheckBox); generalTabWidget = new QWidget; generalTabWidget->setLayout(generalTabLayout); mmgxTabWidget = new QWidget; tabWidget = new QTabWidget; tabWidget->addTab(generalTabWidget, tr("General")); tabWidget->addTab(mmgxTabWidget, tr("MM/GX")); leftLayout = new QVBoxLayout; leftLayout->addLayout(infoLeftLayout); leftLayout->addWidget(tabWidget); // we don't want to expand the left side horizontally; // to change the policy we have to use a widget wrapper leftWidget = new QWidget; leftWidget->setLayout(leftLayout); QSizePolicy leftWidgetPolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); leftWidgetPolicy.setHorizontalStretch(0); leftWidgetPolicy.setVerticalPolicy(leftWidget->sizePolicy().verticalPolicy()); leftWidgetPolicy.setHeightForWidth(leftWidget->sizePolicy().hasHeightForWidth()); leftWidget->setSizePolicy(leftWidgetPolicy); // right side glyphIndexLabel = new QLabel; glyphNameLabel = new QLabel; fontNameLabel = new QLabel; glyphScene = new QGraphicsScene; glyphScene->addItem(new Grid(gridPen, axisPen)); currentGlyphBitmapItem = NULL; currentGlyphOutlineItem = NULL; currentGlyphPointsItem = NULL; currentGlyphPointNumbersItem = NULL; drawGlyph(); glyphView = new QGraphicsViewx; glyphView->setRenderHint(QPainter::Antialiasing, true); glyphView->setDragMode(QGraphicsView::ScrollHandDrag); glyphView->setOptimizationFlags(QGraphicsView::DontSavePainterState); glyphView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate); glyphView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); glyphView->setScene(glyphScene); sizeLabel = new QLabel(tr("Size ")); sizeLabel->setAlignment(Qt::AlignRight); sizeDoubleSpinBox = new QDoubleSpinBox; sizeDoubleSpinBox->setAlignment(Qt::AlignRight); sizeDoubleSpinBox->setDecimals(1); sizeDoubleSpinBox->setRange(1, 500); sizeLabel->setBuddy(sizeDoubleSpinBox); unitsComboBox = new QComboBox; unitsComboBox->insertItem(Units_px, "px"); unitsComboBox->insertItem(Units_pt, "pt"); dpiLabel = new QLabel(tr("DPI ")); dpiLabel->setAlignment(Qt::AlignRight); dpiSpinBox = new QSpinBox; dpiSpinBox->setAlignment(Qt::AlignRight); dpiSpinBox->setRange(10, 600); dpiLabel->setBuddy(dpiSpinBox); toStartButtonx = new QPushButtonx("|<"); toM1000Buttonx = new QPushButtonx("-1000"); toM100Buttonx = new QPushButtonx("-100"); toM10Buttonx = new QPushButtonx("-10"); toM1Buttonx = new QPushButtonx("-1"); toP1Buttonx = new QPushButtonx("+1"); toP10Buttonx = new QPushButtonx("+10"); toP100Buttonx = new QPushButtonx("+100"); toP1000Buttonx = new QPushButtonx("+1000"); toEndButtonx = new QPushButtonx(">|"); zoomLabel = new QLabel(tr("Zoom Factor")); zoomLabel->setAlignment(Qt::AlignRight); zoomSpinBox = new QSpinBoxx; zoomSpinBox->setAlignment(Qt::AlignRight); zoomSpinBox->setRange(1, 1000 - 1000 % 64); zoomSpinBox->setKeyboardTracking(false); zoomLabel->setBuddy(zoomSpinBox); previousFontButton = new QPushButton(tr("Previous Font")); nextFontButton = new QPushButton(tr("Next Font")); previousFaceButton = new QPushButton(tr("Previous Face")); nextFaceButton = new QPushButton(tr("Next Face")); previousNamedInstanceButton = new QPushButton(tr("Previous Named Instance")); nextNamedInstanceButton = new QPushButton(tr("Next Named Instance")); infoRightLayout = new QGridLayout; infoRightLayout->addWidget(glyphIndexLabel, 0, 0); infoRightLayout->addWidget(glyphNameLabel, 0, 1); infoRightLayout->addWidget(fontNameLabel, 0, 2); navigationLayout = new QHBoxLayout; navigationLayout->setSpacing(0); navigationLayout->addStretch(1); navigationLayout->addWidget(toStartButtonx); navigationLayout->addWidget(toM1000Buttonx); navigationLayout->addWidget(toM100Buttonx); navigationLayout->addWidget(toM10Buttonx); navigationLayout->addWidget(toM1Buttonx); navigationLayout->addWidget(toP1Buttonx); navigationLayout->addWidget(toP10Buttonx); navigationLayout->addWidget(toP100Buttonx); navigationLayout->addWidget(toP1000Buttonx); navigationLayout->addWidget(toEndButtonx); navigationLayout->addStretch(1); sizeLayout = new QHBoxLayout; sizeLayout->addStretch(2); sizeLayout->addWidget(sizeLabel); sizeLayout->addWidget(sizeDoubleSpinBox); sizeLayout->addWidget(unitsComboBox); sizeLayout->addStretch(1); sizeLayout->addWidget(dpiLabel); sizeLayout->addWidget(dpiSpinBox); sizeLayout->addStretch(1); sizeLayout->addWidget(zoomLabel); sizeLayout->addWidget(zoomSpinBox); sizeLayout->addStretch(2); fontLayout = new QGridLayout; fontLayout->setColumnStretch(0, 2); fontLayout->addWidget(nextFontButton, 0, 1); fontLayout->addWidget(previousFontButton, 1, 1); fontLayout->setColumnStretch(2, 1); fontLayout->addWidget(nextFaceButton, 0, 3); fontLayout->addWidget(previousFaceButton, 1, 3); fontLayout->setColumnStretch(4, 1); fontLayout->addWidget(nextNamedInstanceButton, 0, 5); fontLayout->addWidget(previousNamedInstanceButton, 1, 5); fontLayout->setColumnStretch(6, 2); rightLayout = new QVBoxLayout; rightLayout->addLayout(infoRightLayout); rightLayout->addWidget(glyphView); rightLayout->addLayout(navigationLayout); rightLayout->addSpacing(10); // XXX px rightLayout->addLayout(sizeLayout); rightLayout->addSpacing(10); // XXX px rightLayout->addLayout(fontLayout); // for symmetry with the left side use a widget also rightWidget = new QWidget; rightWidget->setLayout(rightLayout); // the whole thing ftinspectLayout = new QHBoxLayout; ftinspectLayout->addWidget(leftWidget); ftinspectLayout->addWidget(rightWidget); ftinspectWidget = new QWidget; ftinspectWidget->setLayout(ftinspectLayout); setCentralWidget(ftinspectWidget); setWindowTitle("ftinspect"); } void MainGUI::createConnections() { connect(hintingCheckBox, SIGNAL(clicked()), SLOT(checkHinting())); connect(hintingModeComboBoxx, SIGNAL(currentIndexChanged(int)), SLOT(checkHintingMode())); connect(antiAliasingComboBoxx, SIGNAL(currentIndexChanged(int)), SLOT(checkAntiAliasing())); connect(lcdFilterComboBox, SIGNAL(currentIndexChanged(int)), SLOT(checkLcdFilter())); connect(autoHintingCheckBox, SIGNAL(clicked()), SLOT(checkAutoHinting())); connect(showBitmapCheckBox, SIGNAL(clicked()), SLOT(drawGlyph())); connect(showPointsCheckBox, SIGNAL(clicked()), SLOT(checkShowPoints())); connect(showPointNumbersCheckBox, SIGNAL(clicked()), SLOT(drawGlyph())); connect(showOutlinesCheckBox, SIGNAL(clicked()), SLOT(drawGlyph())); connect(sizeDoubleSpinBox, SIGNAL(valueChanged(double)), SLOT(drawGlyph())); connect(unitsComboBox, SIGNAL(currentIndexChanged(int)), SLOT(checkUnits())); connect(dpiSpinBox, SIGNAL(valueChanged(int)), SLOT(drawGlyph())); connect(zoomSpinBox, SIGNAL(valueChanged(int)), SLOT(zoom())); connect(previousFontButton, SIGNAL(clicked()), SLOT(previousFont())); connect(nextFontButton, SIGNAL(clicked()), SLOT(nextFont())); connect(previousFaceButton, SIGNAL(clicked()), SLOT(previousFace())); connect(nextFaceButton, SIGNAL(clicked()), SLOT(nextFace())); connect(previousNamedInstanceButton, SIGNAL(clicked()), SLOT(previousNamedInstance())); connect(nextNamedInstanceButton, SIGNAL(clicked()), SLOT(nextNamedInstance())); glyphNavigationMapper = new QSignalMapper; connect(glyphNavigationMapper, SIGNAL(mapped(int)), SLOT(adjustGlyphIndex(int))); connect(toStartButtonx, SIGNAL(clicked()), glyphNavigationMapper, SLOT(map())); connect(toM1000Buttonx, SIGNAL(clicked()), glyphNavigationMapper, SLOT(map())); connect(toM100Buttonx, SIGNAL(clicked()), glyphNavigationMapper, SLOT(map())); connect(toM10Buttonx, SIGNAL(clicked()), glyphNavigationMapper, SLOT(map())); connect(toM1Buttonx, SIGNAL(clicked()), glyphNavigationMapper, SLOT(map())); connect(toP1Buttonx, SIGNAL(clicked()), glyphNavigationMapper, SLOT(map())); connect(toP10Buttonx, SIGNAL(clicked()), glyphNavigationMapper, SLOT(map())); connect(toP100Buttonx, SIGNAL(clicked()), glyphNavigationMapper, SLOT(map())); connect(toP1000Buttonx, SIGNAL(clicked()), glyphNavigationMapper, SLOT(map())); connect(toEndButtonx, SIGNAL(clicked()), glyphNavigationMapper, SLOT(map())); glyphNavigationMapper->setMapping(toStartButtonx, -0x10000); glyphNavigationMapper->setMapping(toM1000Buttonx, -1000); glyphNavigationMapper->setMapping(toM100Buttonx, -100); glyphNavigationMapper->setMapping(toM10Buttonx, -10); glyphNavigationMapper->setMapping(toM1Buttonx, -1); glyphNavigationMapper->setMapping(toP1Buttonx, 1); glyphNavigationMapper->setMapping(toP10Buttonx, 10); glyphNavigationMapper->setMapping(toP100Buttonx, 100); glyphNavigationMapper->setMapping(toP1000Buttonx, 1000); glyphNavigationMapper->setMapping(toEndButtonx, 0x10000); connect(fontWatcher, SIGNAL(fileChanged(const QString&)), SLOT(watchCurrentFont())); connect(timer, SIGNAL(timeout()), SLOT(watchCurrentFont())); } void MainGUI::createActions() { loadFontsAct = new QAction(tr("&Load Fonts"), this); loadFontsAct->setShortcuts(QKeySequence::Open); connect(loadFontsAct, SIGNAL(triggered()), SLOT(loadFonts())); closeFontAct = new QAction(tr("&Close Font"), this); closeFontAct->setShortcuts(QKeySequence::Close); connect(closeFontAct, SIGNAL(triggered()), SLOT(closeFont())); exitAct = new QAction(tr("E&xit"), this); exitAct->setShortcuts(QKeySequence::Quit); connect(exitAct, SIGNAL(triggered()), SLOT(close())); aboutAct = new QAction(tr("&About"), this); connect(aboutAct, SIGNAL(triggered()), SLOT(about())); aboutQtAct = new QAction(tr("About &Qt"), this); connect(aboutQtAct, SIGNAL(triggered()), SLOT(aboutQt())); } void MainGUI::createMenus() { menuFile = menuBar()->addMenu(tr("&File")); menuFile->addAction(loadFontsAct); menuFile->addAction(closeFontAct); menuFile->addAction(exitAct); menuHelp = menuBar()->addMenu(tr("&Help")); menuHelp->addAction(aboutAct); menuHelp->addAction(aboutQtAct); } void MainGUI::createStatusBar() { statusBar()->showMessage(""); } void MainGUI::clearStatusBar() { statusBar()->clearMessage(); statusBar()->setStyleSheet(""); } void MainGUI::setDefaults() { // set up mappings between property values and combo box indices hintingModesTrueTypeHash[TT_INTERPRETER_VERSION_35] = HintingMode_TrueType_v35; hintingModesTrueTypeHash[TT_INTERPRETER_VERSION_38] = HintingMode_TrueType_v38; hintingModesTrueTypeHash[TT_INTERPRETER_VERSION_40] = HintingMode_TrueType_v40; hintingModesCFFHash[FT_HINTING_FREETYPE] = HintingMode_CFF_FreeType; hintingModesCFFHash[FT_HINTING_ADOBE] = HintingMode_CFF_Adobe; lcdFilterHash[FT_LCD_FILTER_DEFAULT] = LCDFilter_Default; lcdFilterHash[FT_LCD_FILTER_LIGHT] = LCDFilter_Light; lcdFilterHash[FT_LCD_FILTER_NONE] = LCDFilter_None; lcdFilterHash[FT_LCD_FILTER_LEGACY] = LCDFilter_Legacy; // make copies and remove existing elements... QHash hmTTHash = hintingModesTrueTypeHash; if (hmTTHash.contains(engine->ttInterpreterVersionDefault)) hmTTHash.remove(engine->ttInterpreterVersionDefault); if (hmTTHash.contains(engine->ttInterpreterVersionOther)) hmTTHash.remove(engine->ttInterpreterVersionOther); if (hmTTHash.contains(engine->ttInterpreterVersionOther1)) hmTTHash.remove(engine->ttInterpreterVersionOther1); QHash hmCFFHash = hintingModesCFFHash; if (hmCFFHash.contains(engine->cffHintingEngineDefault)) hmCFFHash.remove(engine->cffHintingEngineDefault); if (hmCFFHash.contains(engine->cffHintingEngineOther)) hmCFFHash.remove(engine->cffHintingEngineOther); // ... to construct a list of always disabled hinting mode combo box items hintingModesAlwaysDisabled = hmTTHash.values(); hintingModesAlwaysDisabled += hmCFFHash.values(); for (int i = 0; i < hintingModesAlwaysDisabled.size(); i++) hintingModeComboBoxx->setItemEnabled(hintingModesAlwaysDisabled[i], false); // the next four values always non-negative currentFontIndex = 0; currentFaceIndex = 0; currentNamedInstanceIndex = 0; currentGlyphIndex = 0; currentCFFHintingMode = hintingModesCFFHash[engine->cffHintingEngineDefault]; currentTTInterpreterVersion = hintingModesTrueTypeHash[engine->ttInterpreterVersionDefault]; hintingCheckBox->setChecked(true); antiAliasingComboBoxx->setCurrentIndex(AntiAliasing_Normal); lcdFilterComboBox->setCurrentIndex(LCDFilter_Light); horizontalHintingCheckBox->setChecked(true); verticalHintingCheckBox->setChecked(true); blueZoneHintingCheckBox->setChecked(true); showBitmapCheckBox->setChecked(true); showOutlinesCheckBox->setChecked(true); gammaSlider->setValue(18); // 1.8 sizeDoubleSpinBox->setValue(20); dpiSpinBox->setValue(96); zoomSpinBox->setValue(20); checkHinting(); checkHintingMode(); checkAutoHinting(); checkAntiAliasing(); checkLcdFilter(); checkShowPoints(); checkUnits(); checkCurrentFontIndex(); checkCurrentFaceIndex(); checkCurrentNamedInstanceIndex(); adjustGlyphIndex(0); zoom(); } void MainGUI::readSettings() { QSettings settings; // QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); // QSize size = settings.value("size", QSize(400, 400)).toSize(); // resize(size); // move(pos); } void MainGUI::writeSettings() { QSettings settings; // settings.setValue("pos", pos()); // settings.setValue("size", size()); } // end of maingui.cpp ft2demos-2.10.1/src/ftinspect/maingui.hpp0000644000175000001440000001411013503605615020110 0ustar00wlusers00000000000000// maingui.hpp // Copyright (C) 2016-2019 by Werner Lemberg. #pragma once #include "engine/engine.hpp" #include "rendering/glyphbitmap.hpp" #include "rendering/glyphoutline.hpp" #include "rendering/glyphpointnumbers.hpp" #include "rendering/glyphpoints.hpp" #include "widgets/qcomboboxx.hpp" #include "widgets/qgraphicsviewx.hpp" #include "widgets/qpushbuttonx.hpp" #include "widgets/qspinboxx.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include FT_LCD_FILTER_H class MainGUI : public QMainWindow { Q_OBJECT public: MainGUI(); ~MainGUI(); void setDefaults(); void update(Engine*); friend class Engine; friend FT_Error faceRequester(FTC_FaceID, FT_Library, FT_Pointer, FT_Face*); protected: void closeEvent(QCloseEvent*); private slots: void about(); void aboutQt(); void adjustGlyphIndex(int); void checkAntiAliasing(); void checkAutoHinting(); void checkCurrentFaceIndex(); void checkCurrentFontIndex(); void checkCurrentNamedInstanceIndex(); void checkHinting(); void checkHintingMode(); void checkLcdFilter(); void checkShowPoints(); void checkUnits(); void closeFont(); void drawGlyph(); void loadFonts(); void nextFace(); void nextFont(); void nextNamedInstance(); void previousFace(); void previousFont(); void previousNamedInstance(); void watchCurrentFont(); void zoom(); private: Engine* engine; QStringList fontList; int currentFontIndex; long currentNumberOfFaces; long currentFaceIndex; int currentNumberOfNamedInstances; int currentNamedInstanceIndex; int currentNumberOfGlyphs; int currentGlyphIndex; int currentCFFHintingMode; int currentTTInterpreterVersion; // layout related stuff GlyphOutline *currentGlyphOutlineItem; GlyphPoints *currentGlyphPointsItem; GlyphPointNumbers *currentGlyphPointNumbersItem; GlyphBitmap *currentGlyphBitmapItem; QAction *aboutAct; QAction *aboutQtAct; QAction *closeFontAct; QAction *exitAct; QAction *loadFontsAct; QCheckBox *autoHintingCheckBox; QCheckBox *blueZoneHintingCheckBox; QCheckBox *hintingCheckBox; QCheckBox *horizontalHintingCheckBox; QCheckBox *segmentDrawingCheckBox; QCheckBox *showBitmapCheckBox; QCheckBox *showOutlinesCheckBox; QCheckBox *showPointNumbersCheckBox; QCheckBox *showPointsCheckBox; QCheckBox *verticalHintingCheckBox; QCheckBox *warpingCheckBox; QComboBoxx *antiAliasingComboBoxx; QComboBoxx *hintingModeComboBoxx; QComboBox *lcdFilterComboBox; QComboBox *unitsComboBox; QDoubleSpinBox *sizeDoubleSpinBox; QFileSystemWatcher *fontWatcher; QGraphicsScene *glyphScene; QGraphicsViewx *glyphView; QGridLayout *fontLayout; QGridLayout *infoRightLayout; QHash hintingModesTrueTypeHash; QHash hintingModesCFFHash; QHash lcdFilterHash; QHBoxLayout *antiAliasingLayout; QHBoxLayout *blueZoneHintingLayout; QHBoxLayout *ftinspectLayout; QHBoxLayout *gammaLayout; QHBoxLayout *hintingModeLayout; QHBoxLayout *horizontalHintingLayout; QHBoxLayout *infoLeftLayout; QHBoxLayout *lcdFilterLayout; QHBoxLayout *navigationLayout; QHBoxLayout *pointNumbersLayout; QHBoxLayout *segmentDrawingLayout; QHBoxLayout *sizeLayout; QHBoxLayout *verticalHintingLayout; QHBoxLayout *warpingLayout; QLabel *antiAliasingLabel; QLabel *dpiLabel; QLabel *fontFilenameLabel; QLabel *fontNameLabel; QLabel *gammaLabel; QLabel *glyphIndexLabel; QLabel *glyphNameLabel; QLabel *hintingModeLabel; QLabel *lcdFilterLabel; QLabel *sizeLabel; QLabel *zoomLabel; QList hintingModesAlwaysDisabled; QLocale *locale; QMenu *menuFile; QMenu *menuHelp; QPen axisPen; QPen blueZonePen; QPen gridPen; QPen offPen; QPen onPen; QPen outlinePen; QPen segmentPen; QPushButton *nextFaceButton; QPushButton *nextFontButton; QPushButton *nextNamedInstanceButton; QPushButton *previousFaceButton; QPushButton *previousFontButton; QPushButton *previousNamedInstanceButton; QPushButtonx *toEndButtonx; QPushButtonx *toM1000Buttonx; QPushButtonx *toM100Buttonx; QPushButtonx *toM10Buttonx; QPushButtonx *toM1Buttonx; QPushButtonx *toP1000Buttonx; QPushButtonx *toP100Buttonx; QPushButtonx *toP10Buttonx; QPushButtonx *toP1Buttonx; QPushButtonx *toStartButtonx; QSignalMapper *glyphNavigationMapper; QSlider *gammaSlider; QSpinBox *dpiSpinBox; QSpinBoxx *zoomSpinBox; QTabWidget *tabWidget; QTimer *timer; QVBoxLayout *generalTabLayout; QVBoxLayout *leftLayout; QVBoxLayout *rightLayout; QVector grayColorTable; QVector monoColorTable; QWidget *ftinspectWidget; QWidget *generalTabWidget; QWidget *leftWidget; QWidget *rightWidget; QWidget *mmgxTabWidget; enum AntiAliasing { AntiAliasing_None, AntiAliasing_Normal, AntiAliasing_Light, AntiAliasing_LCD, AntiAliasing_LCD_BGR, AntiAliasing_LCD_Vertical, AntiAliasing_LCD_Vertical_BGR }; enum HintingMode { HintingMode_TrueType_v35, HintingMode_TrueType_v38, HintingMode_TrueType_v40, HintingMode_CFF_FreeType, HintingMode_CFF_Adobe }; enum LCDFilter { LCDFilter_Default, LCDFilter_Light, LCDFilter_None, LCDFilter_Legacy }; enum Units { Units_px, Units_pt }; void createActions(); void createConnections(); void createLayout(); void createMenus(); void clearStatusBar(); void createStatusBar(); void readSettings(); void setGraphicsDefaults(); void showFont(); void writeSettings(); }; // end of maingui.hpp ft2demos-2.10.1/src/ftinspect/ftinspect.pro0000644000175000001440000000236413506424316020477 0ustar00wlusers00000000000000# ftinspect.pro QMAKE_CXXFLAGS += -isystem ../../../freetype2/include # To avoid conflicts with the FreeType version compiled into or used by Qt, # we use the static library. # # You should adapt this to your setup. unix|macx { LIBS += ../../../freetype2/objs/.libs/libfreetype.a CONFIG += link_pkgconfig PKGCONFIG += libpng harfbuzz zlib bzip2 } win32 { LIBS += ../../../freetyp2/objs/vc2010/freetype2101.lib LIBS += -lpng -lharfbuzz -lz -lbz2 -lm } CONFIG += qt debug # we need access to internal FreeType header files DEFINES += FT2_BUILD_LIBRARY SOURCES += \ engine/engine.cpp \ rendering/glyphbitmap.cpp \ rendering/glyphoutline.cpp \ rendering/glyphpointnumbers.cpp \ rendering/glyphpoints.cpp \ rendering/grid.cpp \ widgets/qcomboboxx.cpp \ widgets/qgraphicsviewx.cpp \ widgets/qpushbuttonx.cpp \ widgets/qspinboxx.cpp \ ftinspect.cpp \ maingui.cpp HEADERS += \ engine/engine.hpp \ rendering/glyphbitmap.hpp \ rendering/glyphoutline.hpp \ rendering/glyphpointnumbers.hpp \ rendering/glyphpoints.hpp \ rendering/grid.hpp \ widgets/qcomboboxx.hpp \ widgets/qgraphicsviewx.hpp \ widgets/qpushbuttonx.hpp \ widgets/qspinboxx.hpp \ maingui.hpp TARGET = ftinspect QT += widgets # end of ftinpect.pro ft2demos-2.10.1/src/ftvalid.c0000644000175000001440000005474413434207203015557 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality font engine */ /* */ /* Copyright (C) 2005-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* ftvalid: Validates layout related tables of OpenType and */ /* TrueTypeGX/AAT. This program calls `FT_OpenType_Validate', */ /* `FT_TrueTypeGX_Validate' or `FT_ClassicKern_Validate' on a */ /* given file, and reports the validation result. */ /* */ /* */ /* written by YAMATO Masatake and SUZUKI Toshiya. */ /* */ /****************************************************************************/ #include #include FT_FREETYPE_H #include FT_TRUETYPE_TABLES_H #include FT_TRUETYPE_TAGS_H #include FT_OPENTYPE_VALIDATE_H #include FT_GX_VALIDATE_H /* the following four header files shouldn't be used in normal programs */ #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_VALIDATE_H #include FT_INTERNAL_MEMORY_H #include FT_INTERNAL_OBJECTS_H #include "common.h" #include "mlgetopt.h" #include #include #include static char* execname; typedef enum { OT_VALIDATE = 0, GX_VALIDATE, CKERN_VALIDATE, LAST_VALIDATE } ValidatorType; static ValidatorType validator; typedef struct TableSpecRec_ { FT_UInt tag; FT_UInt validation_flag; } TableSpecRec, *TableSpec; #define MAKE_TABLE_SPEC( x ) { TTAG_##x, FT_VALIDATE_##x } static TableSpecRec ot_table_spec[] = { MAKE_TABLE_SPEC( BASE ), MAKE_TABLE_SPEC( GDEF ), MAKE_TABLE_SPEC( GPOS ), MAKE_TABLE_SPEC( GSUB ), MAKE_TABLE_SPEC( JSTF ), MAKE_TABLE_SPEC( MATH ), }; #define N_OT_TABLE_SPEC ( sizeof ( ot_table_spec ) / sizeof ( TableSpecRec ) ) static TableSpecRec gx_table_spec[] = { MAKE_TABLE_SPEC( feat ), MAKE_TABLE_SPEC( mort ), MAKE_TABLE_SPEC( morx ), MAKE_TABLE_SPEC( bsln ), MAKE_TABLE_SPEC( just ), MAKE_TABLE_SPEC( kern ), MAKE_TABLE_SPEC( opbd ), MAKE_TABLE_SPEC( trak ), MAKE_TABLE_SPEC( prop ), MAKE_TABLE_SPEC( lcar ), }; #define N_GX_TABLE_SPEC ( sizeof ( gx_table_spec ) / sizeof ( TableSpecRec ) ) typedef struct ValidatorRec_ { ValidatorType type; const char* symbol; const char* unimplemented_message; int (* is_implemented)( FT_Library library ); FT_Error (* run) ( FT_Face face, const char* tables, int validation_level ); int (* list_tables) ( FT_Face face ); TableSpec table_spec; unsigned int n_table_spec; } ValidatorRec, *Validator; static int is_ot_validator_implemented ( FT_Library library ); static int is_gx_validator_implemented ( FT_Library library ); static int is_ckern_validator_implemented ( FT_Library library ); static FT_Error run_ot_validator ( FT_Face face, const char* tables, int validation_level ); static FT_Error run_gx_validator ( FT_Face face, const char* tables, int validation_level ); static FT_Error run_ckern_validator ( FT_Face face, const char* dialect_request, int validation_level ); static int list_ot_tables ( FT_Face face ); static int list_gx_tables ( FT_Face face ); static int list_ckern_tables ( FT_Face face ); static ValidatorRec validators[] = { { OT_VALIDATE, "ot", ( "FT_OpenType_Validate" " is disabled! Recompile FreeType 2 with " "otvalid" " module enabled.\n" ), is_ot_validator_implemented, run_ot_validator, list_ot_tables, ot_table_spec, N_OT_TABLE_SPEC, }, { GX_VALIDATE, "gx", ( "FT_TrueTypeGX_Validate" " is disabled! Recompile FreeType 2 with " "gxvalid" " module enabled.\n" ), is_gx_validator_implemented, run_gx_validator, list_gx_tables, gx_table_spec, N_GX_TABLE_SPEC, }, { CKERN_VALIDATE, "ckern", ( "FT_ClassicKern_Validate" " is disabled! Recompile FreeType 2 with " "gxvalid" /* NOTE: classic kern validator is in gxvalid. */ " module enabled.\n" ), is_ckern_validator_implemented, run_ckern_validator, list_ckern_tables, NULL, 0, }, }; static void panic( int error, const char* message ) { fprintf( stderr, "%s\n error = 0x%04x\n", message, error ); exit( 1 ); } static char* make_tag_chararray ( char chararray[4], FT_UInt tag ) { chararray[0] = (char)( ( tag >> 24 ) & 0xFF ); chararray[1] = (char)( ( tag >> 16 ) & 0xFF ); chararray[2] = (char)( ( tag >> 8 ) & 0xFF ); chararray[3] = (char)( ( tag >> 0 ) & 0xFF ); return chararray; } static void print_tag ( FILE* stream, FT_UInt tag ) { char buffer[5]; buffer[4] = '\0'; fprintf( stream, "%s", make_tag_chararray( buffer, tag ) ); } /* To initialize the internal variable, call this function with FT_Library variable. Then call with NULL. The print messages is printed if call with NULL. */ static void print_usage( FT_Library library_initializer ) { unsigned int i, j; Validator v; static FT_Library library; if (library_initializer) { library = library_initializer; return ; } fprintf( stderr, "\n" "ftvalid: layout table validator -- part of the FreeType project\n" "---------------------------------------------------------------\n" "\n" ); fprintf( stderr, "Usage: %s [options] fontfile\n" "\n", execname ); fprintf( stderr, "Options:\n" "\n" ); fprintf( stderr, " -f index Select font index (default: 0).\n" "\n" ); fprintf( stderr, " -t validator Select validator.\n" " Available validators:\n" " " ); for ( i = 0; i < LAST_VALIDATE; i++ ) { v = &validators[i]; fprintf( stderr, " %s%s", v->symbol, v->is_implemented( library ) ? "" : " (NOT COMPILED IN)" ); } fprintf( stderr, "\n" "\n" ); fprintf( stderr, " -T tbls [ot, gx] Select sfnt table name tags to be validated.\n" " Use `:' to separate tags.\n" "\n" ); for ( i = 0; i < LAST_VALIDATE; i++ ) { v = &validators[i]; if ( v->n_table_spec == 0 ) continue; fprintf( stderr, " Supported tables in %s validator:\n" " ", v->symbol ); for ( j = 0; j < v->n_table_spec; j++ ) { fprintf( stderr, " " ); print_tag( stderr, v->table_spec[j].tag ); } fprintf( stderr, "\n" "\n" ); } fprintf( stderr, " Example: -T \"feat:morx\"\n" "\n" ); fprintf( stderr, " -T dialect [ckern] Select classic kern dialect for validation.\n" " Use `:' to separate dialect names.\n" " If more than one dialect is specified,\n" " all dialects are accepted when validating.\n" "\n" " Supported dialects in ckern validator:\n" " ms apple\n" "\n" ); fprintf( stderr, " -l List the layout-related SFNT tables\n" " available in the font file.\n" " The selected validator (with option `-t')\n" " affects the list.\n" "\n" " ckern is applicable to `kern' table only.\n" " Option `-l' lists dialects supported in ckern validator\n" " only if `kern' table is available in the font file.\n" "\n" ); fprintf( stderr, " -V level Validation level. Possible values:\n" " 0 (default), 1 (tight), 2 (paranoid)\n" "\n" ); fprintf( stderr, " -v Show version." "\n" ); fprintf( stderr, "-------------------------------------------------------------------\n" "\n" ); fprintf( stderr, "`FT2_DEBUG' environment variable:\n" "\n" " You can specify `component:level' pairs for tracing.\n" " `level' must be in the range [1,7].\n" " Available components for ot validator:\n" " otvmodule otvcommon otvbase otvgdef otvgpos otvgsub otvjstf\n" " Available components for gx validator:\n" " gxvmodule gxvcommon gxvfeat gxvmort gxvmorx gxvbsln gxvjust\n" " gxvkern gxvopbd gxvtrak gxvprop gxvlcar\n" " Available components for ckern validator:\n" " gxvkern\n" "\n" " Example:\n" "\n" " FT2_DEBUG=\"otvcommon:5 gxvkern:7\"\n" "\n" "FT2_DEBUG only works if tracing support is compiled into FreeType 2\n" "\n" ); exit( 1 ); } static FT_Error try_load( FT_Face face, FT_ULong tag ) { FT_ULong length; length = 0; return FT_Load_Sfnt_Table( face, tag, 0, NULL, &length ); } static FT_UInt find_validation_flag( FT_UInt tag, const TableSpecRec spec[], int spec_count ) { int i; for ( i = 0; i < spec_count; i++ ) { if ( tag == spec[i].tag ) return spec[i].validation_flag; } fprintf( stderr, "*** Wrong table name: " ); print_tag( stderr, tag ); fprintf( stderr, "\n" ); print_usage( NULL ); return 0; } static FT_UInt parse_table_specs( const char* tables, const TableSpecRec spec[], int spec_count ) { FT_UInt validation_flags; size_t len; unsigned int i; char tag[4]; validation_flags = 0; len = strlen( tables ); if (( len % 5 ) != 4 ) { fprintf( stderr, "*** Wrong length of table names\n" ); print_usage( NULL ); } for ( i = 0; i < len; i++ ) { if ( ( ( i % 5 ) == 4 ) ) { if ( tables[i] != ':' ) { fprintf( stderr, "*** Wrong table separator: %c\n", tables[i] ); print_usage( NULL ); } i++; } tag[i % 5] = tables[i]; if ( ( i % 5 ) == 3 ) validation_flags |= find_validation_flag( FT_MAKE_TAG( tag[0], tag[1], tag[2], tag[3] ), spec, spec_count ); } return validation_flags; } static FT_UInt list_face_tables( FT_Face face, const TableSpecRec spec[], int spec_count ) { FT_Error error; FT_UInt validation_flags; int i; FT_UInt tag; validation_flags = 0; for ( i = 0; i < spec_count; i++ ) { tag = spec[i].tag; error = try_load( face, tag ); if ( error == 0 ) validation_flags |= spec[i].validation_flag; } return validation_flags; } static FT_UInt make_table_specs( FT_Face face, const char* request, const TableSpecRec spec[], int spec_count ) { if ( request == NULL || request[0] == '\0' ) return list_face_tables ( face, spec, spec_count ); else return parse_table_specs ( request, spec, spec_count ); } static int print_tables( FILE* stream, FT_UInt validation_flags, const TableSpecRec spec[], int spec_count ) { int i; int n_print; for ( i = 0, n_print = 0; i < spec_count; i++ ) { if ( spec[i].validation_flag & validation_flags ) { if ( n_print != 0 ) fprintf( stream, "%c", ':' ); print_tag( stream, spec[i].tag ); n_print++; } } fprintf( stream, "\n" ); return !n_print; } static void report_header( FT_UInt validation_flags, const TableSpecRec spec[], int spec_count ) { printf( "[%s:%s] validation targets: ", execname, validators[validator].symbol ); print_tables( stdout, validation_flags, spec, spec_count ); printf( "-------------------------------------------------------------------\n" ); } static void report_result( FT_Bytes data[], FT_UInt validation_flags, const TableSpecRec spec[], int spec_count ) { int i; int n_passes; int n_targets; for ( i = 0, n_passes = 0, n_targets = 0; i < spec_count; i++ ) { if ( spec[i].validation_flag & validation_flags ) { n_targets++; if ( data[i] != NULL ) { printf( "[%s:%s] ", execname, validators[validator].symbol ); print_tag( stdout, spec[i].tag ); printf( "%s", "...pass\n" ); n_passes++; } } } if ( n_passes == 0 && n_targets != 0 ) { printf( "[%s:%s] layout tables are invalid.\n", execname, validators[validator].symbol ); printf( "[%s:%s] set FT2_DEBUG environment variable to\n", execname, validators[validator].symbol ); printf( "[%s:%s] know the validation detail.\n", execname, validators[validator].symbol ); } } /* * OpenType related functions */ static int is_ot_validator_implemented( FT_Library library ) { FT_Module mod; mod = FT_Get_Module( library, "otvalid" ); return mod? 1: 0; } static FT_Error run_ot_validator( FT_Face face, const char* tables, int validation_level ) { FT_UInt validation_flags; FT_Error error; FT_Bytes data[N_OT_TABLE_SPEC]; unsigned int i; validation_flags = (FT_UInt)validation_level; validation_flags |= make_table_specs( face, tables, ot_table_spec, N_OT_TABLE_SPEC ); for ( i = 0; i < N_OT_TABLE_SPEC; i++ ) data[i] = NULL; report_header( validation_flags, ot_table_spec, N_OT_TABLE_SPEC ); error = FT_OpenType_Validate( face, validation_flags, &data[0], &data[1], &data[2], &data[3], &data[4] ); report_result( data, validation_flags, ot_table_spec, N_OT_TABLE_SPEC ); for ( i = 0; i < N_OT_TABLE_SPEC; i++ ) FT_OpenType_Free( face, data[i] ); return error; } static int list_ot_tables( FT_Face face ) { FT_UInt validation_flags; validation_flags = list_face_tables( face, ot_table_spec, N_OT_TABLE_SPEC ); return print_tables( stdout, validation_flags, ot_table_spec, N_OT_TABLE_SPEC ); } /* * TrueTypeGX related functions */ static int is_gx_validator_implemented( FT_Library library ) { FT_Module mod; mod = FT_Get_Module( library, "gxvalid" ); return mod? 1: 0; } static FT_Error run_gx_validator( FT_Face face, const char* tables, int validation_level ) { FT_UInt validation_flags; FT_Error error; FT_Bytes data[N_GX_TABLE_SPEC]; unsigned int i; validation_flags = (FT_UInt)validation_level; validation_flags |= make_table_specs( face, tables, gx_table_spec, N_GX_TABLE_SPEC ); for ( i = 0; i < N_GX_TABLE_SPEC; i++ ) data[i] = NULL; report_header( validation_flags, gx_table_spec, N_GX_TABLE_SPEC ); error = FT_TrueTypeGX_Validate( face, validation_flags, data, N_GX_TABLE_SPEC ); report_result( data, validation_flags, gx_table_spec, N_GX_TABLE_SPEC ); for ( i = 0; i < N_GX_TABLE_SPEC; i++ ) FT_TrueTypeGX_Free( face, data[i] ); return error; } static int list_gx_tables ( FT_Face face ) { FT_UInt validation_flags; validation_flags = list_face_tables( face, gx_table_spec, N_GX_TABLE_SPEC ); return print_tables( stdout, validation_flags, gx_table_spec, N_GX_TABLE_SPEC ); } /* * Classic kern related functions */ static int is_ckern_validator_implemented( FT_Library library ) { FT_Module mod; mod = FT_Get_Module( library, "gxvalid" ); return mod? 1: 0; } static FT_Error run_ckern_validator( FT_Face face, const char* dialect_request, int validation_level ) { FT_UInt validation_flags; FT_Error error; FT_Bytes data; if ( dialect_request == NULL ) dialect_request = "ms:apple"; validation_flags = (FT_UInt)validation_level; if ( strcmp( dialect_request, "ms:apple" ) == 0 || strcmp( dialect_request, "apple:ms" ) == 0 ) validation_flags |= FT_VALIDATE_MS | FT_VALIDATE_APPLE; else if ( strcmp( dialect_request, "ms" ) == 0 ) validation_flags |= FT_VALIDATE_MS; else if ( strcmp( dialect_request, "apple" ) == 0 ) validation_flags |= FT_VALIDATE_APPLE; else { fprintf( stderr, "Wrong classic kern dialect: %s\n", dialect_request ); print_usage( NULL ); } printf( "[%s:%s] validation targets: %s...", execname, validators[validator].symbol, dialect_request ); error = FT_ClassicKern_Validate( face, validation_flags, &data ); if ( data ) printf( "pass\n" ); else if ( data == NULL && error ) printf( "fail\n" ); else printf( "no kern\n" ); FT_ClassicKern_Free( face, data ); return error; } static int list_ckern_tables ( FT_Face face ) { FT_Error error; error = try_load( face, TTAG_kern ); if ( error == 0 ) printf( "ms:apple\n" ); return 0; } /* * Main driver */ int main( int argc, char** argv ) { FT_Library library; FT_Error error; char* fontfile; int option; char* tables; int dump_table_list; int validation_level; int font_index = 0; execname = ft_basename( argv[0] ); error = FT_Init_FreeType( &library ); if ( error ) panic ( error, "Could not initialize FreeType library" ); /* Initialize print_usage internal variable */ print_usage( library ); /* * Parsing options */ validator = OT_VALIDATE; tables = NULL; dump_table_list = 0; validation_level = FT_VALIDATE_DEFAULT; while ( 1 ) { option = getopt( argc, argv, "f:lt:T:vV:" ); if ( option == -1 ) break; switch ( option ) { case 't': { int i; validator = LAST_VALIDATE; for ( i = 0; i < LAST_VALIDATE; i++ ) { if ( strcmp( optarg, validators[i].symbol ) == 0 ) { validator = (ValidatorType)i; break; } } if ( validator == LAST_VALIDATE ) { fprintf( stderr, "*** Unknown validator name: %s\n", optarg ); print_usage( NULL ); } } break; case 'T': tables = optarg; break; case 'l': dump_table_list = 1; break; case 'V': validation_level = atoi( optarg ); if ( validation_level < 0 || validation_level > FT_VALIDATE_PARANOID ) { fprintf( stderr, "*** Validation level is out of range: %d\n", validation_level ); print_usage( NULL ); } break; case 'f': font_index = atoi( optarg ); break; case 'v': { FT_Int major, minor, patch; FT_Library_Version( library, &major, &minor, &patch ); printf( "ftvalid (FreeType) %d.%d", major, minor ); if ( patch ) printf( ".%d", patch ); printf( "\n" ); exit( 0 ); } /* break; */ default: print_usage( NULL ); break; } } argc -= optind; argv += optind; if ( argc == 0 ) { fprintf(stderr, "*** Font file is not specified.\n"); print_usage( NULL ); } else if ( argc > 1 ) { fprintf(stderr, "*** Too many font files.\n"); print_usage( NULL ); } fontfile = argv[0]; /* * Run a validator */ { FT_Face face; FT_Error status; status = 0; if ( !validators[validator].is_implemented( library ) ) panic( FT_Err_Unimplemented_Feature, validators[validator].unimplemented_message ); /* TODO: Multiple faces in a font file? */ error = FT_New_Face( library, fontfile, font_index, &face ); if ( error ) panic( error, "Could not open face." ); if ( dump_table_list ) validators[validator].list_tables( face ); else status = validators[validator].run( face, tables, validation_level ); FT_Done_Face( face ); FT_Done_FreeType( library ); return (int)status; } } /* End */ ft2demos-2.10.1/src/common.c0000644000175000001440000000305413434207203015402 0ustar00wlusers00000000000000/* some utility functions */ #include "common.h" #include #include #include char* ft_basename( const char* name ) { const char* base; const char* current; char c; base = name; current = name; c = *current; while ( c ) { #ifndef macintosh if ( c == '/' || c == '\\' ) #else if ( c == ':' ) #endif base = current + 1; current++; c = *current; } return (char*)base; } void Panic( const char* fmt, ... ) { va_list ap; va_start( ap, fmt ); vprintf( fmt, ap ); va_end( ap ); exit( 1 ); } extern int utf8_next( const char** pcursor, const char* end ) { const unsigned char* p = (const unsigned char*)*pcursor; int ch; if ( (const char*)p >= end ) /* end of stream */ return -1; ch = *p++; if ( ch >= 0x80 ) { int len; if ( ch < 0xc0 ) /* malformed data */ goto BAD_DATA; else if ( ch < 0xe0 ) { len = 1; ch &= 0x1f; } else if ( ch < 0xf0 ) { len = 2; ch &= 0x0f; } else { len = 3; ch &= 0x07; } while ( len > 0 ) { if ( (const char*)p >= end || ( p[0] & 0xc0 ) != 0x80 ) goto BAD_DATA; ch = ( ch << 6 ) | ( p[0] & 0x3f ); p += 1; len -= 1; } } *pcursor = (const char*)p; return ch; BAD_DATA: return -1; } /* End */ ft2demos-2.10.1/src/testname.c0000644000175000001440000000306113434207203015730 0ustar00wlusers00000000000000#include #include #include #include #include FT_FREETYPE_H int main( int argc, char* argv[] ) { FT_Library font_library; FT_Face font_face; FT_Bitmap bitmap; FT_GlyphSlot cur_glyph; FT_Glyph_Metrics glyph_metrics; int glyph_ind; int num_chars; char char_name[256]; if (argc != 2) exit( 1 ); if ( FT_Init_FreeType( &font_library ) ) exit( 1 ); if ( FT_New_Face( font_library, argv[1], 0 , &font_face ) ) exit( 1 ); if ( FT_Set_Char_Size( font_face , 0 , 768 , 300 , 300 ) ) exit( 1 ); num_chars = (int)font_face->num_glyphs; FT_Set_Transform( font_face , NULL , NULL ); for ( glyph_ind = 0 ; glyph_ind < num_chars; glyph_ind++ ) { if ( FT_Load_Glyph( font_face, glyph_ind, FT_LOAD_DEFAULT ) ) exit( 1 ); cur_glyph = font_face->glyph; if ( cur_glyph->format != FT_GLYPH_FORMAT_BITMAP ) if ( FT_Render_Glyph( font_face->glyph, FT_RENDER_MODE_MONO ) ) exit( 1 ); if ( FT_Get_Glyph_Name( font_face, glyph_ind, char_name, 16 ) ) exit( 1 ); bitmap = cur_glyph->bitmap; glyph_metrics = cur_glyph->metrics; printf( "Glyph %d name %s %ld %ld %ld %d %d\n", glyph_ind, char_name, glyph_metrics.horiBearingX / 64, glyph_metrics.horiBearingY / 64, glyph_metrics.horiAdvance / 64, bitmap.width , bitmap.rows ); } return 0; } /* END */ ft2demos-2.10.1/src/ftchkwd.c0000644000175000001440000001202013434207203015535 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality font engine */ /* */ /* Copyright (C) 2003-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* ftchkwd */ /* */ /* NOTE: This is just a test program that is used to show off and */ /* debug the current engine. */ /* */ /****************************************************************************/ #include #include FT_FREETYPE_H #include #include #include FT_Error error; static void Usage( char* name ) { printf( "ftchkwd: test fixed font width -- part of the FreeType project\n" ); printf( "---------------------------------------------------------------------\n" ); printf( "\n" ); printf( "Usage: %s fontname[.ttf|.ttc] [fontname2..]\n", name ); printf( "\n" ); exit( 1 ); } static void Panic( const char* message ) { fprintf( stderr, "%s\n error code = 0x%04x\n", message, error ); exit(1); } static const char* file_basename( const char* pathname ) { const char* base = pathname; const char* p = pathname; while ( *p ) { if ( *p == '/' || *p == '\\' ) base = p + 1; p++; } return base; } static void check_face( FT_Face face, const char* filepathname, int idx ) { int face_has_fixed_flag = FT_IS_FIXED_WIDTH(face); int face_max_advance = face->max_advance_width; int num_proportional = 0; int n; FT_UNUSED( idx ); printf( "%15s : %20s : ", file_basename( filepathname ), face->family_name ? face->family_name : "UNKNOWN FAMILY" ); for ( n = 0; n < face->num_glyphs; n++ ) { /* load the glyph outline */ error = FT_Load_Glyph( face, n, FT_LOAD_NO_SCALE ); if ( error ) continue; if ( face->glyph->metrics.horiAdvance != face_max_advance ) num_proportional++; } if ( num_proportional > 0 ) { if ( face_has_fixed_flag ) printf( "KO! Tagged as fixed, but has %d `proportional' glyphs", num_proportional ); else printf( "OK (proportional)" ); } else { if ( face_has_fixed_flag ) printf( "OK (fixed-width)" ); else printf( "KO! Tagged as proportional but has fixed width" ); } printf( "\n" ); } int main( int argc, char** argv ) { FT_Face face; FT_Library library; int i, file_index; char filename[1024 + 4]; char alt_filename[1024 + 4]; char* execname; char* fname; execname = argv[0]; if ( argc < 2 ) Usage( execname ); error = FT_Init_FreeType( &library ); if ( error ) Panic( "Could not create library object" ); /* Now check all files */ for ( file_index = 1; file_index < argc; file_index++ ) { fname = argv[file_index]; /* try to open the file with no extra extension first */ error = FT_New_Face( library, fname, 0, &face ); if ( !error ) goto Success; if ( error == FT_Err_Unknown_File_Format ) { fprintf( stderr, "%s: unknown format\n", fname ); continue; } /* Ok, we could not load the file. Try to add an extension to */ /* its name if possible. */ i = strlen( fname ); while ( i > 0 && fname[i] != '\\' && fname[i] != '/' ) { if ( fname[i] == '.' ) i = 0; i--; } filename[1024] = '\0'; alt_filename[1024] = '\0'; strncpy( filename, fname, 1024 ); strncpy( alt_filename, fname, 1024 ); #ifndef macintosh if ( i >= 0 ) { strncpy( filename + strlen( filename ), ".ttf", 4 ); strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 ); } #endif /* Load face */ error = FT_New_Face( library, filename, 0, &face ); if ( error ) { if ( error == FT_Err_Unknown_File_Format ) printf( "unknown format\n" ); else printf( "could not find/open file (error: %d)\n", error ); continue; } Success: check_face( face, fname, face->face_index ); FT_Done_Face( face ); } FT_Done_FreeType( library ); exit( 0 ); /* for safety reasons */ return 0; /* never reached */ } /* End */ ft2demos-2.10.1/src/ftmemchk.c0000644000175000001440000001752113434207203015714 0ustar00wlusers00000000000000/* ftmemchk.c */ #include #include FT_FREETYPE_H #include FT_MODULE_H #include #include #include FT_Error error; FT_Library library; FT_Face face; unsigned int num_glyphs; int ptsize; int Fail; int Num; /****************************************************************************/ /****************************************************************************/ /****************************************************************************/ /****************************************************************************/ /* Our own memory allocator. To check that a single block isn't freed */ /* several time, we simply do not call "free".. */ #define MAX_RECORDED_BLOCKS 1638400 #define CHECK_DUPLICATES typedef struct MyBlock { void* base; long size; } MyBlock; static MyBlock my_blocks[ MAX_RECORDED_BLOCKS ]; static int num_my_blocks = 0; /* record a new block in the table, check for duplicates too */ static void record_my_block( void* base, long size ) { if (size <= 0) { fprintf( stderr, "adding a block with non-positive length - should not happen \n" ); exit(1); } if ( num_my_blocks < MAX_RECORDED_BLOCKS ) { MyBlock* block; #ifdef CHECK_DUPLICATES MyBlock* limit; block = my_blocks; limit = block + num_my_blocks; for ( ; block < limit; block++ ) { if ( block->base == base && block->size != 0 ) { fprintf( stderr, "duplicate memory block at %08lx\n", (long)block->base ); exit(1); } } #endif block = my_blocks + num_my_blocks++; block->base = base; block->size = size; } else { fprintf( stderr, "Too many memory blocks -- test exited !!\n" ); exit(1); } } /* forget a block, and check that it isn't part of our table already */ static void forget_my_block( void* base ) { MyBlock* block = my_blocks + num_my_blocks-1; /* we scan in reverse, because transient blocks are always located */ /* at the end of the table.. (it supposedly faster then..) */ for ( ; block >= my_blocks; block-- ) { if ( block->base == base ) { if (block->size > 0) { block->size = 0; return; } else { fprintf( stderr, "Block at %p released twice \n", base ); exit(1); } } } fprintf( stderr, "Trying to release an unallocated block at %p\n", base ); exit(1); } FT_CALLBACK_DEF( void* ) my_alloc( FT_Memory memory, long size ) { void* p = malloc(size); if (p) record_my_block(p,size); memory=memory; return p; } FT_CALLBACK_DEF( void ) my_free( FT_Memory memory, void* block ) { memory=memory; forget_my_block(block); /* free(block); WE DO NOT REALLY FREE THE BLOCK */ } FT_CALLBACK_DEF( void* ) my_realloc( FT_Memory memory, long cur_size, long new_size, void* block ) { void* p; p = my_alloc( memory, new_size ); if (p) { long size; size = cur_size; if (new_size < size) size = new_size; memcpy( p, block, size ); my_free( memory, block ); } return p; } static FT_Memory my_memory( void ) { FT_Memory memory; memory = (FT_Memory)my_alloc( 0, sizeof(*memory) ); if (!memory) { fprintf( stderr, "Unable to allocate debug memory manager !?!\n" ); exit(2); } memory->user = 0; memory->alloc = my_alloc; memory->free = my_free; memory->realloc = my_realloc; return memory; } static void dump_mem( void ) { MyBlock* block = my_blocks + num_my_blocks-1; int bad = 0; printf( "total allocated blocks = %d\n", num_my_blocks ); /* we scan in reverse, because transient blocks are always located */ /* at the end of the table.. (it supposedly faster then..) */ for ( ; block >= my_blocks; block-- ) { if (block->size > 0) { fprintf( stderr, "%p (%6ld bytes) leaked !!\n", block->base, (long)block->size ); bad = 1; } } if (!bad) fprintf( stderr, "no leaked memory block\n\n" ); } /****************************************************************************/ /****************************************************************************/ /****************************************************************************/ /****************************************************************************/ static void Usage( char* name ) { printf( "ftmemchk: simple memory tester -- part of the FreeType project\n" ); printf( "--------------------------------------------------------------\n" ); printf( "\n" ); printf( "Usage: %s ppem fontname[.ttf|.ttc] [fontname2..]\n", name ); printf( "\n" ); exit( 1 ); } static void Panic( const char* message ) { fprintf( stderr, "%s\n error code = 0x%04x\n", message, error ); exit(1); } int main( int argc, char** argv ) { int i, file_index; unsigned int id; char filename[1024 + 4]; char alt_filename[1024 + 4]; char* execname; char* fname; execname = argv[0]; if ( argc < 3 ) Usage( execname ); if ( sscanf( argv[1], "%d", &ptsize ) != 1 ) Usage( execname ); /* Create a new library with our own memory manager */ error = FT_New_Library( my_memory(), &library ); if (error) Panic( "Could not create library object" ); /* the new library has no drivers in it, add the default ones */ /* (implemented in ftinit.c).. */ FT_Add_Default_Modules(library); /* Now check all files */ for ( file_index = 2; file_index < argc; file_index++ ) { fname = argv[file_index]; i = strlen( fname ); while ( i > 0 && fname[i] != '\\' && fname[i] != '/' ) { if ( fname[i] == '.' ) i = 0; i--; } filename[1024] = '\0'; alt_filename[1024] = '\0'; strncpy( filename, fname, 1024 ); strncpy( alt_filename, fname, 1024 ); #ifndef macintosh if ( i >= 0 ) { strncpy( filename + strlen( filename ), ".ttf", 4 ); strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 ); } #endif i = strlen( filename ); fname = filename; while ( i >= 0 ) #ifndef macintosh if ( filename[i] == '/' || filename[i] == '\\' ) #else if ( filename[i] == ':' ) #endif { fname = filename + i + 1; i = -1; } else i--; printf( "%s: ", fname ); /* Load face */ error = FT_New_Face( library, filename, 0, &face ); if (error) { if (error == FT_Err_Invalid_File_Format) printf( "unknown format\n" ); else printf( "could not find/open file (error: %d)\n", error ); continue; } if (error) Panic( "Could not open file" ); num_glyphs = face->num_glyphs; error = FT_Set_Char_Size( face, ptsize << 6, ptsize << 6, 72, 72 ); if (error) Panic( "Could not set character size" ); Fail = 0; { for ( id = 0; id < num_glyphs; id++ ) { error = FT_Load_Glyph( face, id, FT_LOAD_RENDER ); if (error) { if ( Fail < 10 ) printf( "glyph %4u: 0x%04x\n" , id, error ); Fail++; } } } if ( Fail == 0 ) printf( "OK.\n" ); else if ( Fail == 1 ) printf( "1 fail.\n" ); else printf( "%d fails.\n", Fail ); FT_Done_Face( face ); } FT_Done_FreeType(library); dump_mem(); exit( 0 ); /* for safety reasons */ return 0; /* never reached */ } ft2demos-2.10.1/src/ftbench.c0000644000175000001440000010032213434207203015517 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 2002-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* ftbench: bench some common FreeType call paths */ /* */ /****************************************************************************/ #ifndef _GNU_SOURCE #define _GNU_SOURCE /* we want to use extensions to `time.h' if available */ #endif #include #include #include #include #include #include FT_FREETYPE_H #include FT_GLYPH_H #include FT_CACHE_H #include FT_CACHE_CHARMAP_H #include FT_CACHE_IMAGE_H #include FT_CACHE_SMALL_BITMAPS_H #include FT_SYNTHESIS_H #include FT_ADVANCES_H #include FT_OUTLINE_H #include FT_BBOX_H #include FT_MODULE_H #include FT_DRIVER_H #include FT_LCD_FILTER_H #ifdef UNIX #include #else #include "mlgetopt.h" #endif #include "common.h" typedef struct btimer_t_ { double t0; double total; } btimer_t; typedef int (*bcall_t)( btimer_t* timer, FT_Face face, void* user_data ); typedef struct btest_t_ { const char* title; bcall_t bench; int cache_first; void* user_data; } btest_t; typedef struct bcharset_t_ { FT_Int size; FT_ULong* code; } bcharset_t; static FT_Error get_face( FT_Face* face ); /* * Globals */ #define CACHE_SIZE 1024 #define BENCH_TIME 2.0 #define FACE_SIZE 10 static FT_Library lib; static FTC_Manager cache_man; static FTC_CMapCache cmap_cache; static FTC_ImageCache image_cache; static FTC_SBitCache sbit_cache; static FTC_ImageTypeRec font_type; enum { FT_BENCH_LOAD_GLYPH, FT_BENCH_LOAD_ADVANCES, FT_BENCH_RENDER, FT_BENCH_GET_GLYPH, FT_BENCH_GET_CBOX, FT_BENCH_CMAP, FT_BENCH_CMAP_ITER, FT_BENCH_NEW_FACE, FT_BENCH_EMBOLDEN, FT_BENCH_GET_BBOX, FT_BENCH_NEW_FACE_AND_LOAD_GLYPH, N_FT_BENCH }; static const char* bench_desc[] = { "load a glyph (FT_Load_Glyph)", "load advance widths (FT_Get_Advances)", "render a glyph (FT_Render_Glyph)", "load a glyph (FT_Get_Glyph)", "get glyph cbox (FT_Glyph_Get_CBox)", "get glyph indices (FT_Get_Char_Index)", "iterate CMap (FT_Get_{First,Next}_Char)", "open a new face (FT_New_Face)", "embolden (FT_GlyphSlot_Embolden)", "get glyph bbox (FT_Outline_Get_BBox)", "open face and load glyph", NULL }; static int preload; static char* filename; static unsigned int first_index = 0U; static unsigned int last_index = ~0U; static FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL; static FT_Int32 load_flags = FT_LOAD_DEFAULT; static unsigned int tt_interpreter_versions[3]; static int num_tt_interpreter_versions; static unsigned int dflt_tt_interpreter_version; static unsigned int ps_hinting_engines[2]; static int num_ps_hinting_engines; static unsigned int dflt_ps_hinting_engine; static char ps_hinting_engine_names[2][10] = { "freetype", "adobe" }; /* * Dummy face requester (the face object is already loaded) */ static FT_Error face_requester( FTC_FaceID face_id, FT_Library library, FT_Pointer request_data, FT_Face* aface ) { FT_UNUSED( face_id ); FT_UNUSED( library ); *aface = (FT_Face)request_data; return FT_Err_Ok; } /* * timer in milliseconds */ static double get_time( void ) { #if defined _POSIX_TIMERS && _POSIX_TIMERS > 0 struct timespec tv; #ifdef _POSIX_CPUTIME clock_gettime( CLOCK_PROCESS_CPUTIME_ID, &tv ); #else clock_gettime( CLOCK_REALTIME, &tv ); #endif /* _POSIX_CPUTIME */ return 1E6 * (double)tv.tv_sec + 1E-3 * (double)tv.tv_nsec; #else /* clock() accuracy has improved since glibc 2.18 */ return 1E6 * (double)clock() / (double)CLOCKS_PER_SEC; #endif /* _POSIX_TIMERS */ } #define TIMER_START( timer ) ( timer )->t0 = get_time() #define TIMER_STOP( timer ) ( timer )->total += get_time() - ( timer )->t0 #define TIMER_GET( timer ) ( timer )->total #define TIMER_RESET( timer ) ( timer )->total = 0 /* * Bench code */ static void benchmark( FT_Face face, btest_t* test, int max_iter, double max_time ) { int n, done; btimer_t timer, elapsed; if ( test->cache_first ) { if ( !cache_man ) { printf( " %-25s no cache manager\n", test->title ); return; } TIMER_RESET( &timer ); test->bench( &timer, face, test->user_data ); } printf( " %-25s ", test->title ); fflush( stdout ); TIMER_RESET( &timer ); TIMER_RESET( &elapsed ); for ( n = 0, done = 0; !max_iter || n < max_iter; n++ ) { TIMER_START( &elapsed ); done += test->bench( &timer, face, test->user_data ); TIMER_STOP( &elapsed ); if ( TIMER_GET( &elapsed ) > 1E6 * max_time ) break; } if ( done ) printf( "%10.3f us/op %10d done\n", TIMER_GET( &timer ) / (double)done, done ); else printf( "no error-free calls\n" ); } /* * Various tests */ static int test_load( btimer_t* timer, FT_Face face, void* user_data ) { unsigned int i; int done = 0; FT_UNUSED( user_data ); TIMER_START( timer ); for ( i = first_index; i <= last_index; i++ ) { if ( !FT_Load_Glyph( face, i, load_flags ) ) done++; } TIMER_STOP( timer ); return done; } static int test_load_advances( btimer_t* timer, FT_Face face, void* user_data ) { int done = 0; FT_Fixed* advances; FT_ULong flags = *((FT_ULong*)user_data); advances = (FT_Fixed *)calloc( sizeof ( FT_Fixed ), (size_t)face->num_glyphs ); TIMER_START( timer ); FT_Get_Advances( face, first_index, last_index - first_index + 1, (FT_Int32)flags, advances ); done += (int)( last_index - first_index ) + 1; TIMER_STOP( timer ); free( advances ); return done; } static int test_render( btimer_t* timer, FT_Face face, void* user_data ) { unsigned int i; int done = 0; FT_UNUSED( user_data ); for ( i = first_index; i <= last_index; i++ ) { if ( FT_Load_Glyph( face, i, load_flags ) ) continue; TIMER_START( timer ); if ( !FT_Render_Glyph( face->glyph, render_mode ) ) done++; TIMER_STOP( timer ); } return done; } static int test_embolden( btimer_t* timer, FT_Face face, void* user_data ) { unsigned int i; int done = 0; FT_UNUSED( user_data ); for ( i = first_index; i <= last_index; i++ ) { if ( FT_Load_Glyph( face, i, load_flags ) ) continue; TIMER_START( timer ); FT_GlyphSlot_Embolden( face->glyph ); done++; TIMER_STOP( timer ); } return done; } static int test_get_glyph( btimer_t* timer, FT_Face face, void* user_data ) { FT_Glyph glyph; unsigned int i; int done = 0; FT_UNUSED( user_data ); for ( i = first_index; i <= last_index; i++ ) { if ( FT_Load_Glyph( face, i, load_flags ) ) continue; TIMER_START( timer ); if ( !FT_Get_Glyph( face->glyph, &glyph ) ) { FT_Done_Glyph( glyph ); done++; } TIMER_STOP( timer ); } return done; } static int test_get_cbox( btimer_t* timer, FT_Face face, void* user_data ) { FT_Glyph glyph; FT_BBox bbox; unsigned int i; int done = 0; FT_UNUSED( user_data ); for ( i = first_index; i <= last_index; i++ ) { if ( FT_Load_Glyph( face, i, load_flags ) ) continue; if ( FT_Get_Glyph( face->glyph, &glyph ) ) continue; TIMER_START( timer ); FT_Glyph_Get_CBox( glyph, FT_GLYPH_BBOX_PIXELS, &bbox ); TIMER_STOP( timer ); FT_Done_Glyph( glyph ); done++; } return done; } static int test_get_bbox( btimer_t* timer, FT_Face face, void* user_data ) { FT_BBox bbox; unsigned int i; int done = 0; FT_Matrix rot30 = { 0xDDB4, -0x8000, 0x8000, 0xDDB4 }; FT_UNUSED( user_data ); for ( i = first_index; i <= last_index; i++ ) { FT_Outline* outline; if ( FT_Load_Glyph( face, i, load_flags ) ) continue; outline = &face->glyph->outline; /* rotate outline by 30 degrees */ FT_Outline_Transform( outline, &rot30 ); TIMER_START( timer ); FT_Outline_Get_BBox( outline, &bbox ); TIMER_STOP( timer ); done++; } return done; } static int test_get_char_index( btimer_t* timer, FT_Face face, void* user_data ) { bcharset_t* charset = (bcharset_t*)user_data; int i, done = 0; TIMER_START( timer ); for ( i = 0; i < charset->size; i++ ) { if ( FT_Get_Char_Index(face, charset->code[i]) ) done++; } TIMER_STOP( timer ); return done; } static int test_cmap_cache( btimer_t* timer, FT_Face face, void* user_data ) { bcharset_t* charset = (bcharset_t*)user_data; int i, done = 0; FT_UNUSED( face ); if ( !cmap_cache ) { if ( FTC_CMapCache_New( cache_man, &cmap_cache ) ) return 0; } TIMER_START( timer ); for ( i = 0; i < charset->size; i++ ) { if ( FTC_CMapCache_Lookup( cmap_cache, font_type.face_id, 0, charset->code[i] ) ) done++; } TIMER_STOP( timer ); return done; } static int test_image_cache( btimer_t* timer, FT_Face face, void* user_data ) { FT_Glyph glyph; unsigned int i; int done = 0; FT_UNUSED( face ); FT_UNUSED( user_data ); if ( !image_cache ) { if ( FTC_ImageCache_New( cache_man, &image_cache ) ) return 0; } TIMER_START( timer ); for ( i = first_index; i <= last_index; i++ ) { if ( !FTC_ImageCache_Lookup( image_cache, &font_type, i, &glyph, NULL ) ) done++; } TIMER_STOP( timer ); return done; } static int test_sbit_cache( btimer_t* timer, FT_Face face, void* user_data ) { FTC_SBit glyph; unsigned int i; int done = 0; FT_UNUSED( face ); FT_UNUSED( user_data ); if ( !sbit_cache ) { if ( FTC_SBitCache_New( cache_man, &sbit_cache ) ) return 0; } TIMER_START( timer ); for ( i = first_index; i <= last_index; i++ ) { if ( !FTC_SBitCache_Lookup( sbit_cache, &font_type, i, &glyph, NULL ) ) done++; } TIMER_STOP( timer ); return done; } static int test_cmap_iter( btimer_t* timer, FT_Face face, void* user_data ) { FT_UInt idx; FT_ULong charcode; FT_UNUSED( user_data ); TIMER_START( timer ); charcode = FT_Get_First_Char( face, &idx ); while ( idx != 0 ) charcode = FT_Get_Next_Char( face, charcode, &idx ); TIMER_STOP( timer ); return 1; } static int test_new_face( btimer_t* timer, FT_Face face, void* user_data ) { FT_Face bench_face; FT_UNUSED( face ); FT_UNUSED( user_data ); TIMER_START( timer ); if ( !get_face( &bench_face ) ) FT_Done_Face( bench_face ); TIMER_STOP( timer ); return 1; } static int test_new_face_and_load_glyph( btimer_t* timer, FT_Face face, void* user_data ) { FT_Face bench_face; unsigned int i; int done = 0; FT_UNUSED( face ); FT_UNUSED( user_data ); TIMER_START( timer ); if ( !get_face( &bench_face ) ) { for ( i = first_index; i <= last_index; i++ ) { if ( !FT_Load_Glyph( bench_face, i, load_flags ) ) done++; } FT_Done_Face( bench_face ); } TIMER_STOP( timer ); return done; } /* * main */ static void get_charset( FT_Face face, bcharset_t* charset ) { FT_ULong charcode; FT_UInt gindex; int i; charset->code = (FT_ULong*)calloc( (size_t)face->num_glyphs, sizeof ( FT_ULong ) ); if ( !charset->code ) return; if ( face->charmap ) { i = 0; charcode = FT_Get_First_Char( face, &gindex ); /* certain fonts contain a broken charmap that will map character */ /* codes to out-of-bounds glyph indices. Take care of that here. */ /* */ while ( gindex && i < face->num_glyphs ) { if ( gindex >= first_index && gindex <= last_index ) charset->code[i++] = charcode; charcode = FT_Get_Next_Char( face, charcode, &gindex ); } } else { unsigned int j; /* no charmap, do an identity mapping */ for ( i = 0, j = first_index; j <= last_index; i++, j++ ) charset->code[i] = j; } charset->size = i; } static FT_Error get_face( FT_Face* face ) { static unsigned char* memory_file = NULL; static size_t memory_size; int face_index = 0; FT_Error error; if ( preload ) { if ( !memory_file ) { FILE* file = fopen( filename, "rb" ); if ( file == NULL ) { fprintf( stderr, "couldn't find or open `%s'\n", filename ); return 1; } fseek( file, 0, SEEK_END ); memory_size = (size_t)ftell( file ); fseek( file, 0, SEEK_SET ); memory_file = (FT_Byte*)malloc( memory_size ); if ( memory_file == NULL ) { fprintf( stderr, "couldn't allocate memory to pre-load font file\n" ); return 1; } if ( !fread( memory_file, memory_size, 1, file ) ) { fprintf( stderr, "read error\n" ); free( memory_file ); memory_file = NULL; return 1; } } error = FT_New_Memory_Face( lib, memory_file, (FT_Long)memory_size, face_index, face ); } else error = FT_New_Face( lib, filename, face_index, face ); if ( error ) fprintf( stderr, "couldn't load font resource\n"); return error; } static void usage( void ) { int i; char interpreter_versions[32]; char hinting_engines[32]; /* we expect that at least one interpreter version is available */ if ( num_tt_interpreter_versions == 2 ) sprintf(interpreter_versions, "%d and %d", tt_interpreter_versions[0], tt_interpreter_versions[1] ); else sprintf(interpreter_versions, "%d, %d, and %d", tt_interpreter_versions[0], tt_interpreter_versions[1], tt_interpreter_versions[2] ); /* we expect that at least one hinting engine is available */ if ( num_ps_hinting_engines == 1 ) sprintf(hinting_engines, "`%s'", ps_hinting_engine_names[ps_hinting_engines[0]] ); else sprintf(hinting_engines, "`%s' and `%s'", ps_hinting_engine_names[ps_hinting_engines[0]], ps_hinting_engine_names[ps_hinting_engines[1]] ); fprintf( stderr, "\n" "ftbench: run FreeType benchmarks\n" "--------------------------------\n" "\n" "Usage: ftbench [options] fontname\n" "\n" " -C Compare with cached version (if available).\n" " -c N Use at most N iterations for each test\n" " (0 means time limited).\n" " -f L Use hex number L as load flags (see `FT_LOAD_XXX').\n" " -H NAME Use PS hinting engine NAME.\n" " Available versions are %s; default is `%s'.\n" " -I VER Use TT interpreter version VER.\n" " Available versions are %s; default is version %d.\n" " -i IDX Start with index IDX (default is 0).\n" " -j IDX End with index IDX (default is number of glyphs minus one).\n" " -l N Set LCD filter to N\n" " 0: none, 1: default, 2: light, 16: legacy\n" " -m M Set maximum cache size to M KiByte (default is %d).\n", hinting_engines, ps_hinting_engine_names[dflt_ps_hinting_engine], interpreter_versions, dflt_tt_interpreter_version, CACHE_SIZE ); fprintf( stderr, " -p Preload font file in memory.\n" " -r N Set render mode to N\n" " 0: normal, 1: light, 2: mono, 3: LCD, 4: LCD vertical\n" " (default is 0).\n" " -s S Use S ppem as face size (default is %dppem).\n" " If set to zero, don't call FT_Set_Pixel_Sizes.\n" " Use value 0 with option `-f 1' or something similar to\n" " load the glyphs unscaled, otherwise errors will show up.\n", FACE_SIZE ); fprintf( stderr, " -t T Use at most T seconds per bench (default is %.0f).\n" "\n" " -b tests Perform chosen tests (default is all):\n", BENCH_TIME ); for ( i = 0; i < N_FT_BENCH; i++ ) { if ( !bench_desc[i] ) break; fprintf( stderr, " %c %s\n", 'a' + i, bench_desc[i] ); } fprintf( stderr, "\n" " -v Show version.\n" "\n" ); exit( 1 ); } #define TEST( x ) ( !test_string || strchr( test_string, (x) ) ) int main( int argc, char** argv ) { FT_Face face; FT_Error error; unsigned long max_bytes = CACHE_SIZE * 1024; char* test_string = NULL; unsigned int size = FACE_SIZE; int max_iter = 0; double max_time = BENCH_TIME; int compare_cached = 0; size_t i; int j; unsigned int versions[3] = { TT_INTERPRETER_VERSION_35, TT_INTERPRETER_VERSION_38, TT_INTERPRETER_VERSION_40 }; unsigned int engines[2] = { FT_HINTING_FREETYPE, FT_HINTING_ADOBE }; int version; char *engine; if ( FT_Init_FreeType( &lib ) ) { fprintf( stderr, "could not initialize font library\n" ); return 1; } /* collect all available versions, then set again the default */ FT_Property_Get( lib, "truetype", "interpreter-version", &dflt_tt_interpreter_version ); for ( j = 0; j < 3; j++ ) { error = FT_Property_Set( lib, "truetype", "interpreter-version", &versions[j] ); if ( !error ) tt_interpreter_versions[num_tt_interpreter_versions++] = versions[j]; } FT_Property_Set( lib, "truetype", "interpreter-version", &dflt_tt_interpreter_version ); FT_Property_Get( lib, "cff", "hinting-engine", &dflt_ps_hinting_engine ); for ( j = 0; j < 2; j++ ) { error = FT_Property_Set( lib, "cff", "hinting-engine", &engines[j] ); if ( !error ) ps_hinting_engines[num_ps_hinting_engines++] = engines[j]; } FT_Property_Set( lib, "cff", "hinting-engine", &dflt_ps_hinting_engine ); FT_Property_Set( lib, "type1", "hinting-engine", &dflt_ps_hinting_engine ); FT_Property_Set( lib, "t1cid", "hinting-engine", &dflt_ps_hinting_engine ); version = (int)dflt_tt_interpreter_version; engine = ps_hinting_engine_names[dflt_ps_hinting_engine]; while ( 1 ) { int opt; opt = getopt( argc, argv, "b:Cc:f:H:I:i:j:l:m:pr:s:t:v" ); if ( opt == -1 ) break; switch ( opt ) { case 'b': test_string = optarg; break; case 'C': compare_cached = 1; break; case 'c': max_iter = atoi( optarg ); if ( max_iter < 0 ) max_iter = -max_iter; break; case 'f': load_flags = strtol( optarg, NULL, 16 ); break; case 'H': engine = optarg; for ( j = 0; j < num_ps_hinting_engines; j++ ) { if ( !strcmp( engine, ps_hinting_engine_names[j] ) ) { FT_Property_Set( lib, "cff", "hinting-engine", &j ); FT_Property_Set( lib, "type1", "hinting-engine", &j ); FT_Property_Set( lib, "t1cid", "hinting-engine", &j ); break; } } if ( j == num_ps_hinting_engines ) fprintf( stderr, "warning: couldn't set hinting engine\n" ); break; case 'I': version = atoi( optarg ); for ( j = 0; j < num_tt_interpreter_versions; j++ ) { if ( version == (int)tt_interpreter_versions[j] ) { FT_Property_Set( lib, "truetype", "interpreter-version", &version ); break; } } if ( j == num_tt_interpreter_versions ) fprintf( stderr, "warning: couldn't set TT interpreter version\n" ); break; case 'i': { int fi = atoi( optarg ); if ( fi > 0 ) first_index = (unsigned int)fi; } break; case 'j': { int li = atoi( optarg ); if ( li > 0 ) last_index = (unsigned int)li; } break; case 'l': { int filter = atoi( optarg ); switch ( filter ) { case FT_LCD_FILTER_NONE: case FT_LCD_FILTER_DEFAULT: case FT_LCD_FILTER_LIGHT: case FT_LCD_FILTER_LEGACY1: case FT_LCD_FILTER_LEGACY: FT_Library_SetLcdFilter( lib, (FT_LcdFilter)filter ); } } break; case 'm': { int mb = atoi( optarg ); if ( mb > 0 ) max_bytes = (unsigned int)mb * 1024; } break; case 'p': preload = 1; break; case 'r': { int rm = atoi( optarg ); if ( rm < 0 || rm >= FT_RENDER_MODE_MAX ) render_mode = FT_RENDER_MODE_NORMAL; else render_mode = (FT_Render_Mode)rm; } break; case 's': { int sz = atoi( optarg ); /* value 0 is special */ if ( sz < 0 ) size = 1; else size = (unsigned int)sz; } break; case 't': max_time = atof( optarg ); if ( max_time < 0 ) max_time = -max_time; break; case 'v': { FT_Int major, minor, patch; FT_Library_Version( lib, &major, &minor, &patch ); printf( "ftbench (FreeType) %d.%d", major, minor ); if ( patch ) printf( ".%d", patch ); printf( "\n" ); exit( 0 ); } /* break; */ default: usage(); break; } } argc -= optind; argv += optind; if ( argc != 1 ) usage(); filename = *argv; if ( get_face( &face ) ) goto Exit; if ( last_index >= (unsigned int)face->num_glyphs ) last_index = (unsigned int)face->num_glyphs - 1; if ( last_index < first_index ) last_index = first_index; if ( size ) { if ( FT_IS_SCALABLE( face ) ) { if ( FT_Set_Pixel_Sizes( face, size, size ) ) { fprintf( stderr, "failed to set pixel size to %d\n", size ); return 1; } } else { size = (unsigned int)face->available_sizes[0].size >> 6; fprintf( stderr, "using size of first bitmap strike (%dpx)\n", size ); FT_Select_Size( face, 0 ); } } FTC_Manager_New( lib, 0, 0, max_bytes, face_requester, face, &cache_man ); font_type.face_id = (FTC_FaceID)1; font_type.width = size; font_type.height = size; font_type.flags = load_flags; printf( "\n" "ftbench results for font `%s'\n" "---------------------------", filename ); for ( i = 0; i < strlen( filename ); i++ ) putchar( '-' ); putchar( '\n' ); printf( "\n" "family: %s\n" " style: %s\n" "\n", face->family_name, face->style_name ); if ( max_iter ) printf( "number of iterations for each test: at most %d\n", max_iter ); printf( "number of seconds for each test: %s%f\n", max_iter ? "at most " : "", max_time ); printf( "\n" "first glyph index: %d\n" "last glyph index: %d\n" "face size: %dppem\n" "font preloading into memory: %s\n", first_index, last_index, size, preload ? "yes" : "no" ); printf( "\n" "load flags: 0x%X\n" "render mode: %d\n", load_flags, render_mode ); printf( "\n" "CFF hinting engine set to `%s'\n" "TrueType interpreter set to version %d\n" "maximum cache size: %ldKiByte\n", engine, version, max_bytes / 1024 ); printf( "\n" "executing tests:\n" ); for ( j = 0; j < N_FT_BENCH; j++ ) { btest_t test; FT_ULong flags; if ( !TEST( 'a' + j ) ) continue; test.title = NULL; test.bench = NULL; test.cache_first = 0; test.user_data = NULL; switch ( j ) { case FT_BENCH_LOAD_GLYPH: test.title = "Load"; test.bench = test_load; benchmark( face, &test, max_iter, max_time ); if ( compare_cached ) { test.cache_first = 1; test.title = "Load (image cached)"; test.bench = test_image_cache; benchmark( face, &test, max_iter, max_time ); test.title = "Load (sbit cached)"; test.bench = test_sbit_cache; if ( size ) benchmark( face, &test, max_iter, max_time ); else printf( " %-25s disabled (size = 0)\n", test.title ); } break; case FT_BENCH_LOAD_ADVANCES: test.user_data = &flags; test.title = "Load_Advances (Normal)"; test.bench = test_load_advances; flags = FT_LOAD_DEFAULT; benchmark( face, &test, max_iter, max_time ); test.title = "Load_Advances (Fast)"; test.bench = test_load_advances; flags = FT_LOAD_TARGET_LIGHT; benchmark( face, &test, max_iter, max_time ); test.title = "Load_Advances (Unscaled)"; test.bench = test_load_advances; flags = FT_LOAD_NO_SCALE; benchmark( face, &test, max_iter, max_time ); break; case FT_BENCH_RENDER: test.title = "Render"; test.bench = test_render; if ( size ) benchmark( face, &test, max_iter, max_time ); else printf( " %-25s disabled (size = 0)\n", test.title ); break; case FT_BENCH_GET_GLYPH: test.title = "Get_Glyph"; test.bench = test_get_glyph; benchmark( face, &test, max_iter, max_time ); break; case FT_BENCH_GET_CBOX: test.title = "Get_CBox"; test.bench = test_get_cbox; benchmark( face, &test, max_iter, max_time ); break; case FT_BENCH_GET_BBOX: test.title = "Get_BBox"; test.bench = test_get_bbox; benchmark( face, &test, max_iter, max_time ); break; case FT_BENCH_CMAP: { bcharset_t charset; get_charset( face, &charset ); if ( charset.code ) { test.user_data = (void*)&charset; test.title = "Get_Char_Index"; test.bench = test_get_char_index; benchmark( face, &test, max_iter, max_time ); if ( compare_cached ) { test.cache_first = 1; test.title = "Get_Char_Index (cached)"; test.bench = test_cmap_cache; benchmark( face, &test, max_iter, max_time ); } free( charset.code ); } } break; case FT_BENCH_CMAP_ITER: test.title = "Iterate CMap"; test.bench = test_cmap_iter; benchmark( face, &test, max_iter, max_time ); break; case FT_BENCH_NEW_FACE: test.title = "New_Face"; test.bench = test_new_face; benchmark( face, &test, max_iter, max_time ); break; case FT_BENCH_EMBOLDEN: test.title = "Embolden"; test.bench = test_embolden; if ( size ) benchmark( face, &test, max_iter, max_time ); else printf( " %-25s disabled (size = 0)\n", test.title ); break; case FT_BENCH_NEW_FACE_AND_LOAD_GLYPH: test.title = "Create face & load glyph(s)"; test.bench = test_new_face_and_load_glyph; benchmark( face, &test, max_iter, max_time ); break; } } Exit: /* The following is a bit subtle: When we call FTC_Manager_Done, this * normally destroys all FT_Face objects that the cache might have * created by calling the face requester. * * However, this little benchmark uses a tricky face requester that * doesn't create a new FT_Face through FT_New_Face but simply passes a * pointer to the one that was previously created. * * If the cache manager has been used before, the call to * FTC_Manager_Done discards our single FT_Face. * * In the case where no cache manager is in place, or if no test was * run, the call to FT_Done_FreeType releases any remaining FT_Face * object anyway. */ if ( cache_man ) FTC_Manager_Done( cache_man ); FT_Done_FreeType( lib ); return 0; } /* End */ ft2demos-2.10.1/src/Jamfile0000644000175000001440000000221313434207203015234 0ustar00wlusers00000000000000# FreeType 2 src Jamfile (c) 2001, 2003, 2004, 2005, 2007 David Turner # SubDir FT2DEMO_TOP src ; SubDirHdrs $(FT2_INCLUDE) ; SubDirHdrs [ FT2DEMO_SubDir src ] ; SubDirHdrs [ FT2DEMO_SubDir graph ] ; COMMON_LIB = $(LIBPREFIX)ft2common ; Library $(COMMON_LIB) : ftcommon.c common.c output.c ; if $(UNIX) { CCDEFS += UNIX ; LINKLIBS += -lm ; } PROGRAMS = ftbench ftlint ftdump fttimer ftchkwd ftvalid ftpatchk ; GRAPHIC_PROGRAMS = ftview ftmulti ftstring ftgamma ftgrid ftdiff ; { local t ; for t in $(PROGRAMS) $(GRAPHIC_PROGRAMS) { Main $(t) : $(t).c ; LinkLibraries $(t) : $(COMMON_LIB) $(FT2_LIB) ; } for t in $(GRAPHIC_PROGRAMS) { LINKLIBS on $(t)$(SUFEXE) = $(LINKLIBS) $(GRAPH_LINKLIBS) ; LinkLibraries $(t) : $(GRAPH_LIB) ; } } # Compile bytecode debugger when needed. Define the environment # variable FT2_DEBUG_TT to enable this one before calling "jam" # if $(FT2_DEBUG_TT) { if $(UNIX) { DEFINES += UNIX ; } SubDirHdrs $(FT2_INCLUDE)/../src/truetype ; LinkLibraries ttdebug : $(FT2_LIB) ; Main ttdebug : ttdebug.c ; } Main gbench : gbench.c ; # end of src Jamfile ft2demos-2.10.1/src/gbench.h0000644000175000001440000000453613434207203015353 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality font engine */ /* */ /* Copyright (C) 2006-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* */ /* gbench is a small program used to benchmark a new algorithm */ /* performing gamma-corrected alpha-blending. */ /* */ /****************************************************************************/ #ifndef GBENCH_H_ #define GBENCH_H_ typedef enum { GBITMAP_FORMAT_NONE = 0, GBITMAP_FORMAT_RGB24, GBITMAP_FORMAT_GRAY, GBITMAP_FORMAT_RGB, GBITMAP_FORMAT_BGR, GBITMAP_FORMAT_RGBV, GBITMAP_FORMAT_BGRV, GBITMAP_FORMAT_MAX } GBitmapFormat; typedef struct GBitmapRec_ { int width; int height; int pitch; unsigned char* buffer; GBitmapFormat format; } GBitmapRec, *GBitmap; typedef struct GBlitterRec_* GBlitter; typedef void (*GBlitterFunc)( GBlitter blitter, int color ); typedef struct GBlitterRec_ { int width; int height; int src_x; unsigned char* src_line; int src_incr; int dst_x; unsigned char* dst_line; int dst_incr; GBlitterFunc blit; } GBlitterRec; extern void ggamma_set( double gamma ); extern int gblitter_init_rgb24( GBlitter blitter, GBitmap src, int dst_x, int dst_y, int dst_width, int dst_height, void* dst_buffer, int dst_pitch ); #define gblitter_blit(b,c) (b)->blit( (b), (c) ) #endif /* GBENCH_H_ */ /* End */ ft2demos-2.10.1/src/ftsbit.c0000644000175000001440000001644113434207203015411 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 1996-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* ftsbit: a _very_ simple embedded bitmap dumper for FreeType 1.x. */ /* */ /* NOTE: This is just a test program that is used to show off and */ /* debug the current engine. */ /* */ /****************************************************************************/ #include #include #include #include #include FT_FREETYPE_H #ifdef HAVE_LIBINTL_H #ifdef HAVE_LOCALE_H #include #endif #include #include "ftxerr18.h" #else /* !HAVE_LIBINTL */ #define gettext( x ) ( x ) /* We ignore error message strings with this function */ static char* TT_ErrToString18( FT_Error error ) { static char temp[32]; sprintf( temp, "0x%04lx", error ); return temp; } #endif /* !HAVE_LIBINTL */ FT_Error error; FT_Library engine; FT_Resource resource; FT_Face face; FT_Size instance; FT_GlyphSlot glyph; unsigned int num_glyphs; int ptsize; int Fail; int Num; static void Usage( char* name ) { printf( gettext( "ftsbit: simple TrueType 'sbit' dumper -- part of the FreeType project\n" ) ); printf( "---------------------------------------------------------------------\n" ); printf( "\n" ); printf( gettext( "Usage: %s ppem fontname (index)* (index1-index2)*\n\n" ), name ); printf( gettext( " or %s -a ppem fontname (dumps all glyphs)\n" ), name ); printf( "\n" ); exit( EXIT_FAILURE ); } static void dump_bitmap( FT_GlyphSlot glyph, int glyph_index ) { /* Dump the resulting bitmap */ { int y; unsigned char* line = (unsigned char*)glyph->bitmap.buffer; printf( "glyph index %d = %dx%d pixels, ", glyph_index, glyph->bitmap.rows, glyph->bitmap.width ); printf( "advance = %d, minBearing = [%d,%d]\n", glyph->metrics.horiAdvance >> 6, glyph->metrics.horiBearingX >> 6, glyph->metrics.horiBearingY >> 6 ); for ( y = 0; y < glyph->bitmap.rows; y++, line += glyph->bitmap.cols ) { unsigned char* ptr = line; int x; unsigned char mask = 0x80; for ( x = 0; x < glyph->bitmap.width; x++ ) { printf( "%c", (ptr[0] & mask) ? '*' : '.' ); mask >>= 1; if (mask == 0) { mask = 0x80; ptr++; } } printf( "\n" ); } } } static void dump_range( FT_GlyphSlot glyph, int first_glyph, int last_glyph ) { int i; for ( i = first_glyph; i <= last_glyph; i++ ) { error = FT_Load_Glyph( glyph, instance, (unsigned short)i, FT_LOAD_NO_OUTLINE, 0 ); if (error) { printf( " no bitmap for glyph %d\n", i ); printf( gettext( "FreeType error message: %s\n" ), TT_ErrToString18( error ) ); continue; } dump_bitmap(glyph,i); } } int main( int argc, char** argv ) { int i; char filename[1024 + 4]; char alt_filename[1024 + 4]; char* execname; char* fname; int dump_all = 0; #ifdef HAVE_LIBINTL_H setlocale( LC_ALL, "" ); bindtextdomain( "freetype", LOCALEDIR ); textdomain( "freetype" ); #endif execname = argv[0]; if ( argc < 3 ) Usage( execname ); if ( argv[1][0] == '-' && argv[1][1] == 'a' ) { argv++; argc--; dump_all = 1; } if ( sscanf( argv[1], "%d", &ptsize ) != 1 ) Usage( execname ); /* Initialize engine */ if ( (error = FT_Init_FreeType( &engine )) ) { fprintf( stderr, gettext( "Error while initializing engine\n" ) ); goto Failure; } /* Now check all files */ fname = argv[2]; i = strlen( fname ); while ( i > 0 && fname[i] != '\\' && fname[i] != '/' ) { if ( fname[i] == '.' ) i = 0; i--; } filename[1024] = '\0'; alt_filename[1024] = '\0'; strncpy( filename, fname, 1024 ); strncpy( alt_filename, fname, 1024 ); if ( i >= 0 ) { strncpy( filename + strlen( filename ), ".ttf", 4 ); strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 ); } /* Load face */ error = FT_New_Resource( engine, filename, &resource ); if (error) { strcpy( filename, alt_filename ); error = FT_New_Resource( engine, alt_filename, &resource ); } i = strlen( filename ); fname = filename; while ( i >= 0 ) if ( filename[i] == '/' || filename[i] == '\\' ) { fname = filename + i + 1; i = -1; } else i--; if ( error ) { printf( gettext( "Could not find or open file.\n" ) ); goto Failure; } error = FT_New_Face( resource, 0, &face ); if (error) { printf( gettext( "Could not create face object.\n " ) ); goto Failure; } /* get face properties */ num_glyphs = face->num_glyphs; /* create instance */ error = FT_New_Size( face, &instance ); if ( error ) { printf( gettext( "Could not create instance.\n" ) ); goto Failure; } error = FT_Set_Pixel_Sizes( instance, ptsize, ptsize ); if (error) { printf( gettext( "Could not set character size.\n" ) ); goto Failure; } glyph = face->slot; if (dump_all) dump_range( glyph, 0, num_glyphs-1 ); else { for ( i = 3; i < argc; i++ ) { /* check for range in argument string */ int range_check = 0; char* base = argv[i]; char* cur = base; int first, last; while (*cur) { if (*cur == '-') { range_check = 1; break; } cur++; } if (range_check) { if ( sscanf( argv[i], "%d-%d", &first, &last ) != 2 ) Usage( execname ); dump_range( glyph, first, last ); } else { if ( sscanf( argv[i], "%d", &first ) != 1 ) Usage( execname ); dump_range( glyph, first, first ); } } } FT_Done_FreeType( engine ); exit( EXIT_SUCCESS ); /* for safety reasons */ return 0; /* never reached */ Failure: printf( gettext( "FreeType error message: %s\n" ), TT_ErrToString18( error ) ); exit( EXIT_FAILURE ); } /* End */ ft2demos-2.10.1/src/fttry.c0000644000175000001440000001100413434207203015254 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 1996-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* ftlint: a simple TrueType instruction tester. */ /* */ /* NOTE: This is just a test program that is used to show off and */ /* debug the current engine. */ /* */ /****************************************************************************/ #include #include FT_FREETYPE_H #include #include #include #define DUMP_NAME #define gettext( x ) ( x ) FT_Error error; FT_Library library; FT_Face face; unsigned int num_glyphs; int ptsize; int Fail; int Num; static void Usage( char* name ) { printf( "fttry: simple TrueType instruction tester -- part of the FreeType project\n" ); printf( "--------------------------------------------------------------------------\n" ); printf( "\n" ); printf( "Usage: %s ppem glyph fontname [fontname2..]\n\n", name ); printf( " or %s -u glyph fontname [fontname2..]\n", name ); printf( " to load an unscaled glyph\n\n" ); exit( 1 ); } static void Panic( const char* message ) { fprintf( stderr, "%s\n error code = 0x%04x\n", message, error ); exit( 1 ); } int main( int argc, char** argv ) { int i, file_index, glyph_index; char filename[1024 + 4]; char alt_filename[1024 + 4]; char* execname; char* fname; int load_unscaled = 0; execname = argv[0]; if ( argc < 3 ) Usage( execname ); if ( argv[1][0] == '-' && argv[1][1] == 'u' ) load_unscaled = 1; else { if ( sscanf( argv[1], "%d", &ptsize ) != 1 ) Usage( execname ); } argc--; argv++; if ( sscanf( argv[1], "%d", &glyph_index ) != 1 ) Usage( execname ); error = FT_Init_FreeType( &library ); if ( error ) Panic( "Could not create library object" ); /* Now check all files */ for ( file_index = 2; file_index < argc; file_index++ ) { fname = argv[file_index]; i = strlen( fname ); while ( i > 0 && fname[i] != '\\' && fname[i] != '/' ) { if ( fname[i] == '.' ) i = 0; i--; } filename[1024] = '\0'; alt_filename[1024] = '\0'; strncpy( filename, fname, 1024 ); strncpy( alt_filename, fname, 1024 ); if ( i >= 0 ) { strncpy( filename + strlen( filename ), ".ttf", 4 ); strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 ); } i = strlen( filename ); fname = filename; while ( i >= 0 ) if ( filename[i] == '/' || filename[i] == '\\' ) { fname = filename + i + 1; i = -1; } else i--; printf( "%s: ", fname ); /* Load face */ error = FT_New_Face( library, filename, 0, &face ); if ( error ) Panic( "Could not create face object" ); num_glyphs = face->num_glyphs; error = FT_Set_Char_Size( face, ptsize << 6, 0, 0, 0 ); if ( error ) Panic( "Could not set character size" ); #ifdef DUMP_NAME { char name[1024]; error = FT_Get_Glyph_Name( face, glyph_index, name, 1024 ); if ( error ) printf( "no glyph name available\n" ); else printf( "glyph name = '%s'\n", name ); } #endif error = FT_Load_Glyph( face, glyph_index, load_unscaled ? FT_LOAD_NO_SCALE : FT_LOAD_DEFAULT ); if ( error == 0 ) printf( "OK.\n" ); else printf( "Fail with error 0x%04x\n", error ); FT_Done_Face( face ); } FT_Done_FreeType(library); exit( 0 ); /* for safety reasons */ return 0; /* never reached */ } /* End */ ft2demos-2.10.1/src/mlgetopt.h0000644000175000001440000000134013434207203015746 0ustar00wlusers00000000000000/* * This is a cheap replacement for getopt() because that routine is not * available on some platforms and behaves differently on other platforms. * * This code is hereby expressly placed in the public domain. * mleisher@crl.nmsu.edu (Mark Leisher) * 10 October 1997 */ #ifndef MLGETOPT_H_ #define MLGETOPT_H_ #ifdef VMS #define getopt local_getopt #define optind local_optind #define opterr local_opterr #endif #ifdef __cplusplus extern "C" { #endif extern int opterr; extern int optind; extern char* optarg; extern int getopt( #ifdef __STDC__ int argc, char* const* argv, const char* pattern #endif ); #ifdef __cplusplus } #endif #endif /* MLGETOPT_H_ */ /* End */ ft2demos-2.10.1/src/gbench.c0000644000175000001440000004176613434207203015354 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality font engine */ /* */ /* Copyright (C) 2006-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* */ /* gbench is a small program used to benchmark a new algorithm */ /* performing gamma-corrected alpha-blending. */ /* */ /* EXPERIMENTAL: The numbers given here do not correspond to */ /* typical usage patterns yet, and the algorithm */ /* can still be tuned. */ /* */ /****************************************************************************/ #include #include #include #include #include /* * gbench is a small program used to benchmark a new algorithm * performing gamma-corrected alpha-blending. * * EXPERIMENTAL: the numbers given here do not correspond to * typical usage patterns yet, and the algorithm * can still be tuned * */ #ifdef UNIX #include #endif #include "gbench.h" #define xxCACHE static int use_gamma = 0; static unsigned char gamma_ramp[256]; static unsigned char gamma_ramp_inv[256]; #define ALGO_KEY_COUNT 256 #define ALGO_GRADE_BITS 5 #define ALGO_GRADE_COUNT (1 << ALGO_GRADE_BITS) #define ALGO_GRADE_INDEX(x) ((x) >> (8-ALGO_GRADE_BITS)) typedef struct CKeyRec_ { int background; int foreground; unsigned char* grades; } CKeyRec, *CKey; static CKeyRec ckeys [ ALGO_KEY_COUNT ]; static unsigned char cgrades[ ALGO_KEY_COUNT * ALGO_GRADE_COUNT * 3 ]; static long chits = 0; static long cmiss1 = 0; static long cmiss2 = 0; /* clear the cache */ static void cclear( void ) { int nn; for ( nn = 0; nn < ALGO_KEY_COUNT; nn++ ) ckeys[nn].grades = NULL; } /* recompute the grade levels of a given key */ static void ckey_reset( CKey key ) { int back = key->background; int fore = key->foreground; unsigned char* gr = key->grades; int nn; int r1,g1,b1,r2,g2,b2; r1 = (unsigned char)( back >> 16 ); g1 = (unsigned char)( back >> 8 ); b1 = (unsigned char)( back ); r2 = (unsigned char)( fore >> 16 ); g2 = (unsigned char)( fore >> 8 ); b2 = (unsigned char)( fore ); gr[0] = r1; gr[1] = g1; gr[2] = b1; gr[3] = r2; gr[4] = g2; gr[5] = b2; gr += 6; if ( use_gamma ) { r1 = gamma_ramp_inv[r1]; g1 = gamma_ramp_inv[g1]; b1 = gamma_ramp_inv[b1]; r2 = gamma_ramp_inv[r2]; g2 = gamma_ramp_inv[g2]; b2 = gamma_ramp_inv[b2]; } for ( nn = 1; nn < ALGO_GRADE_COUNT-1; nn++ ) { int r = r1 + ((r2-r1)*nn)/(ALGO_GRADE_COUNT-1); int g = g1 + ((g2-g1)*nn)/(ALGO_GRADE_COUNT-1); int b = b1 + ((b2-b1)*nn)/(ALGO_GRADE_COUNT-1); if ( use_gamma ) { r = gamma_ramp[r]; g = gamma_ramp[g]; b = gamma_ramp[b]; } gr[0] = (unsigned char)r; gr[1] = (unsigned char)g; gr[2] = (unsigned char)b; gr += 3; } cmiss2 ++; } /* lookup the grades of a given (background,foreground) couple */ static const unsigned char* clookup( int background, int foreground ) { int index, index0; CKey key; cmiss1++; index0 = ( background + foreground*7 ) % ALGO_KEY_COUNT; index = index0; do { key = ckeys + index; if ( key->grades == NULL ) goto NewNode; if ( key->background == background && key->foreground == foreground ) goto Exit; index = (index+1) % ALGO_KEY_COUNT; } while ( index != index0 ); /* the cache is full, clear it completely */ cclear(); NewNode: key->background = background; key->foreground = foreground; key->grades = cgrades + index0*(3*ALGO_GRADE_COUNT); ckey_reset( key ); Exit: return (const unsigned char*)key->grades; } void ggamma_set( double gamma ) { int ii; double gamma_inv = 1.0f / gamma; cclear(); for ( ii = 0; ii < 256; ii++ ) gamma_ramp[ii] = (unsigned char)( pow( (double)ii/255.0f, gamma )*255 ); for ( ii = 0; ii < 256; ii++ ) gamma_ramp_inv[ii] = (unsigned char)( pow( (double)ii/255.0f, gamma_inv ) * 255.0f ); use_gamma = (gamma != 1.0f); } static void gblitter_blitrgb24_gray_direct( GBlitter blitter, int color ) { unsigned char r = (unsigned char)(color >> 16); unsigned char g = (unsigned char)(color >> 8); unsigned char b = (unsigned char)(color); int h = blitter->height; unsigned char* src_line = blitter->src_line; unsigned char* dst_line = blitter->dst_line; if ( use_gamma ) { int r1 = gamma_ramp_inv[r]; int g1 = gamma_ramp_inv[g]; int b1 = gamma_ramp_inv[b]; do { unsigned char* src = src_line + (blitter->src_x); unsigned char* dst = dst_line + (blitter->dst_x*3); int w = blitter->width; do { int a = src[0]; if ( a < 2 ) { /* nothing */ } else if ( a >= 254 ) { dst[0] = r; dst[1] = g; dst[2] = b; } else { int r0 = dst[0]; int g0 = dst[1]; int b0 = dst[2]; r0 = gamma_ramp_inv[r0]; g0 = gamma_ramp_inv[g0]; b0 = gamma_ramp_inv[b0]; a = a + (a >> 7); r0 += (r1 - r0)*a/256; g0 += (g1 - g0)*a/256; b0 += (b1 - b0)*a/256; r0 = gamma_ramp[r0]; g0 = gamma_ramp[g0]; b0 = gamma_ramp[b0]; dst[0] = (unsigned char)r0; dst[1] = (unsigned char)g0; dst[2] = (unsigned char)b0; } src += 1; dst += 3; } while (--w > 0); src_line += blitter->src_incr; dst_line += blitter->dst_incr; } while (--h > 0); return; } do { unsigned char* src = src_line + (blitter->src_x); unsigned char* dst = dst_line + (blitter->dst_x*3); int w = blitter->width; do { int a = src[0]; if ( a < 2 ) { /* nothing */ } else if ( a >= 254 ) { dst[0] = r; dst[1] = g; dst[2] = b; } else { int r0 = dst[0]; int g0 = dst[1]; int b0 = dst[2]; a = a + (a >> 7); r0 += (r - r0)*a/256; g0 += (g - g0)*a/256; b0 += (b - b0)*a/256; dst[0] = (unsigned char)r0; dst[1] = (unsigned char)g0; dst[2] = (unsigned char)b0; } src += 1; dst += 3; } while (--w > 0); src_line += blitter->src_incr; dst_line += blitter->dst_incr; } while (--h > 0); } static void gblitter_blitrgb24_gray_cache( GBlitter blitter, int color ) { unsigned char r = (unsigned char)(color >> 16); unsigned char g = (unsigned char)(color >> 8); unsigned char b = (unsigned char)(color); int back = -1; const unsigned char* grades = NULL; int h = blitter->height; unsigned char* src_line = blitter->src_line; unsigned char* dst_line = blitter->dst_line; do { unsigned char* src = src_line + (blitter->src_x); unsigned char* dst = dst_line + (blitter->dst_x*3); int w = blitter->width; do { int a = src[0]; if ( a < 2 ) { /* nothing */ } else if ( a >= 254 ) { dst[0] = r; dst[1] = g; dst[2] = b; } else { int back0 = ((int)dst[0] << 16) | ((int)dst[1] << 8) | dst[2]; const unsigned char* g; if ( back0 != back ) { grades = clookup( back0, color ); back = back0; } else chits++; g = grades + ALGO_GRADE_INDEX(a)*3; dst[0] = g[0]; dst[1] = g[1]; dst[2] = g[2]; } src += 1; dst += 3; } while (--w > 0); src_line += blitter->src_incr; dst_line += blitter->dst_incr; } while (--h > 0); } int gblitter_init_rgb24( GBlitter blitter, GBitmap src, int dst_x, int dst_y, int dst_width, int dst_height, void* dst_buffer, int dst_pitch ) { int width = src->width; int height = src->height; int delta; int src_x = 0; int src_y = 0; if ( dst_x < 0 ) { width += dst_x; src_x = -dst_x; dst_x = 0; } delta = dst_x + width - dst_width; if ( delta > 0 ) width -= delta; if ( dst_y < 0 ) { height += dst_y; src_y = -dst_y; dst_y = 0; } delta = dst_y + height - dst_height; if ( delta > 0 ) height -= delta; if ( width <= 0 || height <= 0 ) { blitter->width = 0; blitter->height = 0; blitter->blit = NULL; return 1; } blitter->width = width; blitter->height = height; blitter->src_x = src_x; blitter->src_line = src->buffer + src_y*src->pitch; blitter->src_incr = src->pitch; blitter->dst_x = dst_x; blitter->dst_line = (unsigned char*)dst_buffer + dst_y*dst_pitch; blitter->dst_incr = dst_pitch; return 0; } #include #include #include #include #ifdef UNIX #include #endif typedef int (*bench_t)( int arg ); #define BENCH_TIME 3.0f double get_time(void) { #ifdef UNIX struct timeval tv; gettimeofday(&tv, NULL); return (double)tv.tv_sec + (double)tv.tv_usec / 1E6; #else /* clock() has an awful precision (~10ms) under Linux 2.4 + glibc 2.2 */ return (double)clock() / (double)CLOCKS_PER_SEC; #endif } double bench_time = BENCH_TIME; static void bench( bench_t bench_func, int bench_arg, const char* title, int max) { int i, n, done; double t0, delta; printf("%-30s : ", title); fflush(stdout); n = 0; done = 0; t0 = get_time(); do { if (!(*bench_func)( bench_arg ) ) done++; n++; delta = get_time() - t0; } while ((!max || n < max) && delta < bench_time); printf("%5.3f us/op\n", delta * 1E6 / (double)done); } /* this is un-hinted "W" in Times New Roman * this glyph is very fuzzy */ static const unsigned char glyph_data[18*14] = { 0x4a, 0x91, 0x94, 0x93, 0x5a, 0x00, 0x4c, 0x92, 0x94, 0x94, 0x67, 0x0b, 0x00, 0x00, 0x61, 0x92, 0x93, 0x50, 0x00, 0x65, 0xff, 0xbb, 0x00, 0x00, 0x00, 0x65, 0xff, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x7f, 0x00, 0x00, 0x08, 0xf0, 0xe6, 0x01, 0x00, 0x00, 0x02, 0xe4, 0xf1, 0x05, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x10, 0x00, 0x00, 0x00, 0x9c, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x8e, 0xff, 0x4b, 0x00, 0x00, 0x00, 0x1d, 0xae, 0x00, 0x00, 0x00, 0x00, 0x41, 0xff, 0x99, 0x00, 0x00, 0x00, 0x82, 0xff, 0xa6, 0x00, 0x00, 0x00, 0x74, 0x57, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe3, 0xed, 0x05, 0x00, 0x00, 0xcd, 0xd9, 0xf4, 0x0b, 0x00, 0x00, 0xc1, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0xff, 0x4d, 0x00, 0x33, 0xa1, 0x7a, 0xff, 0x5b, 0x00, 0x25, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0xff, 0xa7, 0x00, 0x8c, 0x46, 0x20, 0xfe, 0xb6, 0x00, 0x7d, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xf5, 0x0d, 0xca, 0x03, 0x00, 0xc4, 0xfb, 0x15, 0xc4, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0xff, 0x98, 0x90, 0x00, 0x00, 0x69, 0xff, 0x98, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0xfe, 0xff, 0x35, 0x00, 0x00, 0x13, 0xfa, 0xff, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xd9, 0x00, 0x00, 0x00, 0x00, 0xb2, 0xe9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x57, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x00, 0x00, 0x08, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const GBitmapRec glyph = { 18, 14, 18, (unsigned char*) glyph_data, GBITMAP_FORMAT_GRAY }; #define SIZE_X 640 #define SIZE_Y 480 static unsigned char buffer[ SIZE_X*3*SIZE_Y ]; unsigned long seed = 0; unsigned long my_rand( void ) { seed = seed * 1103515245 + 12345; return ((seed >>16) & 32767); } #define RAND(n) ((unsigned int)my_rand() % (n)) static int do_glyph( int arg ) { GBlitterRec blit; int dst_x = RAND(SIZE_X); int dst_y = RAND(SIZE_Y); int color = 0xFFFFFF; /* draw white exclusively */ if ( gblitter_init_rgb24( &blit, (GBitmap)&glyph, dst_x, dst_y, SIZE_X, SIZE_Y, buffer, SIZE_X*3 ) ) return 1; if ( arg ) gblitter_blitrgb24_gray_cache( &blit, color ); else gblitter_blitrgb24_gray_direct( &blit, color ); return 0; } static int do_glyph_color( int arg ) { GBlitterRec blit; int dst_x = RAND(SIZE_X); int dst_y = RAND(SIZE_Y); int r = RAND(256); int g = RAND(256); int b = RAND(256); int color = (r << 16) | (g << 8) | b; /* draw in colors */ if ( gblitter_init_rgb24( &blit, (GBitmap)&glyph, dst_x, dst_y, SIZE_X, SIZE_Y, buffer, SIZE_X*3 ) ) return 1; if ( arg ) gblitter_blitrgb24_gray_cache( &blit, color ); else gblitter_blitrgb24_gray_direct( &blit, color ); return 0; } static void dump_cache_stats( void ) { printf( "hits = %ld, miss1 = %ld, miss2 = %ld, hitrate=%.2f%%, miss2rate=%.2f%%\n", chits, cmiss1, cmiss2, (double)chits*100.0 / (chits+cmiss1), (double)cmiss2*100.0 / (double)cmiss1 ); } void usage(void) { fprintf( stderr, "gbench: graphics glyph blending benchmark\n" "-----------------------------------------\n\n" "Usage: gbench [options]\n\n" "options:\n" ); fprintf( stderr, " -t : max time per bench in seconds (default is %.0f)\n", BENCH_TIME ); fprintf( stderr, " -s seed : specify random seed\n" ); fprintf( stderr, " -g gamma : specify gamma\n" ); exit( 1 ); } #define TEST(x) (!tests || strchr(tests, x)) int main(int argc, char** argv) { char* tests = NULL; int size; double gamma = 1.0; while (argc > 1 && argv[1][0] == '-') { switch (argv[1][1]) { case 't': argc--; argv++; if (argc < 1 || sscanf(argv[1], "%lf", &bench_time) != 1) usage(); break; case 'g': argc--; argv++; if (argc < 1 || sscanf(argv[1], "%lf", &gamma) != 1) usage(); break; case 's': if ( argc < 1 ) usage(); seed = (unsigned long)atol( argv[1] ); argc -= 2; argv += 2; break; #if 0 case 'b': argc--; argv++; if (argc < 2) usage(); tests = argv[1]; break; #endif default: fprintf(stderr, "Unknown argument `%s'\n\n", argv[1]); usage(); break; } argc--; argv++; } if ( argc != 1 ) usage(); ggamma_set( gamma ); memset( buffer, 0, sizeof(buffer) ); if (TEST('a')) bench( do_glyph, 0, "direct white glyph", 0 ); chits = cmiss1 = cmiss2 = 0; memset( buffer, 0, sizeof(buffer) ); if (TEST('b')) bench( do_glyph, 1, "cache white glyph", 0 ); dump_cache_stats(); memset( buffer, 0, sizeof(buffer) ); if (TEST('c')) bench( do_glyph_color, 0, "direct color glyph", 0 ); chits = cmiss1 = cmiss2 = 0; memset( buffer, 0, sizeof(buffer) ); if (TEST('d')) bench( do_glyph_color, 1, "cache color glyph", 0 ); dump_cache_stats(); return 0; } /* End */ ft2demos-2.10.1/src/fttimer.c0000644000175000001440000002314213434207203015564 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project - a Free and Portable Quality TrueType Renderer. */ /* */ /* Copyright (C) 1996-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* fttimer: A simple performance benchmark. Now with graylevel rendering */ /* with the '-g' option. */ /* */ /* Be aware that the timer program benchmarks different things */ /* in each release of the FreeType library. Thus, performance */ /* should only be compared between similar release numbers. */ /* */ /* */ /* NOTE: This is just a test program that is used to show off and */ /* debug the current engine. In no way does it shows the final */ /* high-level interface that client applications will use. */ /* */ /****************************************************************************/ #include #include FT_FREETYPE_H #include FT_GLYPH_H #include #include #include #include /* for clock() */ /* SunOS 4.1.* does not define CLOCKS_PER_SEC, so include */ /* to get the HZ macro which is the equivalent. */ #if defined( __sun__ ) && !defined( SVR4 ) && !defined( __SVR4 ) #include #define CLOCKS_PER_SEC HZ #endif #define CHARSIZE 400 /* character point size */ #define MAX_GLYPHS 512 /* Maximum number of glyphs rendered at one time */ char Header[128]; FT_Error error; FT_Library library; FT_Face face; int num_glyphs; FT_Glyph glyphs[MAX_GLYPHS]; int tab_glyphs; int cur_glyph; int pixel_size = CHARSIZE; int repeat_count = 1; int Fail; int Num; short antialias = 1; /* smooth fonts with gray levels */ short force_low; static void Panic( const char* message ) { fprintf( stderr, "%s\n", message ); exit( 1 ); } /*******************************************************************/ /* */ /* Get_Time: */ /* */ /* Returns the current time in milliseconds. */ /* */ /*******************************************************************/ static long Get_Time( void ) { return clock() * 10000 / CLOCKS_PER_SEC; } /*******************************************************************/ /* */ /* LoadChar: */ /* */ /* Loads a glyph into memory. */ /* */ /*******************************************************************/ static FT_Error LoadChar( int idx ) { FT_Glyph glyph; /* load the glyph in the glyph slot */ error = FT_Load_Glyph( face, idx, FT_LOAD_DEFAULT ) || FT_Get_Glyph ( face->glyph, &glyph ); if ( !error ) glyphs[cur_glyph++] = glyph; return error; } /*******************************************************************/ /* */ /* ConvertRaster: */ /* */ /* Performs scan conversion. */ /* */ /*******************************************************************/ static FT_Error ConvertRaster( int idx ) { FT_Glyph bitmap; bitmap = glyphs[idx]; if ( bitmap->format == FT_GLYPH_FORMAT_BITMAP ) error = 0; /* we already have a (embedded) bitmap */ else { error = FT_Glyph_To_Bitmap( &bitmap, antialias ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO, 0, 0 ); if ( !error ) FT_Done_Glyph( bitmap ); } return error; } static void Usage( void ) { fprintf( stderr, "fttimer: simple performance timer -- part of the FreeType project\n" ); fprintf( stderr, "-----------------------------------------------------------------\n\n" ); fprintf( stderr, "Usage: fttimer [options] fontname[.ttf|.ttc]\n\n" ); fprintf( stderr, "options:\n"); fprintf( stderr, " -r : repeat count to be used (default is 1)\n" ); fprintf( stderr, " -s : character pixel size (default is 600)\n" ); fprintf( stderr, " -m : render monochrome glyphs (default is anti-aliased)\n" ); fprintf( stderr, " -a : use smooth anti-aliaser\n" ); fprintf( stderr, " -l : force low quality even at small sizes\n" ); exit( 1 ); } int main( int argc, char** argv ) { int i, total, base, rendered_glyphs; char filename[1024 + 4]; char alt_filename[1024 + 4]; long t, t0, tz0; antialias = 1; force_low = 0; while ( argc > 1 && argv[1][0] == '-' ) { switch ( argv[1][1] ) { case 'm': antialias = 0; break; case 'l': force_low = 1; break; case 's': argc--; argv++; if ( argc < 2 || sscanf( argv[1], "%d", &pixel_size ) != 1 ) Usage(); break; case 'r': argc--; argv++; if ( argc < 2 || sscanf( argv[1], "%d", &repeat_count ) != 1 ) Usage(); if ( repeat_count < 1 ) repeat_count = 1; break; default: fprintf( stderr, "Unknown argument `%s'\n", argv[1] ); Usage(); break; } argc--; argv++; } if ( argc != 2 ) Usage(); i = strlen( argv[1] ); while ( i > 0 && argv[1][i] != '\\' ) { if ( argv[1][i] == '.' ) i = 0; i--; } filename[1024] = '\0'; alt_filename[1024] = '\0'; strncpy( filename, argv[1], 1024 ); strncpy( alt_filename, argv[1], 1024 ); if ( i >= 0 ) { strncpy( filename + strlen( filename ), ".ttf", 4 ); strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 ); } /* Initialize engine */ if ( ( error = FT_Init_FreeType( &library ) ) != 0 ) Panic( "Error while initializing engine" ); /* Load face */ error = FT_New_Face( library, filename, 0, &face ); if ( error == FT_Err_Cannot_Open_Stream ) Panic( "Could not find/open font resource" ); else if ( error ) Panic( "Error while opening font resource" ); /* get face properties and allocate preload arrays */ num_glyphs = face->num_glyphs; tab_glyphs = MAX_GLYPHS; if ( tab_glyphs > num_glyphs ) tab_glyphs = num_glyphs; /* create size */ error = FT_Set_Pixel_Sizes( face, pixel_size, pixel_size ); if ( error ) Panic( "Could not reset instance" ); Num = 0; Fail = 0; total = num_glyphs; base = 0; rendered_glyphs = 0; t0 = 0; /* Initial time */ tz0 = Get_Time(); while ( total > 0 ) { int repeat; /* First, preload 'tab_glyphs' in memory */ cur_glyph = 0; printf( "loading %d glyphs", tab_glyphs ); for ( Num = 0; Num < tab_glyphs; Num++ ) { error = LoadChar( base + Num ); if ( error ) Fail++; total--; } base += tab_glyphs; if ( tab_glyphs > total ) tab_glyphs = total; printf( ", rendering... " ); /* Now, render the loaded glyphs */ t = Get_Time(); for ( repeat = 0; repeat < repeat_count; repeat++ ) { for ( Num = 0; Num < cur_glyph; Num++ ) { if ( ( error = ConvertRaster( Num ) ) != 0 ) Fail++; else rendered_glyphs++; } } t = Get_Time() - t; if ( t < 0 ) t += 1000 * 60 * 60; printf( " = %f s\n", (double)t / 10000 ); t0 += t; /* Now free all loaded outlines */ for ( Num = 0; Num < cur_glyph; Num++ ) FT_Done_Glyph( glyphs[Num] ); } tz0 = Get_Time() - tz0; FT_Done_Face( face ); printf( "\n" ); printf( "rendered glyphs = %d\n", rendered_glyphs ); printf( "render time = %f s\n", (double)t0 / 10000 ); printf( "fails = %d\n", Fail ); printf( "average glyphs/s = %f\n", (double)rendered_glyphs / t0 * 10000 ); printf( "total timing = %f s\n", (double)tz0 / 10000 ); printf( "Fails = %d\n", Fail ); FT_Done_FreeType( library ); exit( 0 ); /* for safety reasons */ return 0; /* never reached */ } /* End */ ft2demos-2.10.1/src/common.h0000644000175000001440000000113113434207203015401 0ustar00wlusers00000000000000#ifndef COMMON_H_ #define COMMON_H_ #ifdef __cplusplus extern "C" { #endif extern char* ft_basename( const char* name ); /* print a message and exit */ extern void Panic( const char* fmt, ... ); /* * Read the next UTF-8 code from `*pcursor' and * returns its value. `end' is the limit of the * input string. * * Return -1 if the end of the input string is * reached, or in case of malformed data. */ extern int utf8_next( const char** pcursor, const char* end ); #ifdef __cplusplus } #endif #endif /* COMMON_H_ */ /* End */ ft2demos-2.10.1/src/compos.c0000644000175000001440000001257213434207203015417 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 1996-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* compos: this is a very simple program used to test the flag */ /* FT_LOAD_NO_RECURSE */ /* */ /* NOTE: This is just a test program that is used to show off and */ /* debug the current engine. */ /* */ /****************************************************************************/ #define FT2_BUILD_LIBRARY #include #include FT_FREETYPE_H #include FT_INTERNAL_GLYPH_LOADER_H #include #include #include #define gettext( x ) ( x ) FT_Error error; FT_Library library; FT_Face face; FT_Size size; FT_GlyphSlot slot; unsigned int num_glyphs; int ptsize; int Fail; int Num; static void Usage( char* name ) { printf( "compos: test FT_LOAD_NO_RECURSE load flag - www.freetype.org\n" ); printf( "------------------------------------------------------------\n" ); printf( "\n" ); printf( "Usage: %s fontname[.ttf|.ttc] [fontname2..]\n", name ); printf( "\n" ); exit( 1 ); } static void Panic( const char* message ) { fprintf( stderr, "%s\n error code = 0x%04x\n", message, error ); exit(1); } int main( int argc, char** argv ) { int i, file_index; unsigned int id; char filename[1024 + 4]; char alt_filename[1024 + 4]; char* execname; char* fname; execname = argv[0]; if ( argc < 2 ) Usage( execname ); error = FT_Init_FreeType( &library ); if (error) Panic( "Could not create library object" ); /* Now check all files */ for ( file_index = 1; file_index < argc; file_index++ ) { fname = argv[file_index]; i = strlen( fname ); while ( i > 0 && fname[i] != '\\' && fname[i] != '/' ) { if ( fname[i] == '.' ) i = 0; i--; } filename[1024] = '\0'; alt_filename[1024] = '\0'; strncpy( filename, fname, 1024 ); strncpy( alt_filename, fname, 1024 ); #ifndef macintosh if ( i >= 0 ) { strncpy( filename + strlen( filename ), ".ttf", 4 ); strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 ); } #endif i = strlen( filename ); fname = filename; while ( i >= 0 ) #ifndef macintosh if ( filename[i] == '/' || filename[i] == '\\' ) #else if ( filename[i] == ':' ) #endif { fname = filename + i + 1; i = -1; } else i--; printf( "%s:\n", fname ); /* Load face */ error = FT_New_Face( library, filename, 0, &face ); if (error) { if (error == FT_Err_Invalid_File_Format) printf( "unknown format\n" ); else printf( "could not find/open file (error: %d)\n", error ); continue; } num_glyphs = face->num_glyphs; slot = face->glyph; Fail = 0; { for ( id = 0; id < num_glyphs; id++ ) { int has_scale; error = FT_Load_Glyph( face, id, FT_LOAD_NO_RECURSE ); if ( !error && slot->format == FT_GLYPH_FORMAT_COMPOSITE ) { unsigned int n; FT_SubGlyph subg = slot->subglyphs; printf( "%4d:", id ); for ( n = 0; n < slot->num_subglyphs; n++, subg++ ) { has_scale = subg->flags & ( FT_SUBGLYPH_FLAG_SCALE | FT_SUBGLYPH_FLAG_XY_SCALE | FT_SUBGLYPH_FLAG_2X2 ); printf( " [%d%c", subg->index, subg->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS ? '*' : ' ' ); if ( subg->arg1|subg->arg2 ) { if ( subg->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) printf( "(%d,%d)", subg->arg1, subg->arg2 ); else printf( "<%d,%d>", subg->arg1, subg->arg2 ); } if (has_scale) printf( "-{%0.3f %0.3f %0.3f %0.3f}", subg->transform.xx/65536.0, subg->transform.xy/65536.0, subg->transform.yx/65536.0, subg->transform.yy/65536.0 ); printf( "]" ); } printf( " adv=%ld lsb=%ld\n", slot->metrics.horiAdvance, slot->metrics.horiBearingX ); } } } FT_Done_Face( face ); } FT_Done_FreeType(library); exit( 0 ); /* for safety reasons */ return 0; /* never reached */ } /* End */ ft2demos-2.10.1/src/output.c0000644000175000001440000002060013434207203015446 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 2015-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* */ /* output.c - string output routines for the FreeType demo programs. */ /* */ /****************************************************************************/ #include "output.h" static char hexdigit[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; void put_ascii_string( char* out, FT_Byte* string, FT_UInt string_len, FT_UInt indent ) { FT_UInt i, j; for ( j = 0; j < indent; j++ ) *out++ = ' '; *out++ = '"'; for ( i = 0; i < string_len; i++ ) { switch ( string[i] ) { case '\n': *out++ = '\\'; *out++ = 'n'; *out++ = '"'; if ( i + 1 < string_len ) { *out++ = '\n'; for ( j = 0; j < indent; j++ ) *out++ = ' '; *out++ = '"'; } break; case '\r': *out++ = '\\'; *out++ = 'r'; break; case '\t': *out++ = '\\'; *out++ = 't'; break; case '\\': *out++ = '\\'; *out++ = '\\'; break; case '"': *out++ = '\\'; *out++ = '"'; break; case 0xA9: *out++ = '('; *out++ = 'c'; *out++ = ')'; break; default: if ( string[i] < 0x80 ) *out++ = (char)string[i]; else { *out++ = '\\'; *out++ = 'x'; *out++ = hexdigit[string[i] >> 4]; *out++ = hexdigit[string[i] & 0xF]; } break; } } if ( string[i - 1] != '\n' ) *out++ = '"'; *out++ = '\0'; } FT_UInt put_ascii_string_size( FT_Byte* string, FT_UInt string_len, FT_UInt indent ) { FT_UInt i, len = 0; /* the code formatting follows `put_ascii_string' */ len += indent; len += 1; for ( i = 0; i < string_len; i++ ) { switch ( string[i] ) { case '\n': len += 3; if ( i + 1 < string_len ) { len += 1; len += indent; len += 1; } break; case '\r': case '\t': case '\\': case '"': len += 2; break; case 0xA9: len += 3; break; default: if ( string[i] < 0x80 ) len += 1; else len += 4; break; } } if ( string[i - 1] != '\n' ) len += 1; len += 1; return len; } void put_ascii( FT_Byte* string, FT_UInt string_len, FT_UInt indent ) { FT_UInt len; char* s; len = put_ascii_string_size( string, string_len, indent ); s = (char*)malloc( len ); if ( !s ) printf( "allocation error for name string" ); else { put_ascii_string( s, string, string_len, indent ); fputs( s, stdout ); free( s ); } } void put_unicode_be16_string( char* out, FT_Byte* string, FT_UInt string_len, FT_UInt indent, FT_Int as_utf8 ) { FT_Int ch = 0; FT_UInt i, j; for ( j = 0; j < indent; j++ ) *out++ = ' '; *out++ = '"'; for ( i = 0; i < string_len; i += 2 ) { ch = ( string[i] << 8 ) | string[i + 1]; switch ( ch ) { case '\n': *out++ = '\\'; *out++ = 'n'; *out++ = '"'; if ( i + 2 < string_len ) { *out++ = '\n'; for ( j = 0; j < indent; j++ ) *out++ = ' '; *out++ = '"'; } continue; case '\r': *out++ = '\\'; *out++ = 'r'; continue; case '\t': *out++ = '\\'; *out++ = 't'; continue; case '\\': *out++ = '\\'; *out++ = '\\'; continue; case '"': *out++ = '\\'; *out++ = '"'; continue; default: break; } if ( as_utf8 ) { /* * UTF-8 encoding * * 0x00000080 - 0x000007FF: * 110xxxxx 10xxxxxx * * 0x00000800 - 0x0000FFFF: * 1110xxxx 10xxxxxx 10xxxxxx */ if ( ch < 0x80 ) *out++ = (char)ch; else if ( ch < 0x800 ) { *out++ = (char)( 0xC0 | ( (FT_UInt)ch >> 6 ) ); *out++ = (char)( 0x80 | ( (FT_UInt)ch & 0x3F ) ); } else { /* we don't handle surrogates */ *out++ = (char)( 0xE0 | ( (FT_UInt)ch >> 12 ) ); *out++ = (char)( 0x80 | ( ( (FT_UInt)ch >> 6 ) & 0x3F ) ); *out++ = (char)( 0x80 | ( (FT_UInt)ch & 0x3F ) ); } continue; } switch ( ch ) { case 0x00A9: *out++ = '('; *out++ = 'c'; *out++ = ')'; continue; case 0x00AE: *out++ = '('; *out++ = 'r'; *out++ = ')'; continue; case 0x2013: *out++ = '-'; *out++ = '-'; continue; case 0x2019: *out++ = '\''; continue; case 0x2122: *out++ = '('; *out++ = 't'; *out++ = 'm'; *out++ = ')'; continue; default: if ( ch < 128 ) *out++ = (char)ch; else { *out++ = '\\'; *out++ = 'U'; *out++ = '+'; *out++ = hexdigit[( ch >> 12 ) & 0xF]; *out++ = hexdigit[( ch >> 8 ) & 0xF]; *out++ = hexdigit[( ch >> 4 ) & 0xF]; *out++ = hexdigit[ ch & 0xF]; } continue; } } if ( ch != '\n' ) *out++ = '"'; *out++ = '\0'; } FT_UInt put_unicode_be16_string_size( FT_Byte* string, FT_UInt string_len, FT_UInt indent, FT_Int as_utf8 ) { FT_Int ch = 0; FT_UInt i, len = 0; /* the code formatting follows `put_unicode_be16_string' */ len += indent; len += 1; for ( i = 0; i < string_len; i += 2 ) { ch = ( string[i] << 8 ) | string[i + 1]; switch ( ch ) { case '\n': len += 3; if ( i + 2 < string_len ) { len += 1; len += indent; len += 1; } continue; case '\r': case '\t': case '\\': case '"': len += 2; continue; default: break; } if ( as_utf8 ) { if ( ch < 0x80 ) len += 1; else if ( ch < 0x800 ) len += 2; else len += 3; continue; } switch ( ch ) { case 0x00A9: case 0x00AE: len += 3; continue; case 0x2013: len += 2; continue; case 0x2019: len += 1; continue; case 0x2122: len += 4; continue; default: if ( ch < 128 ) len += 1; else len += 7; continue; } } if ( ch != '\n' ) len += 1; len += 1; return len; } void put_unicode_be16( FT_Byte* string, FT_UInt string_len, FT_UInt indent, FT_Int utf8 ) { FT_UInt len; char* s; len = put_unicode_be16_string_size( string, string_len, indent, utf8 ); s = (char*)malloc( len ); if ( !s ) printf( "allocation error for name string" ); else { put_unicode_be16_string( s, string, string_len, indent, utf8 ); fputs( s, stdout ); free( s ); } } /* End */ ft2demos-2.10.1/src/ftpatchk.c0000644000175000001440000000337213434207203015721 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 2007-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* */ /* FTpatchk - a simple program that tests whether patented hinting is */ /* necessary. */ /* */ /****************************************************************************/ #include #include #include #include FT_FREETYPE_H int main( int argc, char* argv[] ) { FT_Error error; FT_Library library; error = FT_Init_FreeType( &library ); if ( error ) { fprintf( stderr, "could not create FreeType instance\n" ); exit( 1 ); } for ( ; argc > 1; argc--, argv++ ) { FT_Face face; error = FT_New_Face( library, argv[1], 0, &face ); if ( error ) { fprintf( stderr, "could not open as a valid font: `%s'\n", argv[1] ); continue; } printf( "%-50s %s\n", argv[1], FT_Face_CheckTrueTypePatents( face ) ? "uses patented opcodes" : "doesn't use patented opcodes" ); } exit( 0 ); return 0; } /* End */ ft2demos-2.10.1/src/output.h0000644000175000001440000000375613434207203015470 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 2015-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* */ /* output.h - string output routines for the FreeType demo programs. */ /* */ /****************************************************************************/ #ifndef OUTPUT_H_ #define OUTPUT_H_ #include #include FT_FREETYPE_H void put_ascii_string( char* out, FT_Byte* string, FT_UInt string_len, FT_UInt indent ); FT_UInt put_ascii_string_size( FT_Byte* string, FT_UInt string_len, FT_UInt indent ); void put_ascii( FT_Byte* string, FT_UInt string_len, FT_UInt indent ); void put_unicode_be16_string( char* out, FT_Byte* string, FT_UInt string_len, FT_UInt indent, FT_Int as_utf8 ); FT_UInt put_unicode_be16_string_size( FT_Byte* string, FT_UInt string_len, FT_UInt indent, FT_Int as_utf8 ); void put_unicode_be16( FT_Byte* string, FT_UInt string_len, FT_UInt indent, FT_Int as_utf8 ); #endif /* OUTPUT_H_ */ /* End */ ft2demos-2.10.1/src/ftgamma.c0000644000175000001440000002545313501434334015537 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 2004-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* */ /* ftgamma - gamma matcher */ /* */ /****************************************************************************/ #include "ftcommon.h" #include static FTDemo_Display* display; static grBitmap bit1 = { 300, 600, 600, gr_pixel_mode_gray, 256, NULL }; static grBitmap bit2 = { 288, 600, 600, gr_pixel_mode_gray, 256, NULL }; static int status = 0; static void do_ptrn( grBitmap* bitmap, int x, int y, int w, int h ) { int pitch = bitmap->pitch; int i, j, k; double p[4]; unsigned char* line; for ( i = 0; i < h; i++ ) { for ( k = 0; k < 4; k++) { j = 2 * i + 1 + ( k - 4 ) * h / 2; if ( j > h ) j -= 2 * h; if ( j < -h ) j += 2 * h; if ( j < 0 ) j = -j; j -= h / 4; if ( j < 0 ) j = 0; if ( j > h / 2 ) j = h / 2; p[k] = 2. * j / h; } line = bitmap->buffer + ( y + i ) * pitch + x; for ( j = 0, k = 0; j < w; j++ ) { line[j] = (unsigned char)( 0.5 + 255. * pow ( p[k], 1. / (1. + 2. * j / w ) ) ); k++; if ( k == 4 ) k = 0; } } } static FT_Error GammaPtrn( grBitmap* bitmap ) { int x = 0; int y = 0; int h = ( bitmap->rows - 2 * y ) / 2; int w = bitmap->width - 2 * x; do_ptrn( bitmap, x, y, w, h ); do_ptrn( bitmap, x, y+=h, w, h ); return 0; } static void do_fill( grBitmap* bitmap, int x, int y, int w, int h, int back, int fore ) { int pitch = bitmap->pitch; int i; double b, f; unsigned char* line = bitmap->buffer + y*pitch + x; if ( back == 0 || back == 255 ) for ( i = 0; i < w; i++ ) line[i + ( i & 1 ) * pitch] = (unsigned char)back; else for ( b = back / 255., i = 0; i < w; i++ ) line[i + ( i & 1 ) * pitch] = (unsigned char)( 0.5 + 255. * pow ( b, 1. / (1. + 2. * i / w ) ) ); if ( fore == 0 || fore == 255 ) for ( i = 0; i < w; i++ ) line[i + ( ~i & 1 ) * pitch] = (unsigned char)fore; else for ( f = fore / 255., i = 0; i < w; i++ ) line[i + ( ~i & 1 ) * pitch] = (unsigned char)( 0.5 + 255. * pow ( f, 1. / (1. + 2. * i / w ) ) ); for ( i = 2; i < h; i += 2 ) { memcpy( line + i * pitch, line, (size_t)w ); memcpy( line + i * pitch + pitch, line + pitch, (size_t)w ); } } static FT_Error GammaGrid( grBitmap* bitmap ) { int x = 0; int y = 0; int h = ( bitmap->rows - 2 * y ) / 15; int w = bitmap->width - 2 * x; do_fill( bitmap, x, y, w, h, 85, 255 ); do_fill( bitmap, x, y+=h, w, h, 170, 170 ); do_fill( bitmap, x, y+=h, w, h, 85, 255 ); do_fill( bitmap, x, y+=h, w, h, 170, 170 ); do_fill( bitmap, x, y+=h, w, h, 85, 255 ); do_fill( bitmap, x, y+=h, w, h, 0, 255 ); do_fill( bitmap, x, y+=h, w, h, 127, 127 ); do_fill( bitmap, x, y+=h, w, h, 0, 255 ); do_fill( bitmap, x, y+=h, w, h, 127, 127 ); do_fill( bitmap, x, y+=h, w, h, 0, 255 ); do_fill( bitmap, x, y+=h, w, h, 0, 170 ); do_fill( bitmap, x, y+=h, w, h, 85, 85 ); do_fill( bitmap, x, y+=h, w, h, 0, 170 ); do_fill( bitmap, x, y+=h, w, h, 85, 85 ); do_fill( bitmap, x, y+=h, w, h, 0, 170 ); return 0; } static void event_help( void ) { grEvent dummy_event; FTDemo_Display_Clear( display ); grSetLineHeight( 10 ); grGotoxy( 0, 0 ); grSetMargin( 2, 1 ); grGotobitmap( display->bitmap ); grWriteln( "FreeType Gamma Matcher" ); grLn(); grWriteln( "Use the following keys:" ); grLn(); grWriteln( "F1, ? display this help screen" ); grLn(); grWriteln( "space cycle through color"); grWriteln( "tab alternate patterns"); grWriteln( "G show gamma ramp" ); grLn(); grLn(); grWriteln( "press any key to exit this help screen" ); grRefreshSurface( display->surface ); grListenSurface( display->surface, gr_event_key, &dummy_event ); } static void event_color_change( void ) { static int i = 7; unsigned char r = i & 4 ? 0xff : 0; unsigned char g = i & 2 ? 0xff : 0; unsigned char b = i & 1 ? 0xff : 0; display->back_color = grFindColor( display->bitmap, 0, 0, 0, 0xff ); display->fore_color = grFindColor( display->bitmap, r, g, b, 0xff ); i++; if ( ( i & 0x7 ) == 0 ) i = 1; } static void event_gamma_grid( void ) { grEvent dummy_event; int g; int yside = 11; int xside = 10; int levels = 17; int gammas = 30; int x_0 = ( display->bitmap->width - levels * xside ) / 2; int y_0 = ( display->bitmap->rows - gammas * ( yside + 1 ) ) / 2; int pitch = display->bitmap->pitch; FTDemo_Display_Clear( display ); grGotobitmap( display->bitmap ); if ( pitch < 0 ) pitch = -pitch; memset( display->bitmap->buffer, 100, (unsigned int)( pitch * display->bitmap->rows ) ); grWriteCellString( display->bitmap, 0, 0, "Gamma grid", display->fore_color ); for ( g = 1; g <= gammas; g++ ) { double ggamma = 0.1 * g; char temp[6]; int y = y_0 + ( yside + 1 ) * ( g - 1 ); int nx, ny; unsigned char* line = display->bitmap->buffer + y * display->bitmap->pitch; if ( display->bitmap->pitch < 0 ) line -= display->bitmap->pitch * ( display->bitmap->rows - 1 ); line += x_0 * 3; grSetPixelMargin( x_0 - 32, y + ( yside - 8 ) / 2 ); grGotoxy( 0, 0 ); sprintf( temp, "%.1f", ggamma ); grWrite( temp ); for ( ny = 0; ny < yside; ny++, line += display->bitmap->pitch ) { unsigned char* dst = line; for ( nx = 0; nx < levels; nx++, dst += 3 * xside ) { double p = nx / (double)( levels - 1 ); int gm = (int)( 255.0 * pow( p, ggamma ) + 0.5 ); memset( dst, gm, (unsigned int)( xside * 3 ) ); } } } grRefreshSurface( display->surface ); grListenSurface( display->surface, gr_event_key, &dummy_event ); } static void Render_Bitmap( grBitmap* out, grBitmap* in, int x, int y, grColor color, int lcd ) { int pitch = abs( out->pitch ); int i, ii, j; unsigned char* src; unsigned char* dst; if ( color.chroma[0] == 255 ) for ( src = in->buffer, i = 0; i < in->rows; i++ ) { ii = ( i + 24 * lcd ) % in->rows; dst = out->buffer + ( y + ii ) * pitch + 3 * x; for ( j = 0; j < in->width; j++, src++, dst += 3 ) *dst = *src; } if ( color.chroma[1] == 255 ) for ( src = in->buffer, i = 0; i < in->rows; i++ ) { ii = ( i + 12 * lcd ) % in->rows; dst = out->buffer + ( y + ii ) * pitch + 3 * x + 1; for ( j = 0; j < in->width; j++, src++, dst += 3 ) *dst = *src; } if ( color.chroma[2] == 255 ) for ( src = in->buffer, i = 0; i < in->rows; i++ ) { ii = ( i + 0 * lcd ) % in->rows; dst = out->buffer + ( y + ii ) * pitch + 3 * x + 2; for ( j = 0; j < in->width; j++, src++, dst += 3 ) *dst = *src; } } static int Process_Event( void ) { grEvent event; int ret = 0; grListenSurface( display->surface, 0, &event ); switch ( event.key ) { case grKeyEsc: case grKEY( 'q' ): ret = 1; break; case grKeyF1: case grKEY( '?' ): event_help(); break; case grKeySpace: event_color_change(); break; case grKeyTab: status++; if ( status > 2 ) status = 0; break; case grKEY( 'G' ): event_gamma_grid(); break; default: break; } return ret; } int main( void ) { char buf[4]; int i; display = FTDemo_Display_New( NULL, DIM ); if ( !display ) { PanicZ( "could not allocate display surface" ); } grSetTitle( display->surface, "FreeType Gamma Matcher - press ? for help" ); grNewBitmap( bit1.mode, bit1.grays, bit1.width, bit1.rows, &bit1 ); GammaGrid( &bit1 ); grNewBitmap( bit2.mode, bit2.grays, bit2.width, bit2.rows, &bit2 ); GammaPtrn( &bit2 ); event_color_change(); do { FTDemo_Display_Clear( display ); switch ( status ) { case 0: grWriteCellString( display->bitmap, 236, 75, "Solid-Checkered Pattern", display->fore_color ); Render_Bitmap( display->bitmap, &bit1, 20, 90, display->fore_color, 0 ); break; case 1: grWriteCellString( display->bitmap, 236, 75, "Grayscale Anti-Aliasing", display->fore_color ); Render_Bitmap( display->bitmap, &bit2, 20, 96, display->fore_color, 0 ); break; case 2: grWriteCellString( display->bitmap, 236, 75, "Subpixel Anti-Aliasing", display->fore_color ); Render_Bitmap( display->bitmap, &bit2, 20, 96, display->fore_color, 1 ); break; } for ( i = 0; i <= 10; i++ ) { sprintf( buf, "%.1f", 1. + .2 * i ); grWriteCellString( display->bitmap, 9 + i * 60, 395, buf, display->fore_color ); } grWriteCellString( display->bitmap, display->bitmap->width / 2 - 20, 410, "Gamma", display->fore_color ); grRefreshSurface( display->surface ); } while ( Process_Event() == 0 ); FTDemo_Display_Done( display ); exit( 0 ); /* for safety reasons */ /* return 0; */ /* never reached */ } /* End */ ft2demos-2.10.1/src/ttdebug.10000644000175000001440000000174613506424316015502 0ustar00wlusers00000000000000.TH TTDEBUG 1 "May 2019" "FreeType 2.10.1" . . .SH NAME . ttdebug \- a TrueType bytecode debugger . . .SH SYNOPSIS . .B ttdebug .RI [ options ] .I index size font . . .SH DESCRIPTION . .B ttdebug is an interactive TrueType bytecode debugger working in a terminal. Its spartanic interface faintly resembles debuggers like .BR gdb . . .PP For the specified .IR font , a glyph with the given .I index and .I size is loaded, making it possible to trace the bytecode execution step by step. . .PP This program is part of the FreeType demos package. . . .SH OPTIONS . .TP .BI "\-I " ver Use TrueType interpreter version .IR ver . Available versions are depending on compilation options of FreeType; call .B ttdebug without an argument to get the actual list. . .TP .BI "\-f " face_index To access member font .IR face_index (default zero) in TTCs. . .TP .BI "\-d\ \(dq" "axis1\ axis2\ .\|.\|." \(dq Specify the design coordinates for each variation axis at start-up. . .TP .B \-v Show version. . .\" eof ft2demos-2.10.1/src/ftdump.c0000644000175000001440000006115713501434362015424 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 1996-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /****************************************************************************/ #include #include FT_FREETYPE_H #include FT_SFNT_NAMES_H #include FT_TRUETYPE_IDS_H #include FT_TRUETYPE_TABLES_H #include FT_TRUETYPE_TAGS_H #include FT_MULTIPLE_MASTERS_H /* the following header shouldn't be used in normal programs */ #include FT_INTERNAL_DEBUG_H /* showing driver name */ #include FT_MODULE_H #include FT_INTERNAL_OBJECTS_H #include FT_INTERNAL_DRIVER_H /* error messages */ #undef FTERRORS_H_ #define FT_ERROR_START_LIST { #define FT_ERRORDEF( e, v, s ) case v: str = s; break; #define FT_ERROR_END_LIST default: str = "unknown error"; } #include "common.h" #include "output.h" #include "mlgetopt.h" #include #include #include #include static FT_Error error; static int comma_flag = 0; static int coverage = 0; static int name_tables = 0; static int bytecode = 0; static int tables = 0; static int utf8 = 0; /* PanicZ */ static void PanicZ( FT_Library library, const char* message ) { const FT_String *str; FT_Done_FreeType( library ); switch( error ) #include FT_ERRORS_H fprintf( stderr, "%s\n error = 0x%04x, %s\n", message, error, str ); exit( 1 ); } static void Print_Comma( const char* message ) { if ( comma_flag ) printf( ", " ); printf( "%s", message ); comma_flag = 1; } static void usage( FT_Library library, char* execname ) { FT_Done_FreeType( library ); fprintf( stderr, "\n" "ftdump: simple font dumper -- part of the FreeType project\n" "-----------------------------------------------------------\n" "\n" "Usage: %s [options] fontname\n" "\n", execname ); fprintf( stderr, " -c, -C Print charmap coverage.\n" " -n Print SFNT name tables.\n" " -p Print TrueType programs.\n" " -t Print SFNT table list.\n" " -u Emit UTF8.\n" "\n" " -v Show version.\n" "\n" ); exit( 1 ); } static void Print_Name( FT_Face face ) { const char* ps_name; TT_Header* head; printf( "font name entries\n" ); /* XXX: Foundry? Copyright? Version? ... */ printf( " family: %s\n", face->family_name ); printf( " style: %s\n", face->style_name ); ps_name = FT_Get_Postscript_Name( face ); if ( ps_name == NULL ) ps_name = "UNAVAILABLE"; printf( " postscript: %s\n", ps_name ); head = (TT_Header*)FT_Get_Sfnt_Table( face, FT_SFNT_HEAD ); if ( head ) { char buf[11]; time_t created = head->Created [1]; time_t modified = head->Modified[1]; /* ignore most of upper bits until 2176 and adjust epoch */ created += head->Created [0] == 1 ? 2212122496 : -2082844800; modified += head->Modified[0] == 1 ? 2212122496 : -2082844800; strftime( buf, sizeof( buf ), "%Y-%m-%d", gmtime( &created ) ); printf(" created: %s\n", buf ); strftime( buf, sizeof( buf ), "%Y-%m-%d", gmtime( &modified ) ); printf(" modified: %s\n", buf ); printf(" revision: %.2f\n", head->Font_Revision / 65536.0 ); } } static void Print_Type( FT_Face face ) { FT_Module module; printf( "font type entries\n" ); module = &face->driver->root; printf( " FreeType driver: %s\n", module->clazz->module_name ); /* Is it better to dump all sfnt tag names? */ printf( " sfnt wrapped: %s\n", FT_IS_SFNT( face ) ? (char *)"yes" : (char *)"no" ); /* isScalable? */ comma_flag = 0; printf( " type: " ); if ( FT_IS_SCALABLE( face ) ) { Print_Comma( "scalable" ); if ( FT_HAS_MULTIPLE_MASTERS( face ) ) Print_Comma( "multiple masters" ); } if ( FT_HAS_FIXED_SIZES( face ) ) Print_Comma( "fixed size" ); printf( "\n" ); /* Direction */ comma_flag = 0; printf( " direction: " ); if ( FT_HAS_HORIZONTAL( face ) ) Print_Comma( "horizontal" ); if ( FT_HAS_VERTICAL( face ) ) Print_Comma( "vertical" ); printf( "\n" ); printf( " fixed width: %s\n", FT_IS_FIXED_WIDTH( face ) ? (char *)"yes" : (char *)"no" ); printf( " glyph names: %s\n", FT_HAS_GLYPH_NAMES( face ) ? (char *)"yes" : (char *)"no" ); if ( FT_IS_SCALABLE( face ) ) { printf( " EM size: %d\n", face->units_per_EM ); printf( " global BBox: (%ld,%ld):(%ld,%ld)\n", face->bbox.xMin, face->bbox.yMin, face->bbox.xMax, face->bbox.yMax ); printf( " ascent: %d\n", face->ascender ); printf( " descent: %d\n", face->descender ); printf( " text height: %d\n", face->height ); } } static const char* platform_id( int id ) { switch ( id ) { case TT_PLATFORM_APPLE_UNICODE: return "Apple (Unicode)"; case TT_PLATFORM_MACINTOSH: return "Macintosh"; case TT_PLATFORM_ISO: return "ISO (deprecated)"; case TT_PLATFORM_MICROSOFT: return "Microsoft"; case TT_PLATFORM_CUSTOM: return "custom"; case TT_PLATFORM_ADOBE: return "Adobe"; default: return "UNKNOWN"; } } #define XEXPAND( x ) #x #define EXPAND( x ) XEXPAND( x ) #define NAME_ID( tag, description ) \ case TT_NAME_ID_ ## tag: \ return description " (ID " EXPAND( TT_NAME_ID_ ## tag ) ")" static const char* name_id( int id ) { switch ( id ) { NAME_ID( COPYRIGHT, "copyright" ); NAME_ID( FONT_FAMILY, "font family" ); NAME_ID( FONT_SUBFAMILY, "font subfamily" ); NAME_ID( UNIQUE_ID, "unique font identifier" ); NAME_ID( FULL_NAME, "full name" ); NAME_ID( VERSION_STRING, "version string" ); NAME_ID( PS_NAME, "PostScript name" ); NAME_ID( TRADEMARK, "trademark" ); /* the following values are from the OpenType spec */ NAME_ID( MANUFACTURER, "manufacturer" ); NAME_ID( DESIGNER, "designer" ); NAME_ID( DESCRIPTION, "description" ); NAME_ID( VENDOR_URL, "vendor URL" ); NAME_ID( DESIGNER_URL, "designer URL" ); NAME_ID( LICENSE, "license" ); NAME_ID( LICENSE_URL, "license URL" ); /* number 15 is reserved */ NAME_ID( TYPOGRAPHIC_FAMILY, "typographic family" ); NAME_ID( TYPOGRAPHIC_SUBFAMILY, "typographic subfamily" ); NAME_ID( MAC_FULL_NAME, "Mac full name" ); /* the following code is new as of 2000-01-21 */ NAME_ID( SAMPLE_TEXT, "sample text" ); /* this is new in OpenType 1.3 */ NAME_ID( CID_FINDFONT_NAME, "CID `findfont' name" ); /* this is new in OpenType 1.5 */ NAME_ID( WWS_FAMILY, "WWS family name" ); NAME_ID( WWS_SUBFAMILY, "WWS subfamily name" ); /* this is new in OpenType 1.7 */ NAME_ID( LIGHT_BACKGROUND, "light background palette" ); NAME_ID( DARK_BACKGROUND, "dark background palette" ); /* this is new in OpenType 1.8 */ NAME_ID( VARIATIONS_PREFIX, "variations PostScript name prefix" ); default: return NULL; } } static void Print_Sfnt_Names( FT_Face face ) { FT_SfntName name; FT_UInt num_names, i; printf( "font string entries\n" ); num_names = FT_Get_Sfnt_Name_Count( face ); for ( i = 0; i < num_names; i++ ) { error = FT_Get_Sfnt_Name( face, i, &name ); if ( error == FT_Err_Ok ) { const char* NameID = name_id( name.name_id ); const char* PlatformID = platform_id( name.platform_id ); if ( NameID ) printf( " %-15s [%s]", NameID, PlatformID ); else printf( " Name ID %-5d [%s]", name.name_id, PlatformID ); switch ( name.platform_id ) { case TT_PLATFORM_APPLE_UNICODE: fputs( ":\n", stdout ); switch ( name.encoding_id ) { case TT_APPLE_ID_DEFAULT: case TT_APPLE_ID_UNICODE_1_1: case TT_APPLE_ID_ISO_10646: case TT_APPLE_ID_UNICODE_2_0: put_unicode_be16( name.string, name.string_len, 6, utf8 ); break; default: printf( "{unsupported Unicode encoding %d}", name.encoding_id ); break; } break; case TT_PLATFORM_MACINTOSH: if ( name.language_id != TT_MAC_LANGID_ENGLISH ) printf( " (language=%u)", name.language_id ); fputs( ":\n", stdout ); switch ( name.encoding_id ) { case TT_MAC_ID_ROMAN: /* FIXME: convert from MacRoman to ASCII/ISO8895-1/whatever */ /* (MacRoman is mostly like ISO8895-1 but there are */ /* differences) */ put_ascii( name.string, name.string_len, 6 ); break; default: printf( " [data in encoding %d]", name.encoding_id ); break; } break; case TT_PLATFORM_ISO: fputs( ":\n", stdout ); switch ( name.encoding_id ) { case TT_ISO_ID_7BIT_ASCII: case TT_ISO_ID_8859_1: put_ascii( name.string, name.string_len, 6 ); break; case TT_ISO_ID_10646: put_unicode_be16( name.string, name.string_len, 6, utf8 ); break; default: printf( "{unsupported encoding %d}", name.encoding_id ); break; } break; case TT_PLATFORM_MICROSOFT: if ( name.language_id != TT_MS_LANGID_ENGLISH_UNITED_STATES ) printf( " (language=0x%04x)", name.language_id ); fputs( ":\n", stdout ); switch ( name.encoding_id ) { /* TT_MS_ID_SYMBOL_CS is Unicode, similar to PID/EID=3/1 */ case TT_MS_ID_SYMBOL_CS: case TT_MS_ID_UNICODE_CS: put_unicode_be16( name.string, name.string_len, 6, utf8 ); break; default: printf( "{unsupported encoding %d}", name.encoding_id ); break; } break; default: printf( "{unsupported platform}" ); break; } printf( "\n" ); } } } static void Print_Sfnt_Tables( FT_Face face ) { FT_ULong num_tables, i; FT_ULong tag, length; FT_Byte buffer[4]; FT_Sfnt_Table_Info( face, 0, NULL, &num_tables ); printf( "font tables (%lu)\n", num_tables ); for ( i = 0; i < num_tables; i++ ) { FT_Sfnt_Table_Info( face, (FT_UInt)i, &tag, &length ); if ( length >= 4 ) { length = 4; FT_Load_Sfnt_Table( face, tag, 0, buffer, &length ); } else continue; printf( " %2lu: %c%c%c%c %02X%02X%02X%02X...\n", i, (FT_Char)( tag >> 24 ), (FT_Char)( tag >> 16 ), (FT_Char)( tag >> 8 ), (FT_Char)( tag ), (FT_UInt)buffer[0], (FT_UInt)buffer[1], (FT_UInt)buffer[2], (FT_UInt)buffer[3] ); } } static void Print_Fixed( FT_Face face ) { int i; /* num_fixed_size */ printf( "fixed size\n" ); /* available size */ for ( i = 0; i < face->num_fixed_sizes; i++ ) { FT_Bitmap_Size* bsize = face->available_sizes + i; printf( " %3d: height %d, width %d\n", i, bsize->height, bsize->width ); printf( " size %.3f, x_ppem %.3f, y_ppem %.3f\n", bsize->size / 64.0, bsize->x_ppem / 64.0, bsize->y_ppem / 64.0 ); } } static void Print_Charmaps( FT_Face face ) { int i, active = -1; if ( face->charmap ) active = FT_Get_Charmap_Index( face->charmap ); /* CharMaps */ printf( "charmaps (%d)\n", face->num_charmaps ); for( i = 0; i < face->num_charmaps; i++ ) { FT_Long format = FT_Get_CMap_Format( face->charmaps[i] ); FT_ULong lang_id = FT_Get_CMap_Language_ID( face->charmaps[i] ); if ( format >= 0 ) printf( " %2d: format %2ld, platform %u, encoding %2u", i, format, face->charmaps[i]->platform_id, face->charmaps[i]->encoding_id ); else printf( " %2d: synthetic, platform %u, encoding %2u", i, face->charmaps[i]->platform_id, face->charmaps[i]->encoding_id ); if ( lang_id == 0xFFFFFFFFUL ) printf( " (Unicode Variation Sequences)" ); else printf( " language %lu", lang_id ); if ( i == active ) printf( " (active)" ); printf ( "\n" ); if ( coverage == 2 ) { FT_ULong charcode; FT_UInt gindex; FT_String buf[32]; FT_Set_Charmap( face, face->charmaps[i] ); charcode = FT_Get_First_Char( face, &gindex ); while ( gindex ) { if ( FT_HAS_GLYPH_NAMES ( face ) ) FT_Get_Glyph_Name( face, gindex, buf, 32 ); else buf[0] = '\0'; printf( " 0x%04lx => %d %s\n", charcode, gindex, buf ); charcode = FT_Get_Next_Char( face, charcode, &gindex ); } printf( "\n" ); } else if ( coverage == 1 ) { FT_ULong next, last = ~1; FT_UInt gindex; const char* f1 = ""; const char* f2 = " %04lx"; const char* f3 = ""; FT_Set_Charmap( face, face->charmaps[i] ); next = FT_Get_First_Char( face, &gindex ); while ( gindex ) { if ( next == last + 1 ) { f1 = f3; f3 = "-%04lx"; } else { printf( f1, last ); printf( f2, next ); f1 = ""; f2 = f3 = ",%04lx"; } last = next; next = FT_Get_Next_Char( face, last, &gindex ); } printf( f1, last ); printf( "\n" ); } } } static void Print_MM_Axes( FT_Face face ) { FT_MM_Var* mm; FT_Multi_Master dummy; FT_UInt is_GX, i, num_names; /* MM or GX axes */ error = FT_Get_Multi_Master( face, &dummy ); is_GX = error ? 1 : 0; printf( "%s axes\n", is_GX ? "GX" : "MM" ); error = FT_Get_MM_Var( face, &mm ); if ( error ) { printf( " Can't access axis data (error code %d)\n", error ); return; } num_names = FT_Get_Sfnt_Name_Count( face ); for ( i = 0; i < mm->num_axis; i++ ) { FT_SfntName name; name.string = NULL; if ( is_GX ) { FT_UInt strid = mm->axis[i].strid; FT_UInt j; /* iterate over all name entries */ /* to find an English entry for `strid' */ for ( j = 0; j < num_names; j++ ) { error = FT_Get_Sfnt_Name( face, j, &name ); if ( error ) continue; if ( name.name_id == strid ) { /* XXX we don't have support for Apple's new `ltag' table yet, */ /* thus we ignore TT_PLATFORM_APPLE_UNICODE */ if ( ( name.platform_id == TT_PLATFORM_MACINTOSH && name.language_id == TT_MAC_LANGID_ENGLISH ) || ( name.platform_id == TT_PLATFORM_MICROSOFT && ( name.language_id & 0xFF ) == TT_MS_LANGID_ENGLISH_GENERAL ) ) break; } } } if ( name.string ) { if ( name.platform_id == TT_PLATFORM_MACINTOSH ) put_ascii( name.string, name.string_len, 3 ); else put_unicode_be16( name.string, name.string_len, 3, utf8 ); } else printf( " %s", mm->axis[i].name ); printf( ": [%g;%g], default %g\n", mm->axis[i].minimum / 65536.0, mm->axis[i].maximum / 65536.0, mm->axis[i].def / 65536.0 ); } FT_Done_MM_Var( face->glyph->library, mm ); } static void Print_Bytecode( FT_Byte* buffer, FT_UShort length, const char* tag ) { FT_UShort i; int j = 0; /* status counter */ for ( i = 0; i < length; i++ ) { if ( ( i & 15 ) == 0 ) printf( "\n%s:%04hx ", tag, i ); if ( j == 0 ) { printf( " %02x", (FT_UInt)buffer[i] ); if ( buffer[i] == 0x40 ) j = -1; else if ( buffer[i] == 0x41 ) j = -2; else if ( 0xB0 <= buffer[i] && buffer[i] <= 0xB7 ) j = buffer[i] - 0xAF; else if ( 0xB8 <= buffer[i] && buffer[i] <= 0xBF ) j = 2 * ( buffer[i] - 0xB7 ); } else { printf( "_%02x", (FT_UInt)buffer[i] ); if ( j == -1 ) j = buffer[i]; else if ( j == -2 ) j = 2 * buffer[i]; else j--; } } printf( "\n" ); } static void Print_Programs( FT_Face face ) { FT_ULong length = 0; FT_UShort i; FT_Byte* buffer = NULL; FT_Byte* offset = NULL; TT_Header* head; TT_MaxProfile* maxp; error = FT_Load_Sfnt_Table( face, TTAG_fpgm, 0, NULL, &length ); if ( error || length == 0 ) goto Prep; buffer = (FT_Byte*)malloc( length ); if ( buffer == NULL ) goto Exit; error = FT_Load_Sfnt_Table( face, TTAG_fpgm, 0, buffer, &length ); if ( error ) goto Exit; printf( "font program" ); Print_Bytecode( buffer, (FT_UShort)length, "fpgm" ); Prep: length = 0; error = FT_Load_Sfnt_Table( face, TTAG_prep, 0, NULL, &length ); if ( error || length == 0 ) goto Glyf; buffer = (FT_Byte*)realloc( buffer, length ); if ( buffer == NULL ) goto Exit; error = FT_Load_Sfnt_Table( face, TTAG_prep, 0, buffer, &length ); if ( error ) goto Exit; printf( "\ncontrol value program" ); Print_Bytecode( buffer, (FT_UShort)length, "prep" ); Glyf: length = 0; error = FT_Load_Sfnt_Table( face, TTAG_glyf, 0, NULL, &length ); if ( error || length == 0 ) goto Exit; buffer = (FT_Byte*)realloc( buffer, length ); if ( buffer == NULL ) goto Exit; error = FT_Load_Sfnt_Table( face, TTAG_glyf, 0, buffer, &length ); if ( error ) goto Exit; length = 0; error = FT_Load_Sfnt_Table( face, TTAG_loca, 0, NULL, &length ); if ( error || length == 0 ) goto Exit; offset = (FT_Byte*)malloc( length ); if ( offset == NULL ) goto Exit; error = FT_Load_Sfnt_Table( face, TTAG_loca, 0, offset, &length ); if ( error ) goto Exit; head = (TT_Header*)FT_Get_Sfnt_Table( face, FT_SFNT_HEAD ); maxp = (TT_MaxProfile*)FT_Get_Sfnt_Table( face, FT_SFNT_MAXP ); for ( i = 0; i < maxp->numGlyphs; i++ ) { FT_UInt32 loc; FT_UInt16 len; char tag[5]; if ( head->Index_To_Loc_Format ) loc = (FT_UInt32)offset[4 * i ] << 24 | (FT_UInt32)offset[4 * i + 1] << 16 | (FT_UInt32)offset[4 * i + 2] << 8 | (FT_UInt32)offset[4 * i + 3]; else loc = (FT_UInt32)offset[2 * i ] << 9 | (FT_UInt32)offset[2 * i + 1] << 1; len = (FT_UInt16)( buffer[loc] << 8 | buffer[loc + 1] ); loc += 10; if ( (FT_Int16)len < 0 ) /* composite */ { FT_UShort flags; do { flags = (FT_UInt16)( buffer[loc] << 8 | buffer[loc + 1] ); loc += 4; loc += flags & FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS ? 4 : 2; loc += flags & FT_SUBGLYPH_FLAG_SCALE ? 2 : flags & FT_SUBGLYPH_FLAG_XY_SCALE ? 4 : flags & FT_SUBGLYPH_FLAG_2X2 ? 8 : 0; } while ( flags & 0x20 ); /* more components */ if ( ( flags & 0x100 ) == 0 ) continue; } else loc += 2 * len; len = (FT_UInt16)( buffer[loc] << 8 | buffer[loc + 1] ); if ( len == 0 ) continue; loc += 2; sprintf( tag, "%04hx", i ); printf("\nglyf program %hd (%.4s)", i, tag ); Print_Bytecode( buffer + loc, len, tag ); } Exit: free( buffer ); free( offset ); } int main( int argc, char* argv[] ) { int i, file; char filename[1024]; char alt_filename[1024]; char* execname; int num_faces; int option; FT_Library library; /* the FreeType library */ FT_Face face; /* the font face */ execname = ft_basename( argv[0] ); /* Initialize engine */ error = FT_Init_FreeType( &library ); if ( error ) PanicZ( library, "Could not initialize FreeType library" ); while ( 1 ) { option = getopt( argc, argv, "Ccnptuv" ); if ( option == -1 ) break; switch ( option ) { case 'C': coverage = 2; break; case 'c': coverage = 1; break; case 'n': name_tables = 1; break; case 'p': bytecode = 1; break; case 't': tables = 1; break; case 'u': utf8 = 1; break; case 'v': { FT_Int major, minor, patch; FT_Library_Version( library, &major, &minor, &patch ); printf( "ftdump (FreeType) %d.%d", major, minor ); if ( patch ) printf( ".%d", patch ); printf( "\n" ); exit( 0 ); } /* break; */ default: usage( library, execname ); break; } } argc -= optind; argv += optind; if ( argc != 1 ) usage( library, execname ); file = 0; strncpy( filename, argv[file], 1019 ); strncpy( alt_filename, argv[file], 1019 ); filename[1019] = '\0'; alt_filename[1019] = '\0'; /* try to load the file name as is, first */ error = FT_New_Face( library, argv[file], 0, &face ); if ( !error ) goto Success; #ifndef macintosh i = (int)strlen( argv[file] ); while ( i > 0 && argv[file][i] != '\\' && argv[file][i] != '/' ) { if ( argv[file][i] == '.' ) i = 0; i--; } if ( i >= 0 ) { strncpy( filename + strlen( filename ), ".ttf", 5 ); strncpy( alt_filename + strlen( alt_filename ), ".ttc", 5 ); } #endif /* Load face */ error = FT_New_Face( library, filename, 0, &face ); if ( error ) PanicZ( library, "Could not open face." ); Success: num_faces = face->num_faces; FT_Done_Face( face ); printf( "There %s %d %s in this file.\n", num_faces == 1 ? (char *)"is" : (char *)"are", num_faces, num_faces == 1 ? (char *)"face" : (char *)"faces" ); for ( i = 0; i < num_faces; i++ ) { error = FT_New_Face( library, filename, i, &face ); if ( error ) PanicZ( library, "Could not open face." ); printf( "\n----- Face number: %d -----\n\n", i ); Print_Name( face ); printf( "\n" ); Print_Type( face ); printf( " glyph count: %ld\n", face->num_glyphs ); if ( name_tables && FT_IS_SFNT( face ) ) { printf( "\n" ); Print_Sfnt_Names( face ); } if ( tables && FT_IS_SFNT( face ) ) { printf( "\n" ); Print_Sfnt_Tables( face ); } if ( bytecode && FT_IS_SFNT( face ) ) { printf( "\n" ); Print_Programs( face ); } if ( face->num_fixed_sizes ) { printf( "\n" ); Print_Fixed( face ); } if ( face->num_charmaps ) { printf( "\n" ); Print_Charmaps( face ); } if ( FT_HAS_MULTIPLE_MASTERS( face ) ) { printf( "\n" ); Print_MM_Axes( face ); } FT_Done_Face( face ); } FT_Done_FreeType( library ); exit( 0 ); /* for safety reasons */ /* return 0; */ /* never reached */ } /* End */ ft2demos-2.10.1/src/ftlint.c0000644000175000001440000001211513501434362015413 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality font engine */ /* */ /* Copyright (C) 1996-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* ftlint: a simple font tester. This program tries to load all the */ /* glyphs of a given font. */ /* */ /* NOTE: This is just a test program that is used to show off and */ /* debug the current engine. */ /* */ /****************************************************************************/ #include #include FT_FREETYPE_H #include #include #include #define xxTEST_PSNAMES static FT_Error error; static FT_Library library; static FT_Face face; static unsigned int num_glyphs; static int ptsize; static int Fail; static void Usage( char* name ) { printf( "ftlint: simple font tester -- part of the FreeType project\n" ); printf( "----------------------------------------------------------\n" ); printf( "\n" ); printf( "Usage: %s ppem fontname[.ttf|.ttc] [fontname2..]\n", name ); printf( "\n" ); exit( 1 ); } static void Panic( const char* message ) { fprintf( stderr, "%s\n error code = 0x%04x\n", message, error ); exit(1); } int main( int argc, char** argv ) { int i, file_index; unsigned int id; char filename[1024]; char alt_filename[1024]; char* execname; char* fname; execname = argv[0]; if ( argc < 3 ) Usage( execname ); if ( sscanf( argv[1], "%d", &ptsize ) != 1 ) Usage( execname ); error = FT_Init_FreeType( &library ); if (error) Panic( "Could not create library object" ); /* Now check all files */ for ( file_index = 2; file_index < argc; file_index++ ) { fname = argv[file_index]; /* try to open the file with no extra extension first */ error = FT_New_Face( library, fname, 0, &face ); if (!error) { printf( "%s: ", fname ); goto Success; } if ( error == FT_Err_Unknown_File_Format ) { printf( "unknown format\n" ); continue; } /* ok, we could not load the file, try to add an extension to */ /* its name if possible.. */ i = (int)strlen( fname ); while ( i > 0 && fname[i] != '\\' && fname[i] != '/' ) { if ( fname[i] == '.' ) i = 0; i--; } strncpy( filename, fname, 1019 ); strncpy( alt_filename, fname, 1019 ); filename[1019] = '\0'; alt_filename[1019] = '\0'; #ifndef macintosh if ( i >= 0 ) { strncpy( filename + strlen( filename ), ".ttf", 5 ); strncpy( alt_filename + strlen( alt_filename ), ".ttc", 5 ); } #endif i = (int)strlen( filename ); fname = filename; while ( i >= 0 ) #ifndef macintosh if ( filename[i] == '/' || filename[i] == '\\' ) #else if ( filename[i] == ':' ) #endif { fname = filename + i + 1; i = -1; } else i--; printf( "%s: ", fname ); /* Load face */ error = FT_New_Face( library, filename, 0, &face ); if (error) { if (error == FT_Err_Unknown_File_Format) printf( "unknown format\n" ); else printf( "could not find/open file (error: %d)\n", error ); continue; } if (error) Panic( "Could not open file" ); Success: num_glyphs = (unsigned int)face->num_glyphs; #ifdef TEST_PSNAMES { const char* ps_name = FT_Get_Postscript_Name( face ); printf( "[%s] ", ps_name ? ps_name : "." ); } #endif error = FT_Set_Char_Size( face, ptsize << 6, ptsize << 6, 72, 72 ); if (error) Panic( "Could not set character size" ); Fail = 0; { for ( id = 0; id < num_glyphs; id++ ) { error = FT_Load_Glyph( face, id, FT_LOAD_DEFAULT ); if (error) { if ( Fail < 10 ) printf( "glyph %4u: 0x%04x\n" , id, error ); Fail++; } } } if ( Fail == 0 ) printf( "OK.\n" ); else if ( Fail == 1 ) printf( "1 fail.\n" ); else printf( "%d fails.\n", Fail ); FT_Done_Face( face ); } FT_Done_FreeType(library); exit( 0 ); /* for safety reasons */ /* return 0; */ /* never reached */ } /* End */ ft2demos-2.10.1/src/mlgetopt.c0000644000175000001440000000706013501434362015751 0ustar00wlusers00000000000000/* * This is a cheap replacement for getopt() because that routine is not * available on some platforms and behaves differently on other platforms. * This code was written from scratch without looking at any other * implementation. * * This code is hereby expressly placed in the public domain. * mleisher@crl.nmsu.edu (Mark Leisher) * 10 October 1997 * * Last update 2019-06-10. */ #include "mlgetopt.h" #include #include #include #include #ifdef __STDC__ #define CONST const #else #define CONST #endif /* * Externals visible to programs. */ int opterr = 1; int optind = 1; char* optarg; /* * Internal variables that are used to detect when the global values * need to be reset. */ static int cmdac; static CONST char* cmdname; static char* CONST* cmdav; int #ifdef __STDC__ getopt( int ac, char* const* av, const char* pat ) #else getopt( ac, av, pat ) int ac; char** av; char* pat; #endif { int opt; CONST char* p; CONST char* pp; /* * If there is no pattern, indicate the parsing is done. */ if ( pat == 0 || *pat == 0 ) return -1; /* * Always reset the option argument to NULL. */ optarg = 0; /* * If the number of arguments or argument list do not match the last * values seen, reset the internal pointers and the globals. */ if ( ac != cmdac || av != cmdav ) { optind = 1; cmdac = ac; cmdav = av; /* * Determine the command name in case it is needed for warning * messages. */ for ( cmdname = 0, p = av[0]; *p; p++ ) { if ( *p == '/' || *p == '\\' ) cmdname = p; } /* * Skip the path separator if the name was assigned. */ if ( cmdname ) cmdname++; else cmdname = av[0]; } /* * If the next index is greater than or equal to the number of * arguments, then the command line is done. */ if ( optind >= ac ) return -1; /* * Test the next argument for one of three cases: * 1. The next argument does not have an initial '-'. * 2. The next argument is '-'. * 3. The next argument is '--'. * * In either of these cases, command line processing is done. */ if ( av[optind][0] != '-' || strcmp( av[optind], "-" ) == 0 || strcmp( av[optind], "--" ) == 0 ) return -1; /* * Point at the next command line argument and increment the * command line index. */ p = av[optind++]; /* * Look for the first character of the command line option. */ for ( opt = *(p + 1), pp = pat; *pp && *pp != opt; pp++ ) ; /* * If nothing in the pattern was recognized, then issue a warning * and return a '?'. */ if ( *pp == 0 ) { if ( opterr ) fprintf( stderr, "%s: invalid option -- %c\n", cmdname, opt ); return '?'; } /* * If the option expects an argument, get it. */ if ( *(pp + 1) == ':' && *(optarg = (char*)p + 2) == 0 && (optarg = av[optind++]) == 0 ) { /* * If the option argument is missing, issue a warning and return a '?'. */ if ( opterr ) fprintf( stderr, "%s: option requires an argument -- %c\n", cmdname, opt ); opt = '?'; } /* * Return the option character. */ return opt; } /* End */ ft2demos-2.10.1/src/ttdebug.c0000644000175000001440000025053113501434362015557 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 1996-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* */ /* ttdebug - a simple TrueType debugger for the console. */ /* */ /****************************************************************************/ #include #include #include #ifdef UNIX #ifndef HAVE_POSIX_TERMIOS #include #include #else /* HAVE_POSIX_TERMIOS */ #ifndef HAVE_TCGETATTR #define HAVE_TCGETATTR #endif #ifndef HAVE_TCSETATTR #define HAVE_TCSETATTR #endif #include #endif /* HAVE_POSIX_TERMIOS */ #endif /* UNIX */ /* Define the `getch()' function. On Unix systems, it is an alias */ /* for `getchar()', and the debugger front end must ensure that the */ /* `stdin' file descriptor is not in line-by-line input mode. */ #ifdef _WIN32 #include #define snprintf _snprintf #define getch _getch #else #define getch getchar #endif #include #include FT_FREETYPE_H #include FT_MULTIPLE_MASTERS_H #include "common.h" #include "mlgetopt.h" #include FT_DRIVER_H /* The following header shouldn't be used in normal programs. */ /* `freetype2/src/truetype' must be in the current include path. */ #include "ttobjs.h" #include "ttdriver.h" #include "ttinterp.h" #include "tterrors.h" #define Quit -1 #define Restart -2 static FT_Library library; /* root library object */ static FT_Memory memory; /* system object */ static FT_Driver driver; /* truetype driver */ static TT_Face face; /* truetype face */ static TT_Size size; /* truetype size */ static TT_GlyphSlot glyph; /* truetype glyph slot */ static FT_MM_Var *multimaster; static FT_Fixed* requested_pos; static unsigned int requested_cnt; static unsigned int tt_interpreter_versions[3]; static int num_tt_interpreter_versions; static unsigned int dflt_tt_interpreter_version; /* number formats */ static FT_Bool use_float = 0; /* for points */ static FT_Bool use_hex = 1; /* for integers (except points) */ static FT_Error error; typedef char ByteStr[2]; typedef char WordStr[4]; typedef char LongStr[8]; typedef char DebugStr[128]; static DebugStr tempStr; typedef struct Storage_ { FT_Bool initialized; FT_Long value; } Storage; typedef struct Breakpoint_ { FT_Long IP; FT_Int range; } Breakpoint; /* right now, we support a single breakpoint only */ static Breakpoint breakpoint; #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. */ /* 0x00 */ /* SVTCA[0] */ PACK( 0, 0 ), /* SVTCA[1] */ PACK( 0, 0 ), /* SPVTCA[0] */ PACK( 0, 0 ), /* SPVTCA[1] */ PACK( 0, 0 ), /* SFVTCA[0] */ PACK( 0, 0 ), /* SFVTCA[1] */ PACK( 0, 0 ), /* SPVTL[0] */ PACK( 2, 0 ), /* SPVTL[1] */ PACK( 2, 0 ), /* SFVTL[0] */ PACK( 2, 0 ), /* SFVTL[1] */ 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 ), /* 0x10 */ /* 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 ), /* 0x20 */ /* 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 ), /* 0x30 */ /* IUP[0] */ PACK( 0, 0 ), /* IUP[1] */ PACK( 0, 0 ), /* SHP[0] */ PACK( 0, 0 ), /* loops */ /* SHP[1] */ PACK( 0, 0 ), /* loops */ /* SHC[0] */ PACK( 1, 0 ), /* SHC[1] */ PACK( 1, 0 ), /* SHZ[0] */ PACK( 1, 0 ), /* SHZ[1] */ PACK( 1, 0 ), /* SHPIX */ PACK( 1, 0 ), /* loops */ /* IP */ PACK( 0, 0 ), /* loops */ /* MSIRP[0] */ PACK( 2, 0 ), /* MSIRP[1] */ PACK( 2, 0 ), /* ALIGNRP */ PACK( 0, 0 ), /* loops */ /* RTDG */ PACK( 0, 0 ), /* MIAP[0] */ PACK( 2, 0 ), /* MIAP[1] */ PACK( 2, 0 ), /* 0x40 */ /* 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 ), /* 0x50 */ /* 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 ), /* 0x60 */ /* 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 ), /* 0x70 */ /* 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 ), /* 0x80 */ /* FLIPPT */ PACK( 0, 0 ), /* loops */ /* FLIPRGON */ PACK( 2, 0 ), /* FLIPRGOFF */ PACK( 2, 0 ), /* INS_$83 */ PACK( 0, 0 ), /* INS_$84 */ PACK( 0, 0 ), /* SCANCTRL */ PACK( 1, 0 ), /* SDPVTL[0] */ PACK( 2, 0 ), /* SDPVTL[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 ), /* 0x90 */ /* INS_$90 */ PACK( 0, 0 ), /* GETVAR */ PACK( 0, 0 ), /* GETDATA */ PACK( 0, 1 ), /* 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 ), /* 0xA0 */ /* 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 ), /* 0xB0 */ /* 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 ), /* 0xC0 */ /* 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 ), /* 0xD0 */ /* 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 ), /* 0xE0 */ /* 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 ), /* 0xF0 */ /* 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_String* OpStr[256] = { /* 0x00 */ "SVTCA[y]", "SVTCA[x]", "SPVTCA[y]", "SPVTCA[x]", "SFVTCA[y]", "SFVTCA[x]", "SPVTL[||]", "SPVTL[+]", "SFVTL[||]", "SFVTL[+]", "SPVFS", "SFVFS", "GPV", "GFV", "SFVTPV", "ISECT", /* 0x10 */ "SRP0", "SRP1", "SRP2", "SZP0", "SZP1", "SZP2", "SZPS", "SLOOP", "RTG", "RTHG", "SMD", "ELSE", "JMPR", "SCVTCI", "SSWCI", "SSW", /* 0x20 */ "DUP", "POP", "CLEAR", "SWAP", "DEPTH", "CINDEX", "MINDEX", "ALIGNPTS", "INS_$28", "UTP", "LOOPCALL", "CALL", "FDEF", "ENDF", "MDAP[]", "MDAP[rnd]", /* 0x30 */ "IUP[y]", "IUP[x]", "SHP[rp2]", "SHP[rp1]", "SHC[rp2]", "SHC[rp1]", "SHZ[rp2]", "SHZ[rp1]", "SHPIX", "IP", "MSIRP[]", "MSIRP[rp0]", "ALIGNRP", "RTDG", "MIAP[]", "MIAP[rnd]", /* 0x40 */ "NPUSHB", "NPUSHW", "WS", "RS", "WCVTP", "RCVT", "GC[curr]", "GC[orig]", "SCFS", "MD[curr]", "MD[orig]", "MPPEM", "MPS", "FLIPON", "FLIPOFF", "DEBUG", /* 0x50 */ "LT", "LTEQ", "GT", "GTEQ", "EQ", "NEQ", "ODD", "EVEN", "IF", "EIF", "AND", "OR", "NOT", "DELTAP1", "SDB", "SDS", /* 0x60 */ "ADD", "SUB", "DIV", "MUL", "ABS", "NEG", "FLOOR", "CEILING", "ROUND[G]", "ROUND[B]", "ROUND[W]", "ROUND[]", "NROUND[G]", "NROUND[B]", "NROUND[W]", "NROUND[]", /* 0x70 */ "WCVTF", "DELTAP2", "DELTAP3", "DELTAC1", "DELTAC2", "DELTAC3", "SROUND", "S45ROUND", "JROT", "JROF", "ROFF", "INS_$7B", "RUTG", "RDTG", "SANGW", "AA", /* 0x80 */ "FLIPPT", "FLIPRGON", "FLIPRGOFF", "INS_$83", "INS_$84", "SCANCTRL", "SDPVTL[||]", "SDPVTL[+]", "GETINFO", "IDEF", "ROLL", "MAX", "MIN", "SCANTYPE", "INSTCTRL", "INS_$8F", /* 0x90 */ "INS_$90", "GETVARIATION", "GETDATA", "INS_$93", "INS_$94", "INS_$95", "INS_$96", "INS_$97", "INS_$98", "INS_$99", "INS_$9A", "INS_$9B", "INS_$9C", "INS_$9D", "INS_$9E", "INS_$9F", /* 0xA0 */ "INS_$A0", "INS_$A1", "INS_$A2", "INS_$A3", "INS_$A4", "INS_$A5", "INS_$A6", "INS_$A7", "INS_$A8", "INS_$A9", "INS_$AA", "INS_$AB", "INS_$AC", "INS_$AD", "INS_$AE", "INS_$AF", /* 0xB0 */ "PUSHB[0]", "PUSHB[1]", "PUSHB[2]", "PUSHB[3]", "PUSHB[4]", "PUSHB[5]", "PUSHB[6]", "PUSHB[7]", "PUSHW[0]", "PUSHW[1]", "PUSHW[2]", "PUSHW[3]", "PUSHW[4]", "PUSHW[5]", "PUSHW[6]", "PUSHW[7]", /* 0xC0 */ "MDRP[G]", "MDRP[B]", "MDRP[W]", "MDRP[]", "MDRP[rG]", "MDRP[rB]", "MDRP[rW]", "MDRP[r]", "MDRP[mG]", "MDRP[mB]", "MDRP[mW]", "MDRP[m]", "MDRP[mrG]", "MDRP[mrB]", "MDRP[mrW]", "MDRP[mr]", /* 0xD0 */ "MDRP[pG]", "MDRP[pB]", "MDRP[pW]", "MDRP[p]", "MDRP[prG]", "MDRP[prB]", "MDRP[prW]", "MDRP[pr]", "MDRP[pmG]", "MDRP[pmB]", "MDRP[pmW]", "MDRP[pm]", "MDRP[pmrG]", "MDRP[pmrB]", "MDRP[pmrW]", "MDRP[pmr]", /* 0xE0 */ "MIRP[G]", "MIRP[B]", "MIRP[W]", "MIRP[]", "MIRP[rG]", "MIRP[rB]", "MIRP[rW]", "MIRP[r]", "MIRP[mG]", "MIRP[mB]", "MIRP[mW]", "MIRP[m]", "MIRP[mrG]", "MIRP[mrB]", "MIRP[mrW]", "MIRP[mr]", /* 0xF0 */ "MIRP[pG]", "MIRP[pB]", "MIRP[pW]", "MIRP[p]", "MIRP[prG]", "MIRP[prB]", "MIRP[prW]", "MIRP[pr]", "MIRP[pmG]", "MIRP[pmB]", "MIRP[pmW]", "MIRP[pm]", "MIRP[pmrG]", "MIRP[pmrB]", "MIRP[pmrW]", "MIRP[pmr]" }; /* * structure of documentation string: * * explanation string * [... i3 i2 i1 (stream data) o1 o2 o3 ...] * * The `(stream data)' part represents the top of the stack; this means * that `i1' and `o1' are the top stack values before and after the * operation, respectively. A hyphen indicates that no data is popped (or * pushed). If no argument is either popped from or pushed to the stack, * the stack layout gets omitted. * * In the explanation, the short-hands `[FV]', `[PV]', and `[DPV] mean * `measured along the freedom vector', `measured along the projection * vector', `measured along the dual-projection vector', respectively. * `' indicates that the marked opcode obeys the loop counter. */ static const FT_String* OpStrDoc[256] = { /* 0x00 */ "Set all graphics state vectors to y axis.", "Set all graphics state vectors to x axis.", "Set projection and dual-projection vectors to y axis.", "Set projection and dual-projection vectors to x axis.", "Set freedom vector to y axis.", "Set freedom vector to x axis.", "Set projection and dual-projection vectors parallel to vector P1P2:\n" " p2 p1 (%s) -", "Set projection and dual-projection vectors perpendicular to vector P1P2:\n" " p2 p1 (%s) -", "Set freedom vector parallel to vector P1P2:\n" " p2 p1 (%s) -", "Set freedom vector perpendicular to vector P1P2:\n" " p2 p1 (%s) -", "Set projection and dual-projection vectors from vector (X,Y):\n" " x y (%s) -", "Set freedom vector from vector (X,Y):\n" " x y (%s) -", "Get projection vector (X,Y):\n" " - (%s) y x", "Get freedom vector (X,Y):\n" " - (%s) y x", "Set freedom vector to projection vector.", "Set point P to intersection of lines A0A1 and B0B1:\n" " p a0 a1 b0 b1 (%s) -", /* 0x10 */ "Set RP0 to P:\n" " p (%s) -", "Set RP1 to P:\n" " p (%s) -", "Set RP2 to P:\n" " p (%s) -", "Set ZP0 to zone N:\n" " n (%s) -", "Set ZP1 to zone N:\n" " n (%s) -", "Set ZP2 to zone N:\n" " n (%s) -", "Set all zone pointers to zone N:\n" " n (%s) -", "Set loop counter to N:\n" " n (%s) -", "Set rounding state to 'round to grid'.", "Set rounding state to 'round to half grid'.", "Set minimum distance to N:\n" " n (%s) -", "Mark start of block to be executed if previous IF instruction is false.", "Jump N bytes in instruction stream:\n" " n (%s) -", "Set CVT cut-in value to N:\n" " n (%s) -", "Set single-width cut-in to N:\n" " n (%s) -", "Set single width to N:\n" " n (%s) -", /* 0x20 */ "Duplicate top stack element E:\n" " e (%s) e e", "Pop top element E off the stack:\n" " e (%s) -", "Clear entire stack:\n" " ... (%s) -", "Swap top two elements E1 and E2 of the stack:\n" " e2 e1 (%s) e2 e1", "Return depth N of the stack:\n" " (%s) n", "Copy stack value EK to top of stack:\n" " ... ek ... e2 e1 k (%s) ek e1 e2 ... ek ...", "Move stack value EK to top of stack:\n" " ... ek ... e2 e1 k (%s) ek e1 e2 ... ek-1 ek+1 ...", "Move points P1 and P2 [FV] to their average distance [PV]:\n" " p2 p1 (%s) -", "Invalid opcode.", "Mark point P as untouched:\n" " p (%s) -", "Call N times the function with index I:\n" " n i (%s) -", "Call function with index I:\n" " i (%s) -", "Mark start of function definition with index I:\n" " i (%s) -", "Mark end of FDEF or IDEF.", "Set RP0=RP1=P:\n" " p (%s) -", "Measure [PV] and apply [FV] rounding state, then set RP0=RP1=P:\n" " p (%s) -", /* 0x30 */ "Interpolate untouched points between touched ones in the y direction.", "Interpolate untouched points between toucned ones in the x direction.", "Shift point P [FV] by distance (origin,current) [PV] of RP2 :\n" " p (%s) -", "Shift point P [FV] by distance (origin,current) [PV] of RP1 :\n" " p (%s) -", "Shift contour C [FV] by distance (origin,current) [PV] of RP2:\n" " c (%s) -", "Shift contour C [FV] by distance (origin,current) [PV] of RP1:\n" " c (%s) -", "Shift zone N [FV] by distance (origin,current) [PV] of RP2:\n" " n (%s) -", "Shift zone N [FV] by distance (origin,current) [PV] of RP1:\n" " n (%s) -", "Shift point P [FV] by N pixels :\n" " p n (%s) -", "Interpolate current position of point P between RP1 and RP2 [FV],\n" "preserving relative original distances [PV]:\n" " p (%s) -", "Make distance between points RP0 and P [FV] equal to D [PV],\n" "then set RP1=RP0, RP2=P:\n" " p d (%s) -", "Make distance between points RP0 and P [FV] equal to D [PV],\n" "then set RP1=RP0, RP2=P, RP0=P:\n" " p d (%s) -", "Move point P [FV] until distance to RP0 becomes zero [PV]:\n" " p (%s) -", "Set rounding state to 'round to double grid'.", "Move point P [FV] to CVT index I value [PV], then set RP0=RP1=P:\n" " p i (%s) -", "Move point P [FV] to CVT index I value [PV, cut-in, rounding state],\n" "then set RP0=RP1=P:\n" " p i (%s) -", /* 0x40 */ "Push N bytes to the stack:\n" " - (%s n b1 b2 ... bn) bn ... b2 b1", "Push N words to the stack:\n" " - (%s n w1 w2 ... wn) wn ... w2 w1", "Write X to storage area index I:\n" " i x (%s) -", "Read X from storage area index I:\n" " i (%s) x", "Write X to CVT index I in pixels:\n" " i x (%s) -", "Read X from CVT index I:\n" " i (%s) x", "Get point P's current position X [PV]:\n" " p (%s) x", "Get point P's original position X [DPV]:\n" " p (%s) x", "Move point P [FV] until distance becomes D [PV]:\n" " p d (%s) -", "Get current length D of vector P1P2 [PV]:\n" " p2 p1 (%s) d", "Get original length D of vector P1P2 [DPV]:\n" " p2 p1 (%s) d", "Get number of pixels per EM:\n" " - (%s) ppem", "Get current point size S:\n" " - (%s) s", "Set auto flip to true.", "Set auto flip to false.", "Instruction for debugging; not supported in FreeType.", /* 0x50 */ "Return B=1 if E1 < E2, B=0 otherwise:\n" " e1 e2 (%s) b", "Return B=1 if E1 <= E2, B=0 otherwise:\n" " e1 e2 (%s) b", "Return B=1 if E1 > E2, B=0 otherwise:\n" " e1 e2 (%s) b", "Return B=1 if E1 >= E2, B=0 otherwise:\n" " e1 e2 (%s) b", "Return B=1 if E1 == E2, B=0 otherwise:\n" " e1 e2 (%s) b", "Return B=1 if E1 != E2, B=0 otherwise:\n" " e1 e2 (%s) b", "Return B=1 if E is odd, B=0 otherwise:\n" " e (%s) b", "Return B=1 if E is even, B=0 otherwise:\n" " e (%s) b", "If value E is false, jump to next ELSE or EIF instruction:\n" " e (%s) -", "Mark end of an IF block.", "Return B=1 if both E1 and E2 are not zero, B=0 otherwise:\n" " e1 e2 (%s) b", "Return B=1 if either E1 or E2 is not zero, B=0 otherwise:\n" " e1 e2 (%s) b", "Return B=1 if E is zero, B=0 otherwise:\n" " e (%s) b", "Apply N delta exceptions ARG1 to ARGN [FV] for points P1 to PN\n" "(range [delta base;delta base+15]):\n" " ... arg2 p2 arg1 p1 n (%s) -", "Set delta base to N:\n" " n (%s) -", "Set delta shift to N:\n" " n (%s) -", /* 0x60 */ "Return C = A + B:\n" " a b (%s) c", "Return C = A - B:\n" " a b (%s) c", "Return C = A / B:\n" " a b (%s) c", "Return C = A * B:\n" " a b (%s) c", "Return C = |A|:\n" " a (%s) c", "Return C = -A:\n" " a (%s) c", "Return greatest integer value C which is <= A:\n" " a (%s) c", "Return least integer value C which is >= A:\n" " a (%s) c", "Pop A, perform engine correction for gray, apply rounding state,\n" "and push result as B:\n" " a (%s) b", "Pop A, perform engine correction for black, apply rounding state,\n" "and push result as B:\n" " a (%s) b", "Pop A, perform engine correction for white, apply rounding state,\n" "and push result as B:\n" " a (%s) b", "Pop A, apply rounding state, and push result as B:\n" " a (%s) b", "Pop A, perform engine correction for gray, and push result as B:\n" "a (%s) b", "Pop A, perform engine correction for black, and push result as B:\n" "a (%s) b", "Pop A, perform engine correction for white, and push result as B:\n" "a (%s) b", "This is a no-op.", /* 0x70 */ "Write X to CVT index I in font units:\n" " i x (%s) -", "Apply N delta exceptions ARG1 to ARGN [FV] for points P1 to PN\n" "(range [delta base+16;delta base+31]):\n" " ... arg2 p2 arg1 p1 n (%s) -", "Apply N delta exceptions ARG1 to ARGN [FV] for points P1 to PN\n" "(range [delta base+32;delta base+47]):\n" " ... arg2 p2 arg1 p1 n (%s) -", "Apply N delta exceptions ARG1 to ARGN for CVT values\n" "with indices C1 to CN (range [delta base;delta base+15]:\n" "... arg2 c2 arg1 c1 n (%s) -", "Apply N delta exceptions ARG1 to ARGN for CVT values\n" "with indices C1 to CN (range [delta base+16;delta base+31]):\n" "... arg2 c2 arg1 c1 n (%s) -", "Apply N delta exceptions ARG1 to ARGN for CVT values\n" "with indices C1 to CN (range [delta base+32;delta base+47]):\n" "... arg2 c2 arg1 c1 n (%s) -", "Set rounding state to 'super round to N':\n" " n (%s) -", "Set rounding state to 'super round 45 degrees to N':\n" " n (%s) -", "Jump N bytes in instruction stream if E is true:\n" " n e (%s) -", "Jump N bytes in instruction stream if E is false:\n" " n e (%s) -", "Set rounding state to 'no rounding'.", "Invalid opcode.", "Set rounding state to 'round up to grid'.", "Set rounding state to 'round down to grid'.", "Set angle weight (deprecated, unsupported):\n" " w (%s) -", "Adjust angle (deprecated, unsupported):\n" " a (%s) -", /* 0x80 */ "Flip on-off curve status of point P :\n" " p (%s) -", "Make off-curve points on-curve for index range [A;B]:\n" " a b (%s) -", "Make on-curve points off-curve for index range [A;B]:\n" " a b (%s) -", "Invalid opcode.", "Invalid opcode.", "Set scan control variable to N:\n" " n (%s) -", "Set dual projection vector parallel to vector P1P2:\n" " p2 p1 (%s) -", "Set dual projection vector perpendicular to vector P1P2:\n" " p2 p1 (%s) -", "For selector S, get value V describing rasterizer version\n" "or characteristics of current glyph:\n" " s (%s) v", "Mark start of instruction definition with opcode I:\n" " i (%s) -", "Roll top three stack elements A, B, and C:\n" " c b a (%s) c a b", "Return C=A if A > B, C=B otherwise:\n" " a b (%s) c", "Return C=A if A < B, C=B otherwise:\n" " a b (%s) c", "Make scan converter use rule N:\n" " n (%s) -", "Set selector S to value V in instruction control variable:\n" " v s (%s) -", "Invalid opcode.", /* 0x90 */ "Invalid opcode.", "For variation fonts, get normalized axes coordinates A1, A2, ..., AN:\n" " - (%s) an ... a2 a1", "Old opcode with unknown function, always returning number 17:\n" " - (%s) 17", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", /* 0xA0 */ "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", "Invalid opcode.", /* 0xB0 */ "Push one byte to the stack:\n" " - (%s b1) b1", "Push two bytes to the stack:\n" " - (%s b1 b2) b2 b1", "Push three bytes to the stack:\n" " - (%s b1 b2 b3) b3 b2 b1", "Push four bytes to the stack:\n" " - (%s b1 b3 b3 b4) b4 b3 b2 b1", "Push five bytes to the stack:\n" " - (%s b1 b2 b3 b4 b5) b5 b4 b3 b2 b1", "Push six bytes to the stack:\n" " - (%s b1 b2 b3 b4 b5 b6) b6 b5 b4 b3 b2 b1", "Push seven bytes to the stack:\n" " - (%s b1 b2 b3 b4 b5 b6 b7) b7 b6 b5 b4 b3 b2 b1", "Push eight bytes to the stack:\n" " - (%s b1 b2 b3 b4 b5 b6 b7 b8) b8 b7 b6 b5 b4 b3 b2 b1", "Push one word to the stack:\n" " - (%s w1) w1", "Push two words to the stack:\n" " - (%s w1 w2) w2 w1", "Push three words to the stack:\n" " - (%s w1 w2 w3) w3 w2 w1", "Push four words to the stack:\n" " - (%s w1 w2 w3 w4) w4 w3 w2 w1", "Push five words to the stack:\n" " - (%s w1 w2 w3 w4 w5) w5 w4 w3 w2 w1", "Push six words to the stack:\n" " - (%s w1 w2 w3 w4 w5 w6) w6 w5 w4 w3 w2 w1", "Push seven words to the stack:\n" " - (%s w1 w2 w3 w4 w5 w6 w7) w7 w6 w5 w4 w3 w2 w1", "Push eight words to the stack:\n" " - (%s w1 w2 w3 w4 w5 w6 w7 w8) w8 w7 w6 w5 w4 w3 w2 w1", /* 0xC0 */ "Make current distance between points RP0 and P [FV, gray] equal to\n" "original one [DPV], then set RP1=RP0, RP2=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, black] equal to\n" "original one [DPV], then set RP1=RP0, RP2=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, white] equal to\n" "original one [DPV], then set RP1=RP0, RP2=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV] equal to\n" "original one [DPV], then set RP1=RP0, RP2=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, gray] equal to\n" "original one [DPV, rounding state], then set RP1=RP0, RP2=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, black] equal to\n" "original one [DPV, rounding state], then set RP1=RP0, RP2=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, white] equal to\n" "original one [DPV, rounding state], then set RP1=RP0, RP2=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV] equal to\n" "original one [DPV, rounding state], then set RP1=RP0, RP2=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, gray] equal to\n" "original one [DPV, minimum distance], then set RP1=RP0, RP2=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, black] equal to\n" "original one [DPV, minimum distance], then set RP1=RP0, RP2=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, white] equal to\n" "original one [DPV, minimum distance], then set RP1=RP0, RP2=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV] equal to\n" "original one [DPV, minimum distance], then set RP1=RP0, RP2=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, gray] equal to\n" "original one [DPV, rounding state, minimum distance],\n" "then set RP1=RP0, RP2=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, black] equal to\n" "original one [DPV, rounding state, minimum distance],\n" "then set RP1=RP0, RP2=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, white] equal to\n" "original one [DPV, rounding state, minimum distance],\n" "then set RP1=RP0, RP2=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV] equal to\n" "original one [DPV, rounding state, minimum distance],\n" "then set RP1=RP0, RP2=P:\n" " p (%s) -", /* 0xD0 */ "Make current distance between points RP0 and P [FV, gray] equal to\n" "original one [DPV], then set RP1=RP0, RP2=P, RP0=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, black] equal to\n" "original one [DPV], then set RP1=RP0, RP2=P, RP0=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, white] equal to\n" "original one [DPV], then set RP1=RP0, RP2=P, RP0=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV] equal to\n" "original one [DPV], then set RP1=RP0, RP2=P, RP0=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, gray] equal to\n" "original one [DPV, rounding state], then set RP1=RP0, RP2=P, RP0=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, black] equal to\n" "original one [DPV, rounding state], then set RP1=RP0, RP2=P, RP0=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, white] equal to\n" "original one [DPV, rounding state], then set RP1=RP0, RP2=P, RP0=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV] equal to\n" "original one [DPV, rounding state], then set RP1=RP0, RP2=P, RP0=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, gray] equal to\n" "original one [DPV, minimum distance], then set RP1=RP0, RP2=P, RP0=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, black] equal to\n" "original one [DPV, minimum distance], then set RP1=RP0, RP2=P, RP0=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, white] equal to\n" "original one [DPV, minimum distance], then set RP1=RP0, RP2=P, RP0=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV] equal to\n" "original one [DPV, minimum distance], then set RP1=RP0, RP2=P, RP0=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, gray] equal to\n" "original one [DPV, rounding state, minimum distance],\n" "then set RP1=RP0, RP2=P, RP0=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, black] equal to\n" "original one [DPV, rounding state, minimum distance],\n" "then set RP1=RP0, RP2=P, RP0=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV, white] equal to\n" "original one [DPV, rounding state, minimum distance],\n" "then set RP1=RP0, RP2=P, RP0=P:\n" " p (%s) -", "Make current distance between points RP0 and P [FV] equal to\n" "original one [DPV, rounding state, minimum distance],\n" "then set RP1=RP0, RP2=P, RP0=P:\n" " p (%s) -", /* 0xE0 */ "Make current distance between points RP0 and P [FV, gray] equal to\n" "CVT index I value [DPV], then set RP1=RP0, RP2=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, black] equal to\n" "CVT index I value [DPV], then set RP1=RP0, RP2=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, white] equal to\n" "CVT index I value [DPV], then set RP1=RP0, RP2=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV] equal to\n" "CVT index I value [DPV], then set RP1=RP0, RP2=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, gray] equal to\n" "CVT index I value [DPV, cut-in, rounding state], then set RP1=RP0, RP2=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, black] equal to\n" "CVT index I value [DPV, cut-in, rounding state], then set RP1=RP0, RP2=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, white] equal to\n" "CVT index I value [DPV, cut-in, rounding state], then set RP1=RP0, RP2=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV] equal to\n" "CVT index I value [DPV, cut-in, rounding state], then set RP1=RP0, RP2=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, gray] equal to\n" "CVT index I value [DPV, minimum distance], then set RP1=RP0, RP2=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, black] equal to\n" "CVT index I value [DPV, minimum distance], then set RP1=RP0, RP2=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, white] equal to\n" "CVT index I value [DPV, minimum distance], then set RP1=RP0, RP2=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV] equal to\n" "CVT index I value [DPV, minimum distance], then set RP1=RP0, RP2=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, gray] equal to\n" "CVT index I value [DPV, cut-in, rounding state, minimum distance],\n" "then set RP1=RP0, RP2=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, black] equal to\n" "CVT index I value [DPV, cut-in, rounding state, minimum distance],\n" "then set RP1=RP0, RP2=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, white] equal to\n" "CVT index I value [DPV, cut-in, rounding state, minimum distance],\n" "then set RP1=RP0, RP2=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV] equal to\n" "CVT index I value [DPV, cut-in, rounding state, minimum distance],\n" "then set RP1=RP0, RP2=P:\n" " p i (%s) -", /* 0xF0 */ "Make current distance between points RP0 and P [FV, gray] equal to\n" "CVT index I value [DPV], then set RP1=RP0, RP2=P, RP0=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, black] equal to\n" "CVT index I value [DPV], then set RP1=RP0, RP2=P, RP0=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, white] equal to\n" "CVT index I value [DPV], then set RP1=RP0, RP2=P, RP0=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV] equal to\n" "CVT index I value [DPV], then set RP1=RP0, RP2=P, RP0=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, gray] equal to\n" "CVT index I value [DPV, cut-in, rounding state],\n" "then set RP1=RP0, RP2=P, RP0=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, black] equal to\n" "CVT index I value [DPV, cut-in, rounding state],\n" "then set RP1=RP0, RP2=P, RP0=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, white] equal to\n" "CVT index I value [DPV, cut-in, rounding state],\n" "then set RP1=RP0, RP2=P, RP0=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV] equal to\n" "CVT index I value [DPV, cut-in, rounding state],\n" "then set RP1=RP0, RP2=P, RP0=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, gray] equal to\n" "CVT index I value [DPV, minimum distance], then set RP1=RP0, RP2=P, RP0=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, black] equal to\n" "CVT index I value [DPV, minimum distance], then set RP1=RP0, RP2=P, RP0=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, white] equal to\n" "CVT index I value [DPV, minimum distance], then set RP1=RP0, RP2=P, RP0=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV] equal to\n" "CVT index I value [DPV, minimum distance], then set RP1=RP0, RP2=P, RP0=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, gray] equal to\n" "CVT index I value [DPV, cut-in, rounding state, minimum distance],\n" "then set RP1=RP0, RP2=P, RP0=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, black] equal to\n" "CVT index I value [DPV, cut-in, rounding state, minimum distance],\n" "then set RP1=RP0, RP2=P, RP0=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV, white] equal to\n" "CVT index I value [DPV, cut-in, rounding state, minimum distance],\n" "then set RP1=RP0, RP2=P, RP0=P:\n" " p i (%s) -", "Make current distance between points RP0 and P [FV] equal to\n" "CVT index I value [DPV, cut-in, rounding state, minimum distance],\n" "then set RP1=RP0, RP2=P, RP0=P:\n" " p i (%s) -" }; /********************************************************************* * * Init_Keyboard: Set the input file descriptor to char-by-char * mode on Unix. * *********************************************************************/ #ifdef UNIX static struct termios old_termio; static void Init_Keyboard( void ) { struct termios termio; #ifndef HAVE_TCGETATTR ioctl( 0, TCGETS, &old_termio ); #else tcgetattr( 0, &old_termio ); #endif termio = old_termio; #if 0 termio.c_lflag &= (tcflag_t)~( ICANON + ECHO + ECHOE + ECHOK + ECHONL + ECHOKE ); #else termio.c_lflag &= (tcflag_t)~( ICANON + ECHO + ECHOE + ECHOK + ECHONL ); #endif #ifndef HAVE_TCSETATTR ioctl( 0, TCSETS, &termio ); #else tcsetattr( 0, TCSANOW, &termio ); #endif } static void Reset_Keyboard( void ) { #ifndef HAVE_TCSETATTR ioctl( 0, TCSETS, &old_termio ); #else tcsetattr( 0, TCSANOW, &old_termio ); #endif } #else /* !UNIX */ static void Init_Keyboard( void ) { } static void Reset_Keyboard( void ) { } #endif /* !UNIX */ /* error messages */ #undef FTERRORS_H_ #define FT_ERROR_START_LIST { #define FT_ERRORDEF( e, v, s ) case v: str = s; break; #define FT_ERROR_END_LIST default: str = "unknown error"; } static void Abort( const char* message ) { const FT_String *str; switch( error ) #include FT_ERRORS_H fprintf( stderr, "%s\n error = 0x%04x, %s\n", message, error, str ); Reset_Keyboard(); exit( 1 ); } static void parse_design_coords( char* arg ) { unsigned int i; char* s; /* get number of coordinates; */ /* a group of non-whitespace characters is handled as one argument */ s = arg; for ( requested_cnt = 0; *s; requested_cnt++ ) { while ( isspace( *s ) ) s++; while ( *s && !isspace( *s ) ) s++; } requested_pos = (FT_Fixed*)malloc( sizeof ( FT_Fixed ) * requested_cnt ); s = arg; for ( i = 0; i < requested_cnt; i++ ) { requested_pos[i] = (FT_Fixed)( strtod( s, &s ) * 65536.0 ); /* skip until next whitespace in case of junk */ /* that `strtod' doesn't handle */ while ( *s && !isspace( *s ) ) s++; while ( isspace( *s ) ) s++; } } /****************************************************************** * * Function: Calc_Length * * Description: Compute the length in bytes of current opcode. * *****************************************************************/ #define CUR (*exc) static void Calc_Length( TT_ExecContext exc ) { CUR.opcode = CUR.code[CUR.IP]; switch ( CUR.opcode ) { case 0x40: if ( CUR.IP + 1 >= CUR.codeSize ) Abort( "code range overflow!" ); CUR.length = CUR.code[CUR.IP + 1] + 2; break; case 0x41: if ( CUR.IP + 1 >= CUR.codeSize ) Abort( "code range overflow!" ); CUR.length = CUR.code[CUR.IP + 1] * 2 + 2; break; case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7: CUR.length = CUR.opcode - 0xB0 + 2; break; case 0xB8: case 0xB9: case 0xBA: case 0xBB: case 0xBC: case 0xBD: case 0xBE: case 0xBF: CUR.length = ( CUR.opcode - 0xB8 ) * 2 + 3; break; default: CUR.length = 1; break; } /* make sure result is in range */ if ( CUR.IP + CUR.length > CUR.codeSize ) Abort( "code range overflow!" ); } /* Disassemble the current line. */ /* */ static const FT_String* Cur_U_Line( TT_ExecContext exc ) { FT_String s[32]; FT_Int op, i, n; op = CUR.code[CUR.IP]; sprintf( tempStr, "%s", OpStr[op] ); if ( op == 0x40 ) /* NPUSHB */ { n = CUR.code[CUR.IP + 1]; sprintf( s, "(%d)", n ); strncat( tempStr, s, 8 ); /* limit output */ if ( n > 20 ) n = 20; for ( i = 0; i < n; i++ ) { const FT_String* temp; temp = use_hex ? " $%02x" : " %d"; sprintf( s, temp, CUR.code[CUR.IP + i + 2] ); strncat( tempStr, s, 8 ); } } else if ( op == 0x41 ) /* NPUSHW */ { n = CUR.code[CUR.IP + 1]; sprintf( s, "(%d)", n ); strncat( tempStr, s, 8 ); /* limit output */ if ( n > 20 ) n = 20; for ( i = 0; i < n; i++ ) { if ( use_hex ) sprintf( s, " $%02x%02x", CUR.code[CUR.IP + i * 2 + 2], CUR.code[CUR.IP + i * 2 + 3] ); else { unsigned short temp; temp = (unsigned short)( ( CUR.code[CUR.IP + i * 2 + 2] << 8 ) + CUR.code[CUR.IP + i * 2 + 3] ); sprintf( s, " %d", (signed short)temp ); } strncat( tempStr, s, 8 ); } } else if ( ( op & 0xF8 ) == 0xB0 ) /* PUSHB */ { n = op - 0xB0; for ( i = 0; i <= n; i++ ) { const FT_String* temp; temp = use_hex ? " $%02x" : " %d"; sprintf( s, temp, CUR.code[CUR.IP + i + 1] ); strncat( tempStr, s, 8 ); } } else if ( ( op & 0xF8 ) == 0xB8 ) /* PUSHW */ { n = op - 0xB8; for ( i = 0; i <= n; i++ ) { if ( use_hex ) sprintf( s, " $%02x%02x", CUR.code[CUR.IP + i * 2 + 1], CUR.code[CUR.IP + i * 2 + 2] ); else { unsigned short temp; temp = (unsigned short)( ( CUR.code[CUR.IP + i * 2 + 1] << 8 ) + CUR.code[CUR.IP + i * 2 + 2] ); sprintf( s, " %d", (signed short)temp ); } strncat( tempStr, s, 8 ); } } else if ( op == 0x39 ) /* IP */ { sprintf( s, " rp1=%d, rp2=%d", CUR.GS.rp1, CUR.GS.rp2 ); strncat( tempStr, s, 31 ); } return (FT_String*)tempStr; } /* we have to track the `WS' opcode specially so that we are able */ /* to properly handle uninitialized storage area values */ static void handle_WS( TT_ExecContext exc, Storage* storage ) { if ( CUR.opcode == 0x42 && CUR.top >= 2 ) { FT_ULong idx = (FT_ULong)CUR.stack[CUR.top - 2]; FT_Long value = (FT_Long) CUR.stack[CUR.top - 1]; if ( idx < CUR.storeSize ) { storage[idx].initialized = 1; storage[idx].value = value; } } } static void display_changed_points( TT_GlyphZoneRec* prev, TT_GlyphZoneRec* curr, FT_Bool is_twilight ) { FT_Int A; for ( A = 0; A < curr->n_points; A++ ) { FT_Int diff = 0; if ( prev->org[A].x != curr->org[A].x ) diff |= 1; if ( prev->org[A].y != curr->org[A].y ) diff |= 2; if ( prev->cur[A].x != curr->cur[A].x ) diff |= 4; if ( prev->cur[A].y != curr->cur[A].y ) diff |= 8; if ( prev->tags[A] != curr->tags[A] ) diff |= 16; if ( diff ) { const FT_String* temp; printf( "%3d%s ", A, is_twilight ? "T" : " " ); printf( "%6ld,%6ld ", curr->orus[A].x, curr->orus[A].y ); if ( diff & 16 ) temp = "(%c%c%c)"; else temp = " %c%c%c "; printf( temp, prev->tags[A] & FT_CURVE_TAG_ON ? 'P' : 'C', prev->tags[A] & FT_CURVE_TAG_TOUCH_X ? 'X' : ' ', prev->tags[A] & FT_CURVE_TAG_TOUCH_Y ? 'Y' : ' ' ); if ( diff & 1 ) temp = use_float ? "(%8.2f)" : "(%8ld)"; else temp = use_float ? " %8.2f " : " %8ld "; if ( use_float ) printf( temp, prev->org[A].x / 64.0 ); else printf( temp, prev->org[A].x ); if ( diff & 2 ) temp = use_float ? "(%8.2f)" : "(%8ld)"; else temp = use_float ? " %8.2f " : " %8ld "; if ( use_float ) printf( temp, prev->org[A].y / 64.0 ); else printf( temp, prev->org[A].y ); if ( diff & 4 ) temp = use_float ? "(%8.2f)" : "(%8ld)"; else temp = use_float ? " %8.2f " : " %8ld "; if ( use_float ) printf( temp, prev->cur[A].x / 64.0 ); else printf( temp, prev->cur[A].x ); if ( diff & 8 ) temp = use_float ? "(%8.2f)" : "(%8ld)"; else temp = use_float ? " %8.2f " : " %8ld "; if ( use_float ) printf( temp, prev->cur[A].y / 64.0 ); else printf( temp, prev->cur[A].y ); printf( "\n" ); printf( " " ); if ( diff & 16 ) temp = "(%c%c%c)"; else temp = " "; printf( temp, curr->tags[A] & FT_CURVE_TAG_ON ? 'P' : 'C', curr->tags[A] & FT_CURVE_TAG_TOUCH_X ? 'X' : ' ', curr->tags[A] & FT_CURVE_TAG_TOUCH_Y ? 'Y' : ' ' ); if ( diff & 1 ) temp = use_float ? "[%8.2f]" : "[%8ld]"; else temp = " "; if ( use_float ) printf( temp, curr->org[A].x / 64.0 ); else printf( temp, curr->org[A].x ); if ( diff & 2 ) temp = use_float ? "[%8.2f]" : "[%8ld]"; else temp = " "; if ( use_float ) printf( temp, curr->org[A].y / 64.0 ); else printf( temp, curr->org[A].y ); if ( diff & 4 ) temp = use_float ? "[%8.2f]" : "[%8ld]"; else temp = " "; if ( use_float ) printf( temp, curr->cur[A].x / 64.0 ); else printf( temp, curr->cur[A].x ); if ( diff & 8 ) temp = use_float ? "[%8.2f]" : "[%8ld]"; else temp = " "; if ( use_float ) printf( temp, curr->cur[A].y / 64.0 ); else printf( temp, curr->cur[A].y ); printf( "\n" ); } } } static void show_points_table( TT_GlyphZoneRec* zone, const FT_String* code_range, int n_points, FT_Bool is_twilight ) { int A; if ( code_range[0] == 'g' ) { printf( "%s points\n" "\n", is_twilight ? "twilight" : "glyph" ); printf( " idx " "orig. unscaled " " orig. scaled " " current scaled " "tags\n" ); printf( "-----" "----------------" "--------------------" "--------------------" "----\n" ); } else printf( "Not yet in `glyf' program.\n" ); for ( A = 0; A < n_points; A++ ) { printf( "%3d%s ", A, is_twilight ? "T" : ( A >= n_points - 4 ) ? "F" : " " ); printf( "(%5ld,%5ld) - ", zone->orus[A].x, zone->orus[A].y ); if ( use_float ) { printf( "(%7.2f,%7.2f) - ", zone->org[A].x / 64.0, zone->org[A].y / 64.0 ); printf( "(%7.2f,%7.2f) - ", zone->cur[A].x / 64.0, zone->cur[A].y / 64.0 ); } else { printf( "(%7ld,%7ld) - ", zone->org[A].x, zone->org[A].y ); printf( "(%7ld,%7ld) - ", zone->cur[A].x, zone->cur[A].y ); } printf( "%c%c%c\n", zone->tags[A] & FT_CURVE_TAG_ON ? 'P' : 'C', zone->tags[A] & FT_CURVE_TAG_TOUCH_X ? 'X' : ' ', zone->tags[A] & FT_CURVE_TAG_TOUCH_Y ? 'Y' : ' ' ); } printf( "\n" ); } static FT_Error RunIns( TT_ExecContext exc ) { FT_Int key; FT_Bool really_leave; FT_String ch, oldch = '\0'; FT_Long last_IP = 0; FT_Int last_range = 0; TT_GlyphZoneRec pts; TT_GlyphZoneRec twilight; TT_GlyphZoneRec save_pts; TT_GlyphZoneRec save_twilight; FT_Long* save_cvt; Storage* storage; Storage* save_storage; const FT_String* code_range; const FT_String* round_str[8] = { "to half-grid", "to grid", "to double grid", "down to grid", "up to grid", "off", "super", "super 45" }; error = FT_Err_Ok; pts = CUR.pts; twilight = CUR.twilight; save_pts.n_points = pts.n_points; save_pts.n_contours = pts.n_contours; save_pts.org = (FT_Vector*)malloc( 2 * sizeof ( FT_F26Dot6 ) * save_pts.n_points ); save_pts.cur = (FT_Vector*)malloc( 2 * sizeof ( FT_F26Dot6 ) * save_pts.n_points ); save_pts.tags = (FT_Byte*)malloc( save_pts.n_points ); save_twilight.n_points = twilight.n_points; save_twilight.n_contours = twilight.n_contours; save_twilight.org = (FT_Vector*)malloc( 2 * sizeof ( FT_F26Dot6 ) * save_twilight.n_points ); save_twilight.cur = (FT_Vector*)malloc( 2 * sizeof ( FT_F26Dot6 ) * save_twilight.n_points ); save_twilight.tags = (FT_Byte*)malloc( save_twilight.n_points ); save_cvt = (FT_Long*)malloc( sizeof ( FT_Long ) * CUR.cvtSize ); /* set everything to zero in Storage Area */ storage = (Storage*)calloc( CUR.storeSize, sizeof ( Storage ) ); save_storage = (Storage*)calloc( CUR.storeSize, sizeof ( Storage ) ); CUR.instruction_trap = 1; switch ( CUR.curRange ) { case tt_coderange_glyph: code_range = "glyf"; break; case tt_coderange_cvt: code_range = "prep"; break; default: code_range = "fpgm"; } printf( "Entering `%s' table.\n" "\n", code_range ); really_leave = 0; do { if ( CUR.IP < CUR.codeSize ) { Calc_Length( exc ); 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. */ /* Print the current line. We use an 80-columns console with the */ /* following formatting: */ /* */ /* [loc]:[addr] [opcode] [disassembly] [a][b]|[c][d] */ { char temp[90]; int n, col, pop; int args; sprintf( temp, "%78c\n", ' ' ); /* first letter of location */ switch ( CUR.curRange ) { case tt_coderange_glyph: temp[0] = 'g'; break; case tt_coderange_cvt: temp[0] = 'c'; break; default: temp[0] = 'f'; } /* current IP */ sprintf( temp + 1, "%04lx: %02x %-36.36s", CUR.IP, CUR.opcode, Cur_U_Line( &CUR ) ); strncpy( temp + 46, " (", 3 ); args = CUR.top - 1; pop = Pop_Push_Count[CUR.opcode] >> 4; col = 48; /* special case for IP */ if ( CUR.opcode == 0x39 ) pop = CUR.GS.loop; for ( n = 6; n > 0; n-- ) { int num_chars; if ( pop == 0 ) temp[col - 1] = temp[col - 1] == '(' ? ' ' : ')'; if ( args >= 0 ) { long val = (signed long)CUR.stack[args]; if ( use_hex ) { /* we display signed hexadecimal numbers, which */ /* is easier to read and needs less space */ num_chars = sprintf( temp + col, "%s%04lx", val < 0 ? "-" : "", val < 0 ? -val : val ); } else num_chars = sprintf( temp + col, "%ld", val ); if ( col + num_chars >= 78 ) break; } else num_chars = 0; temp[col + num_chars] = ' '; col += num_chars + 1; pop--; args--; } for ( n = col; n < 78; n++ ) temp[n] = ' '; temp[78] = '\n'; temp[79] = '\0'; printf( "%s", temp ); } /* First, check for empty stack and overflow */ if ( CUR.args < 0 ) { error = FT_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 'case'. */ if ( CUR.new_top > CUR.stackSize ) { error = FT_ERR( Stack_Overflow ); goto LErrorLabel_; } } else { if ( CUR.curRange == tt_coderange_glyph ) { if ( !really_leave ) { printf( "End of `glyf' program reached.\n" ); really_leave = 1; } else { really_leave = 0; goto LErrorLabel_; } } else { printf( "\n" ); goto LErrorLabel_; } } if ( breakpoint.IP == CUR.IP && breakpoint.range == CUR.curRange ) printf( "Hit breakpoint.\n" ); key = 0; do { /* read keyboard */ ch = (FT_String)getch(); switch ( ch ) { /* Help - show keybindings */ case '?': case 'h': printf( "ttdebug Help\n" "\n" "Q quit debugger V show vector info\n" "R restart debugger G show graphics state\n" "c continue to next code range P show points zone\n" "n skip to next instruction T show twilight zone\n" "s step into function S show storage area\n" "f finish current function C show CVT data\n" "l show last bytecode instruction K show full stack\n" "b toggle breakpoint at curr. pos. B show backtrace\n" "p toggle breakpoint at prev. pos. O show opcode docstring\n" "F toggle floating/fixed point format\n" "I toggle hex/decimal integer format H show format help\n" "\n" ); break; case 'H': printf( "Format of value changes:\n" "\n" " idx orus.x orus.y tags org.x org.y cur.x cur.y\n" "\n" " The first line gives the values before the instruction,\n" " the second line the changes after the instruction,\n" " indicated by parentheses and brackets for emphasis.\n" "\n" " `T', `F', `S', `s', or `C' appended to the index indicates\n" " a twilight point, a phantom point, a storage location,\n" " a stack value, or data from the Control Value Table (CVT),\n" " respectively.\n" "\n" " Possible tag values are `P' (on curve), `C' (control point),\n" " `X' (touched horizontally), and `Y' (touched vertically).\n" "\n" "Format of opcode help:\n" "\n" " explanation string[: ... i3 i2 i1 (stream data) o1 o2 o3 ...]\n" "\n" " The `(stream data)' part represents the top of the stack;\n" " this means that `i1' and `o1' are the top stack values\n" " before and after the operation, respectively.\n" " A hyphen indicates that no data is popped (or pushed).\n" " If no argument is either popped from or pushed to the stack,\n" " the colon and the following part gets omitted\n" " (and a full stop is printed instead).\n" "\n" " `[FV]', `[PV]', and `[DPV]' mean `measured along the\n" " freedom vector', `measured along the projection vector', and\n" " `measured along the dual-projection vector', respectively.\n" " `' indicates that the opcode obeys the loop counter.\n" "\n" ); break; /* Toggle between floating and fixed point format */ case 'F': use_float = !use_float; printf( "Use %s point format for displaying non-integer values.\n", use_float ? "floating" : "fixed" ); printf( "\n" ); break; /* Toggle between decimal and hexadimal integer format */ case 'I': use_hex = !use_hex; printf( "Use %s format for displaying integers.\n", use_hex ? "hexadecimal" : "decimal" ); printf( "\n" ); break; /* Show vectors */ case 'V': if ( use_float ) { /* 2.14 numbers */ printf( "freedom (%.5f, %.5f)\n", CUR.GS.freeVector.x / 16384.0, CUR.GS.freeVector.y / 16384.0 ); printf( "projection (%.5f, %.5f)\n", CUR.GS.projVector.x / 16384.0, CUR.GS.projVector.y / 16384.0 ); printf( "dual (%.5f, %.5f)\n", CUR.GS.dualVector.x / 16384.0, CUR.GS.dualVector.y / 16384.0 ); printf( "\n" ); } else { printf( "freedom ($%04hx, $%04hx)\n", CUR.GS.freeVector.x, CUR.GS.freeVector.y ); printf( "projection ($%04hx, $%04hx)\n", CUR.GS.projVector.x, CUR.GS.projVector.y ); printf( "dual ($%04hx, $%04hx)\n", CUR.GS.dualVector.x, CUR.GS.dualVector.y ); printf( "\n" ); } break; /* Show graphics state */ case 'G': { int version; /* this doesn't really belong to the graphics state, */ /* but I consider it a good place to show */ FT_Property_Get( library, "truetype", "interpreter-version", &version ); printf( "hinting engine version: %d\n" "\n", version ); } printf( "rounding state %s\n", round_str[CUR.GS.round_state] ); if ( use_float ) { /* 26.6 numbers */ printf( "minimum distance %.2f\n", CUR.GS.minimum_distance / 64.0 ); printf( "CVT cut-in %.2f\n", CUR.GS.control_value_cutin / 64.0 ); } else { printf( "minimum distance $%04lx\n", CUR.GS.minimum_distance ); printf( "CVT cut-in $%04lx\n", CUR.GS.control_value_cutin ); } printf( "ref. points 0,1,2 %d, %d, %d\n", CUR.GS.rp0, CUR.GS.rp1, CUR.GS.rp2 ); printf( "\n" ); break; /* Show CVT */ case 'C': { if ( code_range[0] == 'f' ) printf( "Not yet in `prep' or `glyf' program.\n" ); else { FT_ULong i; printf( "Control Value Table (CVT) data\n" "\n" ); printf( " idx value \n" "-------------------------\n" ); for ( i = 0; i < CUR.cvtSize; i++ ) printf( "%3ldC %8ld (%8.2f)\n", i, CUR.cvt[i], CUR.cvt[i] / 64.0 ); printf( "\n" ); } } break; /* Show Storage Area */ case 'S': { if ( code_range[0] == 'f' ) printf( "Not yet in `prep' or `glyf' program.\n" ); else { FT_ULong i; printf( "Storage Area\n" "\n" ); printf( " idx value \n" "-------------------------\n" ); for ( i = 0; i < CUR.storeSize; i++ ) { if ( storage[i].initialized ) printf( "%3ldS %8ld (%8.2f)\n", i, storage[i].value, storage[i].value / 64.0 ); else printf( "%3ldS \n", i ); } printf( "\n" ); } } break; /* Show full stack */ case 'K': { int args = CUR.top - 1; if ( args >= 0 ) { printf( "Stack\n" "\n" ); printf( " idx value \n" "-------------------------\n" ); for ( ; args >= 0; args-- ) { long val = (signed long)CUR.stack[args]; printf( "%3lds %8ld (%8.2f)\n", CUR.top - args, val, val / 64.0 ); } printf( "\n" ); } else printf( "Stack empty.\n" ); } break; /* Show glyph points table */ case 'P': show_points_table( &pts, code_range, pts.n_points, 0 ); break; /* Show twilight points table */ case 'T': show_points_table( &twilight, code_range, twilight.n_points, 1 ); break; /* Show backtrace */ case 'B': if ( CUR.callTop <= 0 ) printf( "At top level.\n" ); else { FT_Int i; printf( "Function call backtrace\n" "\n" ); printf( " idx loopcount start end caller\n" "----------------------------------------\n" ); for ( i = CUR.callTop; i > 0; i-- ) { TT_CallRec *rec = &CUR.callStack[i - 1]; printf( " %3d %4ld f%04lx f%04lx %c%04lx\n", rec->Def->opc, rec->Cur_Count, rec->Def->start, rec->Def->end, rec->Caller_Range == tt_coderange_font ? 'f' : ( rec->Caller_Range == tt_coderange_cvt ? 'c' : 'g' ), rec->Caller_IP - 1 ); } printf( "\n" ); } break; /* Show opcode help string */ case 'O': { FT_Int op = CUR.code[CUR.IP]; printf( OpStrDoc[op], OpStr[op] ); printf( "\n" ); } break; default: key = 1; } } while ( !key ); if ( pts.n_points ) { FT_MEM_COPY( save_pts.org, pts.org, pts.n_points * sizeof ( FT_Vector ) ); FT_MEM_COPY( save_pts.cur, pts.cur, pts.n_points * sizeof ( FT_Vector ) ); FT_MEM_COPY( save_pts.tags, pts.tags, pts.n_points ); } if ( twilight.n_points ) { FT_MEM_COPY( save_twilight.org, twilight.org, twilight.n_points * sizeof ( FT_Vector ) ); FT_MEM_COPY( save_twilight.cur, twilight.cur, twilight.n_points * sizeof ( FT_Vector ) ); FT_MEM_COPY( save_twilight.tags, twilight.tags, twilight.n_points ); } if ( CUR.cvtSize ) FT_MEM_COPY( save_cvt, CUR.cvt, CUR.cvtSize * sizeof ( FT_Long ) ); if ( CUR.storeSize ) FT_MEM_COPY( save_storage, storage, CUR.storeSize * sizeof ( Storage ) ); /* a return indicates the last command */ if ( ch == '\r' || ch == '\n' ) ch = oldch; switch ( ch ) { /* quit debugger */ case 'Q': /* without the pedantic hinting flag, */ /* FreeType ignores bytecode errors in `glyf' programs */ CUR.pedantic_hinting = 1; error = Quit; goto LErrorLabel_; /* restart debugger */ case 'R': /* without the pedantic hinting flag, */ /* FreeType ignores bytecode errors in `glyf' programs */ CUR.pedantic_hinting = 1; error = Restart; goto LErrorLabel_; /* continue */ case 'c': if ( CUR.IP < CUR.codeSize ) { last_IP = CUR.IP; last_range = CUR.curRange; /* loop execution until we reach end of current code range */ /* or hit the breakpoint's position */ while ( CUR.IP < CUR.codeSize ) { handle_WS( exc, storage ); if ( ( error = TT_RunIns( exc ) ) != 0 ) goto LErrorLabel_; if ( CUR.IP == breakpoint.IP && CUR.curRange == breakpoint.range ) break; } } break; /* finish current function or hit breakpoint */ case 'f': oldch = ch; if ( CUR.IP < CUR.codeSize ) { if ( code_range[0] == 'f' ) { printf( "Not yet in `prep' or `glyf' program.\n" ); break; } if ( CUR.curRange != tt_coderange_font ) { printf( "Not in a function.\n" ); break; } last_IP = CUR.IP; last_range = CUR.curRange; while ( 1 ) { Calc_Length( exc ); /* this updates CUR.opcode also */ /* we are done if we see the current function's ENDF opcode */ if ( CUR.opcode == 0x2d ) goto Step_into; if ( CUR.opcode == 0x2a || CUR.opcode == 0x2b ) { FT_Long next_IP; /* loop execution until we reach the next opcode */ next_IP = CUR.IP + CUR.length; while ( CUR.IP != next_IP ) { handle_WS( exc, storage ); if ( ( error = TT_RunIns( exc ) ) != 0 ) goto LErrorLabel_; if ( CUR.IP == breakpoint.IP && CUR.curRange == breakpoint.range ) break; } printf( "\n" ); } else { handle_WS( exc, storage ); if ( ( error = TT_RunIns( exc ) ) != 0 ) goto LErrorLabel_; } if ( CUR.IP == breakpoint.IP && CUR.curRange == breakpoint.range ) break; } } break; /* step over or hit breakpoint */ case 'n': if ( CUR.IP < CUR.codeSize ) { FT_Long next_IP; FT_Int saved_range; /* `step over' is equivalent to `step into' except if */ /* the current opcode is a CALL or LOOPCALL */ if ( CUR.opcode != 0x2a && CUR.opcode != 0x2b ) goto Step_into; last_IP = CUR.IP; last_range = CUR.curRange; /* otherwise, loop execution until we reach the next opcode */ saved_range = CUR.curRange; next_IP = CUR.IP + CUR.length; while ( !( CUR.IP == next_IP && CUR.curRange == saved_range ) ) { handle_WS( exc, storage ); if ( ( error = TT_RunIns( exc ) ) != 0 ) goto LErrorLabel_; if ( CUR.IP == breakpoint.IP && CUR.curRange == breakpoint.range ) break; } } oldch = ch; break; /* step into */ case 's': if ( CUR.IP < CUR.codeSize ) { Step_into: last_IP = CUR.IP; last_range = CUR.curRange; handle_WS( exc, storage ); if ( ( error = TT_RunIns( exc ) ) != 0 ) goto LErrorLabel_; } oldch = ch; break; /* toggle breakpoint at current position */ case 'b': if ( breakpoint.IP == CUR.IP && breakpoint.range == CUR.curRange ) { breakpoint.IP = 0; breakpoint.range = 0; printf( "Breakpoint removed.\n" ); } else { breakpoint.IP = CUR.IP; breakpoint.range = CUR.curRange; printf( "Breakpoint set.\n" ); } oldch = ch; break; /* toggle breakpoint at previous position */ case 'p': if ( last_IP == 0 && last_range == 0 ) printf( "No previous position yet to set breakpoint.\n" ); else { if ( breakpoint.IP == last_IP && breakpoint.range == last_range ) { breakpoint.IP = 0; breakpoint.range = 0; printf( "Breakpoint removed from previous position.\n" ); } else { breakpoint.IP = last_IP; breakpoint.range = last_range; printf( "Breakpoint set to previous position (%c%04lx).\n", last_range == tt_coderange_font ? 'f' : ( last_range == tt_coderange_cvt ? 'c' : 'g' ), last_IP ); } } oldch = ch; break; /* show last bytecode instruction */ case 'l': oldch = ch; break; default: printf( "Unknown command. Press ? or h for help.\n" ); oldch = '\0'; break; } display_changed_points(&save_pts, &pts, 0); display_changed_points(&save_twilight, &twilight, 1); { FT_ULong i; for ( i = 0; i < CUR.cvtSize; i++ ) if ( save_cvt[i] != CUR.cvt[i] ) { printf( "%3ldC %8ld (%8.2f)\n", i, save_cvt[i], save_cvt[i] / 64.0 ); printf( " %8ld (%8.2f)\n", CUR.cvt[i], CUR.cvt[i] / 64.0 ); } for ( i = 0; i < CUR.storeSize; i++ ) if ( save_storage[i].initialized != storage[i].initialized || save_storage[i].value != storage[i].value ) { printf( "%3ldS %8ld (%8.2f)\n", i, save_storage[i].value, save_storage[i].value / 64.0 ); printf( " %8ld (%8.2f)\n", storage[i].value, storage[i].value / 64.0 ); } } } while ( 1 ); LErrorLabel_: free( save_pts.org ); free( save_pts.cur ); free( save_pts.tags ); free( save_twilight.org ); free( save_twilight.cur ); free( save_twilight.tags ); free( save_cvt ); free( storage ); free( save_storage ); if ( error && error != Quit && error != Restart ) Abort( "error during execution" ); return error; } static void Usage( char* execname ) { char versions[32]; /* we expect that at least one interpreter version is available */ if ( num_tt_interpreter_versions == 2 ) sprintf(versions, "%d and %d", tt_interpreter_versions[0], tt_interpreter_versions[1] ); else sprintf(versions, "%d, %d, and %d", tt_interpreter_versions[0], tt_interpreter_versions[1], tt_interpreter_versions[2] ); fprintf( stderr, "\n" "ttdebug: simple TTF debugger -- part of the FreeType project\n" "------------------------------------------------------------\n" "\n" ); fprintf( stderr, "Usage: %s [options] idx size font\n" "\n", execname ); fprintf( stderr, " idx The index of the glyph to debug.\n" " size The size of the glyph in pixels (ppem).\n" " font The TrueType font file to debug.\n" "\n" " -I ver Use TrueType interpreter version VER.\n" " Available versions are %s; default is version %d.\n" " -f idx Access font IDX if input file is a TTC (default: 0).\n" " -d \"axis1 axis2 ...\"\n" " Specify the design coordinates for each variation axis\n" " at start-up (ignored if not a variation font).\n" " -v Show version.\n" "\n" "While running, press the `?' key for help.\n" "\n", versions, dflt_tt_interpreter_version ); exit( 1 ); } static char* file_name; static unsigned int glyph_index; static int glyph_size; int main( int argc, char** argv ) { char* execname; int option; char version_string[64]; int i; unsigned int versions[3] = { TT_INTERPRETER_VERSION_35, TT_INTERPRETER_VERSION_38, TT_INTERPRETER_VERSION_40 }; int version; int face_index = 0; int tmp; /* init library, read face object, get driver, create size */ error = FT_Init_FreeType( &library ); if ( error ) Abort( "could not initialize FreeType library" ); memory = library->memory; driver = (FT_Driver)FT_Get_Module( library, "truetype" ); if ( !driver ) Abort( "could not find the TrueType driver in FreeType 2\n" ); { FT_Int major, minor, patch; int offset; FT_Library_Version( library, &major, &minor, &patch ); offset = snprintf( version_string, 64, "ttdebug (FreeType) %d.%d", major, minor ); if ( patch ) offset = snprintf( version_string + offset, (size_t)( 64 - offset ), ".%d", patch ); } /* collect all available versions, then set again the default */ FT_Property_Get( library, "truetype", "interpreter-version", &dflt_tt_interpreter_version ); for ( i = 0; i < 3; i++ ) { error = FT_Property_Set( library, "truetype", "interpreter-version", &versions[i] ); if ( !error ) tt_interpreter_versions[num_tt_interpreter_versions++] = versions[i]; } FT_Property_Set( library, "truetype", "interpreter-version", &dflt_tt_interpreter_version ); execname = ft_basename( argv[0] ); while ( 1 ) { option = getopt( argc, argv, "I:d:f:v" ); if ( option == -1 ) break; switch ( option ) { case 'I': version = atoi( optarg ); if ( version < 0 ) { printf( "invalid TrueType interpreter version = %d\n", version ); Usage( execname ); } for ( i = 0; i < num_tt_interpreter_versions; i++ ) { if ( (unsigned int)version == tt_interpreter_versions[i] ) { FT_Property_Set( library, "truetype", "interpreter-version", &version ); break; } } if ( i == num_tt_interpreter_versions ) { printf( "invalid TrueType interpreter version = %d\n", version ); Usage( execname ); } break; case 'd': parse_design_coords( optarg ); break; case 'f': face_index = atoi( optarg ); break; case 'v': printf( "%s\n", version_string ); exit( 0 ); /* break; */ default: Usage( execname ); break; } } argc -= optind; argv += optind; if ( argc < 3 ) Usage( execname ); /* get glyph index */ if ( sscanf( argv[0], "%d", &tmp ) != 1 || tmp < 0 ) { printf( "invalid glyph index = %s\n", argv[1] ); Usage( execname ); } glyph_index = (unsigned int)tmp; /* get glyph size */ if ( sscanf( argv[1], "%d", &glyph_size ) != 1 || glyph_size < 0 ) { printf( "invalid glyph size = %s\n", argv[1] ); Usage( execname ); } /* get file name */ file_name = argv[2]; Init_Keyboard(); FT_Set_Debug_Hook( library, FT_DEBUG_HOOK_TRUETYPE, (FT_DebugHook_Func)RunIns ); printf( "%s\n" "press key `h' or `?' for help\n" "\n", version_string ); while ( !error ) { error = FT_New_Face( library, file_name, face_index, (FT_Face*)&face ); if ( error ) Abort( "could not open input font file" ); /* find driver and check format */ if ( face->root.driver != driver ) { error = FT_Err_Invalid_File_Format; Abort( "this is not a TrueType font" ); } FT_Done_MM_Var( library, multimaster ); error = FT_Get_MM_Var( (FT_Face)face, &multimaster ); if ( error ) multimaster = NULL; else { unsigned int n; if ( requested_cnt > multimaster->num_axis ) requested_cnt = multimaster->num_axis; for ( n = 0; n < requested_cnt; n++ ) { if ( requested_pos[n] < multimaster->axis[n].minimum ) requested_pos[n] = multimaster->axis[n].minimum; else if ( requested_pos[n] > multimaster->axis[n].maximum ) requested_pos[n] = multimaster->axis[n].maximum; } FT_Set_Var_Design_Coordinates( (FT_Face)face, requested_cnt, requested_pos ); } size = (TT_Size)face->root.size; error = FT_Set_Char_Size( (FT_Face)face, glyph_size << 6, glyph_size << 6, 72, 72 ); if ( error ) Abort( "could not set character size" ); glyph = (TT_GlyphSlot)face->root.glyph; /* now load glyph */ error = FT_Load_Glyph( (FT_Face)face, (FT_UInt)glyph_index, FT_LOAD_NO_BITMAP ); if ( error && error != Quit && error != Restart ) Abort( "could not load glyph" ); if ( error == Restart ) error = FT_Err_Ok; FT_Done_Face( (FT_Face)face ); } Reset_Keyboard(); FT_Done_FreeType( library ); free( requested_pos ); return 0; } /* End */ ft2demos-2.10.1/src/ftdiff.c0000644000175000001440000013555413501472654015400 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 2007-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* */ /* FTDiff - a simple viewer to compare different hinting modes. */ /* */ /* Press ? when running this program to have a list of key-bindings. */ /* */ /****************************************************************************/ #include "ftcommon.h" #include "common.h" #include "mlgetopt.h" #include FT_OUTLINE_H #include FT_LCD_FILTER_H #include FT_DRIVER_H /* showing driver name -- the two internal header files */ /* shouldn't be used in normal programs */ #include FT_MODULE_H #include FT_INTERNAL_OBJECTS_H #include FT_INTERNAL_DRIVER_H #include #include #include #include static void usage( char* execname ) { fprintf( stderr, "\n" "ftdiff: compare font hinting modes -- part of the FreeType project\n" "------------------------------------------------------------------\n" "\n" ); fprintf( stderr, "Usage: %s [options] font ...\n" "\n", execname ); fprintf( stderr, " font The font file(s) to display.\n" " For Type 1 font files, ftdiff also tries to attach\n" " the corresponding metrics file (with extension\n" " `.afm' or `.pfm').\n" "\n" ); fprintf( stderr, " -w W Set the window width to W pixels (default: 640px).\n" " -h H Set the window height to H pixels (default: 480px).\n" " -r R Use resolution R dpi (default: 72dpi).\n" " -s S Set character size to S points (default: 16pt).\n" " -f TEXTFILE Change displayed text, using text in TEXTFILE\n" " (in UTF-8 encoding).\n" "\n" " -v Show version." "\n" ); exit( 1 ); } static void panic( const char* fmt, ... ) { va_list args; va_start( args, fmt ); vfprintf( stderr, fmt, args ); va_end( args ); exit( 1 ); } /** DISPLAY ABSTRACTION **/ typedef enum DisplayMode_ { DISPLAY_MODE_MONO = 0, DISPLAY_MODE_GRAY, DISPLAY_MODE_LCD } DisplayMode; typedef void (*Display_drawFunc)( void* disp, DisplayMode mode, int x, int y, int width, int height, int pitch, void* buffer ); typedef void (*Display_textFunc)( void* disp, int x, int y, const char* msg ); typedef struct DisplayRec_ { void* disp; Display_drawFunc disp_draw; Display_textFunc disp_text; } DisplayRec, *Display; static const char* default_text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras sit amet" " dui. Nam sapien. Fusce vestibulum ornare metus. Maecenas ligula orci," " consequat vitae, dictum nec, lacinia non, elit. Aliquam iaculis" " molestie neque. Maecenas suscipit felis ut pede convallis malesuada." " Aliquam erat volutpat. Nunc pulvinar condimentum nunc. Donec ac sem vel" " leo bibendum aliquam. Pellentesque habitant morbi tristique senectus et" " netus et malesuada fames ac turpis egestas.\n" "\n" "Sed commodo. Nulla ut libero sit amet justo varius blandit. Mauris vitae" " nulla eget lorem pretium ornare. Proin vulputate erat porta risus." " Vestibulum malesuada, odio at vehicula lobortis, nisi metus hendrerit" " est, vitae feugiat quam massa a ligula. Aenean in tellus. Praesent" " convallis. Nullam vel lacus. Aliquam congue erat non urna mollis" " faucibus. Morbi vitae mauris faucibus quam condimentum ornare. Quisque" " sit amet augue. Morbi ullamcorper mattis enim. Aliquam erat volutpat." " Morbi nec felis non enim pulvinar lobortis. Ut libero. Nullam id orci" " quis nisl dapibus rutrum. Suspendisse consequat vulputate leo. Aenean" " non orci non tellus iaculis vestibulum. Sed neque.\n" "\n"; /***********************************************************************/ /***********************************************************************/ /***** *****/ /***** T E X T R E N D E R I N G *****/ /***** *****/ /***********************************************************************/ /***********************************************************************/ typedef enum HintMode_ { HINT_MODE_UNHINTED, HINT_MODE_AUTOHINT, HINT_MODE_AUTOHINT_LIGHT, HINT_MODE_AUTOHINT_LIGHT_SUBPIXEL, HINT_MODE_BYTECODE, HINT_MODE_MAX } HintMode; static const char* const render_mode_names[HINT_MODE_MAX] = { "unhinted", "auto-hinter", "light auto-hinter", "light auto-hinter (subp.)", "native hinter" }; /** RENDER STATE **/ typedef struct ColumnStateRec_ { int use_cboxes; int use_kerning; int use_deltas; int use_lcd_filter; FT_LcdFilter lcd_filter; HintMode hint_mode; DisplayMode disp_mode; int use_custom_lcd_filter; unsigned char filter_weights[5]; int fw_index; unsigned int cff_hinting_engine; unsigned int type1_hinting_engine; unsigned int t1cid_hinting_engine; unsigned int tt_interpreter_versions[3]; int num_tt_interpreter_versions; int tt_interpreter_version_idx; FT_Bool warping; } ColumnStateRec, *ColumnState; typedef struct FontFaceRec_ { const char* filepath; char* family_name; char* style_name; int index; } FontFaceRec, *FontFace; typedef struct RenderStateRec_ { FT_Library library; const char* text; unsigned int resolution; double char_size; int col; ColumnStateRec columns[3]; FontFace faces; unsigned int num_faces; int face_index; const char* filepath; const char* filename; FT_Face face; FT_Size size; char** files; DisplayRec display; char filepath0[1024]; } RenderStateRec, *RenderState; static void render_state_init( RenderState state, Display display, FT_Library library ) { FT_UInt cff_hinting_engine; FT_UInt type1_hinting_engine; FT_UInt t1cid_hinting_engine; FT_Bool warping; unsigned int tt_interpreter_versions[3] = { 0, 0, 0 }; int num_tt_interpreter_versions = 0; int tt_interpreter_version_idx = 0; unsigned int dflt_tt_interpreter_version; int i; unsigned int versions[3] = { TT_INTERPRETER_VERSION_35, TT_INTERPRETER_VERSION_38, TT_INTERPRETER_VERSION_40 }; memset( state, 0, sizeof ( *state ) ); state->library = library; state->text = default_text; state->filepath = state->filepath0; state->filename = ""; state->filepath0[0] = 0; state->resolution = 72; state->char_size = 16; state->display = display[0]; /* get the default value as compiled into FreeType */ FT_Property_Get( library, "cff", "hinting-engine", &cff_hinting_engine ); FT_Property_Get( library, "type1", "hinting-engine", &type1_hinting_engine ); FT_Property_Get( library, "t1cid", "hinting-engine", &t1cid_hinting_engine ); /* collect all available versions, then set again the default */ FT_Property_Get( library, "truetype", "interpreter-version", &dflt_tt_interpreter_version ); for ( i = 0; i < 3; i++ ) { error = FT_Property_Set( library, "truetype", "interpreter-version", &versions[i] ); if ( !error ) tt_interpreter_versions[num_tt_interpreter_versions++] = versions[i]; if ( versions[i] == dflt_tt_interpreter_version ) tt_interpreter_version_idx = i; } FT_Property_Set( library, "truetype", "interpreter-version", &dflt_tt_interpreter_version ); FT_Property_Get( library, "autofitter", "warping", &warping ); state->columns[0].use_cboxes = 0; state->columns[0].use_kerning = 1; state->columns[0].use_deltas = 1; state->columns[0].use_lcd_filter = 1; state->columns[0].lcd_filter = FT_LCD_FILTER_DEFAULT; state->columns[0].hint_mode = HINT_MODE_BYTECODE; state->columns[0].cff_hinting_engine = cff_hinting_engine; state->columns[0].type1_hinting_engine = type1_hinting_engine; state->columns[0].t1cid_hinting_engine = t1cid_hinting_engine; state->columns[0].tt_interpreter_versions[0] = tt_interpreter_versions[0]; state->columns[0].tt_interpreter_versions[1] = tt_interpreter_versions[1]; state->columns[0].tt_interpreter_versions[2] = tt_interpreter_versions[2]; state->columns[0].num_tt_interpreter_versions = num_tt_interpreter_versions; state->columns[0].tt_interpreter_version_idx = tt_interpreter_version_idx; state->columns[0].warping = warping; state->columns[0].use_custom_lcd_filter = 0; state->columns[0].fw_index = 2; /* FreeType default filter weights */ memcpy( state->columns[0].filter_weights, "\x08\x4D\x56\x4D\x08", 5 ); state->columns[1] = state->columns[0]; state->columns[1].hint_mode = HINT_MODE_AUTOHINT; state->columns[1].use_custom_lcd_filter = 1; state->columns[2] = state->columns[0]; state->columns[2].hint_mode = HINT_MODE_UNHINTED; state->col = 1; } static void render_state_done( RenderState state ) { if ( state->filepath != state->filepath0 ) { free( (char*)state->filepath ); state->filepath = state->filepath0; } state->filepath0[0] = 0; state->filename = 0; if ( state->face ) { FT_Done_Face( state->face ); state->face = NULL; state->size = NULL; } if ( state->library ) { FT_Done_FreeType( state->library ); state->library = NULL; } } static void render_state_set_resolution( RenderState state, unsigned int resolution ) { state->resolution = resolution; } static void render_state_set_size( RenderState state, double char_size ) { state->char_size = char_size; } static void render_state_set_face_index( RenderState state, int idx ) { state->face_index = idx; } static void _render_state_rescale( RenderState state ) { if ( state->size ) FT_Set_Char_Size( state->face, 0, (FT_F26Dot6)( state->char_size * 64.0 ), 0, state->resolution ); } static void render_state_set_files( RenderState state, char** files, char* execname ) { FontFace faces = NULL; unsigned int num_faces = 0; unsigned int max_faces = 0; state->files = files; for ( ; files[0] != NULL; files++ ) { FT_Face face; int num_subfonts; int count; error = FT_New_Face( state->library, files[0], -1, &face ); if ( error ) { fprintf( stderr, "ftdiff: could not open font file `%s'\n", files[0] ); continue; } num_subfonts = face->num_faces; FT_Done_Face( face ); for ( count = 0; count < num_subfonts; count++ ) { char* fn; char* family_name; char* sn; char* style_name; error = FT_New_Face( state->library, files[0], count, &face ); if ( error ) { fprintf( stderr, "ftdiff: Opening `%s' failed with code 0x%X, skipping\n", files[0], error ); break; } if ( !FT_IS_SCALABLE( face ) ) { fprintf( stderr, "ftdiff: font `%s' is not scalable, skipping\n", files[0] ); goto Done; } if ( num_faces >= max_faces ) { max_faces += ( max_faces >> 1 ) + 8; faces = (FontFace)realloc( faces, max_faces * sizeof ( faces[0] ) ); if ( faces == NULL ) panic( "ftdiff: not enough memory\n" ); } if ( face->family_name ) fn = face->family_name; else fn = (char*)"(unknown family)"; family_name = (char*)malloc( strlen( fn ) + 1 ); if ( family_name == NULL ) panic( "ftdiff: not enough memory\n" ); strcpy( family_name, fn ); if ( face->style_name ) sn = face->style_name; else sn = (char*)"(unknown style)"; style_name = (char*)malloc( strlen( sn ) + 1 ); if ( style_name == NULL ) panic( "ftdiff: not enough memory\n" ); strcpy( style_name, sn ); faces[num_faces].filepath = files[0]; faces[num_faces].index = count; faces[num_faces].family_name = family_name; faces[num_faces].style_name = style_name; num_faces++; Done: FT_Done_Face( face ); } } state->faces = faces; state->num_faces = num_faces; if ( num_faces == 0 ) { fprintf( stderr, "ftdiff: no input font files!\n" ); usage( execname ); } state->face_index = 0; } static int render_state_set_file( RenderState state ) { const char* filepath; filepath = state->faces[state->face_index].filepath; if ( state->face ) { FT_Done_Face( state->face ); state->face = NULL; state->size = NULL; } if ( filepath != NULL && filepath[0] != 0 ) { error = FT_New_Face( state->library, filepath, state->faces[state->face_index].index, &state->face ); if ( error ) return -1; { unsigned int len = strlen( filepath ); char* p; if ( len + 1 > sizeof ( state->filepath0 ) ) { state->filepath = (const char*)malloc( len + 1 ); if ( state->filepath == NULL ) { state->filepath = state->filepath0; return -1; } } memcpy( (char*)state->filepath, filepath, len + 1 ); p = (char*)strrchr( state->filepath, '\\' ); if ( p == NULL ) p = (char*)strrchr( state->filepath, '/' ); state->filename = p ? p + 1 : state->filepath; } state->size = state->face->size; } return 0; } /** RENDERING **/ static void render_state_draw( RenderState state, const char* text, int idx, int x, int y, int width, int height ) { ColumnState column = &state->columns[idx]; const char* p = text; const char* p_end = p + strlen( text ); long load_flags = FT_LOAD_DEFAULT; FT_Face face; int left = x; int right = x + width; int bottom = y + height; int line_height; FT_UInt prev_glyph = 0; FT_Pos prev_rsb_delta = 0; FT_Pos x_origin = x << 6; HintMode rmode = column->hint_mode; FT_Bool warping = column->warping; FT_Bool have_0x0A = 0; FT_Bool have_0x0D = 0; /* no need to check for errors: the values used here are always valid */ FT_Property_Set( state->library, "cff", "hinting-engine", &column->cff_hinting_engine ); FT_Property_Set( state->library, "type1", "hinting-engine", &column->type1_hinting_engine ); FT_Property_Set( state->library, "t1cid", "hinting-engine", &column->t1cid_hinting_engine ); FT_Property_Set( state->library, "truetype", "interpreter-version", &column->tt_interpreter_versions [column->tt_interpreter_version_idx] ); FT_Property_Set( state->library, "autofitter", "warping", &column->warping ); /* changing a property is in most cases a global operation; */ /* we are on the safe side if we reload the face completely */ /* (this is something a normal program doesn't need to do) */ render_state_set_file( state ); _render_state_rescale( state ); face = state->face; if ( column->use_lcd_filter ) FT_Library_SetLcdFilter( face->glyph->library, column->lcd_filter ); if ( column->use_custom_lcd_filter ) FT_Library_SetLcdFilterWeights( face->glyph->library, column->filter_weights ); y += state->size->metrics.ascender / 64; line_height = state->size->metrics.height / 64; if ( rmode == HINT_MODE_AUTOHINT ) load_flags = FT_LOAD_FORCE_AUTOHINT; if ( rmode == HINT_MODE_AUTOHINT_LIGHT || rmode == HINT_MODE_AUTOHINT_LIGHT_SUBPIXEL ) load_flags = FT_LOAD_TARGET_LIGHT; if ( rmode == HINT_MODE_UNHINTED ) load_flags |= FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP; while ( 1 ) { int ch; FT_UInt gindex; FT_GlyphSlot slot = face->glyph; FT_Bitmap* map = &slot->bitmap; FT_Long xmax; ch = utf8_next( &p, p_end ); if ( ch < 0 ) { p = text; ch = utf8_next( &p, p_end ); } /* handle newlines */ if ( ch == 0x0A ) { if ( have_0x0D ) { have_0x0A = 0; have_0x0D = 0; } else { have_0x0A = 1; x_origin = left << 6; y += line_height; prev_rsb_delta = 0; if ( y >= bottom ) break; } continue; } else if ( ch == 0x0D ) { if ( have_0x0A ) { have_0x0A = 0; have_0x0D = 0; } else { have_0x0D = 1; x_origin = left << 6; y += line_height; prev_rsb_delta = 0; if ( y >= bottom ) break; } continue; } else { have_0x0A = 0; have_0x0D = 0; } gindex = FT_Get_Char_Index( state->face, (FT_ULong)ch ); error = FT_Load_Glyph( face, gindex, load_flags ); if ( error ) continue; if ( column->use_kerning && gindex != 0 && prev_glyph != 0 ) { FT_Vector vec; FT_UInt kerning_mode = FT_KERNING_DEFAULT; if ( rmode == HINT_MODE_UNHINTED ) kerning_mode = FT_KERNING_UNFITTED; FT_Get_Kerning( face, prev_glyph, gindex, kerning_mode, &vec ); x_origin += vec.x; } if ( rmode != HINT_MODE_AUTOHINT_LIGHT_SUBPIXEL && column->use_deltas ) { if ( prev_rsb_delta - face->glyph->lsb_delta > 32 ) x_origin -= 64; else if ( prev_rsb_delta - face->glyph->lsb_delta < -31 ) x_origin += 64; } prev_rsb_delta = face->glyph->rsb_delta; /* implement sub-pixel positioning for */ /* un-hinted and (second) light hinting mode */ if ( ( rmode == HINT_MODE_UNHINTED || rmode == HINT_MODE_AUTOHINT_LIGHT_SUBPIXEL ) && slot->format == FT_GLYPH_FORMAT_OUTLINE ) { FT_Pos shift = x_origin & 63; FT_Outline_Translate( &slot->outline, shift, 0 ); } if ( column->use_cboxes ) { if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) { FT_BBox cbox; FT_Outline_Get_CBox( &slot->outline, &cbox ); xmax = ( x_origin + cbox.xMax + 63 ) >> 6; } else xmax = ( x_origin >> 6 ) + slot->bitmap_left + (FT_Long)slot->bitmap.width; } else { if ( rmode == HINT_MODE_UNHINTED || rmode == HINT_MODE_AUTOHINT_LIGHT_SUBPIXEL ) xmax = slot->linearHoriAdvance >> 10; else xmax = slot->advance.x; xmax += x_origin; xmax >>= 6; xmax -= 1; } if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) FT_Render_Glyph( slot, column->use_lcd_filter ? FT_RENDER_MODE_LCD : FT_RENDER_MODE_NORMAL ); if ( xmax >= right ) { x = left; y += line_height; if ( y >= bottom ) break; x_origin = x << 6; prev_rsb_delta = 0; } { DisplayMode mode = DISPLAY_MODE_MONO; if ( slot->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY ) mode = DISPLAY_MODE_GRAY; else if ( slot->bitmap.pixel_mode == FT_PIXEL_MODE_LCD ) mode = DISPLAY_MODE_LCD; state->display.disp_draw( state->display.disp, mode, ( x_origin >> 6 ) + slot->bitmap_left, y - slot->bitmap_top, (int)map->width, (int)map->rows, map->pitch, map->buffer ); } if ( rmode == HINT_MODE_UNHINTED || rmode == HINT_MODE_AUTOHINT_LIGHT_SUBPIXEL ) x_origin += slot->linearHoriAdvance >> 10; else x_origin += slot->advance.x; prev_glyph = gindex; } /* display footer on this column */ { FT_Module module = &state->face->driver->root; void* disp = state->display.disp; const char* extra; const char* msg; char temp[64]; extra = ""; if ( rmode == HINT_MODE_BYTECODE ) { if ( !strcmp( module->clazz->module_name, "cff" ) ) { switch ( column->cff_hinting_engine ) { case FT_HINTING_FREETYPE: extra = " (CFF FT)"; break; case FT_HINTING_ADOBE: extra = " (CFF Adobe)"; break; } } else if ( !strcmp( module->clazz->module_name, "type1" ) ) { switch ( column->type1_hinting_engine ) { case FT_HINTING_FREETYPE: extra = " (T1 FT)"; break; case FT_HINTING_ADOBE: extra = " (T1 Adobe)"; break; } } else if ( !strcmp( module->clazz->module_name, "t1cid" ) ) { switch ( column->t1cid_hinting_engine ) { case FT_HINTING_FREETYPE: extra = " (CID FT)"; break; case FT_HINTING_ADOBE: extra = " (CID Adobe)"; break; } } else if ( !strcmp( module->clazz->module_name, "truetype" ) ) { switch ( column->tt_interpreter_versions[ column->tt_interpreter_version_idx] ) { case TT_INTERPRETER_VERSION_35: extra = " (TT v35)"; break; case TT_INTERPRETER_VERSION_38: extra = " (TT v38)"; break; case TT_INTERPRETER_VERSION_40: extra = " (TT v40)"; break; } } } else if ( rmode == HINT_MODE_AUTOHINT ) extra = warping ? " (+warp)" : " (-warp)"; sprintf( temp, "%s%s", render_mode_names[column->hint_mode], extra ); state->display.disp_text( disp, left, bottom + 5, temp ); if ( column->use_lcd_filter ) msg = "LCD rendering"; else msg = "gray rendering"; state->display.disp_text( disp, left, bottom + HEADER_HEIGHT + 5, msg ); if ( column->use_lcd_filter ) { if ( column->use_custom_lcd_filter ) { int fwi = column->fw_index; unsigned char* fw = column->filter_weights; sprintf( temp, "%s0x%02X%s0x%02X%s0x%02X%s0x%02X%s0x%02X%s", fwi == 0 ? "[" : " ", fw[0], fwi == 0 ? "]" : ( fwi == 1 ? "[" : " " ), fw[1], fwi == 1 ? "]" : ( fwi == 2 ? "[" : " " ), fw[2], fwi == 2 ? "]" : ( fwi == 3 ? "[" : " " ), fw[3], fwi == 3 ? "]" : ( fwi == 4 ? "[" : " " ), fw[4], fwi == 4 ? "]" : " " ); state->display.disp_text( disp, left, bottom + 2 * HEADER_HEIGHT + 5, temp ); } else { switch ( column->lcd_filter ) { case FT_LCD_FILTER_NONE: msg = "LCD without filtering"; break; case FT_LCD_FILTER_DEFAULT: msg = "default LCD filter"; break; case FT_LCD_FILTER_LIGHT: msg = "light LCD filter"; break; default: msg = "legacy LCD filter"; } state->display.disp_text( disp, left, bottom + 2 * HEADER_HEIGHT + 5, msg ); } } else { msg = ""; state->display.disp_text( disp, left, bottom + 2 * HEADER_HEIGHT + 5, msg ); } sprintf( temp, "%s %s %s", column->use_kerning ? "+kern" : "-kern", column->use_deltas ? "+delta" : "-delta", column->use_cboxes ? "glyph boxes" : "adv. widths" ); state->display.disp_text( disp, left, bottom + 3 * HEADER_HEIGHT + 5, temp ); if ( state->col == idx ) state->display.disp_text( disp, left, bottom + 4 * HEADER_HEIGHT + 5, "************************" ); } } /***********************************************************************/ /***********************************************************************/ /***** *****/ /***** D I S P L A Y *****/ /***** *****/ /***********************************************************************/ /***********************************************************************/ #include "graph.h" #include "grobjs.h" #include "grfont.h" typedef struct ADisplayRec_ { int width; int height; grSurface* surface; grBitmap* bitmap; grColor fore_color; grColor back_color; double gamma; } ADisplayRec, *ADisplay; static int adisplay_init( ADisplay display, grPixelMode mode, int width, int height ) { grSurface* surface; grBitmap bit; if ( mode != gr_pixel_mode_gray && mode != gr_pixel_mode_rgb24 ) return -1; grInitDevices(); bit.mode = mode; bit.width = width; bit.rows = height; bit.grays = 256; surface = grNewSurface( 0, &bit ); if ( !surface ) return -1; display->width = width; display->height = height; display->surface = surface; display->bitmap = &surface->bitmap; display->gamma = GAMMA; grSetTargetGamma( display->bitmap, display->gamma ); memset( &display->fore_color, 0, sizeof( grColor ) ); memset( &display->back_color, 0xff, sizeof( grColor ) ); return 0; } static void adisplay_clear( ADisplay display ) { grBitmap* bit = display->bitmap; int pitch = bit->pitch; if ( pitch < 0 ) pitch = -pitch; if ( bit->mode == gr_pixel_mode_gray ) memset( bit->buffer, display->back_color.value, (unsigned int)( pitch * bit->rows ) ); else { unsigned char* p = bit->buffer; int i, j; for ( i = 0; i < bit->rows; i++ ) { for ( j = 0; j < bit->width; j++ ) memcpy( p + 3 * j, display->back_color.chroma, 3 ); p += pitch; } } } static void adisplay_done( ADisplay display ) { grDoneBitmap( display->bitmap ); grDoneSurface( display->surface ); display->bitmap = NULL; display->surface = NULL; grDoneDevices(); } static void adisplay_draw_glyph( void* _display, DisplayMode mode, int x, int y, int width, int height, int pitch, void* buffer ) { ADisplay display = (ADisplay)_display; grBitmap glyph; glyph.width = width; glyph.rows = height; glyph.pitch = pitch; glyph.buffer = (unsigned char*)buffer; glyph.grays = 256; glyph.mode = gr_pixel_mode_mono; if ( mode == DISPLAY_MODE_GRAY ) glyph.mode = gr_pixel_mode_gray; else if ( mode == DISPLAY_MODE_LCD ) glyph.mode = gr_pixel_mode_lcd; grBlitGlyphToBitmap( display->bitmap, &glyph, x, y, display->fore_color ); } static void adisplay_draw_text( void* _display, int x, int y, const char* msg ) { ADisplay adisplay = (ADisplay)_display; grWriteCellString( adisplay->bitmap, x, y, msg, adisplay->fore_color ); } static void adisplay_change_gamma( ADisplay display, double delta ) { /* use epsilons */ display->gamma += delta; if ( display->gamma > 2.9999 ) display->gamma = 3.0; else if ( display->gamma < 0.0001 ) display->gamma = 0.0; grSetTargetGamma( display->bitmap, display->gamma ); } static void event_help( RenderState state ) { char buf[256]; char version[64]; const char* format; FT_Int major, minor, patch; ADisplay display = (ADisplay)state->display.disp; grEvent dummy_event; FT_Library_Version( state->library, &major, &minor, &patch ); format = patch ? "%d.%d.%d" : "%d.%d"; sprintf( version, format, major, minor, patch ); adisplay_clear( display ); grSetLineHeight( 10 ); grGotoxy( 0, 0 ); grSetMargin( 2, 1 ); grGotobitmap( display->bitmap ); sprintf( buf, "FreeType Hinting Mode Comparator - part of the FreeType %s test suite", version ); grWriteln( buf ); grLn(); grWriteln( "Use the following keys:" ); grLn(); /* |----------------------------------| |----------------------------------| */ grWriteln( "F1, ? display this help screen " ); grWriteln( " " ); grWriteln( "global parameters: " ); grWriteln( " p, n previous/next font 1, 2, 3 select column " ); grWriteln( " Up, Down adjust size by 0.5pt Left, Right switch between columns " ); grWriteln( " PgUp, PgDn adjust size by 5pt g, v adjust gamma value " ); grWriteln( " " ); grWriteln( " per-column parameters: " ); grWriteln( " d toggle lsb/rsb deltas hinting modes: " ); grWriteln( " h cycle hinting mode A unhinted " ); grWriteln( " H cycle hinting engine B auto-hinter " ); grWriteln( " (if CFF or TTF) C light auto-hinter " ); grWriteln( " w toggle warping (if D light auto-hinter " ); grWriteln( " normal auto-hinting) (subpixel) " ); grWriteln( " k toggle kerning (only E native hinter " ); grWriteln( " from `kern' table) " ); grWriteln( " r toggle rendering mode " ); grWriteln( " x toggle layout mode " ); grWriteln( " " ); grWriteln( " l cycle LCD filtering " ); grWriteln( " [, ] select custom LCD " ); grWriteln( " filter weight " ); grWriteln( " -, +(=) adjust selected custom " ); grWriteln( " LCD filter weight " ); /* |----------------------------------| |----------------------------------| */ grLn(); grLn(); grWriteln( "press any key to exit this help screen" ); grRefreshSurface( display->surface ); grListenSurface( display->surface, gr_event_key, &dummy_event ); } static void event_change_gamma( RenderState state, double delta ) { ADisplay display = (ADisplay)state->display.disp; adisplay_change_gamma( display, delta ); } static void event_change_size( RenderState state, double delta ) { double char_size = state->char_size; char_size += delta; if ( char_size < 6.0 ) char_size = 6.0; else if ( char_size > 300.0 ) char_size = 300.0; render_state_set_size( state, char_size ); } static void event_change_face_index( RenderState state, int idx ) { if ( idx < 0 ) idx = 0; if ( idx >= (int)state->num_faces ) idx = (int)state->num_faces - 1; render_state_set_face_index( state, idx ); } static int process_event( RenderState state, grEvent* event ) { int ret = 0; ColumnState column = &state->columns[state->col]; if ( event->key >= 'A' && event->key < 'A' + HINT_MODE_MAX ) { column->hint_mode = (HintMode)( event->key - 'A' ); return ret; } switch ( event->key ) { case grKeyEsc: case grKEY( 'q' ): ret = 1; break; case grKeyF1: case grKEY( '?' ): event_help( state ); break; case grKeyLeft: if ( --state->col < 0 ) state->col = 2; break; case grKeyRight: if ( ++state->col > 2 ) state->col = 0; break; case grKeyUp: event_change_size( state, 0.5 ); break; case grKeyDown: event_change_size( state, -0.5 ); break; case grKeyPageUp: event_change_size( state, 5. ); break; case grKeyPageDown: event_change_size( state, -5. ); break; case grKEY( '1' ): state->col = 0; break; case grKEY( '2' ): state->col = 1; break; case grKEY( '3' ): state->col = 2; break; case grKEY( 'd' ): column->use_deltas = !column->use_deltas; break; case grKEY( 'g' ): event_change_gamma( state, 0.1 ); break; case grKEY( 'h' ): column->hint_mode = (HintMode)( ( column->hint_mode + 1 ) % HINT_MODE_MAX ); break; case grKEY( 'H' ): { FT_Module module = &state->face->driver->root; if ( column->hint_mode == HINT_MODE_BYTECODE ) { if ( !strcmp( module->clazz->module_name, "cff" ) ) { FTDemo_Event_Cff_Hinting_Engine_Change( state->library, &column->cff_hinting_engine, 1 ); } else if ( !strcmp( module->clazz->module_name, "type1" ) ) { FTDemo_Event_Type1_Hinting_Engine_Change( state->library, &column->type1_hinting_engine, 1 ); } else if ( !strcmp( module->clazz->module_name, "t1cid" ) ) { FTDemo_Event_T1cid_Hinting_Engine_Change( state->library, &column->t1cid_hinting_engine, 1 ); } else if ( !strcmp( module->clazz->module_name, "truetype" ) ) { column->tt_interpreter_version_idx += 1; column->tt_interpreter_version_idx %= column->num_tt_interpreter_versions; FT_Property_Set( state->library, "truetype", "interpreter-version", &column->tt_interpreter_versions[ column->tt_interpreter_version_idx] ); } } } break; case grKEY( 'w' ): { FT_Bool new_warping_state = !column->warping; error = FT_Property_Set( state->library, "autofitter", "warping", &new_warping_state ); if ( !error ) column->warping = new_warping_state; } break; case grKEY( 'k' ): column->use_kerning = !column->use_kerning; break; case grKEY( 'l' ): switch ( column->lcd_filter ) { case FT_LCD_FILTER_NONE: column->lcd_filter = FT_LCD_FILTER_DEFAULT; break; case FT_LCD_FILTER_DEFAULT: if ( !column->use_custom_lcd_filter ) column->use_custom_lcd_filter = 1; else { column->use_custom_lcd_filter = 0; column->lcd_filter = FT_LCD_FILTER_LIGHT; } break; case FT_LCD_FILTER_LIGHT: column->lcd_filter = FT_LCD_FILTER_LEGACY; break; case FT_LCD_FILTER_LEGACY: column->lcd_filter = FT_LCD_FILTER_NONE; break; default: /* to satisfy picky compilers */ break; } break; case grKEY( 'n' ): event_change_face_index( state, state->face_index + 1 ); break; case grKEY( 'p' ): event_change_face_index( state, state->face_index - 1 ); break; case grKEY( 'r' ): column->use_lcd_filter = !column->use_lcd_filter; break; case grKEY( 'v' ): event_change_gamma( state, -0.1 ); break; case grKEY( 'x' ): column->use_cboxes = !column->use_cboxes; break; case grKEY( '[' ): if ( !column->use_custom_lcd_filter ) break; column->fw_index--; if ( column->fw_index < 0 ) column->fw_index = 4; break; case grKEY( ']' ): if ( !column->use_custom_lcd_filter ) break; column->fw_index++; if ( column->fw_index > 4 ) column->fw_index = 0; break; case grKEY( '-' ): if ( !column->use_custom_lcd_filter ) break; column->filter_weights[column->fw_index]--; break; case grKEY( '+' ): case grKEY( '=' ): if ( !column->use_custom_lcd_filter ) break; column->filter_weights[column->fw_index]++; break; default: break; } return ret; } static void write_global_info( RenderState state ) { ADisplay adisplay = (ADisplay)state->display.disp; char gamma[] = "sRGB"; char buf[256]; FontFace face = &state->faces[state->face_index]; const char* basename; basename = ft_basename( state->filename ); sprintf( buf, "%.50s %.50s (file `%.100s')", face->family_name, face->style_name, basename ); grWriteCellString( adisplay->bitmap, 0, 5, buf, adisplay->fore_color ); if ( adisplay->gamma != 0.0 ) sprintf( gamma, "%.1f", adisplay->gamma ); sprintf( buf, "%.1fpt (%dppem) at %ddpi, gamma: %s", state->char_size, (int)(state->char_size * state->resolution / 72 + 0.5), state->resolution, gamma ); grWriteCellString( adisplay->bitmap, 0, 5 + HEADER_HEIGHT, buf, adisplay->fore_color ); } int main( int argc, char** argv ) { FT_Library library; ADisplayRec adisplay[1]; RenderStateRec state[1]; DisplayRec display[1]; int width = 640; int height = 480; int resolution = -1; double size = -1; const char* textfile = NULL; char* text = (char*)default_text; char* execname; int option; execname = ft_basename( argv[0] ); if ( FT_Init_FreeType( &library ) != 0 ) panic( "could not initialize FreeType\n" ); while ( 1 ) { option = getopt( argc, argv, "f:h:r:s:vw:" ); if ( option == -1 ) break; switch ( option ) { case 'f': textfile = optarg; break; case 'h': height = atoi( optarg ); if ( height < 1 ) usage( execname ); break; case 'r': resolution = atoi( optarg ); break; case 's': size = atof( optarg ); break; case 'v': { FT_Int major, minor, patch; FT_Library_Version( library, &major, &minor, &patch ); printf( "ftdiff (FreeType) %d.%d", major, minor ); if ( patch ) printf( ".%d", patch ); printf( "\n" ); exit( 0 ); } /* break; */ case 'w': width = atoi( optarg ); if ( width < 1 ) usage( execname ); break; default: usage( execname ); break; } } argc -= optind; argv += optind; if ( argc < 1 ) usage( execname ); /* Read Text File, if any */ if ( textfile != NULL ) { FILE* tfile = fopen( textfile, "r" ); if ( tfile == NULL ) fprintf( stderr, "could not read textfile '%s'\n", textfile ); else { int tsize; fseek( tfile, 0, SEEK_END ); tsize = ftell( tfile ); fseek( tfile, 0, SEEK_SET ); text = (char*)malloc( (unsigned int)( tsize + 1 ) ); if ( text ) { if ( !fread( text, (unsigned int)tsize, 1, tfile ) ) { fprintf( stderr, "read error\n" ); text = (char *)default_text; } else text[tsize] = '\0'; } else { fprintf( stderr, "not enough memory to read `%s'\n", textfile ); text = (char *)default_text; } fclose( tfile ); } } /* Initialize display */ if ( adisplay_init( adisplay, gr_pixel_mode_rgb24, width, height ) < 0 ) { fprintf( stderr, "could not initialize display! Aborting.\n" ); exit( 1 ); } display->disp = adisplay; display->disp_draw = adisplay_draw_glyph; display->disp_text = adisplay_draw_text; render_state_init( state, display, library ); if ( resolution > 0 ) render_state_set_resolution( state, (unsigned int)resolution ); if ( size > 0.0 ) render_state_set_size( state, size ); render_state_set_files( state, argv, execname ); grSetTitle( adisplay->surface, "FreeType Text Proofer, press ? for help" ); for (;;) { grEvent event; int border_width; int column_x_start[3]; int column_y_start; int column_height; int column_width; adisplay_clear( adisplay ); /* We have this layout: */ /* */ /* | n ----x---- n n ----x---- n n ----x---- n | */ /* */ /* w = 6 * n + 3 * x */ border_width = 10; /* n */ column_width = ( width - 6 * border_width ) / 3; /* x */ column_x_start[0] = border_width; column_x_start[1] = 3 * border_width + column_width; column_x_start[2] = 5 * border_width + 2 * column_width; column_y_start = 10 + 2 * HEADER_HEIGHT; column_height = height - 8 * HEADER_HEIGHT - 5; render_state_draw( state, text, 0, column_x_start[0], column_y_start, column_width, column_height ); render_state_draw( state, text, 1, column_x_start[1], column_y_start, column_width, column_height ); render_state_draw( state, text, 2, column_x_start[2], column_y_start, column_width, column_height ); write_global_info( state ); grRefreshSurface( adisplay->surface ); grListenSurface( adisplay->surface, 0, &event ); if ( process_event( state, &event ) ) break; } render_state_done( state ); adisplay_done( adisplay ); exit( 0 ); /* for safety reasons */ /* return 0; */ /* never reached */ } /* End */ ft2demos-2.10.1/src/ftstring.c0000644000175000001440000006501013501472654015763 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 1996-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* */ /* ftstring.c - simple text string display */ /* */ /****************************************************************************/ #include "ftcommon.h" #include "common.h" #include "mlgetopt.h" #include #include #include #include #include #include FT_LCD_FILTER_H #include FT_TRIGONOMETRY_H #define CELLSTRING_HEIGHT 8 #define MAXPTSIZE 500 /* dtp */ static const char* Sample[] = { "The quick brown fox jumps over the lazy dog", /* Luís argüia à Júlia que «brações, fé, chá, óxido, pôr, zângão» */ /* eram palavras do português */ "Lu\u00EDs arg\u00FCia \u00E0 J\u00FAlia que \u00ABbra\u00E7\u00F5es, " "f\u00E9, ch\u00E1, \u00F3xido, p\u00F4r, z\u00E2ng\u00E3o\u00BB eram " "palavras do portugu\u00EAs", /* Ο καλύμνιος σφουγγαράς ψιθύρισε πως θα βουτήξει χωρίς να διστάζει */ "\u039F \u03BA\u03B1\u03BB\u03CD\u03BC\u03BD\u03B9\u03BF\u03C2 \u03C3" "\u03C6\u03BF\u03C5\u03B3\u03B3\u03B1\u03C1\u03AC\u03C2 \u03C8\u03B9" "\u03B8\u03CD\u03C1\u03B9\u03C3\u03B5 \u03C0\u03C9\u03C2 \u03B8\u03B1 " "\u03B2\u03BF\u03C5\u03C4\u03AE\u03BE\u03B5\u03B9 \u03C7\u03C9\u03C1" "\u03AF\u03C2 \u03BD\u03B1 \u03B4\u03B9\u03C3\u03C4\u03AC\u03B6\u03B5" "\u03B9", /* Съешь ещё этих мягких французских булок да выпей же чаю */ "\u0421\u044A\u0435\u0448\u044C \u0435\u0449\u0451 \u044D\u0442\u0438" "\u0445 \u043C\u044F\u0433\u043A\u0438\u0445 \u0444\u0440\u0430\u043D" "\u0446\u0443\u0437\u0441\u043A\u0438\u0445 \u0431\u0443\u043B\u043E" "\u043A \u0434\u0430 \u0432\u044B\u043F\u0435\u0439 \u0436\u0435 " "\u0447\u0430\u044E", /* 天地玄黃,宇宙洪荒。日月盈昃,辰宿列張。寒來暑往,秋收冬藏。*/ "\u5929\u5730\u7384\u9EC3\uFF0C\u5B87\u5B99\u6D2A\u8352\u3002\u65E5" "\u6708\u76C8\u6603\uFF0C\u8FB0\u5BBF\u5217\u5F35\u3002\u5BD2\u4F86" "\u6691\u5F80\uFF0C\u79CB\u6536\u51AC\u85CF\u3002", /* いろはにほへと ちりぬるを わかよたれそ つねならむ */ /* うゐのおくやま けふこえて あさきゆめみし ゑひもせす */ "\u3044\u308D\u306F\u306B\u307B\u3078\u3068 \u3061\u308A\u306C\u308B" "\u3092 \u308F\u304B\u3088\u305F\u308C\u305D \u3064\u306D\u306A\u3089" "\u3080 \u3046\u3090\u306E\u304A\u304F\u3084\u307E \u3051\u3075\u3053" "\u3048\u3066 \u3042\u3055\u304D\u3086\u3081\u307F\u3057 \u3091\u3072" "\u3082\u305B\u3059", /* 키스의 고유조건은 입술끼리 만나야 하고 특별한 기술은 필요치 않다 */ "\uD0A4\uC2A4\uC758 \uACE0\uC720\uC870\uAC74\uC740 \uC785\uC220\uB07C" "\uB9AC \uB9CC\uB098\uC57C \uD558\uACE0 \uD2B9\uBCC4\uD55C \uAE30" "\uC220\uC740 \uD544\uC694\uCE58 \uC54A\uB2E4" }; enum { RENDER_MODE_STRING, RENDER_MODE_TEXT, RENDER_MODE_WATERFALL, RENDER_MODE_KERNCMP, N_RENDER_MODES }; static struct status_ { const char* keys; const char* dims; const char* device; int render_mode; unsigned long encoding; int res; int ptsize; /* current point size */ int angle; const char* text; FTDemo_String_Context sc; FT_Matrix trans_matrix; int font_index; const char* header; char header_buffer[256]; } status = { "", DIM, NULL, RENDER_MODE_STRING, FT_ENCODING_UNICODE, 72, 48, 0, NULL, { 0, 0, 0x8000, 0, NULL, 0, 0 }, { 0, 0, 0, 0 }, 0, NULL, { 0 } }; static FTDemo_Display* display; static FTDemo_Handle* handle; static FT_Glyph wheel, daisy, aster; /* stress test glyphs */ static void flower_init( FT_Glyph* glyph, FT_F26Dot6 radius, unsigned int i, int v, int w, int reflect, char order ) { FT_Outline* outline; FT_Vector* vec; FT_Vector* limit; char* tag; FT_Fixed s = FT_Sin( FT_ANGLE_PI4 / i ); FT_Pos b, d, p = 0, q = radius; FT_New_Glyph( handle->library, FT_GLYPH_FORMAT_OUTLINE, glyph ); outline = &((FT_OutlineGlyph)*glyph)->outline; FT_Outline_New( handle->library, 6 * i, 1, outline ); outline->contours[0] = outline->n_points - 1; if ( order == FT_CURVE_TAG_CUBIC ) q += q / 3; for ( vec = outline->points, tag = outline->tags; i--; vec += 6, tag += 6 ) { b = p + FT_MulFix( q, s ); d = q - FT_MulFix( p, s ); vec[0].x = vec[3].y = 0; vec[0].y = vec[3].x = 0; tag[0] = tag[3] = FT_CURVE_TAG_ON; vec[1].x = vec[5].y = ( v * p + w * b ) / ( v + w ); vec[1].y = vec[5].x = ( v * q + w * d ) / ( v + w ); tag[1] = tag[5] = order; vec[2].x = vec[4].y = ( v * b + w * p ) / ( v + w ); vec[2].y = vec[4].x = ( v * d + w * q ) / ( v + w ); tag[2] = tag[4] = order; p = b; q = d; } limit = outline->points + outline->n_points; if ( reflect & 1 ) for( vec = outline->points; vec < limit; vec++ ) vec->x = -vec->x; if ( reflect & 2 ) for( vec = outline->points; vec < limit; vec++ ) vec->y = -vec->y; } /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /**** ****/ /**** E V E N T H A N D L I N G ****/ /**** ****/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ static void event_help( void ) { char buf[256]; char version[64] = ""; grEvent dummy_event; FTDemo_Version( handle, version ); FTDemo_Display_Clear( display ); grSetLineHeight( 10 ); grGotoxy( 0, 0 ); grSetMargin( 2, 1 ); grGotobitmap( display->bitmap ); sprintf( buf, "FreeType String Viewer - part of the FreeType %s test suite", version ); grWriteln( buf ); grLn(); grWriteln( "This program is used to display a string of text using" ); grWriteln( "the new convenience API of the FreeType 2 library." ); grLn(); grWriteln( "Use the following keys :" ); grLn(); grWriteln( " F1 or ? : display this help screen" ); grLn(); grWriteln( " b : toggle embedded bitmaps (and disable rotation)" ); grWriteln( " f : toggle forced auto-hinting" ); grWriteln( " h : toggle outline hinting" ); grLn(); grWriteln( " 1-4 : select rendering mode" ); grWriteln( " l : cycle through anti-aliasing modes" ); grWriteln( " k : cycle through kerning modes" ); grWriteln( " t : cycle through kerning degrees" ); grWriteln( " Space : cycle through color" ); grWriteln( " Tab : cycle through sample strings" ); grWriteln( " V : toggle vertical rendering" ); grLn(); grWriteln( " g : increase gamma by 0.1" ); grWriteln( " v : decrease gamma by 0.1" ); grLn(); grWriteln( " n : next font" ); grWriteln( " p : previous font" ); grLn(); grWriteln( " Up : increase pointsize by 1 unit" ); grWriteln( " Down : decrease pointsize by 1 unit" ); grWriteln( " Page Up : increase pointsize by 10 units" ); grWriteln( " Page Down : decrease pointsize by 10 units" ); grLn(); grWriteln( " Left : move left" ); grWriteln( " Right : move right" ); grWriteln( " Home : flush left" ); grWriteln( " End : flush right" ); grLn(); grWriteln( " F5 : rotate counter-clockwise" ); grWriteln( " F6 : rotate clockwise" ); grWriteln( " F7 : big rotate counter-clockwise" ); grWriteln( " F8 : big rotate clockwise" ); grLn(); grWriteln( " P : print PNG file" ); grWriteln( " q,ESC : quit" ); grLn(); grWriteln( "press any key to exit this help screen" ); grRefreshSurface( display->surface ); grListenSurface( display->surface, gr_event_key, &dummy_event ); } static void event_font_change( int delta ) { if ( status.font_index + delta >= handle->num_fonts || status.font_index + delta < 0 ) return; status.font_index += delta; FTDemo_Set_Current_Font( handle, handle->fonts[status.font_index] ); FTDemo_Set_Current_Charsize( handle, status.ptsize, status.res ); } static void event_center_change( FT_Fixed delta ) { status.sc.center += delta; if ( status.sc.center > 0x10000 ) status.sc.center = 0x10000; else if ( status.sc.center < 0 ) status.sc.center = 0; } static void event_angle_change( int delta ) { double radian; FT_Fixed cosinus; FT_Fixed sinus; status.angle += delta; if ( status.angle <= -180 ) status.angle += 360; if ( status.angle > 180 ) status.angle -= 360; if ( status.angle == 0 ) { status.sc.matrix = NULL; return; } status.sc.matrix = &status.trans_matrix; radian = status.angle * 3.14159265 / 180.0; cosinus = (FT_Fixed)( cos( radian ) * 65536.0 ); sinus = (FT_Fixed)( sin( radian ) * 65536.0 ); status.trans_matrix.xx = cosinus; status.trans_matrix.yx = sinus; status.trans_matrix.xy = -sinus; status.trans_matrix.yy = cosinus; } static void event_lcdmode_change( void ) { const char *lcd_mode; handle->lcd_mode++; switch ( handle->lcd_mode ) { case LCD_MODE_AA: lcd_mode = " normal AA"; break; case LCD_MODE_LIGHT: lcd_mode = " light AA"; break; case LCD_MODE_LIGHT_SUBPIXEL: lcd_mode = " light AA (subpixel positioning)"; break; case LCD_MODE_RGB: lcd_mode = " LCD (horiz. RGB)"; break; case LCD_MODE_BGR: lcd_mode = " LCD (horiz. BGR)"; break; case LCD_MODE_VRGB: lcd_mode = " LCD (vert. RGB)"; break; case LCD_MODE_VBGR: lcd_mode = " LCD (vert. BGR)"; break; default: handle->lcd_mode = LCD_MODE_MONO; lcd_mode = " monochrome"; } sprintf( status.header_buffer, "mode changed to %s", lcd_mode ); status.header = status.header_buffer; } static void event_color_change( void ) { static int i = 0; unsigned char r = i & 4 ? 0xff : 0; unsigned char g = i & 2 ? 0xff : 0; unsigned char b = i & 1 ? 0xff : 0; display->back_color = grFindColor( display->bitmap, r, g, b, 0xff ); display->fore_color = grFindColor( display->bitmap, ~r, ~g, ~b, 0xff ); display->warn_color = grFindColor( display->bitmap, r, ~g, ~b, 0xff ); i++; } static void event_text_change( void ) { static int i = 0; status.text = Sample[i]; i++; if ( i >= (int)( sizeof( Sample ) / sizeof( Sample[0] ) ) ) i = 0; } static void event_gamma_change( double delta ) { display->gamma += delta; if ( display->gamma > 3.0 ) display->gamma = 3.0; else if ( display->gamma < 0.1 ) display->gamma = 0.1; grSetTargetGamma( display->bitmap, display->gamma ); } static void event_size_change( int delta ) { status.ptsize += delta; if ( status.ptsize < 1 * 64 ) status.ptsize = 1 * 64; else if ( status.ptsize > MAXPTSIZE * 64 ) status.ptsize = MAXPTSIZE * 64; FTDemo_Set_Current_Charsize( handle, status.ptsize, status.res ); } static void event_render_mode_change( int delta ) { if ( delta ) { status.render_mode = ( status.render_mode + delta ) % N_RENDER_MODES; if ( status.render_mode < 0 ) status.render_mode += N_RENDER_MODES; } switch ( status.render_mode ) { case RENDER_MODE_KERNCMP: status.header = "Kerning comparison"; break; default: status.header = NULL; break; } } static int Process_Event( void ) { grEvent event; FTDemo_String_Context* sc = &status.sc; int ret = 0; if ( *status.keys ) event.key = grKEY( *status.keys++ ); else grListenSurface( display->surface, 0, &event ); if ( event.key >= '1' && event.key < '1' + N_RENDER_MODES ) { status.render_mode = (int)( event.key - '1' ); event_render_mode_change( 0 ); return ret; } switch ( event.key ) { case grKeyEsc: case grKEY( 'q' ): ret = 1; goto Exit; case grKeyF1: case grKEY( '?' ): event_help(); goto Exit; case grKEY( 'P' ): { FT_String str[64] = "ftstring (FreeType) "; FTDemo_Version( handle, str ); FTDemo_Display_Print( display, "ftstring.png", str ); } goto Exit; case grKEY( 'b' ): handle->use_sbits = !handle->use_sbits; status.header = handle->use_sbits ? "embedded bitmaps are now used when available" : "embedded bitmaps are now ignored"; goto Flags; case grKEY( 'f' ): handle->autohint = !handle->autohint; status.header = handle->autohint ? "forced auto-hinting is now on" : "forced auto-hinting is now off"; goto Flags; case grKEY( 'h' ): handle->hinted = !handle->hinted; status.header = handle->hinted ? "glyph hinting is now active" : "glyph hinting is now ignored"; goto Flags; case grKEY( 'l' ): event_lcdmode_change(); goto Flags; case grKEY( 'k' ): sc->kerning_mode = ( sc->kerning_mode + 1 ) % N_KERNING_MODES; status.header = sc->kerning_mode == KERNING_MODE_SMART ? "pair kerning and side bearing correction is now active" : sc->kerning_mode == KERNING_MODE_NORMAL ? "pair kerning is now active" : "pair kerning is now ignored"; goto String; case grKEY( 't' ): sc->kerning_degree = ( sc->kerning_degree + 1 ) % N_KERNING_DEGREES; status.header = sc->kerning_degree == KERNING_DEGREE_NONE ? "no track kerning" : sc->kerning_degree == KERNING_DEGREE_LIGHT ? "light track kerning active" : sc->kerning_degree == KERNING_DEGREE_MEDIUM ? "medium track kerning active" : "tight track kerning active"; goto String; case grKeySpace: event_color_change(); goto Exit; case grKeyTab: event_text_change(); FTDemo_String_Set( handle, status.text ); goto String; case grKEY( 'V' ): sc->vertical = !sc->vertical; status.header = sc->vertical ? "using vertical layout" : "using horizontal layout"; goto Exit; case grKEY( 'g' ): event_gamma_change( 0.1 ); goto Exit; case grKEY( 'v' ): event_gamma_change( -0.1 ); goto Exit; case grKEY( 'n' ): event_font_change( 1 ); FTDemo_String_Set( handle, status.text ); goto Flags; case grKEY( 'p' ): event_font_change( -1 ); FTDemo_String_Set( handle, status.text ); goto Flags; case grKeyUp: event_size_change( 64 ); goto String; case grKeyDown: event_size_change( -64 ); goto String; case grKeyPageUp: event_size_change( 640 ); goto String; case grKeyPageDown: event_size_change( -640 ); goto String; case grKeyLeft: event_center_change( -0x800 ); goto Exit; case grKeyRight: event_center_change( 0x800 ); goto Exit; case grKeyHome: event_center_change( -0x10000 ); goto Exit; case grKeyEnd: event_center_change( 0x10000 ); goto Exit; case grKeyF5: event_angle_change( -3 ); goto Exit; case grKeyF6: event_angle_change( 3 ); goto Exit; case grKeyF7: event_angle_change( -30 ); goto Exit; case grKeyF8: event_angle_change( 30 ); goto Exit; default: break; } Flags: FTDemo_Update_Current_Flags( handle ); String: FTDemo_String_Load( handle, &status.sc ); Exit: return ret; } static void write_header( FT_Error error_code ) { FTDemo_Draw_Header( handle, display, status.ptsize, status.res, -1, error_code ); if ( status.header ) grWriteCellString( display->bitmap, 0, 2 * HEADER_HEIGHT, status.header, display->fore_color ); grRefreshSurface( display->surface ); } static void usage( char* execname ) { fprintf( stderr, "\n" "ftstring: string viewer -- part of the FreeType project\n" "-------------------------------------------------------\n" "\n" ); fprintf( stderr, "Usage: %s [options] pt font ...\n" "\n", execname ); fprintf( stderr, " pt The point size for the given resolution.\n" " If resolution is 72dpi, this directly gives the\n" " ppem value (pixels per EM).\n" ); fprintf( stderr, " font The font file(s) to display.\n" " For Type 1 font files, ftstring also tries to attach\n" " the corresponding metrics file (with extension\n" " `.afm' or `.pfm').\n" "\n" ); fprintf( stderr, " -d WxHxD Set the window width, height, and color depth\n" " (default: 640x480x24).\n" " -k keys Emulate sequence of keystrokes upon start-up.\n" " If the keys contain `q', use batch mode.\n" " -r R Use resolution R dpi (default: 72dpi).\n" " -e enc Specify encoding tag (default: Unicode).\n" " Common values: `unic' (Unicode), `symb' (symbol),\n" " `ADOB' (Adobe standard), `ADBC' (Adobe custom).\n" " -m text Use `text' for rendering.\n" "\n" " -v Show version.\n" "\n" ); exit( 1 ); } static void parse_cmdline( int* argc, char*** argv ) { char* execname; int option; execname = ft_basename( (*argv)[0] ); while ( 1 ) { option = getopt( *argc, *argv, "d:e:k:m:r:v" ); if ( option == -1 ) break; switch ( option ) { case 'd': status.dims = optarg; break; case 'e': status.encoding = FTDemo_Make_Encoding_Tag( optarg ); break; case 'k': status.keys = optarg; while ( *optarg && *optarg != 'q' ) optarg++; if ( *optarg == 'q' ) status.device = "batch"; break; case 'm': if ( *argc < 3 ) usage( execname ); status.text = optarg; break; case 'r': status.res = atoi( optarg ); if ( status.res < 1 ) usage( execname ); break; case 'v': { FT_String str[64] = "ftstring (FreeType) "; FTDemo_Version( handle, str ); printf( "%s\n", str ); exit( 0 ); } /* break; */ default: usage( execname ); break; } } *argc -= optind; *argv += optind; if ( *argc <= 1 ) usage( execname ); status.ptsize = (int)( atof( *argv[0] ) * 64.0 ); if ( status.ptsize == 0 ) status.ptsize = 64; (*argc)--; (*argv)++; } static FT_Error Render_String( void ) { int x, y = display->bitmap->rows - 4; x = 4; FTDemo_Draw_Glyph( handle, display, daisy, &x, &y ); x = display->bitmap->width - 4; FTDemo_Draw_Glyph( handle, display, aster, &x, &y ); FTDemo_String_Draw( handle, display, &status.sc, FT_MulFix( display->bitmap->width, status.sc.center), display->bitmap->rows / 2 ); return FT_Err_Ok; } static FT_Error Render_Text( void ) { int x = FT_MulFix( display->bitmap->width, status.sc.center); int y, step_y; int offset = 0; FT_Size size; FTDemo_String_Context sc = status.sc; sc.extent = display->bitmap->width * 64; sc.vertical = 0; error = FTDemo_Get_Size( handle, &size ); if ( error ) return error; step_y = ( size->metrics.height >> 6 ) + 1; y = 40 + ( size->metrics.ascender >> 6 ); for ( ; y < display->bitmap->rows + ( size->metrics.descender >> 6 ); y += step_y ) { sc.offset = offset; offset += FTDemo_String_Draw( handle, display, &sc, x, y ); offset %= handle->string_length; } return FT_Err_Ok; } static FT_Error Render_Waterfall( void ) { int pt_size = status.ptsize, step, pt_height; int y = 40; int x = FT_MulFix( display->bitmap->width, status.sc.center); FT_Size size; FTDemo_String_Context sc = status.sc; sc.vertical = 0; pt_height = 64 * 72 * display->bitmap->rows / status.res; step = ( pt_size * pt_size / pt_height + 64 ) & ~63; pt_size = pt_size - step * ( pt_size / step ); /* remainder */ while ( 1 ) { pt_size += step; FTDemo_Set_Current_Charsize( handle, pt_size, status.res ); FTDemo_String_Load( handle, &status.sc ); error = FTDemo_Get_Size( handle, &size ); if ( error ) { /* probably a non-existent bitmap font size */ continue; } if ( pt_size == status.ptsize ) grFillHLine( display->bitmap, x - 4, y, 8, display->warn_color ); y += ( size->metrics.height >> 6 ) + 1; if ( y >= display->bitmap->rows ) break; if ( pt_size == status.ptsize ) grFillHLine( display->bitmap, x - 4, y, 8, display->warn_color ); FTDemo_String_Draw( handle, display, &sc, x, y + ( size->metrics.descender >> 6 ) ); } FTDemo_Set_Current_Charsize( handle, status.ptsize, status.res ); FTDemo_String_Load( handle, &status.sc ); return FT_Err_Ok; } static FT_Error Render_KernCmp( void ) { FT_Size size; FTDemo_String_Context sc = { 0, 0, 0, 0, NULL, 0, 0 }; FT_Int x, y; FT_Int height; x = 55; FTDemo_Get_Size( handle, &size ); height = size->metrics.y_ppem; if ( height < CELLSTRING_HEIGHT ) height = CELLSTRING_HEIGHT; /* First line: none */ FTDemo_String_Load( handle, &sc ); y = CELLSTRING_HEIGHT * 2 + display->bitmap->rows / 4 + height; grWriteCellString( display->bitmap, 5, y - ( height + CELLSTRING_HEIGHT ) / 2, "none", display->fore_color ); FTDemo_String_Draw( handle, display, &sc, x, y ); /* Second line: track kern only */ sc.kerning_degree = status.sc.kerning_degree; FTDemo_String_Load( handle, &sc ); y += height; grWriteCellString( display->bitmap, 5, y - ( height + CELLSTRING_HEIGHT ) / 2, "track", display->fore_color ); FTDemo_String_Draw( handle, display, &sc, x, y ); /* Third line: track kern + pair kern */ sc.kerning_mode = status.sc.kerning_mode; FTDemo_String_Load( handle, &sc ); y += height; grWriteCellString( display->bitmap, 5, y - ( height + CELLSTRING_HEIGHT ) / 2, "both", display->fore_color ); FTDemo_String_Draw( handle, display, &sc, x, y ); return FT_Err_Ok; } int main( int argc, char** argv ) { /* Initialize engine */ handle = FTDemo_New(); parse_cmdline( &argc, &argv ); flower_init( &wheel, 8192, 20, 3, 1, 0, FT_CURVE_TAG_ON ); flower_init( &daisy, 8192, 20, 4, 1, 0, FT_CURVE_TAG_CONIC ); flower_init( &aster, 8192, 20, 5, 1, 1, FT_CURVE_TAG_CUBIC ); FT_Library_SetLcdFilter( handle->library, FT_LCD_FILTER_LIGHT ); handle->encoding = status.encoding; for ( ; argc > 0; argc--, argv++ ) { error = FTDemo_Install_Font( handle, argv[0], 0, 0 ); if ( error ) { fprintf( stderr, "failed to install %s", argv[0] ); if ( error == FT_Err_Invalid_CharMap_Handle ) fprintf( stderr, ": missing valid charmap\n" ); else fprintf( stderr, "\n" ); } } if ( handle->num_fonts == 0 ) PanicZ( "could not open any font file" ); display = FTDemo_Display_New( status.device, status.dims ); if ( !display ) PanicZ( "could not allocate display surface" ); grSetTitle( display->surface, "FreeType String Viewer - press ? for help" ); status.header = NULL; if ( !status.text ) event_text_change(); event_color_change(); event_gamma_change( 0 ); event_font_change( 0 ); FTDemo_String_Set( handle, status.text ); FTDemo_Update_Current_Flags( handle ); FTDemo_String_Load( handle, &status.sc ); do { FTDemo_Display_Clear( display ); switch ( status.render_mode ) { case RENDER_MODE_STRING: error = Render_String(); break; case RENDER_MODE_TEXT: error = Render_Text(); break; case RENDER_MODE_WATERFALL: error = Render_Waterfall(); break; case RENDER_MODE_KERNCMP: error = Render_KernCmp(); break; } write_header( error ); status.header = 0; } while ( !Process_Event() ); printf( "Execution completed successfully.\n" ); FTDemo_Display_Done( display ); FTDemo_Done( handle ); exit( 0 ); /* for safety reasons */ /* return 0; */ /* never reached */ } /* End */ ft2demos-2.10.1/src/ftview.c0000644000175000001440000016021713501472654015434 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 1996-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* */ /* FTView - a simple font viewer. */ /* */ /* This is a new version using the MiGS graphics subsystem for */ /* blitting and display. */ /* */ /* Press ? when running this program to have a list of key-bindings. */ /* */ /****************************************************************************/ #include "ftcommon.h" #include "common.h" #include "mlgetopt.h" #include /* the following header shouldn't be used in normal programs */ #include FT_INTERNAL_DEBUG_H /* showing driver name */ #include FT_MODULE_H #include FT_INTERNAL_OBJECTS_H #include FT_INTERNAL_DRIVER_H #include FT_STROKER_H #include FT_SYNTHESIS_H #include FT_LCD_FILTER_H #include FT_DRIVER_H #include FT_COLOR_H #include FT_BITMAP_H #define MAXPTSIZE 500 /* dtp */ #ifdef CEIL #undef CEIL #endif #define CEIL( x ) ( ( (x) + 63 ) >> 6 ) #define START_X 18 * 8 #define START_Y 3 * HEADER_HEIGHT #define INIT_SIZE( size, start_x, start_y, step_y, x, y ) \ do { \ start_x = START_X; \ start_y = CEIL( size->metrics.ascender - \ size->metrics.descender ) + START_Y; \ step_y = CEIL( size->metrics.height ) + 4; \ \ x = start_x; \ y = start_y; \ } while ( 0 ) #define X_TOO_LONG( x, display ) \ ( (x) >= (display)->bitmap->width - 3 ) #define Y_TOO_LONG( y, display ) \ ( (y) >= (display)->bitmap->rows - 3 ) #ifdef _WIN32 #define snprintf _snprintf #endif /* omit LCD_MODE_LIGHT_SUBPIXEL; we don't need it in this application */ static int lcd_modes[] = { LCD_MODE_MONO, LCD_MODE_AA, LCD_MODE_LIGHT, LCD_MODE_RGB, LCD_MODE_BGR, LCD_MODE_VRGB, LCD_MODE_VBGR }; #define N_LCD_IDXS ( (int)( sizeof ( lcd_modes ) / sizeof ( int ) ) ) enum { RENDER_MODE_ALL = 0, RENDER_MODE_FANCY, RENDER_MODE_STROKE, RENDER_MODE_TEXT, RENDER_MODE_WATERFALL, N_RENDER_MODES }; static struct status_ { int update; const char* keys; const char* dims; const char* device; int render_mode; int res; int ptsize; /* current point size, 26.6 format */ int lcd_idx; double xbold_factor; double ybold_factor; double radius; double slant; unsigned int cff_hinting_engine; unsigned int type1_hinting_engine; unsigned int t1cid_hinting_engine; unsigned int tt_interpreter_versions[3]; int num_tt_interpreter_versions; int tt_interpreter_version_idx; FT_Bool warping; int font_idx; int offset; /* as selected by the user */ int topleft; /* as displayed by ftview */ int num_fails; int preload; int lcd_filter; unsigned char filter_weights[5]; int fw_idx; } status = { 1, "", DIM, NULL, RENDER_MODE_ALL, 72, 48, 1, 0.04, 0.04, 0.02, 0.22, 0, 0, 0, { 0 }, 0, 0, 0, /* default values are set at runtime */ 0, 0, 0, 0, 0, FT_LCD_FILTER_DEFAULT, { 0x08, 0x4D, 0x56, 0x4D, 0x08 }, 2 }; static FTDemo_Display* display; static FTDemo_Handle* handle; /* In UTF-8 encoding: The quick brown fox jumps over the lazy dog 0123456789 âêîûôäëïöüÿàùéèç &#~"'(-`_^@)=+° ABCDEFGHIJKLMNOPQRSTUVWXYZ $£^¨*µù%!§:/;.,?<> The trailing space is for `looping' in case `Text' gets displayed more than once. */ static const char* Text = "The quick brown fox jumps over the lazy dog" " 0123456789" " \303\242\303\252\303\256\303\273\303\264" "\303\244\303\253\303\257\303\266\303\274\303\277" "\303\240\303\271\303\251\303\250\303\247" " &#~\"\'(-`_^@)=+\302\260" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" " $\302\243^\302\250*\302\265\303\271%!\302\247:/;.,?<> "; static void Fatal( const char* message ) { FTDemo_Display_Done( display ); FTDemo_Done( handle ); PanicZ( message ); } static FT_Error Render_Stroke( int num_indices, int offset ) { int start_x, start_y, step_y, x, y, width; int i, have_topleft; FT_Size size; FT_Face face; FT_GlyphSlot slot; FT_Fixed radius; error = FTDemo_Get_Size( handle, &size ); if ( error ) { /* probably a non-existent bitmap font size */ return error; } INIT_SIZE( size, start_x, start_y, step_y, x, y ); face = size->face; slot = face->glyph; radius = (FT_Fixed)( size->metrics.y_ppem * 64 * status.radius ); FT_Stroker_Set( handle->stroker, radius, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0 ); have_topleft = 0; for ( i = offset; i < num_indices; i++ ) { FT_UInt glyph_idx; glyph_idx = FTDemo_Get_Index( handle, (FT_UInt32)i ); error = FT_Load_Glyph( face, glyph_idx, handle->load_flags | FT_LOAD_NO_BITMAP ); if ( !error && slot->format == FT_GLYPH_FORMAT_OUTLINE ) { FT_Glyph glyph; error = FT_Get_Glyph( slot, &glyph ); if ( error ) goto Next; error = FT_Glyph_Stroke( &glyph, handle->stroker, 1 ); if ( error ) { FT_Done_Glyph( glyph ); goto Next; } width = slot->advance.x ? slot->advance.x >> 6 : size->metrics.y_ppem / 2; if ( X_TOO_LONG( x + width, display ) ) { x = start_x; y += step_y; if ( Y_TOO_LONG( y, display ) ) { FT_Done_Glyph( glyph ); break; } } /* extra space between glyphs */ x++; if ( slot->advance.x == 0 ) { grFillRect( display->bitmap, x, y - width, width, width, display->warn_color ); x += width; } error = FTDemo_Draw_Glyph( handle, display, glyph, &x, &y ); if ( error ) goto Next; else FT_Done_Glyph( glyph ); if ( !have_topleft ) { have_topleft = 1; status.topleft = i; } } else Next: status.num_fails++; } return error; } static FT_Error Render_Fancy( int num_indices, int offset ) { int start_x, start_y, step_y, x, y, width; int i, have_topleft; FT_Size size; FT_Face face; FT_GlyphSlot slot; FT_Matrix shear; FT_Pos xstr, ystr; error = FTDemo_Get_Size( handle, &size ); if ( error ) { /* probably a non-existent bitmap font size */ return error; } INIT_SIZE( size, start_x, start_y, step_y, x, y ); face = size->face; slot = face->glyph; /***************************************************************/ /* */ /* 2*2 affine transformation matrix, 16.16 fixed float format */ /* */ /* Shear matrix: */ /* */ /* | x' | | 1 k | | x | x' = x + ky */ /* | | = | | * | | <==> */ /* | y' | | 0 1 | | y | y' = y */ /* */ /* outline' shear outline */ /* */ /***************************************************************/ shear.xx = 1 << 16; shear.xy = (FT_Fixed)( status.slant * ( 1 << 16 ) ); shear.yx = 0; shear.yy = 1 << 16; xstr = (FT_Pos)( size->metrics.y_ppem * 64 * status.xbold_factor ); ystr = (FT_Pos)( size->metrics.y_ppem * 64 * status.ybold_factor ); have_topleft = 0; for ( i = offset; i < num_indices; i++ ) { FT_UInt glyph_idx; glyph_idx = FTDemo_Get_Index( handle, (FT_UInt32)i ); error = FT_Load_Glyph( face, glyph_idx, handle->load_flags ); if ( error ) goto Next; /* this is essentially the code of function */ /* `FT_GlyphSlot_Embolden' */ if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) { FT_Outline_Transform( &slot->outline, &shear ); error = FT_Outline_EmboldenXY( &slot->outline, xstr, ystr ); /* ignore error */ } else if ( slot->format == FT_GLYPH_FORMAT_BITMAP ) { /* round to full pixels */ xstr &= ~63; ystr &= ~63; error = FT_GlyphSlot_Own_Bitmap( slot ); if ( error ) goto Next; error = FT_Bitmap_Embolden( slot->library, &slot->bitmap, xstr, ystr ); if ( error ) goto Next; } else goto Next; 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.horiAdvance += xstr; slot->metrics.vertAdvance += ystr; if ( slot->format == FT_GLYPH_FORMAT_BITMAP ) slot->bitmap_top += ystr >> 6; width = slot->advance.x ? slot->advance.x >> 6 : size->metrics.y_ppem / 2; if ( X_TOO_LONG( x + width, display ) ) { x = start_x; y += step_y; if ( Y_TOO_LONG( y, display ) ) break; } /* extra space between glyphs */ x++; if ( slot->advance.x == 0 ) { grFillRect( display->bitmap, x, y - width, width, width, display->warn_color ); x += width; } error = FTDemo_Draw_Slot( handle, display, slot, &x, &y ); if ( error ) goto Next; if ( !have_topleft ) { have_topleft = 1; status.topleft = i; } continue; Next: status.num_fails++; } return error; } static FT_Error Render_All( int num_indices, int offset ) { int start_x, start_y, step_y, x, y, width; int i, have_topleft; FT_Size size; FT_Face face; FT_GlyphSlot slot; FT_Color* palette; error = FTDemo_Get_Size( handle, &size ); if ( error ) { /* probably a non-existent bitmap font size */ return error; } INIT_SIZE( size, start_x, start_y, step_y, x, y ); face = size->face; slot = face->glyph; error = FT_Palette_Select( face, handle->current_font->palette_index, &palette ); if ( error ) palette = NULL; have_topleft = 0; for ( i = offset; i < num_indices; i++ ) { FT_LayerIterator iterator; FT_UInt glyph_idx; FT_Bool have_layers; FT_UInt layer_glyph_idx; FT_UInt layer_color_idx; glyph_idx = FTDemo_Get_Index( handle, (FT_UInt32)i ); /* check whether we have glyph color layers */ iterator.p = NULL; have_layers = FT_Get_Color_Glyph_Layer( face, glyph_idx, &layer_glyph_idx, &layer_color_idx, &iterator ); if ( palette && have_layers && handle->use_layers ) { FT_Int32 load_flags = handle->load_flags; FT_Bitmap bitmap; FT_Vector bitmap_offset = { 0, 0 }; /* * We want to handle glyph layers manually, thus switching off * `FT_LOAD_COLOR' and ensuring normal AA render mode. */ load_flags &= ~FT_LOAD_COLOR; load_flags |= FT_LOAD_RENDER; load_flags &= ~FT_LOAD_TARGET_( 0xF ); load_flags |= FT_LOAD_TARGET_NORMAL; FT_Bitmap_Init( &bitmap ); do { FT_Vector slot_offset; error = FT_Load_Glyph( face, layer_glyph_idx, load_flags ); if ( error ) break; slot_offset.x = slot->bitmap_left * 64; slot_offset.y = slot->bitmap_top * 64; error = FT_Bitmap_Blend( handle->library, &slot->bitmap, slot_offset, &bitmap, &bitmap_offset, palette[layer_color_idx] ); } while ( FT_Get_Color_Glyph_Layer( face, glyph_idx, &layer_glyph_idx, &layer_color_idx, &iterator ) ); if ( error ) { FT_Bitmap_Done( handle->library, &bitmap ); goto Next; } else { FT_Bitmap_Done( handle->library, &slot->bitmap ); slot->bitmap = bitmap; slot->bitmap_left = bitmap_offset.x / 64; slot->bitmap_top = bitmap_offset.y / 64; } } else { error = FT_Load_Glyph( face, glyph_idx, handle->load_flags ); if ( error ) goto Next; } width = slot->advance.x ? slot->advance.x >> 6 : size->metrics.y_ppem / 2; if ( X_TOO_LONG( x + width, display ) ) { x = start_x; y += step_y; if ( Y_TOO_LONG( y, display ) ) break; } /* extra space between glyphs */ x++; if ( slot->advance.x == 0 ) { grFillRect( display->bitmap, x, y - width, width, width, display->warn_color ); x += width; } error = FTDemo_Draw_Slot( handle, display, slot, &x, &y ); if ( error ) goto Next; if ( !have_topleft ) { have_topleft = 1; status.topleft = i; } continue; Next: status.num_fails++; } return FT_Err_Ok; } static FT_Error Render_Text( int num_indices, int offset ) { int start_x, start_y, step_y, x, y; FT_Size size; int have_topleft; const char* p; const char* pEnd; int ch; error = FTDemo_Get_Size( handle, &size ); if ( error ) { /* probably a non-existent bitmap font size */ return error; } INIT_SIZE( size, start_x, start_y, step_y, x, y ); p = Text; pEnd = p + strlen( Text ); while ( offset-- ) { ch = utf8_next( &p, pEnd ); if ( ch < 0 ) { p = Text; ch = utf8_next( &p, pEnd ); } } have_topleft = 0; while ( num_indices-- ) { FT_UInt glyph_idx; ch = utf8_next( &p, pEnd ); if ( ch < 0 ) { p = Text; ch = utf8_next( &p, pEnd ); /* not a single character of the text string could be displayed */ if ( !have_topleft ) return error; } glyph_idx = FTDemo_Get_Index( handle, (FT_UInt32)ch ); error = FTDemo_Draw_Index( handle, display, glyph_idx, &x, &y ); if ( error ) goto Next; if ( !have_topleft ) { have_topleft = 1; status.topleft = ch; } if ( X_TOO_LONG( x + ( size->metrics.max_advance >> 6 ), display ) ) { x = start_x; y += step_y; if ( Y_TOO_LONG( y, display ) ) break; } continue; Next: status.num_fails++; } return FT_Err_Ok; } static FT_Error Render_Waterfall( int mid_size, int offset ) { int start_x, start_y, step_y, x, y; int pt_size, step, pt_height; FT_Size size; int have_topleft, start; char text[256]; const char* p; const char* pEnd; start_x = START_X; start_y = START_Y; have_topleft = 0; pt_height = 64 * 72 * display->bitmap->rows / status.res; step = ( mid_size * mid_size / pt_height + 64 ) & ~63; pt_size = mid_size - step * ( mid_size / step ); /* remainder */ while ( 1 ) { int first = offset; int ch; pt_size += step; FTDemo_Set_Current_Charsize( handle, pt_size, status.res ); error = FTDemo_Get_Size( handle, &size ); if ( error ) { /* probably a non-existent bitmap font size */ continue; } step_y = ( size->metrics.height >> 6 ) + 1; x = start_x; y = start_y + ( size->metrics.ascender >> 6 ); start_y += step_y; if ( y >= display->bitmap->rows ) break; p = Text; pEnd = p + strlen( Text ); while ( first-- ) { ch = utf8_next( &p, pEnd ); if ( ch < 0 ) { p = Text; ch = utf8_next( &p, pEnd ); } } start = snprintf( text, 256, "%g: ", pt_size / 64.0 ); snprintf( text + start, (unsigned int)( 256 - start ), "%s", p ); p = text; pEnd = p + strlen( text ); while ( 1 ) { FT_UInt glyph_idx; const char* oldp; oldp = p; ch = utf8_next( &p, pEnd ); if ( ch < 0 ) { /* end of the text (or invalid UTF-8); continue to next size */ break; } glyph_idx = FTDemo_Get_Index( handle, (FT_UInt32)ch ); error = FTDemo_Draw_Index( handle, display, glyph_idx, &x, &y ); if ( error ) goto Next; /* `topleft' should be the first character after the size string */ if ( oldp - text == start && !have_topleft ) { have_topleft = 1; status.topleft = ch; } if ( X_TOO_LONG( x + ( size->metrics.max_advance >> 6 ), display ) ) break; continue; Next: status.num_fails++; } } FTDemo_Set_Current_Charsize( handle, mid_size, status.res ); FTDemo_Get_Size( handle, &size ); return FT_Err_Ok; } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** REST OF THE APPLICATION/PROGRAM *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ static void event_help( void ) { char buf[256]; char version[64] = ""; grEvent dummy_event; FTDemo_Version( handle, version ); FTDemo_Display_Clear( display ); grSetLineHeight( 10 ); grGotoxy( 0, 0 ); grSetMargin( 2, 1 ); grGotobitmap( display->bitmap ); sprintf( buf, "FreeType Glyph Viewer - part of the FreeType %s test suite", version ); grWriteln( buf ); grLn(); grWriteln( "Use the following keys:" ); grLn(); /* |----------------------------------| |----------------------------------| */ grWriteln( "F1, ? display this help screen " ); grWriteln( " " ); grWriteln( "render modes: anti-aliasing modes: " ); grWriteln( " 1 all glyphs A monochrome " ); grWriteln( " 2 all glyphs fancy B normal " ); grWriteln( " (emboldened / slanted) C light " ); grWriteln( " 3 all glyphs stroked D horizontal RGB (LCD) " ); grWriteln( " 4 text string E horizontal BGR (LCD) " ); grWriteln( " 5 waterfall F vertical RGB (LCD) " ); grWriteln( " space cycle forwards G vertical BGR (LCD) " ); grWriteln( " backspace cycle backwards k, l cycle back and forth " ); grWriteln( " " ); grWriteln( "b toggle embedded bitmaps i, I cycle through color " ); grWriteln( " color palette " ); grWriteln( "c toggle coloured bitmaps x, X adjust horizontal " ); grWriteln( "z toggle colour-layered emboldening (in mode 2)" ); grWriteln( " glyphs y, Y adjust vertical " ); grWriteln( " emboldening (in mode 2)" ); grWriteln( "K toggle cache modes s, S adjust slanting " ); grWriteln( " (in mode 2) " ); grWriteln( "p, n previous/next font r, R adjust stroking radius " ); grWriteln( " (in mode 3) " ); grWriteln( "Up, Down adjust size by 1 unit " ); grWriteln( "PgUp, PgDn adjust size by 10 units L cycle through " ); grWriteln( " LCD filtering " ); grWriteln( "Left, Right adjust index by 1 [, ] select custom LCD " ); grWriteln( "F7, F8 adjust index by 16 filter weight " ); grWriteln( "F9, F10 adjust index by 256 (if custom filtering) " ); grWriteln( "F11, F12 adjust index by 4096 -, +(=) adjust selected custom " ); grWriteln( " LCD filter weight " ); grWriteln( "h toggle hinting " ); grWriteln( "H cycle through hinting g, v adjust gamma value " ); grWriteln( " engines (if available) " ); grWriteln( "f toggle forced auto- Tab cycle through charmaps " ); grWriteln( " hinting (if hinting) " ); grWriteln( "w toggle warping P print PNG file " ); grWriteln( " (if available) q, ESC quit ftview " ); /* |----------------------------------| |----------------------------------| */ grLn(); grLn(); grWriteln( "press any key to exit this help screen" ); grRefreshSurface( display->surface ); grListenSurface( display->surface, gr_event_key, &dummy_event ); } static int event_tt_interpreter_version_change( void ) { status.tt_interpreter_version_idx += 1; status.tt_interpreter_version_idx %= status.num_tt_interpreter_versions; error = FT_Property_Set( handle->library, "truetype", "interpreter-version", &status.tt_interpreter_versions[ status.tt_interpreter_version_idx] ); if ( !error ) return 1; return 0; } static int event_warping_change( void ) { if ( handle->lcd_mode == LCD_MODE_AA && handle->autohint ) { FT_Bool new_warping_state = !status.warping; error = FT_Property_Set( handle->library, "autofitter", "warping", &new_warping_state ); if ( !error ) { /* Resetting the cache is perhaps a bit harsh, but I'm too */ /* lazy to walk over all loaded fonts to check whether they */ /* are auto-hinted, then unloading them explicitly. */ FTC_Manager_Reset( handle->cache_manager ); status.warping = new_warping_state; return 1; } } return 0; } static void event_gamma_change( double delta ) { display->gamma += delta; if ( display->gamma > 3.0 ) display->gamma = 3.0; else if ( display->gamma < 0.0 ) display->gamma = 0.0; grSetTargetGamma( display->bitmap, display->gamma ); } static int event_bold_change( double xdelta, double ydelta ) { double old_xbold_factor = status.xbold_factor; double old_ybold_factor = status.ybold_factor; status.xbold_factor += xdelta; status.ybold_factor += ydelta; if ( status.xbold_factor > 0.1 ) status.xbold_factor = 0.1; else if ( status.xbold_factor < -0.1 ) status.xbold_factor = -0.1; if ( status.ybold_factor > 0.1 ) status.ybold_factor = 0.1; else if ( status.ybold_factor < -0.1 ) status.ybold_factor = -0.1; return ( old_xbold_factor == status.xbold_factor && old_ybold_factor == status.ybold_factor ) ? 0 : 1; } static int event_radius_change( double delta ) { double old_radius = status.radius; status.radius += delta; if ( status.radius > 0.05 ) status.radius = 0.05; else if ( status.radius < 0.0 ) status.radius = 0.0; return old_radius == status.radius ? 0 : 1; } static int event_slant_change( double delta ) { double old_slant = status.slant; status.slant += delta; if ( status.slant > 1.0 ) status.slant = 1.0; else if ( status.slant < -1.0 ) status.slant = -1.0; return old_slant == status.slant ? 0 : 1; } static int event_size_change( int delta ) { int old_ptsize = status.ptsize; status.ptsize += delta; if ( status.ptsize < 64 * 1 ) status.ptsize = 1 * 64; else if ( status.ptsize > MAXPTSIZE * 64 ) status.ptsize = MAXPTSIZE * 64; FTDemo_Set_Current_Charsize( handle, status.ptsize, status.res ); return old_ptsize == status.ptsize ? 0 : 1; } static int event_index_change( int delta ) { int old_offset = status.offset; int num_indices = handle->current_font->num_indices; status.offset += delta; if ( status.offset < 0 ) status.offset = 0; else if ( status.offset >= num_indices ) status.offset = num_indices - 1; return old_offset == status.offset ? 0 : 1; } static void event_render_mode_change( int delta ) { if ( delta ) status.render_mode = ( status.render_mode + delta + N_RENDER_MODES ) % N_RENDER_MODES; } static int event_encoding_change( void ) { PFont font = handle->current_font; if ( handle->encoding != FT_ENCODING_ORDER ) font->cmap_index++; else font->cmap_index = 0; FTDemo_Set_Current_Font( handle, font ); status.offset = handle->encoding == FT_ENCODING_ORDER ? 0 : 0x20; return 1; } static int event_font_change( int delta ) { int num_indices; if ( status.font_idx + delta >= handle->num_fonts || status.font_idx + delta < 0 ) return 0; status.font_idx += delta; FTDemo_Set_Current_Font( handle, handle->fonts[status.font_idx] ); FTDemo_Set_Current_Charsize( handle, status.ptsize, status.res ); FTDemo_Update_Current_Flags( handle ); num_indices = handle->current_font->num_indices; if ( status.offset >= num_indices ) status.offset = num_indices - 1; return 1; } static int event_palette_change( int delta ) { FT_Size size; FT_Face face; FT_Palette_Data palette; int palette_index = handle->current_font->palette_index; int old_palette_index = palette_index; error = FTDemo_Get_Size( handle, &size ); if ( error ) { /* probably a non-existent bitmap font size */ return 0; } face = size->face; error = FT_Palette_Data_Get( face, &palette ); if ( error || !palette.num_palettes ) return 0; palette_index += delta; if ( palette_index < 0 ) palette_index = palette.num_palettes - 1; else if ( palette_index >= palette.num_palettes ) palette_index = 0; handle->current_font->palette_index = palette_index; return old_palette_index == palette_index ? 0 : 1; } static int Process_Event( void ) { grEvent event; int ret = 0; if ( *status.keys ) event.key = grKEY( *status.keys++ ); else grListenSurface( display->surface, 0, &event ); status.update = 0; if ( status.render_mode == (int)( event.key - '1' ) ) return ret; if ( event.key >= '1' && event.key < '1' + N_RENDER_MODES ) { status.render_mode = (int)( event.key - '1' ); event_render_mode_change( 0 ); status.update = 1; return ret; } if ( event.key >= 'A' && event.key < 'A' + N_LCD_IDXS ) { int lcd_idx = (int)( event.key - 'A' ); if ( status.lcd_idx == lcd_idx ) return ret; handle->lcd_mode = lcd_modes[lcd_idx]; FTDemo_Update_Current_Flags( handle ); status.update = 1; status.lcd_idx = lcd_idx; return ret; } switch ( event.key ) { case grKeyEsc: case grKEY( 'q' ): ret = 1; break; case grKeyF1: case grKEY( '?' ): event_help(); status.update = 1; break; case grKEY( 'P' ): { FT_String str[64] = "ftview (FreeType) "; FTDemo_Version( handle, str ); FTDemo_Display_Print( display, "ftview.png", str ); } status.update = 0; break; case grKEY( 'b' ): handle->use_sbits = !handle->use_sbits; FTDemo_Update_Current_Flags( handle ); status.update = 1; break; case grKEY( 'c' ): handle->use_color = !handle->use_color; FTDemo_Update_Current_Flags( handle ); status.update = 1; break; case grKEY( 'z' ): handle->use_layers = !handle->use_layers; FTDemo_Update_Current_Flags( handle ); status.update = 1; break; case grKEY( 'i' ): status.update = event_palette_change( 1 ); break; case grKEY( 'I' ): status.update = event_palette_change( -1 ); break; case grKEY( 'K' ): handle->use_sbits_cache = !handle->use_sbits_cache; status.update = 1; break; case grKEY( 'f' ): if ( handle->hinted ) { handle->autohint = !handle->autohint; FTDemo_Update_Current_Flags( handle ); status.update = 1; } break; case grKEY( 'h' ): handle->hinted = !handle->hinted; FTDemo_Update_Current_Flags( handle ); status.update = 1; break; case grKEY( 'H' ): if ( !handle->autohint && handle->lcd_mode != LCD_MODE_LIGHT ) { FT_Face face; FT_Module module; error = FTC_Manager_LookupFace( handle->cache_manager, handle->scaler.face_id, &face ); if ( !error ) { module = &face->driver->root; if ( !strcmp( module->clazz->module_name, "cff" ) ) status.update = FTDemo_Event_Cff_Hinting_Engine_Change( handle->library, &status.cff_hinting_engine, 1 ); else if ( !strcmp( module->clazz->module_name, "type1" ) ) status.update = FTDemo_Event_Type1_Hinting_Engine_Change( handle->library, &status.type1_hinting_engine, 1 ); else if ( !strcmp( module->clazz->module_name, "t1cid" ) ) status.update = FTDemo_Event_T1cid_Hinting_Engine_Change( handle->library, &status.t1cid_hinting_engine, 1 ); else if ( !strcmp( module->clazz->module_name, "truetype" ) ) status.update = event_tt_interpreter_version_change(); if ( status.update ) { /* Resetting the cache is perhaps a bit harsh, but I'm too */ /* lazy to walk over all loaded fonts to check whether they */ /* are of type TTF, then unloading them explicitly. */ FTC_Manager_Reset( handle->cache_manager ); } } } break; case grKEY( 'l' ): case grKEY( 'k' ): status.lcd_idx = ( status.lcd_idx + ( event.key == grKEY( 'l' ) ? 1 : -1 ) + N_LCD_IDXS ) % N_LCD_IDXS; handle->lcd_mode = lcd_modes[status.lcd_idx]; FTDemo_Update_Current_Flags( handle ); status.update = 1; break; case grKEY( 'w' ): status.update = event_warping_change(); break; case grKeySpace: event_render_mode_change( 1 ); status.update = 1; break; case grKeyBackSpace: event_render_mode_change( -1 ); status.update = 1; break; case grKeyTab: status.update = event_encoding_change(); break; case grKEY( 's' ): if ( status.render_mode == RENDER_MODE_FANCY ) status.update = event_slant_change( 0.02 ); break; case grKEY( 'S' ): if ( status.render_mode == RENDER_MODE_FANCY ) status.update = event_slant_change( -0.02 ); break; case grKEY( 'r' ): if ( status.render_mode == RENDER_MODE_STROKE ) status.update = event_radius_change( 0.005 ); break; case grKEY( 'R' ): if ( status.render_mode == RENDER_MODE_STROKE ) status.update = event_radius_change( -0.005 ); break; case grKEY( 'x' ): if ( status.render_mode == RENDER_MODE_FANCY ) status.update = event_bold_change( 0.005, 0.0 ); break; case grKEY( 'X' ): if ( status.render_mode == RENDER_MODE_FANCY ) status.update = event_bold_change( -0.005, 0.0 ); break; case grKEY( 'y' ): if ( status.render_mode == RENDER_MODE_FANCY ) status.update = event_bold_change( 0.0, 0.005 ); break; case grKEY( 'Y' ): if ( status.render_mode == RENDER_MODE_FANCY ) status.update = event_bold_change( 0.0, -0.005 ); break; case grKEY( 'g' ): event_gamma_change( 0.1 ); status.update = 1; break; case grKEY( 'v' ): event_gamma_change( -0.1 ); status.update = 1; break; case grKEY( 'n' ): status.update = event_font_change( 1 ); break; case grKEY( 'p' ): status.update = event_font_change( -1 ); break; case grKeyUp: status.update = event_size_change( 64 ); break; case grKeyDown: status.update = event_size_change( -64 ); break; case grKeyPageUp: status.update = event_size_change( 640 ); break; case grKeyPageDown: status.update = event_size_change( -640 ); break; case grKeyLeft: status.update = event_index_change( -1 ); break; case grKeyRight: status.update = event_index_change( 1 ); break; case grKeyF7: status.update = event_index_change( -0x10 ); break; case grKeyF8: status.update = event_index_change( 0x10 ); break; case grKeyF9: status.update = event_index_change( -0x100 ); break; case grKeyF10: status.update = event_index_change( 0x100 ); break; case grKeyF11: status.update = event_index_change( -0x1000 ); break; case grKeyF12: status.update = event_index_change( 0x1000 ); break; default: break; } if ( FT_Library_SetLcdFilterWeights( NULL, NULL ) == FT_Err_Unimplemented_Feature || handle->lcd_mode < LCD_MODE_RGB ) return ret; switch ( event.key ) { case grKEY( 'L' ): FTC_Manager_RemoveFaceID( handle->cache_manager, handle->scaler.face_id ); status.lcd_filter++; switch ( status.lcd_filter ) { case FT_LCD_FILTER_NONE: case FT_LCD_FILTER_DEFAULT: case FT_LCD_FILTER_LIGHT: case FT_LCD_FILTER_LEGACY1: FT_Library_SetLcdFilter( handle->library, (FT_LcdFilter)status.lcd_filter ); break; default: FT_Library_SetLcdFilterWeights( handle->library, status.filter_weights ); status.lcd_filter = -1; } status.update = 1; break; case grKEY( '[' ): if ( status.lcd_filter < 0 ) { status.fw_idx--; if ( status.fw_idx < 0 ) status.fw_idx = 4; status.update = 1; } break; case grKEY( ']' ): if ( status.lcd_filter < 0 ) { status.fw_idx++; if ( status.fw_idx > 4 ) status.fw_idx = 0; status.update = 1; } break; case grKEY( '-' ): if ( status.lcd_filter < 0 ) { FTC_Manager_RemoveFaceID( handle->cache_manager, handle->scaler.face_id ); status.filter_weights[status.fw_idx]--; FT_Library_SetLcdFilterWeights( handle->library, status.filter_weights ); status.update = 1; } break; case grKEY( '+' ): case grKEY( '=' ): if ( status.lcd_filter < 0 ) { FTC_Manager_RemoveFaceID( handle->cache_manager, handle->scaler.face_id ); status.filter_weights[status.fw_idx]++; FT_Library_SetLcdFilterWeights( handle->library, status.filter_weights ); status.update = 1; } break; default: break; } return ret; } static void write_header( FT_Error error_code ) { char buf[256]; int line = 4; FT_Face face; FTC_Manager_LookupFace( handle->cache_manager, handle->scaler.face_id, &face ); FTDemo_Draw_Header( handle, display, status.ptsize, status.res, status.render_mode != RENDER_MODE_TEXT && status.render_mode != RENDER_MODE_WATERFALL ? status.topleft : -1, error_code ); /* render mode */ { const char* render_mode = NULL; switch ( status.render_mode ) { case RENDER_MODE_ALL: render_mode = "all glyphs"; break; case RENDER_MODE_FANCY: render_mode = "fancy"; break; case RENDER_MODE_STROKE: render_mode = "stroked"; break; case RENDER_MODE_TEXT: render_mode = "text string"; break; case RENDER_MODE_WATERFALL: render_mode = "waterfall"; break; } sprintf( buf, "%d: %s", status.render_mode + 1, render_mode ); grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, buf, display->fore_color ); } if ( status.render_mode == RENDER_MODE_FANCY ) { /* x emboldening */ sprintf( buf, " x: % .3f", status.xbold_factor ); grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, buf, display->fore_color ); /* y emboldening */ sprintf( buf, " y: % .3f", status.ybold_factor ); grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, buf, display->fore_color ); /* slanting */ sprintf( buf, " s: % .3f", status.slant ); grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, buf, display->fore_color ); } if ( status.render_mode == RENDER_MODE_STROKE ) { /* stroking radius */ sprintf( buf, " radius: %.3f", status.radius ); grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, buf, display->fore_color ); } line++; /* anti-aliasing */ { const char* lcd_mode; switch ( handle->lcd_mode ) { case LCD_MODE_AA: lcd_mode = "normal AA"; break; case LCD_MODE_LIGHT: lcd_mode = "light AA"; break; case LCD_MODE_RGB: lcd_mode = "LCD (horiz. RGB)"; break; case LCD_MODE_BGR: lcd_mode = "LCD (horiz. BGR)"; break; case LCD_MODE_VRGB: lcd_mode = "LCD (vert. RGB)"; break; case LCD_MODE_VBGR: lcd_mode = "LCD (vert. BGR)"; break; default: handle->lcd_mode = 0; lcd_mode = "monochrome"; } grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, lcd_mode, display->fore_color ); } /* hinting */ sprintf( buf, "hinting: %s", handle->hinted ? "on" : "off" ); grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, buf, display->fore_color ); if ( handle->hinted ) { /* auto-hinting */ sprintf( buf, " forced auto: %s", ( handle->autohint || handle->lcd_mode == LCD_MODE_LIGHT ) ? "on" : "off" ); grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, buf, display->fore_color ); } if ( !handle->autohint && handle->lcd_mode != LCD_MODE_LIGHT ) { /* hinting engine */ FT_Module module; const char* hinting_engine = NULL; module = &face->driver->root; if ( !strcmp( module->clazz->module_name, "cff" ) ) { switch ( status.cff_hinting_engine ) { case FT_HINTING_FREETYPE: hinting_engine = "FreeType"; break; case FT_HINTING_ADOBE: hinting_engine = "Adobe"; break; } } else if ( !strcmp( module->clazz->module_name, "type1" ) ) { switch ( status.type1_hinting_engine ) { case FT_HINTING_FREETYPE: hinting_engine = "FreeType"; break; case FT_HINTING_ADOBE: hinting_engine = "Adobe"; break; } } else if ( !strcmp( module->clazz->module_name, "t1cid" ) ) { switch ( status.t1cid_hinting_engine ) { case FT_HINTING_FREETYPE: hinting_engine = "FreeType"; break; case FT_HINTING_ADOBE: hinting_engine = "Adobe"; break; } } else if ( !strcmp( module->clazz->module_name, "truetype" ) ) { switch ( status.tt_interpreter_versions[ status.tt_interpreter_version_idx] ) { case TT_INTERPRETER_VERSION_35: hinting_engine = "v35"; break; case TT_INTERPRETER_VERSION_38: hinting_engine = "v38"; break; case TT_INTERPRETER_VERSION_40: hinting_engine = "v40"; break; } } if ( hinting_engine ) { sprintf( buf, "engine: %s", hinting_engine ); grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, buf, display->fore_color ); } } if ( handle->lcd_mode == LCD_MODE_AA && handle->autohint ) { sprintf( buf, "warping: %s", status.warping ? "on" : "off" ); grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, buf, display->fore_color ); } line++; /* embedded bitmaps */ sprintf( buf, "bitmaps: %s", handle->use_sbits ? "on" : "off" ); grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, buf, display->fore_color ); if ( FT_HAS_COLOR( face ) ) { sprintf( buf, "color:" ); grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, buf, display->fore_color ); /* color bitmaps */ sprintf( buf, " bitmaps: %s", handle->use_color ? "on" : "off" ); grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, buf, display->fore_color ); /* color-layered glyphs */ sprintf( buf, " outlines: %s", handle->use_layers ? "on" : "off" ); grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, buf, display->fore_color ); /* color palette */ sprintf( buf, " palette idx: %d", handle->current_font->palette_index ); grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, buf, display->fore_color ); } /* cache */ sprintf( buf, "cache: %s", handle->use_sbits_cache ? "on" : "off" ); grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, buf, display->fore_color ); line++; /* LCD filtering */ if ( FT_Library_SetLcdFilterWeights( NULL, NULL ) != FT_Err_Unimplemented_Feature && handle->lcd_mode >= LCD_MODE_RGB ) { sprintf( buf, "filter: %s", status.lcd_filter == 0 ? "none" : status.lcd_filter == 1 ? "default" : status.lcd_filter == 2 ? "light" : status.lcd_filter == 3 ? "legacy" : "custom" ); grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, buf, display->fore_color ); /* custom LCD filter settings */ if ( status.lcd_filter < 0 ) { int fwi = status.fw_idx; unsigned char* fw = status.filter_weights; int i; for ( i = 0; i < 5; i++ ) { sprintf( buf, " %s0x%02X%s", fwi == i ? "[" : " ", fw[i], fwi == i ? "]" : " " ); grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, buf, display->fore_color ); } } } grRefreshSurface( display->surface ); } static void usage( char* execname ) { fprintf( stderr, "\n" "ftview: simple glyph viewer -- part of the FreeType project\n" "-----------------------------------------------------------\n" "\n" ); fprintf( stderr, "Usage: %s [options] pt font ...\n" "\n", execname ); fprintf( stderr, " pt The point size for the given resolution.\n" " If resolution is 72dpi, this directly gives the\n" " ppem value (pixels per EM).\n" ); fprintf( stderr, " font The font file(s) to display.\n" " For Type 1 font files, ftview also tries to attach\n" " the corresponding metrics file (with extension\n" " `.afm' or `.pfm').\n" "\n" ); fprintf( stderr, " -d WxHxD Set the window width, height, and color depth\n" " (default: 640x480x24).\n" " -k keys Emulate sequence of keystrokes upon start-up.\n" " If the keys contain `q', use batch mode.\n" " -r R Use resolution R dpi (default: 72dpi).\n" " -f index Specify first index to display (default: 0).\n" " -e enc Specify encoding tag (default: no encoding).\n" " Common values: `unic' (Unicode), `symb' (symbol),\n" " `ADOB' (Adobe standard), `ADBC' (Adobe custom).\n" " -m text Use `text' for rendering.\n" ); fprintf( stderr, " -l mode Set start-up rendering mode (0 <= mode <= %d).\n", N_LCD_IDXS - 1 ); fprintf( stderr, " -L N,... Set LCD filter or geometry by comma-separated values.\n" " -p Preload file in memory to simulate memory-mapping.\n" "\n" " -v Show version.\n" "\n" ); exit( 1 ); } static void parse_cmdline( int* argc, char** argv[] ) { char* execname; int option; execname = ft_basename( (*argv)[0] ); while ( 1 ) { option = getopt( *argc, *argv, "d:e:f:k:L:l:m:pr:v" ); if ( option == -1 ) break; switch ( option ) { case 'd': status.dims = optarg; break; case 'e': handle->encoding = FTDemo_Make_Encoding_Tag( optarg ); break; case 'f': status.offset = atoi( optarg ); break; case 'k': status.keys = optarg; while ( *optarg && *optarg != 'q' ) optarg++; if ( *optarg == 'q' ) status.device = "batch"; break; case 'l': status.lcd_idx = atoi( optarg ); if ( status.lcd_idx < 0 || status.lcd_idx >= N_LCD_IDXS ) { fprintf( stderr, "argument to `l' must be in the range [0;%d]\n", N_LCD_IDXS - 1 ); exit( 3 ); } handle->lcd_mode = lcd_modes[status.lcd_idx]; break; case 'L': { int i, buf[6]; i = sscanf( optarg, "%d,%d,%d,%d,%d,%d", buf, buf + 1, buf + 2, buf + 3, buf + 4, buf + 5 ); if ( FT_Library_SetLcdFilterWeights( NULL, NULL ) != FT_Err_Unimplemented_Feature && i == 5 ) { status.filter_weights[0] = (unsigned char)buf[0]; status.filter_weights[1] = (unsigned char)buf[1]; status.filter_weights[2] = (unsigned char)buf[2]; status.filter_weights[3] = (unsigned char)buf[3]; status.filter_weights[4] = (unsigned char)buf[4]; FT_Library_SetLcdFilterWeights( handle->library, status.filter_weights ); status.lcd_filter = -1; } else if ( FT_Library_SetLcdGeometry( NULL, NULL ) != FT_Err_Unimplemented_Feature && i == 6 ) { FT_Vector sub[3] = { { buf[0], buf[1] }, { buf[2], buf[3] }, { buf[4], buf[5] } }; FT_Library_SetLcdGeometry( handle->library, sub ); } } break; case 'm': Text = optarg; status.render_mode = RENDER_MODE_TEXT; break; case 'p': status.preload = 1; break; case 'r': status.res = atoi( optarg ); if ( status.res < 1 ) usage( execname ); break; case 'v': { FT_String str[64] = "ftview (FreeType) "; FTDemo_Version( handle, str ); printf( "%s\n", str ); exit( 0 ); } /* break; */ default: usage( execname ); break; } } *argc -= optind; *argv += optind; if ( *argc <= 1 ) usage( execname ); status.ptsize = (int)( atof( *argv[0] ) * 64.0 ); if ( status.ptsize == 0 ) status.ptsize = 64 * 10; (*argc)--; (*argv)++; } int main( int argc, char* argv[] ) { unsigned int dflt_tt_interpreter_version; int i; unsigned int versions[3] = { TT_INTERPRETER_VERSION_35, TT_INTERPRETER_VERSION_38, TT_INTERPRETER_VERSION_40 }; /* Initialize engine */ handle = FTDemo_New(); parse_cmdline( &argc, &argv ); if ( status.lcd_filter != -1 ) FT_Library_SetLcdFilter( handle->library, (FT_LcdFilter)status.lcd_filter ); /* get the default values as compiled into FreeType */ FT_Property_Get( handle->library, "cff", "hinting-engine", &status.cff_hinting_engine ); FT_Property_Get( handle->library, "type1", "hinting-engine", &status.type1_hinting_engine ); FT_Property_Get( handle->library, "t1cid", "hinting-engine", &status.t1cid_hinting_engine ); /* collect all available versions, then set again the default */ FT_Property_Get( handle->library, "truetype", "interpreter-version", &dflt_tt_interpreter_version ); for ( i = 0; i < 3; i++ ) { error = FT_Property_Set( handle->library, "truetype", "interpreter-version", &versions[i] ); if ( !error ) status.tt_interpreter_versions[ status.num_tt_interpreter_versions++] = versions[i]; if ( versions[i] == dflt_tt_interpreter_version ) status.tt_interpreter_version_idx = i; } FT_Property_Set( handle->library, "truetype", "interpreter-version", &dflt_tt_interpreter_version ); FT_Property_Get( handle->library, "autofitter", "warping", &status.warping ); if ( status.preload ) FTDemo_Set_Preload( handle, 1 ); for ( ; argc > 0; argc--, argv++ ) FTDemo_Install_Font( handle, argv[0], 0, 0 ); if ( handle->num_fonts == 0 ) Fatal( "could not find/open any font file" ); display = FTDemo_Display_New( status.device, status.dims ); if ( !display ) Fatal( "could not allocate display surface" ); grSetTitle( display->surface, "FreeType Glyph Viewer - press ? for help" ); status.num_fails = 0; event_font_change( 0 ); do { if ( !status.update ) continue; FTDemo_Display_Clear( display ); switch ( status.render_mode ) { case RENDER_MODE_ALL: error = Render_All( handle->current_font->num_indices, status.offset ); break; case RENDER_MODE_FANCY: error = Render_Fancy( handle->current_font->num_indices, status.offset ); break; case RENDER_MODE_STROKE: error = Render_Stroke( handle->current_font->num_indices, status.offset ); break; case RENDER_MODE_TEXT: error = Render_Text( -1, status.offset ); break; case RENDER_MODE_WATERFALL: error = Render_Waterfall( status.ptsize, status.offset ); break; } write_header( error ); } while ( Process_Event() == 0 ); printf( "Execution completed successfully.\n" ); printf( "Fails = %d\n", status.num_fails ); FTDemo_Display_Done( display ); FTDemo_Done( handle ); exit( 0 ); /* for safety reasons */ /* return 0; */ /* never reached */ } /* End */ ft2demos-2.10.1/src/ftmulti.c0000644000175000001440000010150113502347420015574 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 1996-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* */ /* FTMulti- a simple multiple masters font viewer */ /* */ /* Press ? when running this program to have a list of key-bindings */ /* */ /****************************************************************************/ #include #include FT_FREETYPE_H #include FT_FONT_FORMATS_H #include FT_MODULE_H #include FT_DRIVER_H #include FT_MULTIPLE_MASTERS_H #include "common.h" #include "mlgetopt.h" #include #include #include #include #include "graph.h" #include "grfont.h" #define DIM_X 640 #define DIM_Y 480 #define MAXPTSIZE 500 /* dtp */ #define MAX_MM_AXES 6 /* definitions in ftcommon.c */ unsigned int FTDemo_Event_Cff_Hinting_Engine_Change( FT_Library library, unsigned int* current, unsigned int delta ); unsigned int FTDemo_Event_Type1_Hinting_Engine_Change( FT_Library library, unsigned int* current, unsigned int delta ); unsigned int FTDemo_Event_T1cid_Hinting_Engine_Change( FT_Library library, unsigned int* current, unsigned int delta ); static char Header[256]; static const char* new_header = NULL; static const unsigned char* Text = (unsigned char*) "The quick brown fox jumps over the lazy dog 0123456789 " "\342\352\356\373\364\344\353\357\366\374\377\340\371\351\350\347 " "&#~\"\'(-`_^@)=+\260 ABCDEFGHIJKLMNOPQRSTUVWXYZ " "$\243^\250*\265\371%!\247:/;.,?<>"; static FT_Library library; /* the FreeType library */ static FT_Face face; /* the font face */ static FT_Size size; /* the font size */ static FT_GlyphSlot glyph; /* the glyph slot */ static unsigned long encoding = FT_ENCODING_NONE; static unsigned int cff_hinting_engine; static unsigned int type1_hinting_engine; static unsigned int t1cid_hinting_engine; static unsigned int tt_interpreter_versions[3]; static unsigned int num_tt_interpreter_versions; static unsigned int tt_interpreter_version_idx; static const char* font_format; static FT_Error error; /* error returned by FreeType? */ static grSurface* surface; /* current display surface */ static grBitmap* bit; /* current display bitmap */ static int width = DIM_X; /* window width */ static int height = DIM_Y; /* window height */ static int num_glyphs; /* number of glyphs */ static int ptsize; /* current point size */ static int hinted = 1; /* is glyph hinting active? */ static int grouping = 1; /* is axis grouping active? */ static int antialias = 1; /* is anti-aliasing active? */ static int use_sbits = 1; /* do we use embedded bitmaps? */ static int Num; /* current first glyph index */ static int res = 72; static grColor fore_color = { 255 }; static int Fail; static int graph_init = 0; static int render_mode = 1; static FT_MM_Var *multimaster = NULL; static FT_Fixed design_pos [MAX_MM_AXES]; static FT_Fixed requested_pos[MAX_MM_AXES]; static unsigned int requested_cnt = 0; static unsigned int used_num_axis = 0; /* * We use the following arrays to support both the display of all axes and * the grouping of axes. If grouping is active, hidden axes that have the * same tag as a non-hidden axis are not displayed; instead, they receive * the same axis value as the non-hidden one. */ static unsigned int hidden[MAX_MM_AXES]; static int shown_axes[MAX_MM_AXES]; /* array of axis indices */ static unsigned int num_shown_axes; #define DEBUGxxx #ifdef DEBUG #define LOG( x ) LogMessage x #else #define LOG( x ) /* empty */ #endif #ifdef DEBUG static void LogMessage( const char* fmt, ... ) { va_list ap; va_start( ap, fmt ); vfprintf( stderr, fmt, ap ); va_end( ap ); } #endif /* PanicZ */ static void PanicZ( const char* message ) { fprintf( stderr, "%s\n error = 0x%04x\n", message, error ); exit( 1 ); } static unsigned long make_tag( char *s ) { int i; unsigned long l = 0; for ( i = 0; i < 4; i++ ) { if ( !s[i] ) break; l <<= 8; l += (unsigned long)s[i]; } return l; } static void parse_design_coords( char *s ) { for ( requested_cnt = 0; requested_cnt < MAX_MM_AXES && *s; requested_cnt++ ) { requested_pos[requested_cnt] = (FT_Fixed)( strtod( s, &s ) * 65536.0 ); while ( *s==' ' ) ++s; } } static void set_up_axes( void ) { if ( grouping ) { int i, j, idx; /* * `ftmulti' is a diagnostic tool that should be able to handle * pathological situations also; for this reason the looping code * below is a bit more complicated in comparison to normal * applications. * * In particular, the loop handles the following cases gracefully, * avoiding grouping. * * . multiple non-hidden axes have the same tag * * . multiple hidden axes have the same tag without a corresponding * non-hidden axis */ idx = -1; for ( i = 0; i < (int)used_num_axis; i++ ) { int do_skip; unsigned long tag = multimaster->axis[i].tag; do_skip = 0; if ( hidden[i] ) { /* if axis is hidden, check whether an already assigned */ /* non-hidden axis has the same tag; if yes, skip it */ for ( j = 0; j <= idx; j++ ) if ( !hidden[shown_axes[j]] && multimaster->axis[shown_axes[j]].tag == tag ) { do_skip = 1; break; } } else { /* otherwise check whether we have already assigned this axis */ for ( j = 0; j <= idx; j++ ) if ( shown_axes[j] == i ) { do_skip = 1; break; } } if ( do_skip ) continue; /* we have a new axis to display */ shown_axes[++idx] = i; /* if axis is hidden, use a non-hidden axis */ /* with the same tag instead if available */ if ( hidden[i] ) { for ( j = i + 1; j < (int)used_num_axis; j++ ) if ( !hidden[j] && multimaster->axis[j].tag == tag ) shown_axes[idx] = j; } } num_shown_axes = idx + 1; } else { unsigned int i; /* show all axes */ for ( i = 0; i < used_num_axis; i++ ) shown_axes[i] = i; num_shown_axes = used_num_axis; } } /* Clear `bit' bitmap/pixmap */ static void Clear_Display( void ) { long bitmap_size = (long)bit->pitch * bit->rows; if ( bitmap_size < 0 ) bitmap_size = -bitmap_size; memset( bit->buffer, 0, (unsigned long)bitmap_size ); } /* Initialize the display bitmap named `bit' */ static void Init_Display( void ) { grBitmap bitmap = { height, width, 0, gr_pixel_mode_gray, 256, NULL }; grInitDevices(); surface = grNewSurface( 0, &bitmap ); if ( !surface ) PanicZ( "could not allocate display surface\n" ); bit = (grBitmap*)surface; graph_init = 1; } /* Render a single glyph with the `grays' component */ static FT_Error Render_Glyph( int x_offset, int y_offset ) { grBitmap bit3; FT_Pos x_top, y_top; /* first, render the glyph image into a bitmap */ if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) { error = FT_Render_Glyph( glyph, antialias ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO ); if ( error ) return error; } /* now blit it to our display screen */ bit3.rows = (int)glyph->bitmap.rows; bit3.width = (int)glyph->bitmap.width; bit3.pitch = glyph->bitmap.pitch; bit3.buffer = glyph->bitmap.buffer; switch ( glyph->bitmap.pixel_mode ) { case FT_PIXEL_MODE_MONO: bit3.mode = gr_pixel_mode_mono; bit3.grays = 0; break; case FT_PIXEL_MODE_GRAY: bit3.mode = gr_pixel_mode_gray; bit3.grays = glyph->bitmap.num_grays; } /* Then, blit the image to the target surface */ x_top = x_offset + glyph->bitmap_left; y_top = y_offset - glyph->bitmap_top; grBlitGlyphToBitmap( bit, &bit3, x_top, y_top, fore_color ); return 0; } static void Reset_Scale( int pointSize ) { (void)FT_Set_Char_Size( face, pointSize << 6, pointSize << 6, (FT_UInt)res, (FT_UInt)res ); } static FT_Error LoadChar( unsigned int idx, int hint ) { int flags; flags = FT_LOAD_DEFAULT; if ( !hint ) flags |= FT_LOAD_NO_HINTING; if ( !use_sbits ) flags |= FT_LOAD_NO_BITMAP; return FT_Load_Glyph( face, idx, flags ); } static FT_Error Render_All( unsigned int first_glyph, int pt_size ) { FT_F26Dot6 start_x, start_y, step_y, x, y; unsigned int i; start_x = 4; start_y = pt_size + ( num_shown_axes > MAX_MM_AXES / 2 ? 52 : 44 ); step_y = size->metrics.y_ppem + 10; x = start_x; y = start_y; i = first_glyph; #if 0 while ( i < first_glyph + 1 ) #else while ( i < (unsigned int)num_glyphs ) #endif { if ( !( error = LoadChar( i, hinted ) ) ) { #ifdef DEBUG if ( i <= first_glyph + 6 ) { LOG(( "metrics[%02d] = [%x %x]\n", i, glyph->metrics.horiBearingX, glyph->metrics.horiAdvance )); if ( i == first_glyph + 6 ) LOG(( "-------------------------\n" )); } #endif Render_Glyph( x, y ); x += ( ( glyph->metrics.horiAdvance + 32 ) >> 6 ) + 1; if ( x + size->metrics.x_ppem > bit->width ) { x = start_x; y += step_y; if ( y >= bit->rows ) return FT_Err_Ok; } } else Fail++; i++; } return FT_Err_Ok; } static FT_Error Render_Text( unsigned int first_glyph, int pt_size ) { FT_F26Dot6 start_x, start_y, step_y, x, y; unsigned int i; const unsigned char* p; start_x = 4; start_y = pt_size + ( num_shown_axes > MAX_MM_AXES / 2 ? 52 : 44 ); step_y = size->metrics.y_ppem + 10; x = start_x; y = start_y; i = first_glyph; p = Text; while ( i > 0 && *p ) { p++; i--; } while ( *p ) { if ( !( error = LoadChar( FT_Get_Char_Index( face, (unsigned char)*p ), hinted ) ) ) { #ifdef DEBUG if ( i <= first_glyph + 6 ) { LOG(( "metrics[%02d] = [%x %x]\n", i, glyph->metrics.horiBearingX, glyph->metrics.horiAdvance )); if ( i == first_glyph + 6 ) LOG(( "-------------------------\n" )); } #endif Render_Glyph( x, y ); x += ( ( glyph->metrics.horiAdvance + 32 ) >> 6 ) + 1; if ( x + size->metrics.x_ppem > bit->width ) { x = start_x; y += step_y; if ( y >= bit->rows ) return FT_Err_Ok; } } else Fail++; i++; p++; } return FT_Err_Ok; } static void Help( void ) { char buf[256]; char version[64]; FT_Int major, minor, patch; grEvent dummy_event; FT_Library_Version( library, &major, &minor, &patch ); if ( patch ) sprintf( version, "%d.%d.%d", major, minor, patch ); else sprintf( version, "%d.%d", major, minor ); Clear_Display(); grSetLineHeight( 10 ); grGotoxy( 0, 0 ); grSetMargin( 2, 1 ); grGotobitmap( bit ); sprintf( buf, "FreeType MM Glyph Viewer - part of the FreeType %s test suite", version ); grWriteln( buf ); grLn(); grWriteln( "This program displays all glyphs from one or several" ); grWriteln( "Multiple Masters, GX, or OpenType Variation font files." ); grLn(); grWriteln( "Use the following keys:"); grLn(); grWriteln( "? display this help screen" ); grWriteln( "A toggle axis grouping" ); grWriteln( "a toggle anti-aliasing" ); grWriteln( "h toggle outline hinting" ); grWriteln( "b toggle embedded bitmaps" ); grWriteln( "space toggle rendering mode" ); grLn(); grWriteln( "p, n previous/next font" ); grLn(); grWriteln( "H cycle through hinting engines (if available)" ); grLn(); grWriteln( "Up, Down change pointsize by 1 unit" ); grWriteln( "PgUp, PgDn change pointsize by 10 units" ); grLn(); grWriteln( "Left, Right adjust index by 1" ); grWriteln( "F7, F8 adjust index by 10" ); grWriteln( "F9, F10 adjust index by 100" ); grWriteln( "F11, F12 adjust index by 1000" ); grLn(); grWriteln( "F1, F2 adjust first axis by 1/50th of its range" ); grWriteln( "F3, F4 adjust second axis by 1/50th of its range" ); grWriteln( "F5, F6 adjust third axis by 1/50th of its range" ); grWriteln( "1, 2 adjust fourth axis by 1/50th of its range" ); grWriteln( "3, 4 adjust fifth axis by 1/50th of its range" ); grWriteln( "5, 6 adjust sixth axis by 1/50th of its range" ); grLn(); grWriteln( "Axes marked with an asterisk are hidden." ); grLn(); grLn(); grWriteln( "press any key to exit this help screen" ); grRefreshSurface( surface ); grListenSurface( surface, gr_event_key, &dummy_event ); } static void tt_interpreter_version_change( void ) { tt_interpreter_version_idx += 1; tt_interpreter_version_idx %= num_tt_interpreter_versions; FT_Property_Set( library, "truetype", "interpreter-version", &tt_interpreter_versions[tt_interpreter_version_idx] ); } static int Process_Event( void ) { grEvent event; int i; unsigned int axis; grListenSurface( surface, 0, &event ); switch ( event.key ) { case grKeyEsc: /* ESC or q */ case grKEY( 'q' ): return 0; case grKEY( '?' ): Help(); break; /* mode keys */ case grKEY( 'A' ): grouping = !grouping; new_header = grouping ? "axis grouping is now on" : "axis grouping is now off"; set_up_axes(); break; case grKEY( 'a' ): antialias = !antialias; new_header = antialias ? "anti-aliasing is now on" : "anti-aliasing is now off"; break; case grKEY( 'b' ): use_sbits = !use_sbits; new_header = use_sbits ? "embedded bitmaps are now used if available" : "embedded bitmaps are now ignored"; break; case grKEY( 'n' ): case grKEY( 'p' ): return (int)event.key; case grKEY( 'h' ): hinted = !hinted; new_header = hinted ? "glyph hinting is now active" : "glyph hinting is now ignored"; break; case grKEY( ' ' ): render_mode ^= 1; new_header = render_mode ? "rendering all glyphs in font" : "rendering test text string"; break; case grKEY( 'H' ): if ( !strcmp( font_format, "CFF" ) ) FTDemo_Event_Cff_Hinting_Engine_Change( library, &cff_hinting_engine, 1); else if ( !strcmp( font_format, "Type 1" ) ) FTDemo_Event_Type1_Hinting_Engine_Change( library, &type1_hinting_engine, 1); else if ( !strcmp( font_format, "CID Type 1" ) ) FTDemo_Event_T1cid_Hinting_Engine_Change( library, &t1cid_hinting_engine, 1); else if ( !strcmp( font_format, "TrueType" ) ) tt_interpreter_version_change(); break; /* MM related keys */ case grKeyF1: i = -20; axis = 0; goto Do_Axis; case grKeyF2: i = 20; axis = 0; goto Do_Axis; case grKeyF3: i = -20; axis = 1; goto Do_Axis; case grKeyF4: i = 20; axis = 1; goto Do_Axis; case grKeyF5: i = -20; axis = 2; goto Do_Axis; case grKeyF6: i = 20; axis = 2; goto Do_Axis; case grKEY( '1' ): i = -20; axis = 3; goto Do_Axis; case grKEY( '2' ): i = 20; axis = 3; goto Do_Axis; case grKEY( '3' ): i = -20; axis = 4; goto Do_Axis; case grKEY( '4' ): i = 20; axis = 4; goto Do_Axis; case grKEY( '5' ): i = -20; axis = 5; goto Do_Axis; case grKEY( '6' ): i = 20; axis = 5; goto Do_Axis; /* scaling related keys */ case grKeyPageUp: i = 10; goto Do_Scale; case grKeyPageDown: i = -10; goto Do_Scale; case grKeyUp: i = 1; goto Do_Scale; case grKeyDown: i = -1; goto Do_Scale; /* glyph index related keys */ case grKeyLeft: i = -1; goto Do_Glyph; case grKeyRight: i = 1; goto Do_Glyph; case grKeyF7: i = -10; goto Do_Glyph; case grKeyF8: i = 10; goto Do_Glyph; case grKeyF9: i = -100; goto Do_Glyph; case grKeyF10: i = 100; goto Do_Glyph; case grKeyF11: i = -1000; goto Do_Glyph; case grKeyF12: i = 1000; goto Do_Glyph; default: ; } return 1; Do_Axis: if ( axis < num_shown_axes ) { FT_Var_Axis* a; FT_Fixed pos; unsigned int n; /* convert to real axis index */ axis = (unsigned int)shown_axes[axis]; a = multimaster->axis + axis; pos = design_pos[axis]; /* * Normalize i. Changing by 20 is all very well for PostScript fonts, * which tend to have a range of ~1000 per axis, but it's not useful * for mac fonts, which have a range of ~3. And it's rather extreme * for optical size even in PS. */ pos += FT_MulDiv( i, a->maximum - a->minimum, 1000 ); if ( pos < a->minimum ) pos = a->minimum; if ( pos > a->maximum ) pos = a->maximum; /* for MM fonts, round the design coordinates to integers, */ /* otherwise round to two decimal digits to make the PS name short */ if ( !FT_IS_SFNT( face ) ) pos = FT_RoundFix( pos ); else { double x; x = pos / 65536.0 * 100.0; x += x < 0.0 ? -0.5 : 0.5; x = (int)x; x = x / 100.0 * 65536.0; x += x < 0.0 ? -0.5 : 0.5; pos = (int)x; } design_pos[axis] = pos; if ( grouping ) { /* synchronize hidden axes with visible axis */ for ( n = 0; n < used_num_axis; n++ ) if ( hidden[n] && multimaster->axis[n].tag == a->tag ) design_pos[n] = pos; } FT_Set_Var_Design_Coordinates( face, used_num_axis, design_pos ); } return 1; Do_Scale: ptsize += i; if ( ptsize < 1 ) ptsize = 1; if ( ptsize > MAXPTSIZE ) ptsize = MAXPTSIZE; return 1; Do_Glyph: Num += i; if ( Num < 0 ) Num = 0; if ( Num >= num_glyphs ) Num = num_glyphs - 1; return 1; } static void usage( char* execname ) { fprintf( stderr, "\n" "ftmulti: multiple masters font viewer - part of FreeType\n" "--------------------------------------------------------\n" "\n" ); fprintf( stderr, "Usage: %s [options] pt font ...\n" "\n", execname ); fprintf( stderr, " pt The point size for the given resolution.\n" " If resolution is 72dpi, this directly gives the\n" " ppem value (pixels per EM).\n" ); fprintf( stderr, " font The font file(s) to display.\n" "\n" ); fprintf( stderr, " -w W Set window width to W pixels (default: %dpx).\n" " -h H Set window height to H pixels (default: %dpx).\n" "\n", DIM_X, DIM_Y ); fprintf( stderr, " -e encoding Specify encoding tag (default: no encoding).\n" " Common values: `unic' (Unicode), `symb' (symbol),\n" " `ADOB' (Adobe standard), `ADBC' (Adobe custom).\n" " -r R Use resolution R dpi (default: 72dpi).\n" " -f index Specify first glyph index to display.\n" " -d \"axis1 axis2 ...\"\n" " Specify the design coordinates for each\n" " variation axis at start-up.\n" "\n" " -v Show version." "\n" ); exit( 1 ); } int main( int argc, char* argv[] ) { int old_ptsize, orig_ptsize, file; int first_glyph = 0; int XisSetup = 0; char* execname; int option; int file_loaded; unsigned int n; unsigned int dflt_tt_interpreter_version; unsigned int versions[3] = { TT_INTERPRETER_VERSION_35, TT_INTERPRETER_VERSION_38, TT_INTERPRETER_VERSION_40 }; execname = ft_basename( argv[0] ); /* Initialize engine */ error = FT_Init_FreeType( &library ); if ( error ) PanicZ( "Could not initialize FreeType library" ); /* get the default value as compiled into FreeType */ FT_Property_Get( library, "cff", "hinting-engine", &cff_hinting_engine ); FT_Property_Get( library, "type1", "hinting-engine", &type1_hinting_engine ); FT_Property_Get( library, "t1cid", "hinting-engine", &t1cid_hinting_engine ); /* collect all available versions, then set again the default */ FT_Property_Get( library, "truetype", "interpreter-version", &dflt_tt_interpreter_version ); for ( n = 0; n < 3; n++ ) { error = FT_Property_Set( library, "truetype", "interpreter-version", &versions[n] ); if ( !error ) tt_interpreter_versions[ num_tt_interpreter_versions++] = versions[n]; if ( versions[n] == dflt_tt_interpreter_version ) tt_interpreter_version_idx = n; } FT_Property_Set( library, "truetype", "interpreter-version", &dflt_tt_interpreter_version ); while ( 1 ) { option = getopt( argc, argv, "d:e:f:h:r:vw:" ); if ( option == -1 ) break; switch ( option ) { case 'd': parse_design_coords( optarg ); break; case 'e': encoding = make_tag( optarg ); break; case 'f': first_glyph = atoi( optarg ); break; case 'h': height = atoi( optarg ); if ( height < 1 ) usage( execname ); break; case 'r': res = atoi( optarg ); if ( res < 1 ) usage( execname ); break; case 'v': { FT_Int major, minor, patch; FT_Library_Version( library, &major, &minor, &patch ); printf( "ftmulti (FreeType) %d.%d", major, minor ); if ( patch ) printf( ".%d", patch ); printf( "\n" ); exit( 0 ); } /* break; */ case 'w': width = atoi( optarg ); if ( width < 1 ) usage( execname ); break; default: usage( execname ); break; } } argc -= optind; argv += optind; if ( argc <= 1 ) usage( execname ); if ( sscanf( argv[0], "%d", &orig_ptsize ) != 1 ) orig_ptsize = 64; file = 1; NewFile: ptsize = orig_ptsize; hinted = 1; file_loaded = 0; /* Load face */ error = FT_New_Face( library, argv[file], 0, &face ); if ( error ) { face = NULL; goto Display_Font; } font_format = FT_Get_Font_Format( face ); if ( encoding != FT_ENCODING_NONE ) { error = FT_Select_Charmap( face, (FT_Encoding)encoding ); if ( error ) goto Display_Font; } /* retrieve multiple master information */ FT_Done_MM_Var( library, multimaster ); error = FT_Get_MM_Var( face, &multimaster ); if ( error ) { multimaster = NULL; goto Display_Font; } /* if the user specified a position, use it, otherwise */ /* set the current position to the default of each axis */ if ( multimaster->num_axis > MAX_MM_AXES ) { fprintf( stderr, "only handling first %d variation axes (of %d)\n", MAX_MM_AXES, multimaster->num_axis ); used_num_axis = MAX_MM_AXES; } else used_num_axis = multimaster->num_axis; for ( n = 0; n < MAX_MM_AXES; n++ ) shown_axes[n] = -1; for ( n = 0; n < used_num_axis; n++ ) { unsigned int flags; (void)FT_Get_Var_Axis_Flags( multimaster, n, &flags ); hidden[n] = flags & FT_VAR_AXIS_FLAG_HIDDEN; } set_up_axes(); for ( n = 0; n < used_num_axis; n++ ) { design_pos[n] = n < requested_cnt ? requested_pos[n] : multimaster->axis[n].def; if ( design_pos[n] < multimaster->axis[n].minimum ) design_pos[n] = multimaster->axis[n].minimum; else if ( design_pos[n] > multimaster->axis[n].maximum ) design_pos[n] = multimaster->axis[n].maximum; /* for MM fonts, round the design coordinates to integers */ if ( !FT_IS_SFNT( face ) ) design_pos[n] = FT_RoundFix( design_pos[n] ); } error = FT_Set_Var_Design_Coordinates( face, used_num_axis, design_pos ); if ( error ) goto Display_Font; file_loaded++; Reset_Scale( ptsize ); num_glyphs = face->num_glyphs; glyph = face->glyph; size = face->size; Display_Font: /* initialize graphics if needed */ if ( !XisSetup ) { XisSetup = 1; Init_Display(); } grSetTitle( surface, "FreeType Glyph Viewer - press ? for help" ); old_ptsize = ptsize; if ( file_loaded >= 1 ) { Fail = 0; Num = first_glyph; if ( Num >= num_glyphs ) Num = num_glyphs - 1; if ( Num < 0 ) Num = 0; } for ( ;; ) { int key; Clear_Display(); if ( file_loaded >= 1 ) { switch ( render_mode ) { case 0: Render_Text( (unsigned int)Num, ptsize ); break; default: Render_All( (unsigned int)Num, ptsize ); } sprintf( Header, "%.50s %.50s (file %.100s)", face->family_name, face->style_name, ft_basename( argv[file] ) ); if ( !new_header ) new_header = Header; grWriteCellString( bit, 0, 0, new_header, fore_color ); new_header = NULL; sprintf( Header, "PS name: %s", FT_Get_Postscript_Name( face ) ); grWriteCellString( bit, 0, 16, Header, fore_color ); sprintf( Header, "axes:" ); { unsigned int limit = num_shown_axes > MAX_MM_AXES / 2 ? MAX_MM_AXES / 2 : num_shown_axes; for ( n = 0; n < limit; n++ ) { char temp[100]; int axis; axis = shown_axes[n]; sprintf( temp, " %.50s%s: %.02f", multimaster->axis[axis].name, hidden[axis] ? "*" : "", design_pos[axis] / 65536.0 ); strncat( Header, temp, sizeof ( Header ) - strlen( Header ) - 1 ); } } grWriteCellString( bit, 0, 24, Header, fore_color ); if ( num_shown_axes > MAX_MM_AXES / 2 ) { unsigned int limit = num_shown_axes; sprintf( Header, " " ); for ( n = MAX_MM_AXES / 2; n < limit; n++ ) { char temp[100]; int axis; axis = shown_axes[n]; sprintf( temp, " %.50s%s: %.02f", multimaster->axis[axis].name, hidden[axis] ? "*" : "", design_pos[axis] / 65536.0 ); strncat( Header, temp, sizeof ( Header ) - strlen( Header ) - 1 ); } grWriteCellString( bit, 0, 32, Header, fore_color ); } { unsigned int tt_ver = tt_interpreter_versions[ tt_interpreter_version_idx]; const char* format_str = NULL; if ( !strcmp( font_format, "CFF" ) ) format_str = ( cff_hinting_engine == FT_HINTING_FREETYPE ? "CFF (FreeType)" : "CFF (Adobe)" ); else if ( !strcmp( font_format, "Type 1" ) ) format_str = ( type1_hinting_engine == FT_HINTING_FREETYPE ? "Type 1 (FreeType)" : "Type 1 (Adobe)" ); else if ( !strcmp( font_format, "CID Type 1" ) ) format_str = ( t1cid_hinting_engine == FT_HINTING_FREETYPE ? "CID Type 1 (FreeType)" : "CID Type 1 (Adobe)" ); else if ( !strcmp( font_format, "TrueType" ) ) format_str = ( tt_ver == TT_INTERPRETER_VERSION_35 ? "TrueType (v35)" : ( tt_ver == TT_INTERPRETER_VERSION_38 ? "TrueType (v38)" : "TrueType (v40)" ) ); sprintf( Header, "at %d points, first glyph = %d, format = %s", ptsize, Num, format_str ); } } else sprintf( Header, "%.100s: not an MM font file, or could not be opened", ft_basename( argv[file] ) ); grWriteCellString( bit, 0, 8, Header, fore_color ); grRefreshSurface( surface ); if ( !( key = Process_Event() ) ) goto End; if ( key == 'n' ) { if ( file_loaded >= 1 ) FT_Done_Face( face ); if ( file < argc - 1 ) file++; goto NewFile; } if ( key == 'p' ) { if ( file_loaded >= 1 ) FT_Done_Face( face ); if ( file > 1 ) file--; goto NewFile; } if ( key == 'H' ) { /* enforce reloading */ if ( file_loaded >= 1 ) FT_Done_Face( face ); goto NewFile; } if ( ptsize != old_ptsize ) { Reset_Scale( ptsize ); old_ptsize = ptsize; } } End: grDoneSurface( surface ); grDoneDevices(); free ( multimaster ); FT_Done_Face ( face ); FT_Done_FreeType( library ); printf( "Execution completed successfully.\n" ); printf( "Fails = %d\n", Fail ); exit( 0 ); /* for safety reasons */ /* return 0; */ /* never reached */ } /* End */ ft2demos-2.10.1/src/ftcommon.c0000644000175000001440000014356013503605624015751 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 2005-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* */ /* ftcommon.c - common routines for the graphic FreeType demo programs. */ /* */ /****************************************************************************/ #ifndef _GNU_SOURCE #define _GNU_SOURCE /* we use `strcasecmp' */ #endif #include #include FT_FREETYPE_H #include FT_MODULE_H #include FT_CACHE_H #include FT_CACHE_MANAGER_H #include FT_BITMAP_H #include FT_FONT_FORMATS_H /* error messages */ #undef FTERRORS_H_ #define FT_ERROR_START_LIST { #define FT_ERRORDEF( e, v, s ) case v: str = s; break; #define FT_ERROR_END_LIST default: str = "unknown error"; } #include "common.h" #include "ftcommon.h" #include #include #include #include #ifdef FT_CONFIG_OPTION_USE_PNG #include #endif #ifdef _WIN32 #define strcasecmp _stricmp #endif #define N_HINTING_ENGINES 2 FT_Error error; #undef NODEBUG #ifndef NODEBUG void LogMessage( const char* fmt, ... ) { va_list ap; va_start( ap, fmt ); vfprintf( stderr, fmt, ap ); va_end( ap ); } #endif /* NODEBUG */ /* PanicZ */ void PanicZ( const char* message ) { const FT_String *str; switch( error ) #include FT_ERRORS_H fprintf( stderr, "%s\n error = 0x%04x, %s\n", message, error, str ); exit( 1 ); } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** DISPLAY-SPECIFIC DEFINITIONS *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ FTDemo_Display* FTDemo_Display_New( const char* device, const char* dims ) { FTDemo_Display* display; grPixelMode mode; grSurface* surface; grBitmap bit; int width, height, depth = 24; if ( sscanf( dims, "%dx%dx%d", &width, &height, &depth ) < 2 ) return NULL; switch ( depth ) { case 8: mode = gr_pixel_mode_gray; break; case 15: mode = gr_pixel_mode_rgb555; break; case 16: mode = gr_pixel_mode_rgb565; break; case 32: mode = gr_pixel_mode_rgb32; break; default: mode = gr_pixel_mode_rgb24; break; } display = (FTDemo_Display *)malloc( sizeof ( FTDemo_Display ) ); if ( !display ) return NULL; grInitDevices(); bit.mode = mode; bit.width = width; bit.rows = height; bit.grays = 256; surface = grNewSurface( device, &bit ); if ( !surface ) { free( display ); return NULL; } display->surface = surface; display->bitmap = &surface->bitmap; display->fore_color = grFindColor( display->bitmap, 0x00, 0x00, 0x00, 0xff ); display->back_color = grFindColor( display->bitmap, 0xff, 0xff, 0xff, 0xff ); display->warn_color = grFindColor( display->bitmap, 0xff, 0x00, 0x00, 0xff ); display->gamma = GAMMA; grSetTargetGamma( display->bitmap, display->gamma ); return display; } void FTDemo_Display_Done( FTDemo_Display* display ) { if ( !display ) return; grDoneBitmap( display->bitmap ); grDoneSurface( display->surface ); grDoneDevices(); free( display ); } void FTDemo_Display_Clear( FTDemo_Display* display ) { grBitmap* bit = display->bitmap; grFillRect( bit, 0, 0, bit->width, bit->rows, display->back_color ); } int FTDemo_Display_Print( FTDemo_Display* display, const char* filename, FT_String* ver_str ) { #ifdef FT_CONFIG_OPTION_USE_PNG grBitmap* bit = display->bitmap; int width = bit->width; int height = bit->rows; int color_type; int code = 1; FILE *fp = NULL; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_bytep row = NULL; /* Set color_type */ switch ( bit-> mode ) { case gr_pixel_mode_gray: color_type = PNG_COLOR_TYPE_GRAY; break; case gr_pixel_mode_rgb24: color_type = PNG_COLOR_TYPE_RGB; break; case gr_pixel_mode_rgb32: color_type = PNG_COLOR_TYPE_RGB_ALPHA; break; default: fprintf( stderr, "Unsupported color type\n" ); goto Exit0; } /* Open file for writing (binary mode) */ fp = fopen( filename, "wb" ); if ( fp == NULL ) { fprintf( stderr, "Could not open file %s for writing\n", filename ); goto Exit0; } /* Initialize write structure */ png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); if ( png_ptr == NULL ) { fprintf( stderr, "Could not allocate write struct\n" ); goto Exit1; } /* Initialize info structure */ info_ptr = png_create_info_struct( png_ptr ); if ( info_ptr == NULL ) { fprintf( stderr, "Could not allocate info struct\n" ); goto Exit2; } /* Set up exception handling */ if ( setjmp( png_jmpbuf( png_ptr ) ) ) { fprintf( stderr, "Error during png creation\n" ); goto Exit2; } png_init_io( png_ptr, fp ); /* Write header (8 bit colour depth) */ png_set_IHDR( png_ptr, info_ptr, width, height, 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE ); /* Record version string */ if ( ver_str != NULL ) { png_text text; text.compression = PNG_TEXT_COMPRESSION_NONE; text.key = (char *)"Software"; text.text = ver_str; png_set_text( png_ptr, info_ptr, &text, 1 ); } /* Set gamma */ png_set_gAMA( png_ptr, info_ptr, 1.0 / display->gamma ); png_write_info( png_ptr, info_ptr ); /* Write image rows */ row = bit->buffer; if ( bit->pitch < 0 ) row -= ( bit->rows - 1 ) * bit->pitch; while ( height-- ) { png_write_row( png_ptr, row ); row += bit->pitch; } /* End write */ png_write_end( png_ptr, NULL ); code = 0; Exit2: png_destroy_write_struct( &png_ptr, &info_ptr ); Exit1: fclose( fp ); Exit0: return code; #endif /* FT_CONFIG_OPTION_USE_PNG */ } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** FREETYPE-SPECIFIC DEFINITIONS *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ #define FLOOR( x ) ( (x) & -64 ) #define CEIL( x ) ( ( (x) + 63 ) & -64 ) #define ROUND( x ) ( ( (x) + 32 ) & -64 ) #define TRUNC( x ) ( (x) >> 6 ) /*************************************************************************/ /* */ /* The face requester is a function provided by the client application */ /* to the cache manager, whose role is to translate an `abstract' face */ /* ID into a real FT_Face object. */ /* */ /* In this program, the face IDs are simply pointers to TFont objects. */ /* */ static FT_Error my_face_requester( FTC_FaceID face_id, FT_Library lib, FT_Pointer request_data, FT_Face* aface ) { PFont font = (PFont)face_id; FT_UNUSED( request_data ); if ( font->file_address != NULL ) error = FT_New_Memory_Face( lib, (const FT_Byte*)font->file_address, (FT_Long)font->file_size, font->face_index, aface ); else error = FT_New_Face( lib, font->filepathname, font->face_index, aface ); if ( !error ) { const char* format = FT_Get_Font_Format( *aface ); if ( !strcmp( format, "Type 1" ) ) { char orig[5]; char* suffix = (char*)strrchr( font->filepathname, '.' ); int has_extension = suffix && ( strcasecmp( suffix, ".pfa" ) == 0 || strcasecmp( suffix, ".pfb" ) == 0 ); if ( has_extension ) memcpy( orig, suffix, 5 ); else /* we have already allocated four more bytes */ suffix = (char*)font->filepathname + strlen( font->filepathname ); memcpy( suffix, ".afm", 5 ); if ( FT_Attach_File( *aface, font->filepathname ) ) { memcpy( suffix, ".pfm", 5 ); FT_Attach_File( *aface, font->filepathname ); } if ( has_extension ) memcpy( suffix, orig, 5 ); else *suffix = '\0'; } if ( (*aface)->charmaps && font->cmap_index < (*aface)->num_charmaps ) (*aface)->charmap = (*aface)->charmaps[font->cmap_index]; } return error; } FTDemo_Handle* FTDemo_New( void ) { FTDemo_Handle* handle; handle = (FTDemo_Handle *)malloc( sizeof ( FTDemo_Handle ) ); if ( !handle ) return NULL; memset( handle, 0, sizeof ( FTDemo_Handle ) ); error = FT_Init_FreeType( &handle->library ); if ( error ) PanicZ( "could not initialize FreeType" ); error = FTC_Manager_New( handle->library, 0, 0, 0, my_face_requester, 0, &handle->cache_manager ); if ( error ) PanicZ( "could not initialize cache manager" ); error = FTC_SBitCache_New( handle->cache_manager, &handle->sbits_cache ); if ( error ) PanicZ( "could not initialize small bitmaps cache" ); error = FTC_ImageCache_New( handle->cache_manager, &handle->image_cache ); if ( error ) PanicZ( "could not initialize glyph image cache" ); error = FTC_CMapCache_New( handle->cache_manager, &handle->cmap_cache ); if ( error ) PanicZ( "could not initialize charmap cache" ); FT_Bitmap_Init( &handle->bitmap ); FT_Stroker_New( handle->library, &handle->stroker ); handle->encoding = FT_ENCODING_ORDER; handle->hinted = 1; handle->use_sbits = 1; handle->use_color = 1; handle->use_layers = 1; handle->autohint = 0; handle->lcd_mode = LCD_MODE_AA; handle->use_sbits_cache = 1; /* string_init */ memset( handle->string, 0, sizeof ( TGlyph ) * MAX_GLYPHS ); handle->string_length = 0; return handle; } void FTDemo_Done( FTDemo_Handle* handle ) { int i; if ( !handle ) return; for ( i = 0; i < handle->max_fonts; i++ ) { if ( handle->fonts[i] ) { if ( handle->fonts[i]->filepathname ) free( (void*)handle->fonts[i]->filepathname ); free( handle->fonts[i] ); } } free( handle->fonts ); /* string_done */ for ( i = 0; i < MAX_GLYPHS; i++ ) { PGlyph glyph = handle->string + i; if ( glyph->image ) FT_Done_Glyph( glyph->image ); } FT_Stroker_Done( handle->stroker ); FT_Bitmap_Done( handle->library, &handle->bitmap ); FTC_Manager_Done( handle->cache_manager ); FT_Done_FreeType( handle->library ); free( handle ); } void FTDemo_Version( FTDemo_Handle* handle, FT_String* str ) { FT_Int major, minor, patch; FT_String format[] = "%d.%d.%d"; FT_Library_Version( handle->library, &major, &minor, &patch ); if ( !patch ) format[5] = '\0'; /* terminate early */ /* append the version string */ sprintf( str + strlen( str ), format, major, minor, patch ); } FT_Error FTDemo_Install_Font( FTDemo_Handle* handle, const char* filepath, FT_Bool outline_only, FT_Bool no_instances ) { static char filename[1024 + 5]; long i, num_faces; unsigned int len; FT_Face face; len = strlen( filepath ); if ( len > 1024 ) len = 1024; strncpy( filename, filepath, len ); filename[len] = 0; /* We use a conservative approach here, at the cost of calling */ /* `FT_New_Face' quite often. The idea is that our demo programs */ /* should be able to try all faces and named instances of a font, */ /* expecting that some faces don't work for various reasons, e.g., */ /* a broken subfont, or an unsupported NFNT bitmap font in a Mac */ /* dfont resource that holds more than a single font. */ error = FT_New_Face( handle->library, filename, -1, &face ); if ( error ) return error; num_faces = face->num_faces; FT_Done_Face( face ); /* allocate new font object(s) */ for ( i = 0; i < num_faces; i++ ) { PFont font; long j, instance_count; error = FT_New_Face( handle->library, filename, -( i + 1 ), &face ); if ( error ) continue; instance_count = no_instances ? 0 : face->style_flags >> 16; FT_Done_Face( face ); /* load face with and without named instances */ for ( j = 0; j < instance_count + 1; j++ ) { error = FT_New_Face( handle->library, filename, ( j << 16 ) + i, &face ); if ( error ) continue; if ( outline_only && !FT_IS_SCALABLE( face ) ) { FT_Done_Face( face ); continue; } font = (PFont)malloc( sizeof ( *font ) ); /* We allocate four more bytes since we want to attach an AFM */ /* or PFM file for Type 1 fonts (if available). Such fonts */ /* always have the extension `.afm' or `.pfm'. */ font->filepathname = (char*)malloc( strlen( filename ) + 4 + 1 ); strcpy( (char*)font->filepathname, filename ); font->face_index = ( j << 16 ) + i; if ( handle-> encoding != FT_ENCODING_ORDER && FT_Select_Charmap( face, (FT_Encoding)handle->encoding ) == FT_Err_Ok ) font->cmap_index = FT_Get_Charmap_Index( face->charmap ); else font->cmap_index = face->num_charmaps; /* FT_ENCODING_ORDER */ font->palette_index = 0; if ( handle->preload ) { FILE* file = fopen( filename, "rb" ); size_t file_size; if ( file == NULL ) /* shouldn't happen */ { free( (void*)font->filepathname ); free( font ); return FT_Err_Invalid_Argument; } fseek( file, 0, SEEK_END ); file_size = (size_t)ftell( file ); fseek( file, 0, SEEK_SET ); if ( file_size <= 0 ) { free( font ); fclose( file ); return FT_Err_Invalid_Stream_Operation; } font->file_address = malloc( file_size ); if ( !font->file_address ) { free( font ); fclose( file ); return FT_Err_Out_Of_Memory; } if ( !fread( font->file_address, file_size, 1, file ) ) { free( font->file_address ); free( font ); fclose( file ); return FT_Err_Invalid_Stream_Read; } font->file_size = file_size; fclose( file ); } else { font->file_address = NULL; font->file_size = 0; } FT_Done_Face( face ); face = NULL; if ( handle->max_fonts == 0 ) { handle->max_fonts = 16; handle->fonts = (PFont*)calloc( (size_t)handle->max_fonts, sizeof ( PFont ) ); } else if ( handle->num_fonts >= handle->max_fonts ) { handle->max_fonts *= 2; handle->fonts = (PFont*)realloc( handle->fonts, (size_t)handle->max_fonts * sizeof ( PFont ) ); memset( &handle->fonts[handle->num_fonts], 0, (size_t)( handle->max_fonts - handle->num_fonts ) * sizeof ( PFont ) ); } handle->fonts[handle->num_fonts++] = font; } } return FT_Err_Ok; } void FTDemo_Set_Current_Font( FTDemo_Handle* handle, PFont font ) { FT_Face face; handle->current_font = font; handle->scaler.face_id = (FTC_FaceID)font; error = FTC_Manager_LookupFace( handle->cache_manager, handle->scaler.face_id, &face ); if ( font->cmap_index < face->num_charmaps ) handle->encoding = face->charmaps[font->cmap_index]->encoding; else handle->encoding = FT_ENCODING_ORDER; switch ( handle->encoding ) { case FT_ENCODING_ORDER: font->num_indices = face->num_glyphs; break; case FT_ENCODING_UNICODE: font->num_indices = 0x110000L; break; case FT_ENCODING_ADOBE_LATIN_1: case FT_ENCODING_ADOBE_STANDARD: case FT_ENCODING_ADOBE_EXPERT: case FT_ENCODING_ADOBE_CUSTOM: case FT_ENCODING_APPLE_ROMAN: font->num_indices = 0x100L; break; /* some fonts use range 0x00-0x100, others have 0xF000-0xF0FF */ case FT_ENCODING_MS_SYMBOL: font->num_indices = 0x10000L; break; default: font->num_indices = 0x10000L; } } void FTDemo_Set_Current_Size( FTDemo_Handle* handle, int pixel_size ) { FT_Face face; if ( pixel_size > 0xFFFF ) pixel_size = 0xFFFF; error = FTC_Manager_LookupFace( handle->cache_manager, handle->scaler.face_id, &face ); if ( !error && !FT_IS_SCALABLE ( face ) ) { int i, j = 0; int c, d = abs( (int)face->available_sizes[j].y_ppem - pixel_size * 64 ); for ( i = 1; i < face->num_fixed_sizes; i++ ) { c = abs( (int)face->available_sizes[i].y_ppem - pixel_size * 64 ); if ( c < d ) { d = c; j = i; } } pixel_size = face->available_sizes[j].y_ppem / 64 ; } handle->scaler.width = (FT_UInt)pixel_size; handle->scaler.height = (FT_UInt)pixel_size; handle->scaler.pixel = 1; /* activate integer format */ handle->scaler.x_res = 0; handle->scaler.y_res = 0; } void FTDemo_Set_Current_Charsize( FTDemo_Handle* handle, int char_size, int resolution ) { FT_Face face; /* in 26.6 format, corresponding to (almost) 0x4000ppem */ if ( char_size > 0xFFFFF ) char_size = 0xFFFFF; error = FTC_Manager_LookupFace( handle->cache_manager, handle->scaler.face_id, &face ); if ( !error && !FT_IS_SCALABLE ( face ) ) { int pixel_size = char_size * resolution / 72; int i, j = 0; int c, d = abs( (int)face->available_sizes[j].y_ppem - pixel_size ); for ( i = 1; i < face->num_fixed_sizes; i++ ) { c = abs( (int)face->available_sizes[i].y_ppem - pixel_size ); if ( c < d ) { d = c; j = i; } } char_size = face->available_sizes[j].y_ppem * 72 / resolution; } handle->scaler.width = (FT_UInt)char_size; handle->scaler.height = (FT_UInt)char_size; handle->scaler.pixel = 0; /* activate 26.6 format */ handle->scaler.x_res = (FT_UInt)resolution; handle->scaler.y_res = (FT_UInt)resolution; } void FTDemo_Set_Preload( FTDemo_Handle* handle, int preload ) { handle->preload = !!preload; } void FTDemo_Update_Current_Flags( FTDemo_Handle* handle ) { FT_Int32 flags, target; flags = FT_LOAD_DEFAULT; /* really 0 */ if ( handle->autohint ) flags |= FT_LOAD_FORCE_AUTOHINT; if ( !handle->use_sbits ) flags |= FT_LOAD_NO_BITMAP; if ( handle->use_color ) flags |= FT_LOAD_COLOR; if ( handle->hinted ) { target = 0; switch ( handle->lcd_mode ) { case LCD_MODE_MONO: target = FT_LOAD_TARGET_MONO; break; case LCD_MODE_LIGHT: case LCD_MODE_LIGHT_SUBPIXEL: target = FT_LOAD_TARGET_LIGHT; break; case LCD_MODE_RGB: case LCD_MODE_BGR: target = FT_LOAD_TARGET_LCD; break; case LCD_MODE_VRGB: case LCD_MODE_VBGR: target = FT_LOAD_TARGET_LCD_V; break; default: target = FT_LOAD_TARGET_NORMAL; } flags |= target; } else { flags |= FT_LOAD_NO_HINTING; if ( handle->lcd_mode == LCD_MODE_MONO ) flags |= FT_LOAD_MONOCHROME; } handle->load_flags = flags; } FT_UInt FTDemo_Get_Index( FTDemo_Handle* handle, FT_UInt32 charcode ) { if ( handle->encoding != FT_ENCODING_ORDER ) { FTC_FaceID face_id = handle->scaler.face_id; PFont font = handle->current_font; return FTC_CMapCache_Lookup( handle->cmap_cache, face_id, font->cmap_index, charcode ); } else return (FT_UInt)charcode; } FT_Error FTDemo_Get_Size( FTDemo_Handle* handle, FT_Size* asize ) { FT_Size size; error = FTC_Manager_LookupSize( handle->cache_manager, &handle->scaler, &size ); if ( !error ) *asize = size; return error; } void FTDemo_Draw_Header( FTDemo_Handle* handle, FTDemo_Display* display, int ptsize, int res, int idx, int error_code ) { FT_Face face; char buf[256]; const char* basename; int ppem; int line = 0; int x; error = FTC_Manager_LookupFace( handle->cache_manager, handle->scaler.face_id, &face ); if ( error ) { FTDemo_Display_Done( display ); FTDemo_Done( handle ); PanicZ( "can't access font file" ); } /* font and file name */ basename = ft_basename( handle->current_font->filepathname ); sprintf( buf, "%.50s %.50s (file `%.100s')", face->family_name, face->style_name, basename ); grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, buf, display->fore_color ); /* ppem, pt and dpi, instance */ ppem = FT_IS_SCALABLE( face ) ? FT_MulFix( face->units_per_EM, face->size->metrics.y_scale ) : face->size->metrics.y_ppem * 64; if ( res == 72 ) x = sprintf( buf, "%.4g ppem", ppem / 64.0 ); else x = sprintf( buf, "%g pt at %d dpi, %.4g ppem", ptsize / 64.0, res, ppem / 64.0 ); if ( face->face_index >> 16 ) x += sprintf( buf + x, ", instance %ld/%ld", face->face_index >> 16, face->style_flags >> 16 ); grWriteCellString( display->bitmap, 0, line * HEADER_HEIGHT, buf, display->fore_color ); if ( abs( ptsize * res / 64 - face->size->metrics.y_ppem * 72 ) > 36 || error_code ) { switch ( error_code ) { case FT_Err_Ok: sprintf( buf, "Available size shown" ); break; case FT_Err_Invalid_Pixel_Size: sprintf( buf, "Invalid pixel size" ); break; case FT_Err_Invalid_PPem: sprintf( buf, "Invalid ppem value" ); break; default: sprintf( buf, "Error 0x%04x", (FT_UShort)error_code ); } grWriteCellString( display->bitmap, 8 * x + 16, line * HEADER_HEIGHT, buf, display->warn_color ); } /* gamma */ if ( display->gamma == 0.0 ) sprintf( buf, "gamma: sRGB" ); else sprintf( buf, "gamma = %.1f", display->gamma ); grWriteCellString( display->bitmap, display->bitmap->width - 8 * 11, line * HEADER_HEIGHT, buf, display->fore_color ); line++; /* encoding charcode or glyph index, glyph name */ if ( idx >= 0 ) { const char* encoding = NULL; FT_UInt glyph_idx = FTDemo_Get_Index( handle, (FT_UInt32)idx ); switch ( handle->encoding ) { case FT_ENCODING_ORDER: encoding = "glyph order"; break; case FT_ENCODING_MS_SYMBOL: encoding = "MS Symbol"; break; case FT_ENCODING_UNICODE: encoding = "Unicode"; break; case FT_ENCODING_SJIS: encoding = "SJIS"; break; case FT_ENCODING_PRC: encoding = "PRC"; break; case FT_ENCODING_BIG5: encoding = "Big5"; break; case FT_ENCODING_WANSUNG: encoding = "Wansung"; break; case FT_ENCODING_JOHAB: encoding = "Johab"; break; case FT_ENCODING_ADOBE_STANDARD: encoding = "Adobe Standard"; break; case FT_ENCODING_ADOBE_EXPERT: encoding = "Adobe Expert"; break; case FT_ENCODING_ADOBE_CUSTOM: encoding = "Adobe Custom"; break; case FT_ENCODING_ADOBE_LATIN_1: encoding = "Latin 1"; break; case FT_ENCODING_OLD_LATIN_2: encoding = "Latin 2"; break; case FT_ENCODING_APPLE_ROMAN: encoding = "Apple Roman"; break; default: encoding = "Other"; } if ( handle->encoding == FT_ENCODING_ORDER ) x = sprintf( buf, "%s idx: %d", encoding, idx ); else if ( handle->encoding == FT_ENCODING_UNICODE ) x = sprintf( buf, "%s charcode: U+%04X (glyph idx %d)", encoding, idx, glyph_idx ); else x = sprintf( buf, "%s charcode: 0x%X (glyph idx %d)", encoding, idx, glyph_idx ); if ( FT_HAS_GLYPH_NAMES( face ) ) { x += sprintf( buf + x, ", name: " ); FT_Get_Glyph_Name( face, glyph_idx, buf + x, (FT_UInt)( 256 - x ) ); } grWriteCellString( display->bitmap, 0, (line++) * HEADER_HEIGHT, buf, display->fore_color ); } } FT_Error FTDemo_Glyph_To_Bitmap( FTDemo_Handle* handle, FT_Glyph glyf, grBitmap* target, int* left, int* top, int* x_advance, int* y_advance, FT_Glyph* aglyf ) { FT_BitmapGlyph bitmap; FT_Bitmap* source; *aglyf = NULL; error = FT_Err_Ok; if ( glyf->format == FT_GLYPH_FORMAT_OUTLINE ) { FT_Render_Mode render_mode; switch ( handle->lcd_mode ) { case LCD_MODE_MONO: render_mode = FT_RENDER_MODE_MONO; break; case LCD_MODE_LIGHT: case LCD_MODE_LIGHT_SUBPIXEL: render_mode = FT_RENDER_MODE_LIGHT; break; case LCD_MODE_RGB: case LCD_MODE_BGR: render_mode = FT_RENDER_MODE_LCD; break; case LCD_MODE_VRGB: case LCD_MODE_VBGR: render_mode = FT_RENDER_MODE_LCD_V; break; default: render_mode = FT_RENDER_MODE_NORMAL; } /* render the glyph to a bitmap, don't destroy original */ error = FT_Glyph_To_Bitmap( &glyf, render_mode, NULL, 0 ); if ( error ) return error; *aglyf = glyf; } if ( glyf->format != FT_GLYPH_FORMAT_BITMAP ) PanicZ( "invalid glyph format returned!" ); bitmap = (FT_BitmapGlyph)glyf; source = &bitmap->bitmap; target->rows = (int)source->rows; target->width = (int)source->width; target->pitch = source->pitch; target->buffer = source->buffer; target->grays = source->num_grays; switch ( source->pixel_mode ) { case FT_PIXEL_MODE_MONO: target->mode = gr_pixel_mode_mono; break; case FT_PIXEL_MODE_GRAY: target->mode = gr_pixel_mode_gray; target->grays = source->num_grays; break; case FT_PIXEL_MODE_GRAY2: case FT_PIXEL_MODE_GRAY4: (void)FT_Bitmap_Convert( handle->library, source, &handle->bitmap, 1 ); target->pitch = handle->bitmap.pitch; target->buffer = handle->bitmap.buffer; target->mode = gr_pixel_mode_gray; target->grays = handle->bitmap.num_grays; break; case FT_PIXEL_MODE_LCD: target->mode = handle->lcd_mode == LCD_MODE_RGB ? gr_pixel_mode_lcd : gr_pixel_mode_lcd2; target->grays = source->num_grays; break; case FT_PIXEL_MODE_LCD_V: target->mode = handle->lcd_mode == LCD_MODE_VRGB ? gr_pixel_mode_lcdv : gr_pixel_mode_lcdv2; target->grays = source->num_grays; break; case FT_PIXEL_MODE_BGRA: target->mode = gr_pixel_mode_bgra; target->grays = source->num_grays; break; default: return FT_Err_Invalid_Glyph_Format; } *left = bitmap->left; *top = bitmap->top; *x_advance = ( glyf->advance.x + 0x8000 ) >> 16; *y_advance = ( glyf->advance.y + 0x8000 ) >> 16; return error; } FT_Error FTDemo_Index_To_Bitmap( FTDemo_Handle* handle, FT_ULong Index, grBitmap* target, int* left, int* top, int* x_advance, int* y_advance, FT_Glyph* aglyf ) { unsigned int width, height; *aglyf = NULL; *x_advance = 0; /* use the SBits cache to store small glyph bitmaps; this is a lot */ /* more memory-efficient */ /* */ width = handle->scaler.width; height = handle->scaler.height; if ( handle->use_sbits_cache && !handle->scaler.pixel ) { width = ( ( width * handle->scaler.x_res + 36 ) / 72 ) >> 6; height = ( ( height * handle->scaler.y_res + 36 ) / 72 ) >> 6; } if ( handle->use_sbits_cache && width < 48 && height < 48 ) { FTC_SBit sbit; FT_Bitmap source; error = FTC_SBitCache_LookupScaler( handle->sbits_cache, &handle->scaler, (FT_ULong)handle->load_flags, Index, &sbit, NULL ); if ( error ) goto Exit; if ( sbit->buffer ) { target->rows = sbit->height; target->width = sbit->width; target->pitch = sbit->pitch; target->buffer = sbit->buffer; target->grays = sbit->max_grays + 1; switch ( sbit->format ) { case FT_PIXEL_MODE_MONO: target->mode = gr_pixel_mode_mono; break; case FT_PIXEL_MODE_GRAY: target->mode = gr_pixel_mode_gray; break; case FT_PIXEL_MODE_GRAY2: case FT_PIXEL_MODE_GRAY4: source.rows = sbit->height; source.width = sbit->width; source.pitch = sbit->pitch; source.buffer = sbit->buffer; source.pixel_mode = sbit->format; (void)FT_Bitmap_Convert( handle->library, &source, &handle->bitmap, 1 ); target->pitch = handle->bitmap.pitch; target->buffer = handle->bitmap.buffer; target->mode = gr_pixel_mode_gray; target->grays = handle->bitmap.num_grays; break; case FT_PIXEL_MODE_LCD: target->mode = handle->lcd_mode == LCD_MODE_RGB ? gr_pixel_mode_lcd : gr_pixel_mode_lcd2; break; case FT_PIXEL_MODE_LCD_V: target->mode = handle->lcd_mode == LCD_MODE_VRGB ? gr_pixel_mode_lcdv : gr_pixel_mode_lcdv2; break; case FT_PIXEL_MODE_BGRA: target->mode = gr_pixel_mode_bgra; break; default: return FT_Err_Invalid_Glyph_Format; } *left = sbit->left; *top = sbit->top; *x_advance = sbit->xadvance; *y_advance = sbit->yadvance; goto Exit; } } /* otherwise, use an image cache to store glyph outlines, and render */ /* them on demand. we can thus support very large sizes easily.. */ { FT_Glyph glyf; error = FTC_ImageCache_LookupScaler( handle->image_cache, &handle->scaler, (FT_ULong)handle->load_flags, Index, &glyf, NULL ); if ( !error ) error = FTDemo_Glyph_To_Bitmap( handle, glyf, target, left, top, x_advance, y_advance, aglyf ); } Exit: /* don't accept a `missing' character with zero or negative width */ if ( Index == 0 && *x_advance <= 0 ) *x_advance = 1; return error; } FT_Error FTDemo_Draw_Index( FTDemo_Handle* handle, FTDemo_Display* display, unsigned int gindex, int* pen_x, int* pen_y ) { int left, top, x_advance, y_advance; grBitmap bit3; FT_Glyph glyf; error = FTDemo_Index_To_Bitmap( handle, gindex, &bit3, &left, &top, &x_advance, &y_advance, &glyf ); if ( error ) return error; /* now render the bitmap into the display surface */ grBlitGlyphToBitmap( display->bitmap, &bit3, *pen_x + left, *pen_y - top, display->fore_color ); if ( glyf ) FT_Done_Glyph( glyf ); *pen_x += x_advance; return FT_Err_Ok; } FT_Error FTDemo_Draw_Glyph_Color( FTDemo_Handle* handle, FTDemo_Display* display, FT_Glyph glyph, int* pen_x, int* pen_y, grColor color ) { int left, top, x_advance, y_advance; grBitmap bit3; FT_Glyph glyf; error = FTDemo_Glyph_To_Bitmap( handle, glyph, &bit3, &left, &top, &x_advance, &y_advance, &glyf ); if ( error ) { FT_Done_Glyph( glyph ); return error; } /* now render the bitmap into the display surface */ grBlitGlyphToBitmap( display->bitmap, &bit3, *pen_x + left, *pen_y - top, color ); if ( glyf ) FT_Done_Glyph( glyf ); *pen_x += x_advance; return FT_Err_Ok; } FT_Error FTDemo_Draw_Glyph( FTDemo_Handle* handle, FTDemo_Display* display, FT_Glyph glyph, int* pen_x, int* pen_y ) { return FTDemo_Draw_Glyph_Color( handle, display, glyph, pen_x, pen_y, display->fore_color ); } FT_Error FTDemo_Draw_Slot( FTDemo_Handle* handle, FTDemo_Display* display, FT_GlyphSlot slot, int* pen_x, int* pen_y ) { FT_Glyph glyph; error = FT_Get_Glyph( slot, &glyph ); if ( error ) return error; error = FTDemo_Draw_Glyph( handle, display, glyph, pen_x, pen_y ); if ( !error ) FT_Done_Glyph( glyph ); return error; } void FTDemo_String_Set( FTDemo_Handle* handle, const char* string ) { const char* p = string; const char* end = p + strlen( string ); unsigned long codepoint; int ch; int expect; PGlyph glyph = handle->string; handle->string_length = 0; codepoint = expect = 0; for (;;) { ch = utf8_next( &p, end ); if ( ch < 0 ) break; codepoint = (unsigned long)ch; glyph->glyph_index = FTDemo_Get_Index( handle, codepoint ); glyph++; handle->string_length++; if ( handle->string_length >= MAX_GLYPHS ) break; } } FT_Error FTDemo_String_Load( FTDemo_Handle* handle, FTDemo_String_Context* sc ) { FT_Size size; FT_Face face; FT_Int i; FT_Int length = handle->string_length; PGlyph glyph, prev; FT_Pos track_kern = 0; error = FTDemo_Get_Size( handle, &size ); if ( error ) return error; face = size->face; for ( glyph = handle->string, i = 0; i < length; glyph++, i++ ) { /* clear existing image if there is one */ if ( glyph->image ) { FT_Done_Glyph( glyph->image ); glyph->image = NULL; } /* load the glyph and get the image */ if ( !FT_Load_Glyph( face, glyph->glyph_index, handle->load_flags ) && !FT_Get_Glyph( face->glyph, &glyph->image ) ) { FT_Glyph_Metrics* metrics = &face->glyph->metrics; /* note that in vertical layout, y-positive goes downwards */ glyph->vvector.x = metrics->vertBearingX - metrics->horiBearingX; glyph->vvector.y = -metrics->vertBearingY - metrics->horiBearingY; glyph->vadvance.x = 0; glyph->vadvance.y = -metrics->vertAdvance; glyph->lsb_delta = face->glyph->lsb_delta; glyph->rsb_delta = face->glyph->rsb_delta; glyph->hadvance.x = metrics->horiAdvance; glyph->hadvance.y = 0; } } if ( sc->kerning_degree ) { /* this function needs and returns points, not pixels */ if ( !FT_Get_Track_Kerning( face, (FT_Fixed)handle->scaler.width << 10, -sc->kerning_degree, &track_kern ) ) track_kern = (FT_Pos)( ( track_kern / 1024.0 * handle->scaler.x_res ) / 72.0 ); } for ( prev = handle->string + length, glyph = handle->string, i = 0; i < length; prev = glyph, glyph++, i++ ) { if ( !glyph->image ) continue; if ( handle->lcd_mode == LCD_MODE_LIGHT_SUBPIXEL ) glyph->hadvance.x += glyph->lsb_delta - glyph->rsb_delta; prev->hadvance.x += track_kern; if ( sc->kerning_mode ) { FT_Vector kern; FT_Get_Kerning( face, prev->glyph_index, glyph->glyph_index, FT_KERNING_UNFITTED, &kern ); prev->hadvance.x += kern.x; prev->hadvance.y += kern.y; if ( handle->lcd_mode != LCD_MODE_LIGHT_SUBPIXEL && sc->kerning_mode > KERNING_MODE_NORMAL ) { if ( prev->rsb_delta - glyph->lsb_delta > 32 ) prev->hadvance.x -= 64; else if ( prev->rsb_delta - glyph->lsb_delta < -31 ) prev->hadvance.x += 64; } } if ( handle->lcd_mode != LCD_MODE_LIGHT_SUBPIXEL && handle->hinted ) { prev->hadvance.x = ROUND( prev->hadvance.x ); prev->hadvance.y = ROUND( prev->hadvance.y ); } } return FT_Err_Ok; } int FTDemo_String_Draw( FTDemo_Handle* handle, FTDemo_Display* display, FTDemo_String_Context* sc, int x, int y ) { int first = sc->offset; int last = handle->string_length; int m, n; FT_Vector pen = { 0, 0}; FT_Vector advance; if ( x < 0 || y < 0 || x > display->bitmap->width || y > display->bitmap->rows ) return 0; /* change to Cartesian coordinates */ y = display->bitmap->rows - y; /* calculate the extent */ if ( sc->extent ) for( n = first; n < first + last || pen.x > 0; n++ ) /* chk progress */ { m = n % handle->string_length; /* recycling */ if ( pen.x + handle->string[m].hadvance.x > sc->extent ) { last = n; break; } pen.x += handle->string[m].hadvance.x; pen.y += handle->string[m].hadvance.y; } else if ( sc->vertical ) for ( n = first; n < last; n++ ) { pen.x += handle->string[n].vadvance.x; pen.y += handle->string[n].vadvance.y; } else for ( n = first; n < last; n++ ) { pen.x += handle->string[n].hadvance.x; pen.y += handle->string[n].hadvance.y; } pen.x = FT_MulFix( pen.x, sc->center ); pen.y = FT_MulFix( pen.y, sc->center ); /* XXX sbits */ /* get pen position */ FT_Vector_Transform( &pen, sc->matrix ); pen.x = ( x << 6 ) - pen.x; pen.y = ( y << 6 ) - pen.y; for ( n = first; n < last; n++ ) { PGlyph glyph = handle->string + n % handle->string_length; FT_Glyph image; FT_BBox bbox; if ( !glyph->image ) continue; /* copy image */ error = FT_Glyph_Copy( glyph->image, &image ); if ( error ) continue; if ( image->format != FT_GLYPH_FORMAT_BITMAP ) { if ( sc->vertical ) error = FT_Glyph_Transform( image, NULL, &glyph->vvector ); if ( !error ) error = FT_Glyph_Transform( image, sc->matrix, &pen ); if ( error ) { FT_Done_Glyph( image ); continue; } } else { FT_BitmapGlyph bitmap = (FT_BitmapGlyph)image; if ( sc->vertical ) { bitmap->left += ( glyph->vvector.x + pen.x ) >> 6; bitmap->top += ( glyph->vvector.y + pen.y ) >> 6; } else { bitmap->left += pen.x >> 6; bitmap->top += pen.y >> 6; } } advance = sc->vertical ? glyph->vadvance : glyph->hadvance; if ( sc->matrix ) FT_Vector_Transform( &advance, sc->matrix ); pen.x += advance.x; pen.y += advance.y; FT_Glyph_Get_CBox( image, FT_GLYPH_BBOX_PIXELS, &bbox ); #if 0 if ( n == 0 ) { fprintf( stderr, "bbox = [%ld %ld %ld %ld]\n", bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax ); } #endif /* check bounding box; if it is completely outside the */ /* display surface, we don't need to render it */ if ( bbox.xMax > 0 && bbox.yMax > 0 && bbox.xMin < display->bitmap->width && bbox.yMin < display->bitmap->rows ) { int left, top, dummy1, dummy2; grBitmap bit3; FT_Glyph glyf; error = FTDemo_Glyph_To_Bitmap( handle, image, &bit3, &left, &top, &dummy1, &dummy2, &glyf ); if ( !error ) { /* change back to the usual coordinates */ top = display->bitmap->rows - top; /* now render the bitmap into the display surface */ grBlitGlyphToBitmap( display->bitmap, &bit3, left, top, display->fore_color ); if ( glyf ) FT_Done_Glyph( glyf ); } } FT_Done_Glyph( image ); } return last - first; } FT_Error FTDemo_Sketch_Glyph_Color( FTDemo_Handle* handle, FTDemo_Display* display, FT_Glyph glyph, FT_Pos x, FT_Pos y, grColor color ) { grSurface* surface = (grSurface*)display->surface; grBitmap* target = display->bitmap; unsigned char* origin; FT_Outline* outline; FT_Raster_Params params; if ( glyph->format != FT_GLYPH_FORMAT_OUTLINE ) return FT_Err_Ok; origin = target->buffer; if ( target->pitch < 0 ) origin += ( y - target->rows ) * target->pitch; else origin += ( y - 1 ) * target->pitch; switch ( target->mode ) { case gr_pixel_mode_gray: origin += x; break; case gr_pixel_mode_rgb565: origin += x * 2; break; case gr_pixel_mode_rgb24: origin += x * 3; break; case gr_pixel_mode_rgb32: origin += x * 4; break; default: fprintf( stderr, "Unsupported target\n" ); return FT_Err_Ok; } surface->origin = origin; surface->gcolor = ((GBlenderPixel)color.chroma[0] << 16) | ((GBlenderPixel)color.chroma[1] << 8 ) | ((GBlenderPixel)color.chroma[2] ) ; outline = &((FT_OutlineGlyph)glyph)->outline; params.source = outline; params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT | FT_RASTER_FLAG_CLIP; params.gray_spans = (FT_SpanFunc)surface->gray_spans; params.user = surface; params.clip_box.xMin = -x; params.clip_box.yMin = y - target->rows; params.clip_box.xMax = -x + target->width; params.clip_box.yMax = y; return FT_Outline_Render( handle->library, outline, ¶ms ); } unsigned long FTDemo_Make_Encoding_Tag( const char* s ) { int i; unsigned long l = 0; for ( i = 0; i < 4; i++ ) { if ( !s[i] ) break; l <<= 8; l += (unsigned long)s[i]; } return l; } int FTDemo_Event_Cff_Hinting_Engine_Change( FT_Library library, unsigned int* current, unsigned int delta ) { unsigned int new_cff_hinting_engine = 0; if ( delta ) new_cff_hinting_engine = ( *current + delta + N_HINTING_ENGINES ) % N_HINTING_ENGINES; error = FT_Property_Set( library, "cff", "hinting-engine", &new_cff_hinting_engine ); if ( !error ) { *current = new_cff_hinting_engine; return 1; } return 0; } int FTDemo_Event_Type1_Hinting_Engine_Change( FT_Library library, unsigned int* current, unsigned int delta ) { unsigned int new_type1_hinting_engine = 0; if ( delta ) new_type1_hinting_engine = ( *current + delta + N_HINTING_ENGINES ) % N_HINTING_ENGINES; error = FT_Property_Set( library, "type1", "hinting-engine", &new_type1_hinting_engine ); if ( !error ) { *current = new_type1_hinting_engine; return 1; } return 0; } int FTDemo_Event_T1cid_Hinting_Engine_Change( FT_Library library, unsigned int* current, unsigned int delta ) { unsigned int new_t1cid_hinting_engine = 0; if ( delta ) new_t1cid_hinting_engine = ( *current + delta + N_HINTING_ENGINES ) % N_HINTING_ENGINES; error = FT_Property_Set( library, "t1cid", "hinting-engine", &new_t1cid_hinting_engine ); if ( !error ) { *current = new_t1cid_hinting_engine; return 1; } return 0; } /* End */ ft2demos-2.10.1/src/ftcommon.h0000644000175000001440000003126413503605624015753 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 2005-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* */ /* ftcommon.h - common routines for the graphic FreeType demo programs. */ /* */ /****************************************************************************/ #ifndef FT_COMMON_H_ #define FT_COMMON_H_ #include #include FT_FREETYPE_H #include FT_CACHE_H #include FT_CACHE_MANAGER_H #include FT_GLYPH_H #include FT_STROKER_H #include FT_BITMAP_H #include #include extern FT_Error error; /* forward declarations */ extern void PanicZ( const char* message ); #undef NODEBUG #ifndef NODEBUG #define LOG( x ) LogMessage##x void LogMessage( const char* fmt, ... ); #else /* !DEBUG */ #define LOG( x ) /* */ #endif /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** DISPLAY-SPECIFIC DEFINITIONS *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /* default window dimensions */ #define DIM "640x480" /* baseline distance between header lines */ #define HEADER_HEIGHT 12 /* default gamma setting */ #define GAMMA 1.8 /* special encoding to display glyphs in order */ #define FT_ENCODING_ORDER 0xFFFF #include "graph.h" #include "grobjs.h" #include "grfont.h" typedef struct { grSurface* surface; grBitmap* bitmap; grColor fore_color; grColor back_color; grColor warn_color; double gamma; } FTDemo_Display; FTDemo_Display* FTDemo_Display_New( const char* device, const char* dims ); void FTDemo_Display_Done( FTDemo_Display* display ); /* fill the bitmap with background color */ void FTDemo_Display_Clear( FTDemo_Display* display ); /* dump display image in PNG format */ int FTDemo_Display_Print( FTDemo_Display* display, const char* filename, FT_String* ver_str ); /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** FREETYPE-SPECIFIC DEFINITIONS *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ #define MAX_GLYPHS 512 /* at most 512 glyphs in the string */ #define MAX_GLYPH_BYTES 150000 /* 150kB for the glyph image cache */ typedef struct TGlyph_ { FT_UInt glyph_index; FT_Glyph image; /* the glyph image */ FT_Pos lsb_delta; /* delta caused by hinting */ FT_Pos rsb_delta; /* delta caused by hinting */ FT_Vector hadvance; /* kerned horizontal advance */ FT_Vector vvector; /* vert. origin => hori. origin */ FT_Vector vadvance; /* vertical advance */ } TGlyph, *PGlyph; /* this simple record is used to model a given `installed' face */ typedef struct TFont_ { const char* filepathname; int face_index; int cmap_index; int palette_index; int num_indices; void* file_address; /* for preloaded files */ size_t file_size; } TFont, *PFont; enum { LCD_MODE_MONO = 0, LCD_MODE_AA, LCD_MODE_LIGHT, LCD_MODE_LIGHT_SUBPIXEL, LCD_MODE_RGB, LCD_MODE_BGR, LCD_MODE_VRGB, LCD_MODE_VBGR, N_LCD_MODES }; enum { KERNING_DEGREE_NONE = 0, KERNING_DEGREE_LIGHT, KERNING_DEGREE_MEDIUM, KERNING_DEGREE_TIGHT, N_KERNING_DEGREES }; enum { KERNING_MODE_NONE = 0, /* 0: no kerning; */ KERNING_MODE_NORMAL, /* 1: `kern' values */ KERNING_MODE_SMART, /* 2: `kern' + side bearing errors */ N_KERNING_MODES }; typedef struct { int kerning_mode; int kerning_degree; FT_Fixed center; /* 0..1 */ int vertical; /* displayed vertically? */ FT_Matrix* matrix; /* string transformation */ FT_Pos extent; /* extent to fill, glyphs recycled */ int offset; /* initial glyph */ } FTDemo_String_Context; typedef struct { FT_Library library; /* the FreeType library */ FTC_Manager cache_manager; /* the cache manager */ FTC_ImageCache image_cache; /* the glyph image cache */ FTC_SBitCache sbits_cache; /* the glyph small bitmaps cache */ FTC_CMapCache cmap_cache; /* the charmap cache */ PFont* fonts; /* installed fonts */ int num_fonts; int max_fonts; int use_sbits_cache; /* toggle sbits cache */ /* use FTDemo_Set_Current_XXX to set the following two fields */ PFont current_font; /* selected font */ FTC_ScalerRec scaler; FT_Int32 load_flags; /* call FTDemo_Update_Current_Flags after setting any of the following fields */ int hinted; /* is glyph hinting active? */ int use_sbits; /* do we use embedded bitmaps? */ int use_color; /* do we use coloured glyphs? */ int use_layers; /* do we use color-layered glyphs? */ int autohint; /* force auto-hinting */ int lcd_mode; /* mono, aa, light, vrgb, ... */ int preload; /* force font file preloading */ /* don't touch the following fields! */ /* used for string rendering */ TGlyph string[MAX_GLYPHS]; int string_length; unsigned long encoding; FT_Stroker stroker; FT_Bitmap bitmap; /* used as bitmap conversion buffer */ } FTDemo_Handle; FTDemo_Handle* FTDemo_New( void ); void FTDemo_Done( FTDemo_Handle* handle ); /* append version information */ void FTDemo_Version( FTDemo_Handle* handle, FT_String* str ); /* install a font */ FT_Error FTDemo_Install_Font( FTDemo_Handle* handle, const char* filepath, FT_Bool outline_only, FT_Bool no_instances ); void FTDemo_Set_Preload( FTDemo_Handle* handle, int preload ); void FTDemo_Set_Current_Font( FTDemo_Handle* handle, PFont font ); void FTDemo_Set_Current_Size( FTDemo_Handle* handle, int pixel_size ); void FTDemo_Set_Current_Charsize( FTDemo_Handle* handle, int point_size, int res ); void FTDemo_Update_Current_Flags( FTDemo_Handle* handle ); /* charcode => glyph index of current font */ FT_UInt FTDemo_Get_Index( FTDemo_Handle* handle, FT_UInt32 charcode ); /* get FT_Size of current font */ FT_Error FTDemo_Get_Size( FTDemo_Handle* handle, FT_Size* asize ); /* draw common header */ void FTDemo_Draw_Header( FTDemo_Handle* handle, FTDemo_Display* display, int ptsize, int res, int idx, int error_code ); /* convert a FT_Glyph to a grBitmap (don't free target->buffer) */ /* if aglyf != NULL, you should FT_Glyph_Done the aglyf */ FT_Error FTDemo_Glyph_To_Bitmap( FTDemo_Handle* handle, FT_Glyph glyf, grBitmap* target, int* left, int* top, int* x_advance, int* y_advance, FT_Glyph* aglyf ); /* get a grBitmap from glyph index (don't free target->buffer) */ /* if aglyf != NULL, you should FT_Glyph_Done the aglyf */ FT_Error FTDemo_Index_To_Bitmap( FTDemo_Handle* handle, FT_ULong Index, grBitmap* target, int* left, int* top, int* x_advance, int* y_advance, FT_Glyph* aglyf ); /* given glyph index, draw a glyph on the display */ FT_Error FTDemo_Draw_Index( FTDemo_Handle* handle, FTDemo_Display* display, unsigned int gindex, int* pen_x, int* pen_y); /* given FT_Glyph, draw a glyph on the display */ FT_Error FTDemo_Draw_Glyph( FTDemo_Handle* handle, FTDemo_Display* display, FT_Glyph glyph, int* pen_x, int* pen_y); FT_Error FTDemo_Draw_Glyph_Color( FTDemo_Handle* handle, FTDemo_Display* display, FT_Glyph glyph, int* pen_x, int* pen_y, grColor color ); /* given FT_GlyphSlot, draw a glyph on the display */ FT_Error FTDemo_Draw_Slot( FTDemo_Handle* handle, FTDemo_Display* display, FT_GlyphSlot slot, int* pen_x, int* pen_y); /* set the string to be drawn */ void FTDemo_String_Set( FTDemo_Handle* handle, const char* string ); /* load kerned advances with hinting compensation */ FT_Error FTDemo_String_Load( FTDemo_Handle* handle, FTDemo_String_Context* sc ); /* draw a string centered at (center_x, center_y) -- */ /* returns the number of rendered glyphs */ /* note that handle->use_sbits_cache is not supported */ int FTDemo_String_Draw( FTDemo_Handle* handle, FTDemo_Display* display, FTDemo_String_Context* sc, int center_x, int center_y ); /* draw an outline glyph directly onto display surface */ FT_Error FTDemo_Sketch_Glyph_Color( FTDemo_Handle* handle, FTDemo_Display* display, FT_Glyph glyph, FT_Pos x, FT_Pos y, grColor color ); /* make a FT_Encoding tag from a string */ unsigned long FTDemo_Make_Encoding_Tag( const char* s ); int FTDemo_Event_Cff_Hinting_Engine_Change( FT_Library library, unsigned int* current, unsigned int delta ); int FTDemo_Event_Type1_Hinting_Engine_Change( FT_Library library, unsigned int* current, unsigned int delta ); int FTDemo_Event_T1cid_Hinting_Engine_Change( FT_Library library, unsigned int* current, unsigned int delta ); #endif /* FTCOMMON_H_ */ /* End */ ft2demos-2.10.1/src/ftgrid.c0000644000175000001440000017115213504615522015403 0ustar00wlusers00000000000000/****************************************************************************/ /* */ /* The FreeType project -- a free and portable quality TrueType renderer. */ /* */ /* Copyright (C) 1996-2019 by */ /* D. Turner, R.Wilhelm, and W. Lemberg */ /* */ /* */ /* FTGrid - a simple viewer to show glyph outlines on a grid */ /* */ /* Press ? when running this program to have a list of key-bindings */ /* */ /****************************************************************************/ #include "ftcommon.h" #include "common.h" #include "output.h" #include "mlgetopt.h" #include /* the following header shouldn't be used in normal programs */ #include FT_INTERNAL_DEBUG_H /* showing driver name */ #include FT_MODULE_H #include FT_INTERNAL_OBJECTS_H #include FT_INTERNAL_DRIVER_H #include FT_STROKER_H #include FT_SYNTHESIS_H #include FT_LCD_FILTER_H #include FT_DRIVER_H #include FT_MULTIPLE_MASTERS_H #include FT_SFNT_NAMES_H #include FT_TRUETYPE_IDS_H #include FT_TRIGONOMETRY_H #define MAXPTSIZE 500 /* dtp */ #define MAX_MM_AXES 32 #ifdef _WIN32 #define snprintf _snprintf #endif #ifdef FT_DEBUG_AUTOFIT /* these variables, structures, and declarations are for */ /* communication with the debugger in the autofit module; */ /* normal programs don't need this */ struct AF_GlyphHintsRec_; typedef struct AF_GlyphHintsRec_* AF_GlyphHints; extern int _af_debug_disable_horz_hints; extern int _af_debug_disable_vert_hints; extern int _af_debug_disable_blue_hints; extern AF_GlyphHints _af_debug_hints; #ifdef __cplusplus extern "C" { #endif extern void af_glyph_hints_dump_segments( AF_GlyphHints hints, FT_Bool to_stdout ); extern void af_glyph_hints_dump_points( AF_GlyphHints hints, FT_Bool to_stdout ); extern void af_glyph_hints_dump_edges( AF_GlyphHints hints, FT_Bool to_stdout ); extern FT_Error af_glyph_hints_get_num_segments( AF_GlyphHints hints, FT_Int dimension, FT_Int* num_segments ); extern FT_Error af_glyph_hints_get_segment_offset( AF_GlyphHints hints, FT_Int dimension, FT_Int idx, FT_Pos *offset, FT_Bool *is_blue, FT_Pos *blue_offset ); #ifdef __cplusplus } #endif #endif /* FT_DEBUG_AUTOFIT */ #define BUFSIZE 256 #define DO_BITMAP 1 #define DO_GRAY_BITMAP 2 #define DO_OUTLINE 4 #define DO_DOTS 8 #define DO_DOTNUMBERS 16 typedef struct GridStatusRec_ { const char* keys; const char* dims; const char* device; int ptsize; int res; int Num; /* glyph index */ int font_index; int scale; int x_origin; int y_origin; int scale_0; int x_origin_0; int y_origin_0; int disp_width; int disp_height; grBitmap* disp_bitmap; grColor axis_color; grColor grid_color; grColor outline_color; grColor on_color; grColor off_color; grColor segment_color; grColor blue_color; int work; int do_horz_hints; int do_vert_hints; int do_blue_hints; int do_segment; int do_grid; int do_alt_colors; FT_LcdFilter lcd_filter; const char* header; char header_buffer[BUFSIZE]; FT_Stroker stroker; unsigned int cff_hinting_engine; unsigned int type1_hinting_engine; unsigned int t1cid_hinting_engine; unsigned int tt_interpreter_versions[3]; int num_tt_interpreter_versions; int tt_interpreter_version_idx; FT_Bool warping; FT_MM_Var* mm; char* axis_name[MAX_MM_AXES]; FT_Fixed design_pos[MAX_MM_AXES]; FT_Fixed requested_pos[MAX_MM_AXES]; FT_UInt requested_cnt; FT_UInt current_axis; FT_UInt used_num_axis; int no_named_instances; } GridStatusRec, *GridStatus; static GridStatusRec status; static FT_Glyph circle; static void grid_status_init( GridStatus st ) { st->keys = ""; st->dims = DIM; st->device = NULL; /* default */ st->res = 72; st->scale = 64; st->x_origin = 0; st->y_origin = 0; st->work = DO_BITMAP | DO_OUTLINE | DO_DOTS; st->do_horz_hints = 1; st->do_vert_hints = 1; st->do_blue_hints = 1; st->do_segment = 0; st->do_grid = 1; st->do_alt_colors = 0; st->Num = 0; st->lcd_filter = FT_LCD_FILTER_DEFAULT; st->header = NULL; st->mm = NULL; st->current_axis = 0; st->no_named_instances = 0; } static void grid_status_display( GridStatus st, FTDemo_Display* display ) { st->disp_width = display->bitmap->width; st->disp_height = display->bitmap->rows; st->disp_bitmap = display->bitmap; } static void grid_status_colors( GridStatus st, FTDemo_Display* display ) { st->axis_color = grFindColor( display->bitmap, 0, 0, 0, 255 ); /* black */ st->grid_color = grFindColor( display->bitmap, 192, 192, 192, 255 ); /* gray */ st->outline_color = grFindColor( display->bitmap, 255, 0, 0, 255 ); /* red */ st->on_color = grFindColor( display->bitmap, 255, 0, 0, 255 ); /* red */ st->off_color = grFindColor( display->bitmap, 0, 128, 0, 255 ); /* dark green */ st->segment_color = grFindColor( display->bitmap, 64, 255, 128, 64 ); /* light green */ st->blue_color = grFindColor( display->bitmap, 64, 64, 255, 64 ); /* light blue */ } static void grid_status_alt_colors( GridStatus st, FTDemo_Display* display ) { /* colours are adjusted for color-blind people, */ /* cf. http://jfly.iam.u-tokyo.ac.jp/color */ st->axis_color = grFindColor( display->bitmap, 0, 0, 0, 255 ); /* black */ st->grid_color = grFindColor( display->bitmap, 192, 192, 192, 255 ); /* gray */ st->outline_color = grFindColor( display->bitmap, 230, 159, 0, 255 ); /* orange */ st->on_color = grFindColor( display->bitmap, 230, 159, 0, 255 ); /* orange */ st->off_color = grFindColor( display->bitmap, 86, 180, 233, 255 ); /* sky blue */ st->segment_color = grFindColor( display->bitmap, 204, 121, 167, 64 ); /* reddish purple */ st->blue_color = grFindColor( display->bitmap, 0, 114, 178, 64 ); /* blue */ } static void grid_status_rescale_initial( GridStatus st, FTDemo_Handle* handle ) { FT_Size size; FT_Error err = FTDemo_Get_Size( handle, &size ); FT_F26Dot6 margin = 6; if ( !err ) { int xmin = 0; int ymin = size->metrics.descender; int xmax = size->metrics.max_advance; int ymax = size->metrics.ascender; FT_F26Dot6 x_scale, y_scale; if ( xmax - xmin ) x_scale = st->disp_width * ( 64 - 2 * margin ) / ( xmax - xmin ); else x_scale = 64; if ( ymax - ymin ) y_scale = st->disp_height * ( 64 - 2 * margin ) / ( ymax - ymin ); else y_scale = 64; if ( x_scale <= y_scale ) st->scale = x_scale; else st->scale = y_scale; st->x_origin = 32 * st->disp_width - ( xmax + xmin ) * st->scale / 2; st->y_origin = 32 * st->disp_height + ( ymax + ymin ) * st->scale / 2; } else { st->scale = 64; st->x_origin = st->disp_width * margin; st->y_origin = st->disp_height * ( 64 - margin ); } st->x_origin >>= 6; st->y_origin >>= 6; st->scale_0 = st->scale; st->x_origin_0 = st->x_origin; st->y_origin_0 = st->y_origin; } static void grid_status_draw_grid( GridStatus st ) { int x_org = st->x_origin; int y_org = st->y_origin; int xy_incr = st->scale; if ( xy_incr >= 2 ) { int x2 = x_org; int y2 = y_org; for ( ; x2 < st->disp_width; x2 += xy_incr ) grFillVLine( st->disp_bitmap, x2, 0, st->disp_height, st->grid_color ); for ( x2 = x_org - xy_incr; x2 >= 0; x2 -= xy_incr ) grFillVLine( st->disp_bitmap, x2, 0, st->disp_height, st->grid_color ); for ( ; y2 < st->disp_height; y2 += xy_incr ) grFillHLine( st->disp_bitmap, 0, y2, st->disp_width, st->grid_color ); for ( y2 = y_org - xy_incr; y2 >= 0; y2 -= xy_incr ) grFillHLine( st->disp_bitmap, 0, y2, st->disp_width, st->grid_color ); } grFillVLine( st->disp_bitmap, x_org, 0, st->disp_height, st->axis_color ); grFillHLine( st->disp_bitmap, 0, y_org, st->disp_width, st->axis_color ); } #ifdef FT_DEBUG_AUTOFIT static void grid_hint_draw_segment( GridStatus st, FT_Size size, AF_GlyphHints hints ) { FT_Fixed x_scale = size->metrics.x_scale; FT_Fixed y_scale = size->metrics.y_scale; FT_Int dimension; int x_org = st->x_origin; int y_org = st->y_origin; for ( dimension = 1; dimension >= 0; dimension-- ) { FT_Int num_seg; FT_Int count; af_glyph_hints_get_num_segments( hints, dimension, &num_seg ); for ( count = 0; count < num_seg; count++ ) { int pos; FT_Pos offset; FT_Bool is_blue; FT_Pos blue_offset; af_glyph_hints_get_segment_offset( hints, dimension, count, &offset, &is_blue, &blue_offset); if ( dimension == 0 ) /* AF_DIMENSION_HORZ is 0 */ { offset = FT_MulFix( offset, x_scale ); pos = x_org + ( ( offset * st->scale ) >> 6 ); grFillVLine( st->disp_bitmap, pos, 0, st->disp_height, st->segment_color ); } else { offset = FT_MulFix( offset, y_scale ); pos = y_org - ( ( offset * st->scale ) >> 6 ); if ( is_blue ) { int blue_pos; blue_offset = FT_MulFix( blue_offset, y_scale ); blue_pos = y_org - ( ( blue_offset * st->scale ) >> 6 ); if ( blue_pos == pos ) grFillHLine( st->disp_bitmap, 0, blue_pos, st->disp_width, st->blue_color ); else { grFillHLine( st->disp_bitmap, 0, blue_pos, st->disp_width, st->blue_color ); grFillHLine( st->disp_bitmap, 0, pos, st->disp_width, st->segment_color ); } } else grFillHLine( st->disp_bitmap, 0, pos, st->disp_width, st->segment_color ); } } } } #endif /* FT_DEBUG_AUTOFIT */ static void circle_init( FTDemo_Handle* handle, FT_F26Dot6 radius ) { FT_Outline* outline; char* tag; FT_Vector* vec; FT_F26Dot6 disp = (FT_F26Dot6)( radius * 0.5523 ); /* so that Bézier curve touches circle at 0, 45, and 90 degrees */ FT_New_Glyph( handle->library, FT_GLYPH_FORMAT_OUTLINE, &circle ); outline = &((FT_OutlineGlyph)circle)->outline; FT_Outline_New( handle->library, 12, 1, outline ); outline->contours[0] = outline->n_points - 1; vec = outline->points; tag = outline->tags; vec->x = radius; vec->y = 0; vec++; *tag++ = FT_CURVE_TAG_ON; vec->x = radius; vec->y = disp; vec++; *tag++ = FT_CURVE_TAG_CUBIC; vec->x = disp; vec->y = radius; vec++; *tag++ = FT_CURVE_TAG_CUBIC; vec->x = 0; vec->y = radius; vec++; *tag++ = FT_CURVE_TAG_ON; vec->x = -disp; vec->y = radius; vec++; *tag++ = FT_CURVE_TAG_CUBIC; vec->x = -radius; vec->y = disp; vec++; *tag++ = FT_CURVE_TAG_CUBIC; vec->x = -radius; vec->y = 0; vec++; *tag++ = FT_CURVE_TAG_ON; vec->x = -radius; vec->y = -disp; vec++; *tag++ = FT_CURVE_TAG_CUBIC; vec->x = -disp; vec->y = -radius; vec++; *tag++ = FT_CURVE_TAG_CUBIC; vec->x = 0; vec->y = -radius; vec++; *tag++ = FT_CURVE_TAG_ON; vec->x = disp; vec->y = -radius; vec++; *tag++ = FT_CURVE_TAG_CUBIC; vec->x = radius; vec->y = -disp; vec++; *tag++ = FT_CURVE_TAG_CUBIC; } static void circle_draw( FT_F26Dot6 center_x, FT_F26Dot6 center_y, FTDemo_Handle* handle, FTDemo_Display* display, grColor color ) { FT_Outline* outline = &((FT_OutlineGlyph)circle)->outline; int x = center_x >> 6; int y = center_y >> 6; /* subpixel adjustment considering downward direction of y-axis */ FT_Outline_Translate( outline, center_x & 63, -( center_y & 63 ) ); FTDemo_Draw_Glyph_Color( handle, display, circle, &x, &y, color ); FT_Outline_Translate( outline, -( center_x & 63 ), center_y & 63 ); } static void bitmap_scale( GridStatus st, grBitmap* bit, int scale ) { unsigned char* s = bit->buffer; unsigned char* t; unsigned char* line; int pitch; int width; int i, j, k; pitch = bit->pitch > 0 ? bit->pitch : -bit->pitch; width = bit->width; t = (unsigned char*)malloc( (size_t)( pitch * bit->rows * scale * scale ) ); if ( !t ) return; line = t; switch( bit->mode ) { case gr_pixel_mode_mono: for ( i = 0; i < bit->rows; i++ ) { for ( j = 0; j < pitch * scale * 8; j++ ) if ( s[i * pitch + j / scale / 8] & ( 0x80 >> ( j / scale & 7 ) ) ) line[j / 8] |= 0x80 >> ( j & 7 ); else line[j / 8] &= ~( 0x80 >> ( j & 7 ) ); for ( k = 1; k < scale; k++, line += pitch * scale ) memcpy( line + pitch * scale, line, (size_t)( pitch * scale ) ); line += pitch * scale; /* center specks */ if ( scale > 8 ) for ( j = scale / 2; j < width * scale; j += scale ) line[j / 8 - scale / 2 * pitch * scale] ^= 0x80 >> ( j & 7 ); } break; case gr_pixel_mode_gray: Gray: for ( i = 0; i < bit->rows; i++ ) { for ( j = 0; j < pitch; j++ ) memset( line + j * scale, s[i * pitch + j], (size_t)scale ); for ( k = 1; k < scale; k++, line += pitch * scale ) memcpy( line + pitch * scale, line, (size_t)( pitch * scale ) ); line += pitch * scale; } break; case gr_pixel_mode_lcd: case gr_pixel_mode_lcd2: if ( st->work & DO_GRAY_BITMAP ) goto Gray; for ( i = 0; i < bit->rows; i++ ) { for ( j = 0; j < width; j += 3 ) for ( k = 0; k < scale; k++ ) { line[j * scale + 3 * k ] = s[i * pitch + j ]; line[j * scale + 3 * k + 1] = s[i * pitch + j + 1]; line[j * scale + 3 * k + 2] = s[i * pitch + j + 2]; } for ( k = 1; k < scale; k++, line += pitch * scale ) memcpy( line + pitch * scale, line, (size_t)( pitch * scale ) ); line += pitch * scale; } break; case gr_pixel_mode_lcdv: case gr_pixel_mode_lcdv2: if ( st->work & DO_GRAY_BITMAP ) goto Gray; for ( i = 0; i < bit->rows; i += 3 ) { for ( j = 0; j < pitch; j++ ) { memset( line + j * scale, s[i * pitch + j], (size_t)scale ); memset( line + j * scale + pitch * scale, s[i * pitch + pitch + j], (size_t)scale ); memset( line + j * scale + 2 * pitch * scale, s[i * pitch + 2 * pitch + j], (size_t)scale ); } for ( k = 1; k < scale; k++, line += 3 * pitch * scale ) memcpy( line + 3 * pitch * scale, line, (size_t)( 3 * pitch * scale ) ); line += 3 * pitch * scale; } break; default: return; } bit->buffer = t; bit->rows *= scale; bit->width *= scale; bit->pitch *= scale; } static void grid_status_draw_outline( GridStatus st, FTDemo_Handle* handle, FTDemo_Display* display ) { FT_Error err; FT_Size size; FT_GlyphSlot slot; FT_UInt glyph_idx; int scale = st->scale; int ox = st->x_origin; int oy = st->y_origin; err = FTDemo_Get_Size( handle, &size ); if ( err ) return; glyph_idx = FTDemo_Get_Index( handle, (FT_UInt32)st->Num ); #ifdef FT_DEBUG_AUTOFIT _af_debug_disable_horz_hints = !st->do_horz_hints; _af_debug_disable_vert_hints = !st->do_vert_hints; _af_debug_disable_blue_hints = !st->do_blue_hints; #endif if ( FT_Load_Glyph( size->face, glyph_idx, handle->load_flags | FT_LOAD_NO_BITMAP ) ) return; slot = size->face->glyph; if ( st->do_grid ) { /* show advance width */ grFillVLine( st->disp_bitmap, st->x_origin + ( ( slot->metrics.horiAdvance + slot->lsb_delta - slot->rsb_delta ) * scale >> 6 ), 0, st->disp_height, st->axis_color ); /* show ascender and descender */ grFillHLine( st->disp_bitmap, 0, st->y_origin - ( size->metrics.ascender * scale >> 6 ), st->disp_width, st->axis_color ); grFillHLine( st->disp_bitmap, 0, st->y_origin - ( size->metrics.descender * scale >> 6 ), st->disp_width, st->axis_color ); } /* render scaled bitmap */ if ( st->work & DO_BITMAP ) { FT_Glyph glyph, glyf; int left, top, x_advance, y_advance; grBitmap bitg; FT_Get_Glyph( slot, &glyph ); error = FTDemo_Glyph_To_Bitmap( handle, glyph, &bitg, &left, &top, &x_advance, &y_advance, &glyf); if ( !error ) { bitmap_scale( st, &bitg, scale ); grBlitGlyphToBitmap( display->bitmap, &bitg, ox + left * scale, oy - top * scale, st->axis_color ); free( bitg.buffer ); if ( glyf ) FT_Done_Glyph( glyf ); } FT_Done_Glyph( glyph ); } if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) { FT_Glyph glyph; FT_Outline* gimage = &slot->outline; int nn; #ifdef FT_DEBUG_AUTOFIT /* Draw segment before drawing glyph. */ if ( status.do_segment && handle->load_flags & FT_LOAD_FORCE_AUTOHINT ) grid_hint_draw_segment( &status, size, _af_debug_hints ); #endif /* scale the outline */ for ( nn = 0; nn < gimage->n_points; nn++ ) { FT_Vector* vec = &gimage->points[nn]; /* half-pixel shift hints the stroked path */ vec->x = vec->x * scale + 32; vec->y = vec->y * scale - 32; } /* stroke then draw it */ if ( st->work & DO_OUTLINE ) { FT_Get_Glyph( slot, &glyph ); FT_Glyph_Stroke( &glyph, st->stroker, 1 ); error = FTDemo_Sketch_Glyph_Color( handle, display, glyph, ox, oy, st->outline_color ); if ( !error ) FT_Done_Glyph( glyph ); } /* draw the points... */ if ( st->work & DO_DOTS ) { for ( nn = 0; nn < gimage->n_points; nn++ ) circle_draw( st->x_origin * 64 + gimage->points[nn].x, st->y_origin * 64 - gimage->points[nn].y, handle, display, ( gimage->tags[nn] & FT_CURVE_TAG_ON ) ? st->on_color : st->off_color ); } /* ... and point numbers */ if ( st->work & DO_DOTNUMBERS ) { FT_Vector* points = gimage->points; FT_Short* contours = gimage->contours; char* tags = gimage->tags; short c, n; char number_string[10]; size_t number_string_len = sizeof ( number_string ); FT_Long octant_x[8] = { 1024, 724, 0, -724, -1024, -724, 0, 724 }; FT_Long octant_y[8] = { 0, 724, 1024, 724, 0, -724, -1024, -724 }; c = 0; n = 0; for ( ; c < gimage->n_contours; c++ ) { for (;;) { short prev, next; FT_Vector in, out, middle; FT_Fixed in_len, out_len, middle_len; int num_digits; /* find previous and next point in outline */ if ( c == 0 ) { if ( contours[c] == 0 ) { prev = 0; next = 0; } else { prev = n > 0 ? n - 1 : contours[c]; next = n < contours[c] ? n + 1 : 0; } } else { prev = n > ( contours[c - 1] + 1 ) ? n - 1 : contours[c]; next = n < contours[c] ? n + 1 : contours[c - 1] + 1; } /* get vectors to previous and next point and normalize them; */ /* we use 16.16 format to improve the computation precision */ in.x = ( points[prev].x - points[n].x ) * 1024; in.y = ( points[prev].y - points[n].y ) * 1024; out.x = ( points[next].x - points[n].x ) * 1024; out.y = ( points[next].y - points[n].y ) * 1024; in_len = FT_Vector_Length( &in ); out_len = FT_Vector_Length( &out ); if ( in_len ) { in.x = FT_DivFix( in.x, in_len ); in.y = FT_DivFix( in.y, in_len ); } if ( out_len ) { out.x = FT_DivFix( out.x, out_len ); out.y = FT_DivFix( out.y, out_len ); } middle.x = in.x + out.x; middle.y = in.y + out.y; /* we use a delta of 1 << 13 (corresponding to 1/8px) */ if ( ( middle.x < 4096 ) && ( middle.x > -4096 ) && ( middle.y < 4096 ) && ( middle.y > -4096 ) ) { /* in case of vectors in almost exactly opposite directions, */ /* use a vector orthogonal to them */ middle.x = out.y; middle.y = -out.x; if ( ( middle.x < 4096 ) && ( middle.x > -4096 ) && ( middle.y < 4096 ) && ( middle.y > -4096 ) ) { /* use direction based on point index for the offset */ /* if we still don't have a good value */ middle.x = octant_x[n % 8]; middle.y = octant_y[n % 8]; } } /* normalize `middle' vector (which is never zero) and */ /* convert it back to 26.6 format, this time using a */ /* length of 8 pixels to get some distance between the */ /* point and the number */ middle_len = FT_Vector_Length( &middle ); middle.x = FT_DivFix( middle.x, middle_len ) >> 7; middle.y = FT_DivFix( middle.y, middle_len ) >> 7; num_digits = snprintf( number_string, number_string_len, "%d", n ); /* we now position the point number in the opposite */ /* direction of the `middle' vector, adding some offset */ /* since the string drawing function expects the upper */ /* left corner of the number string (the font size is 8x8 */ /* pixels) */ grWriteCellString( display->bitmap, st->x_origin + ( ( points[n].x - middle.x ) >> 6 ) - ( middle.x > 0 ? ( num_digits - 1 ) * 8 + 2 : 2 ), st->y_origin - ( ( ( points[n].y - middle.y ) >> 6 ) + 8 / 2 ), number_string, ( tags[n] & FT_CURVE_TAG_ON ) ? st->on_color : st->off_color ); n++; if ( n > contours[c] ) break; } } } } } static FTDemo_Display* display; static FTDemo_Handle* handle; #if 0 static const unsigned char* Text = (unsigned char*) "The quick brown fox jumps over the lazy dog 0123456789 " "\342\352\356\373\364\344\353\357\366\374\377\340\371\351\350\347 " "&#~\"\'(-`_^@)=+\260 ABCDEFGHIJKLMNOPQRSTUVWXYZ " "$\243^\250*\265\371%!\247:/;.,?<>"; #endif static void Fatal( const char* message ) { FTDemo_Display_Done( display ); FTDemo_Done( handle ); PanicZ( message ); } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** REST OF THE APPLICATION/PROGRAM *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ static void event_help( void ) { char buf[BUFSIZE]; char version[64] = ""; grEvent dummy_event; FTDemo_Version( handle, version ); FTDemo_Display_Clear( display ); grSetLineHeight( 10 ); grGotoxy( 0, 0 ); grSetMargin( 2, 1 ); grGotobitmap( display->bitmap ); sprintf( buf, "FreeType Glyph Grid Viewer - part of the FreeType %s test suite", version ); grWriteln( buf ); grLn(); grWriteln( "Use the following keys:" ); grLn(); /* |----------------------------------| |----------------------------------| */ #ifdef FT_DEBUG_AUTOFIT grWriteln( "F1, ? display this help screen if autohinting: " ); grWriteln( " H toggle horiz. hinting " ); grWriteln( "i, k move grid up/down V toggle vert. hinting " ); grWriteln( "j, l move grid left/right B toggle blue zone hinting" ); grWriteln( "PgUp, PgDn zoom in/out grid s toggle segment drawing " ); grWriteln( "SPC reset zoom and position (unfitted, with blues) " ); grWriteln( " 1 dump edge hints " ); grWriteln( "p, n previous/next font 2 dump segment hints " ); grWriteln( " 3 dump point hints " ); #else grWriteln( "F1, ? display this help screen i, k move grid up/down " ); grWriteln( " j, l move grid left/right " ); grWriteln( "p, n previous/next font PgUp, PgDn zoom in/out grid " ); grWriteln( " SPC reset zoom and position " ); #endif /* FT_DEBUG_AUTOFIT */ grWriteln( "Up, Down adjust size by 0.5pt if not auto-hinting: " ); grWriteln( " H cycle through hinting " ); grWriteln( "Left, Right adjust index by 1 engines (if available) " ); grWriteln( "F7, F8 adjust index by 16 if normal auto-hinting: " ); grWriteln( "F9, F10 adjust index by 256 w toggle warping " ); grWriteln( "F11, F12 adjust index by 4096 (if available) " ); grWriteln( " " ); grWriteln( "h toggle hinting b toggle bitmap " ); grWriteln( "f toggle forced auto- d toggle dot display " ); grWriteln( " hinting (if hinting) o toggle outline display " ); grWriteln( "G toggle grid display D toggle dotnumber display" ); grWriteln( "C change color palette " ); grWriteln( " if Multiple Master or GX font: " ); grWriteln( "F5, F6 cycle through F2 cycle through axes " ); grWriteln( " anti-aliasing modes F3, F4 adjust current axis by " ); grWriteln( "L cycle through LCD 1/50th of its range " ); grWriteln( " filters " ); grWriteln( " P print PNG file " ); grWriteln( "g, v adjust gamma value q, ESC quit ftgrid " ); /* |----------------------------------| |----------------------------------| */ grLn(); grLn(); grWriteln( "press any key to exit this help screen" ); grRefreshSurface( display->surface ); grListenSurface( display->surface, gr_event_key, &dummy_event ); } static void event_font_change( int delta ) { FT_Error err; FT_Size size; FT_UInt n, num_names; FT_Int instance_index; FT_Multi_Master dummy; int num_indices, is_GX; if ( status.font_index + delta >= handle->num_fonts || status.font_index + delta < 0 ) return; status.font_index += delta; FTDemo_Set_Current_Font( handle, handle->fonts[status.font_index] ); FTDemo_Set_Current_Charsize( handle, status.ptsize, status.res ); FTDemo_Update_Current_Flags( handle ); num_indices = handle->current_font->num_indices; if ( status.Num >= num_indices ) status.Num = num_indices - 1; err = FTDemo_Get_Size( handle, &size ); if ( err ) return; free( status.mm ); status.mm = NULL; err = FT_Get_MM_Var( size->face, &status.mm ); if ( err ) return; if ( status.mm->num_axis >= MAX_MM_AXES ) { fprintf( stderr, "only handling first %d GX axes (of %d)\n", MAX_MM_AXES, status.mm->num_axis ); status.used_num_axis = MAX_MM_AXES; } else status.used_num_axis = status.mm->num_axis; err = FT_Get_Multi_Master( size->face, &dummy ); is_GX = err ? 1 : 0; num_names = FT_Get_Sfnt_Name_Count( size->face ); /* in `face_index', the instance index starts with value 1 */ instance_index = ( size->face->face_index >> 16 ) - 1; for ( n = 0; n < MAX_MM_AXES; n++ ) { free( status.axis_name[n] ); status.axis_name[n] = NULL; } for ( n = 0; n < status.used_num_axis; n++ ) { if ( status.requested_cnt ) { status.design_pos[n] = n < status.requested_cnt ? status.requested_pos[n] : status.mm->axis[n].def; if ( status.design_pos[n] < status.mm->axis[n].minimum ) status.design_pos[n] = status.mm->axis[n].minimum; else if ( status.design_pos[n] > status.mm->axis[n].maximum ) status.design_pos[n] = status.mm->axis[n].maximum; } else if ( FT_IS_NAMED_INSTANCE( size->face ) ) status.design_pos[n] = status.mm->namedstyle[instance_index]. coords[n]; else status.design_pos[n] = status.mm->axis[n].def; if ( is_GX ) { FT_SfntName name; FT_UInt strid, j; name.string = NULL; strid = status.mm->axis[n].strid; /* iterate over all name entries */ /* to find an English entry for `strid' */ for ( j = 0; j < num_names; j++ ) { error = FT_Get_Sfnt_Name( size->face, j, &name ); if ( error ) continue; if ( name.name_id == strid ) { /* XXX we don't have support for Apple's new `ltag' table yet, */ /* thus we ignore TT_PLATFORM_APPLE_UNICODE */ if ( ( name.platform_id == TT_PLATFORM_MACINTOSH && name.language_id == TT_MAC_LANGID_ENGLISH ) || ( name.platform_id == TT_PLATFORM_MICROSOFT && ( name.language_id & 0xFF ) == TT_MS_LANGID_ENGLISH_GENERAL ) ) break; } } if ( name.string ) { FT_UInt len; char* s; if ( name.platform_id == TT_PLATFORM_MACINTOSH ) { len = put_ascii_string_size( name.string, name.string_len, 0 ); s = (char*)malloc( len ); if ( s ) { put_ascii_string( s, name.string, name.string_len, 0 ); status.axis_name[n] = s; } } else { len = put_unicode_be16_string_size( name.string, name.string_len, 0, 0 ); s = (char*)malloc( len ); if ( s ) { put_unicode_be16_string( s, name.string, name.string_len, 0, 0 ); status.axis_name[n] = s; } } } } } (void)FT_Set_Var_Design_Coordinates( size->face, status.used_num_axis, status.design_pos ); } static void event_tt_interpreter_version_change( void ) { status.tt_interpreter_version_idx += 1; status.tt_interpreter_version_idx %= status.num_tt_interpreter_versions; error = FT_Property_Set( handle->library, "truetype", "interpreter-version", &status.tt_interpreter_versions[ status.tt_interpreter_version_idx] ); if ( !error ) { /* Resetting the cache is perhaps a bit harsh, but I'm too */ /* lazy to walk over all loaded fonts to check whether they */ /* are of type TTF, then unloading them explicitly. */ FTC_Manager_Reset( handle->cache_manager ); event_font_change( 0 ); } sprintf( status.header_buffer, "TrueType engine changed to version %d", status.tt_interpreter_versions[ status.tt_interpreter_version_idx]); status.header = (const char *)status.header_buffer; } static void event_warping_change( void ) { if ( handle->lcd_mode == LCD_MODE_AA && handle->autohint ) { FT_Bool new_warping_state = !status.warping; error = FT_Property_Set( handle->library, "autofitter", "warping", &new_warping_state ); if ( !error ) { /* Resetting the cache is perhaps a bit harsh, but I'm too */ /* lazy to walk over all loaded fonts to check whether they */ /* are auto-hinted, then unloading them explicitly. */ FTC_Manager_Reset( handle->cache_manager ); status.warping = new_warping_state; event_font_change( 0 ); } status.header = status.warping ? "warping enabled" : "warping disabled"; } else status.header = "need normal anti-aliasing mode to toggle warping"; } static void event_gamma_change( double delta ) { display->gamma += delta; if ( display->gamma > 3.0 ) display->gamma = 3.0; else if ( display->gamma < 0.0 ) display->gamma = 0.0; grSetTargetGamma( display->bitmap, display->gamma ); } static void event_grid_reset( GridStatus st ) { st->x_origin = st->x_origin_0; st->y_origin = st->y_origin_0; st->scale = st->scale_0; } static void event_grid_translate( int dx, int dy ) { status.x_origin += 32 * dx; status.y_origin += 32 * dy; } static void event_grid_zoom( double zoom ) { int scale_old = status.scale; status.scale *= zoom; /* avoid same zoom value due to truncation */ /* to integer in above multiplication */ if ( status.scale == scale_old && zoom > 1.0 ) status.scale++; sprintf( status.header_buffer, "zoom scale %d:1", status.scale ); status.header = (const char *)status.header_buffer; } static void event_lcd_mode_change( int delta ) { const char* lcd_mode = NULL; handle->lcd_mode = ( handle->lcd_mode + delta + N_LCD_MODES ) % N_LCD_MODES; switch ( handle->lcd_mode ) { case LCD_MODE_MONO: lcd_mode = "monochrome"; break; case LCD_MODE_AA: lcd_mode = "normal AA"; break; case LCD_MODE_LIGHT: lcd_mode = "light AA"; break; case LCD_MODE_LIGHT_SUBPIXEL: lcd_mode = "light AA (subpixel positioning)"; break; case LCD_MODE_RGB: lcd_mode = "LCD (horiz. RGB)"; break; case LCD_MODE_BGR: lcd_mode = "LCD (horiz. BGR)"; break; case LCD_MODE_VRGB: lcd_mode = "LCD (vert. RGB)"; break; case LCD_MODE_VBGR: lcd_mode = "LCD (vert. BGR)"; break; } if ( delta ) { FTC_Manager_Reset( handle->cache_manager ); event_font_change( 0 ); } sprintf( status.header_buffer, "rendering mode changed to %s", lcd_mode ); status.header = (const char *)status.header_buffer; FTDemo_Update_Current_Flags( handle ); } static void event_lcd_filter_change( void ) { if ( handle->lcd_mode >= LCD_MODE_RGB ) { const char* lcd_filter = NULL; switch( status.lcd_filter ) { case FT_LCD_FILTER_DEFAULT: status.lcd_filter = FT_LCD_FILTER_LIGHT; break; case FT_LCD_FILTER_LIGHT: status.lcd_filter = FT_LCD_FILTER_LEGACY1; break; case FT_LCD_FILTER_LEGACY1: status.lcd_filter = FT_LCD_FILTER_NONE; break; case FT_LCD_FILTER_NONE: default: status.lcd_filter = FT_LCD_FILTER_DEFAULT; break; } switch ( status.lcd_filter ) { case FT_LCD_FILTER_DEFAULT: lcd_filter = "default"; break; case FT_LCD_FILTER_LIGHT: lcd_filter = "light"; break; case FT_LCD_FILTER_LEGACY1: lcd_filter = "legacy"; break; case FT_LCD_FILTER_NONE: default: lcd_filter = "none"; break; } sprintf( status.header_buffer, "LCD filter changed to %s", lcd_filter ); status.header = (const char *)status.header_buffer; FT_Library_SetLcdFilter( handle->library, status.lcd_filter ); } else status.header = "need LCD mode to change filter"; } static void event_size_change( int delta ) { status.ptsize += delta; if ( status.ptsize < 1 * 64 ) status.ptsize = 1 * 64; else if ( status.ptsize > MAXPTSIZE * 64 ) status.ptsize = MAXPTSIZE * 64; FTDemo_Set_Current_Charsize( handle, status.ptsize, status.res ); } static void event_index_change( int delta ) { int num_indices = handle->current_font->num_indices; status.Num += delta; if ( status.Num < 0 ) status.Num = 0; else if ( status.Num >= num_indices ) status.Num = num_indices - 1; } static void event_axis_change( int delta ) { FT_Error err; FT_Size size; FT_Var_Axis* a; FT_Fixed pos; err = FTDemo_Get_Size( handle, &size ); if ( err ) return; if ( !status.mm ) return; a = status.mm->axis + status.current_axis; pos = status.design_pos[status.current_axis]; /* * Normalize i. Changing by 20 is all very well for PostScript fonts, * which tend to have a range of ~1000 per axis, but it's not useful * for mac fonts, which have a range of ~3. And it's rather extreme * for optical size even in PS. */ pos += FT_MulDiv( delta, a->maximum - a->minimum, 1000 ); if ( pos < a->minimum ) pos = a->minimum; if ( pos > a->maximum ) pos = a->maximum; status.design_pos[status.current_axis] = pos; (void)FT_Set_Var_Design_Coordinates( size->face, status.used_num_axis, status.design_pos ); } static int Process_Event( void ) { grEvent event; int ret = 0; if ( *status.keys ) event.key = grKEY( *status.keys++ ); else grListenSurface( display->surface, 0, &event ); status.header = NULL; switch ( event.key ) { case grKeyEsc: case grKEY( 'q' ): ret = 1; break; case grKeyF1: case grKEY( '?' ): event_help(); break; case grKEY( 'P' ): { FT_String str[64] = "ftgrid (FreeType) "; FTDemo_Version( handle, str ); FTDemo_Display_Print( display, "ftgrid.png", str ); } break; case grKEY( 'f' ): handle->autohint = !handle->autohint; status.header = handle->autohint ? "forced auto-hinting is now on" : "forced auto-hinting is now off"; FTDemo_Update_Current_Flags( handle ); break; #ifdef FT_DEBUG_AUTOFIT case grKEY( '1' ): if ( handle->hinted && ( handle->autohint || handle->lcd_mode == LCD_MODE_LIGHT || handle->lcd_mode == LCD_MODE_LIGHT_SUBPIXEL ) ) { status.header = "dumping glyph edges to stdout"; af_glyph_hints_dump_edges( _af_debug_hints, 1 ); } break; case grKEY( '2' ): if ( handle->hinted && ( handle->autohint || handle->lcd_mode == LCD_MODE_LIGHT || handle->lcd_mode == LCD_MODE_LIGHT_SUBPIXEL ) ) { status.header = "dumping glyph segments to stdout"; af_glyph_hints_dump_segments( _af_debug_hints, 1 ); } break; case grKEY( '3' ): if ( handle->hinted && ( handle->autohint || handle->lcd_mode == LCD_MODE_LIGHT || handle->lcd_mode == LCD_MODE_LIGHT_SUBPIXEL ) ) { status.header = "dumping glyph points to stdout"; af_glyph_hints_dump_points( _af_debug_hints, 1 ); } break; #endif /* FT_DEBUG_AUTOFIT */ case grKEY( 'C' ): status.do_alt_colors = !status.do_alt_colors; if ( status.do_alt_colors ) { status.header = "use alternative colors"; grid_status_alt_colors( &status, display ); } else { status.header = "use default colors"; grid_status_colors( &status, display ); } break; case grKEY( 'L' ): event_lcd_filter_change(); break; case grKEY( 'g' ): event_gamma_change( 0.1 ); break; case grKEY( 'v' ): event_gamma_change( -0.1 ); break; case grKEY( 'n' ): event_font_change( 1 ); break; case grKEY( 'h' ): handle->hinted = !handle->hinted; status.header = handle->hinted ? "glyph hinting is now active" : "glyph hinting is now ignored"; FTC_Manager_Reset( handle->cache_manager ); event_font_change( 0 ); break; case grKEY( 'G' ): status.do_grid = !status.do_grid; status.header = status.do_grid ? "grid drawing enabled" : "grid drawing disabled"; break; case grKEY( 'd' ): status.work ^= DO_DOTS; break; case grKEY( 'D' ): status.work ^= DO_DOTNUMBERS; break; case grKEY( 'o' ): status.work ^= DO_OUTLINE; break; case grKEY( 'b' ): status.work ^= DO_BITMAP; if ( status.work & DO_BITMAP ) status.work ^= DO_GRAY_BITMAP; break; case grKEY( 'p' ): event_font_change( -1 ); break; case grKEY( 'H' ): if ( !( handle->autohint || handle->lcd_mode == LCD_MODE_LIGHT || handle->lcd_mode == LCD_MODE_LIGHT_SUBPIXEL ) ) { FT_Face face; FT_Module module; error = FTC_Manager_LookupFace( handle->cache_manager, handle->scaler.face_id, &face ); if ( !error ) { module = &face->driver->root; if ( !strcmp( module->clazz->module_name, "cff" ) ) { if ( FTDemo_Event_Cff_Hinting_Engine_Change( handle->library, &status.cff_hinting_engine, 1 ) ) { /* Resetting the cache is perhaps a bit harsh, but I'm too */ /* lazy to walk over all loaded fonts to check whether they */ /* are of type CFF, then unloading them explicitly. */ FTC_Manager_Reset( handle->cache_manager ); event_font_change( 0 ); } sprintf( status.header_buffer, "CFF engine changed to %s", status.cff_hinting_engine == FT_HINTING_FREETYPE ? "FreeType" : "Adobe" ); status.header = (const char *)status.header_buffer; } else if ( !strcmp( module->clazz->module_name, "type1" ) ) { if ( FTDemo_Event_Type1_Hinting_Engine_Change( handle->library, &status.type1_hinting_engine, 1 ) ) { /* Resetting the cache is perhaps a bit harsh, but I'm too */ /* lazy to walk over all loaded fonts to check whether they */ /* are of type Type1, then unloading them explicitly. */ FTC_Manager_Reset( handle->cache_manager ); event_font_change( 0 ); } sprintf( status.header_buffer, "Type 1 engine changed to %s", status.type1_hinting_engine == FT_HINTING_FREETYPE ? "FreeType" : "Adobe" ); status.header = (const char *)status.header_buffer; } else if ( !strcmp( module->clazz->module_name, "t1cid" ) ) { if ( FTDemo_Event_T1cid_Hinting_Engine_Change( handle->library, &status.t1cid_hinting_engine, 1 ) ) { /* Resetting the cache is perhaps a bit harsh, but I'm too */ /* lazy to walk over all loaded fonts to check whether they */ /* are of type CID, then unloading them explicitly. */ FTC_Manager_Reset( handle->cache_manager ); event_font_change( 0 ); } sprintf( status.header_buffer, "CID engine changed to %s", status.t1cid_hinting_engine == FT_HINTING_FREETYPE ? "FreeType" : "Adobe" ); status.header = (const char *)status.header_buffer; } else if ( !strcmp( module->clazz->module_name, "truetype" ) ) event_tt_interpreter_version_change(); } } #ifdef FT_DEBUG_AUTOFIT else { status.do_horz_hints = !status.do_horz_hints; status.header = status.do_horz_hints ? "horizontal hinting enabled" : "horizontal hinting disabled"; } #endif break; case grKEY( 'w' ): event_warping_change(); break; #ifdef FT_DEBUG_AUTOFIT case grKEY( 'V' ): if ( handle->autohint || handle->lcd_mode == LCD_MODE_LIGHT || handle->lcd_mode == LCD_MODE_LIGHT_SUBPIXEL ) { status.do_vert_hints = !status.do_vert_hints; status.header = status.do_vert_hints ? "vertical hinting enabled" : "vertical hinting disabled"; } else status.header = "need autofit mode to toggle vertical hinting"; break; case grKEY( 'B' ): if ( handle->autohint || handle->lcd_mode == LCD_MODE_LIGHT || handle->lcd_mode == LCD_MODE_LIGHT_SUBPIXEL ) { status.do_blue_hints = !status.do_blue_hints; status.header = status.do_blue_hints ? "blue zone hinting enabled" : "blue zone hinting disabled"; } else status.header = "need autofit mode to toggle blue zone hinting"; break; case grKEY( 's' ): status.do_segment = !status.do_segment; status.header = status.do_segment ? "segment drawing enabled" : "segment drawing disabled"; break; #endif /* FT_DEBUG_AUTOFIT */ case grKeyLeft: event_index_change( -1 ); break; case grKeyRight: event_index_change( 1 ); break; case grKeyF7: event_index_change( -0x10 ); break; case grKeyF8: event_index_change( 0x10 ); break; case grKeyF9: event_index_change( -0x100 ); break; case grKeyF10: event_index_change( 0x100 ); break; case grKeyF11: event_index_change( -0x1000 ); break; case grKeyF12: event_index_change( 0x1000 ); break; case grKeyUp: event_size_change( 32 ); break; case grKeyDown: event_size_change( -32 ); break; case grKEY( ' ' ): event_grid_reset( &status ); #if 0 status.do_horz_hints = 1; status.do_vert_hints = 1; status.do_blue_hints = 1; #endif break; case grKEY( 'i' ): event_grid_translate( 0, -1 ); break; case grKEY( 'k' ): event_grid_translate( 0, 1 ); break; case grKEY( 'j' ): event_grid_translate( -1, 0 ); break; case grKEY( 'l' ): event_grid_translate( 1, 0 ); break; case grKeyPageUp: event_grid_zoom( 1.25 ); break; case grKeyPageDown: event_grid_zoom( 1 / 1.25 ); break; case grKeyF2: if ( status.mm ) { status.current_axis++; status.current_axis %= status.used_num_axis; } break; case grKeyF3: event_axis_change( -20 ); break; case grKeyF4: event_axis_change( 20 ); break; case grKeyF5: event_lcd_mode_change( -1 ); break; case grKeyF6: event_lcd_mode_change( 1 ); break; default: ; } return ret; } static void write_header( FT_Error error_code ) { FTDemo_Draw_Header( handle, display, status.ptsize, status.res, status.Num, error_code ); if ( status.header ) grWriteCellString( display->bitmap, 0, 3 * HEADER_HEIGHT, status.header, display->fore_color ); if ( status.mm ) { const char* format = "%s axis: %.02f"; snprintf( status.header_buffer, BUFSIZE, format, status.axis_name[status.current_axis] ? status.axis_name[status.current_axis] : status.mm->axis[status.current_axis].name, status.design_pos[status.current_axis] / 65536.0 ); status.header = (const char *)status.header_buffer; grWriteCellString( display->bitmap, 0, 4 * HEADER_HEIGHT, status.header, display->fore_color ); } grRefreshSurface( display->surface ); } static void usage( char* execname ) { fprintf( stderr, "\n" "ftgrid: simple glyph grid viewer -- part of the FreeType project\n" "----------------------------------------------------------------\n" "\n" ); fprintf( stderr, "Usage: %s [options] pt font ...\n" "\n", execname ); fprintf( stderr, " pt The point size for the given resolution.\n" " If resolution is 72dpi, this directly gives the\n" " ppem value (pixels per EM).\n" ); fprintf( stderr, " font The font file(s) to display.\n" " For Type 1 font files, ftgrid also tries to attach\n" " the corresponding metrics file (with extension\n" " `.afm' or `.pfm').\n" "\n" ); fprintf( stderr, " -d WxHxD Set the window width, height, and color depth\n" " (default: 640x480x24).\n" " -k keys Emulate sequence of keystrokes upon start-up.\n" " If the keys contain `q', use batch mode.\n" " -r R Use resolution R dpi (default: 72dpi).\n" " -f index Specify first index to display (default: 0).\n" " -e enc Specify encoding tag (default: no encoding).\n" " Common values: `unic' (Unicode), `symb' (symbol),\n" " `ADOB' (Adobe standard), `ADBC' (Adobe custom).\n" " -a \"axis1 axis2 ...\"\n" " Specify the design coordinates for each\n" " Multiple Master axis at start-up. Implies `-n'.\n" " -n Don't display named instances of variation fonts.\n" "\n" " -v Show version." "\n" ); exit( 1 ); } static void parse_cmdline( int* argc, char** argv[] ) { char* execname; int option; execname = ft_basename( (*argv)[0] ); while ( 1 ) { option = getopt( *argc, *argv, "a:d:e:f:k:nr:v" ); if ( option == -1 ) break; switch ( option ) { case 'a': { FT_UInt cnt; FT_Fixed* pos = status.requested_pos; char* s = optarg; for ( cnt = 0; cnt < MAX_MM_AXES && *s; cnt++ ) { pos[cnt] = (FT_Fixed)( strtod( s, &s ) * 65536.0 ); while ( *s == ' ' ) ++s; } status.requested_cnt = cnt; status.no_named_instances = 1; } break; case 'd': status.dims = optarg; break; case 'e': handle->encoding = FTDemo_Make_Encoding_Tag( optarg ); status.Num = 0x20; break; case 'f': status.Num = atoi( optarg ); break; case 'k': status.keys = optarg; while ( *optarg && *optarg != 'q' ) optarg++; if ( *optarg == 'q' ) status.device = "batch"; break; case 'n': status.no_named_instances = 1; break; case 'r': status.res = atoi( optarg ); if ( status.res < 1 ) usage( execname ); break; case 'v': { FT_String str[64] = "ftgrid (FreeType) "; FTDemo_Version( handle, str ); printf( "%s\n", str ); exit( 0 ); } /* break; */ default: usage( execname ); break; } } *argc -= optind; *argv += optind; if ( *argc <= 1 ) usage( execname ); status.ptsize = (int)( atof( *argv[0] ) * 64.0 ); if ( status.ptsize == 0 ) status.ptsize = 64 * 10; (*argc)--; (*argv)++; } int main( int argc, char* argv[] ) { int n; unsigned int dflt_tt_interpreter_version; unsigned int versions[3] = { TT_INTERPRETER_VERSION_35, TT_INTERPRETER_VERSION_38, TT_INTERPRETER_VERSION_40 }; /* initialize engine */ handle = FTDemo_New(); grid_status_init( &status ); circle_init( handle, 128 ); parse_cmdline( &argc, &argv ); /* get the default value as compiled into FreeType */ FT_Property_Get( handle->library, "cff", "hinting-engine", &status.cff_hinting_engine ); FT_Property_Get( handle->library, "type1", "hinting-engine", &status.type1_hinting_engine ); FT_Property_Get( handle->library, "t1cid", "hinting-engine", &status.t1cid_hinting_engine ); /* collect all available versions, then set again the default */ FT_Property_Get( handle->library, "truetype", "interpreter-version", &dflt_tt_interpreter_version ); for ( n = 0; n < 3; n++ ) { error = FT_Property_Set( handle->library, "truetype", "interpreter-version", &versions[n] ); if ( !error ) status.tt_interpreter_versions[ status.num_tt_interpreter_versions++] = versions[n]; if ( versions[n] == dflt_tt_interpreter_version ) status.tt_interpreter_version_idx = n; } FT_Property_Set( handle->library, "truetype", "interpreter-version", &dflt_tt_interpreter_version ); FT_Property_Get( handle->library, "autofitter", "warping", &status.warping ); FT_Library_SetLcdFilter( handle->library, status.lcd_filter ); FT_Stroker_New( handle->library, &status.stroker ); FT_Stroker_Set( status.stroker, 32, FT_STROKER_LINECAP_BUTT, FT_STROKER_LINEJOIN_BEVEL, 0x20000 ); for ( ; argc > 0; argc--, argv++ ) FTDemo_Install_Font( handle, argv[0], 0, status.no_named_instances ? 1 : 0 ); if ( handle->num_fonts == 0 ) Fatal( "could not find/open any font file" ); display = FTDemo_Display_New( status.device, status.dims ); if ( !display ) Fatal( "could not allocate display surface" ); grSetTitle( display->surface, "FreeType Glyph Grid Viewer - press ? for help" ); grid_status_display( &status, display ); grid_status_colors( &status, display ); event_font_change( 0 ); grid_status_rescale_initial( &status, handle ); do { FTDemo_Display_Clear( display ); if ( status.do_grid ) grid_status_draw_grid( &status ); if ( status.work ) grid_status_draw_outline( &status, handle, display ); write_header( 0 ); } while ( !Process_Event() ); printf( "Execution completed successfully.\n" ); for ( n = 0; n < MAX_MM_AXES; n++ ) free( status.axis_name[n] ); FT_Done_MM_Var( handle->library, status.mm ); FT_Stroker_Done( status.stroker ); FTDemo_Display_Done( display ); FTDemo_Done( handle ); exit( 0 ); /* for safety reasons */ /* return 0; */ /* never reached */ } /* End */ ft2demos-2.10.1/src/ftbench.10000644000175000001440000000503113506424316015444 0ustar00wlusers00000000000000'\" t .TH FTVIEW 1 "May 2019" "Freetype 2.10.1" . . .SH NAME . ftbench \- benchmark some common FreeType paths . . .SH SYNOPSIS . .B ftbench .RI [ options ] .I fontname . . .SH DESCRIPTION . The .B ftbench tool measures performance of some common FreeType operations. . .PP This program is part of the FreeType demos package. . . .SH OPTIONS . .TP .BI \-b \ tests Perform chosen tests: . .RS .TS tab (@); rB l. a@load glyphs (FT_Load_Glyph) b@load advance widths (FT_Get_Advances) c@render glyphs (FT_Render_Glyph) d@load glyphs (FT_Get_Glyph) e@get glyph cboxes (FT_Glyph_Get_CBox) f@get glyph indices (FT_Get_Char_Index) g@iterate CMap (FT_Get_{First,Next}_Char) h@open a new face (FT_New_Face or FT_New_Memory_Face) i@embolden glyphs (FT_GlyphSlot_Embolden) j@get glyph bboxes (FT_Outline_Get_BBox) k@open a new face and load glyphs .TE .RE . .IP (default is .BR abcdefghijk , this is, all tests). . .IP The number of used glyphs per test (within a single iteration) is given by options .B \-i and .BR \-j . . .TP .B \-C Compare with cached version if available. . .TP .BI \-c \ n Use at most .I n iterations for each test (0 means time limited). . .TP .BI \-f \ l Use .B hexadecimal (not decimal) number .I l as load flags (see the .RB ` FT_LOAD_XXX ' macros in the FreeType reference). . .TP .BI "\-H " name Using CFF hinting engine .IR name . Available versions are depending on compilation options of FreeType; call .B ftbench without an argument to get the actual list. . .TP .BI "\-I " ver Using TT interpreter version .IR ver . Available versions are depending on compilation options of FreeType; call .B ftbench without an argument to get the actual list. . .TP .BI \-i \ idx Start with glyph index .I idx (default is 0). . .TP .BI \-j \ idx End with glyph index .I idx (default is the number of glyphs minus one). . .TP .BI \-m \ m Set maximum cache size to .I M KiByte (default is 1024). . .TP .B \-p Preload font file in memory (this is, testing .B FT_New_Memory_Face instead of .BR FT_New_Face ). . .TP .BI \-r \ n Set render mode to .IR n : . .RS .TS tab (@); rB l. 0@normal 1@light 2@mono 3@horizontal LCD 4@vertical LCD .TE .RE . .IP (default is 0). This corresponds to the values of the .RB ` FT_RENDER_MODE_XXX ' flags. . .TP .BI \-s \ s Use .I s ppem as face size (default is 10ppem). If set to zero, don't call .BR FT_Set_Pixel_Sizes . Use value\ 0 with option .RB ` "-f\ 1" ' or something similar to load the glyphs unscaled, otherwise errors will show up. . .TP .BI \-t \ t Use at most .I t seconds per test (default is 2). . .TP .B \-v Show version. . .\" eof ft2demos-2.10.1/src/ftdiff.10000644000175000001440000000172213506424316015300 0ustar00wlusers00000000000000.TH FTDIFF 1 "May 2019" "FreeType 2.10.1" . . .SH NAME . ftdiff \- compare font hinting modes . . .SH SYNOPSIS . .B ftdiff .RI [ options ] .IR font \ .\|.\|. . . .SH DESCRIPTION . .B ftdiff displays text in three columns, using the font or fonts given on the command line, and applies different FreeType hinting modes to each column. . .TP .B font The font file(s) to display. For Type\ 1 font files, .B ftdiff also tries to attach the corresponding metrics file (with extension `.afm' or `.pfm'). . .PP This program is part of the FreeType demos package. . . .SH OPTIONS . .TP .BI \-w \ w Set the window width to .I w pixels (default: 640px). . .TP .BI \-h \ h Set the window height to .I h pixels (default: 480px). . .TP .BI \-r \ r Use resolution .I r dpi (default: 72dpi). . .TP .BI \-s \ s Set character size to .I s points (default: 16pt). . .TP .BI \-f \ textfile Change displayed text, using text in .I textfile (in UTF-8 encoding). . .TP .B \-v Show version. . .\" eof ft2demos-2.10.1/src/ftdump.10000644000175000001440000000102313506424316015327 0ustar00wlusers00000000000000.TH FTDUMP 1 "May 2019" "FreeType 2.10.1" . . .SH NAME . ftdump \- simple font dumper . . .SH SYNOPSIS . .B ftdump .RI [ options ] .I fontname . . .SH DESCRIPTION . .B ftdump lists information about a font file that is relevant for FreeType. . .PP This program is part of the FreeType demos package. . . .SH OPTIONS . .TP .B \-c, \-C Print charmap coverage. . .TP .B \-n Print SFNT name tables. . .TP .B \-p Print TrueType programs. . .TP .B \-t Print SFNT table list. . .TP .B \-u Emit UTF-8. . .TP .B \-v Show version. . .\" eof ft2demos-2.10.1/src/ftgamma.10000644000175000001440000000245113506424316015452 0ustar00wlusers00000000000000.TH FTGAMMA 1 "May 2019" "FreeType 2.10.1" . . .SH NAME . ftgamma \- screen gamma calibration helper . . .SH SYNOPSIS . .B ftgamma . . .SH DESCRIPTION . The .B ftgamma demo program opens a window showing series of gray stripes filled with solid color and checkered pattern of pixels. Your monitor's gamma value roughly corresponds to the horizontal position where the solid and checkered stripes are equally bright when seen from some distance. Three brightness targets are explored: 33%, 50%, and 67%. If the input-output curve of your monitor does not follow ideal power law relationship, you might observe slightly different gamma values at different brightness levels. It is also possible to examine gamma values for basic colors. . .PP Two alternative patterns relevant to font rendering are also provided, where slightly slanted lines are rendered using grayscale and subpixel anti-aliasing. In the grayscale case, the correct gamma helps to achieve uniform perceived thickness of the lines. The gamma value that corresponds to vanishing moiré pattern is ideal for anti-aliased font rendering. In the subpixel case, the correct gamma removes color fringes that remain even after LCD filtering. . .PP This program does not have any options. . .PP This program is part of the FreeType demos package. . .\" eof ft2demos-2.10.1/src/ftgrid.10000644000175000001440000000327613506424316015323 0ustar00wlusers00000000000000.TH FTGRID 1 "May 2019" "Freetype 2.10.1" . . .SH NAME . ftgrid \- simple glyph grid viewer . . .SH SYNOPSIS . .B ftgrid .RI [ options ] .I pt font .\|.\|. . . .SH DESCRIPTION . .B ftgrid displays the glyphs of a font as outlines right before the conversion from outlines to pixels take place. It also displays the resulting bitmap. It is possible to interactively change hinting and rendering options, thus visualizing the applied distortions to the outlines. . .TP .B pt The point size for the given resolution. If resolution is 72dpi, this directly gives the ppem value (pixels per EM). . .TP .B font The font file(s) to display. For Type 1 font files, .B ftgrid also tries to attach the corresponding metrics file (with extension `.afm' or `.pfm'). . .PP This program is part of the FreeType demos package. . . .SH OPTIONS . .TP .BI \-d \ W x H x D Set the window width to .I W pixels, the height to .I H pixels, and the depth to .I D bpp (default: 640x480x24). . .TP .BI \-r \ r Use resolution .I r dpi (default: 72dpi). . .TP .BI \-f \ index Specify first index to display (default: 0). . .TP .BI \-e \ enc Specify encoding tag (default: no encoding). Common values: .B unic (Unicode), .B symb (symbol), .B ADOB (Adobe standard), .B ADBC (Adobe custom). . .TP .BI "\-a\ \(dq" "axis1\ axis2\ .\|.\|." \(dq For Multiple Master, GX, or OpenType variation fonts, specify design coordinates for each axis at start-up. This option implies option .BR \-n . Ignored for all other font formats. . .TP .B \-n Don't display named instances of variation fonts. . .TP .BI \-k \ keys Emulate sequence of keystrokes upon start-up. If the keystrokes contain 'q', the program operates in batch mode. . .TP .B \-v Show version. . .\" eof ft2demos-2.10.1/src/ftlint.10000644000175000001440000000074513506424316015342 0ustar00wlusers00000000000000.TH FTLINT 1 "May 2019" "Freetype 2.10.1" . . .SH NAME . ftlint \- simple font tester . . .SH SYNOPSIS . .B ftlint .I ppem .IR fontname [ .ttf | .ttc "] .\|.\|." . . .SH DESCRIPTION . .B ftlint opens the given font(s), loads and renders all glyphs at the given ppem value, and reports failing glyphs if there are less than ten fails, or the number of fails only if there are more fails. . .PP This program does not have any options. It is part of the FreeType demos package. . .\" eof ft2demos-2.10.1/src/ftmulti.10000644000175000001440000000214513506424316015522 0ustar00wlusers00000000000000.TH FTMULTI 1 "May 2019" "Freetype 2.10.1" . . .SH NAME . ftmulti \- multiple masters font viewer . . .SH SYNOPSIS . .B ftmulti .RI [ options ] .I pt .IR fontname \ .\|.\|. . . .SH DESCRIPTION . .B ftmulti is an interactive viewer for variation fonts (Multiple Masters, GX, OpenType). . .TP .B pt The point size for the given resolution. If resolution is 72dpi, this directly gives the ppem value (pixels per EM). . .TP .B font The font file(s) to display. . .PP This program is part of the FreeType demos package. . . .SH OPTIONS . .TP .BI \-w \ w Set the window width to .I w pixels (default: 640px). . .TP .BI \-h \ h Set the window height to .I h pixels (default: 480px). . .TP .BI \-e \ encoding Specify encoding tag (default: no encoding). Common values: .B unic (Unicode), .B symb (symbol), .B ADOB (Adobe standard), .B ADBC (Adobe custom). . .TP .BI \-r \ r Use resolution .I r dpi (default: 72 dpi). . .TP .BI \-f \ index Specify first glyph index to display. . .TP .BI "\-d\ \(dq" "axis1\ axis2\ .\|.\|." \(dq Specify the design coordinates for each variation axis at start-up. . .TP .B \-v Show version. . .\" eof ft2demos-2.10.1/src/ftstring.10000644000175000001440000000265713506424316015706 0ustar00wlusers00000000000000.TH FTSTRING 1 "May 2019" "Freetype 2.10.1" . . .SH NAME . ftstring \- string viewer . . .SH SYNOPSIS . .B ftstring .RI [ options ] .I pt font .\|.\|. . . .SH DESCRIPTION . .B ftstring displays a text string with the given font, allowing to change various rendering and display options interactively. . .TP .B pt The point size for the given resolution. If resolution is 72dpi, this directly gives the ppem value (pixels per EM). . .TP .B font The font file(s) to display. For Type 1 font files, .B ftstring also tries to attach the corresponding metrics file (with extension `.afm' or `.pfm'). . .PP Besides the string, .B ftstring also displays two stress test pattens sensitive to rendering flaws, such as incorrect gamma settings. Alternative text-carpeting and waterfall views are also available. This program is part of the FreeType demos package. . . .SH OPTIONS . .TP .BI \-d \ W x H x D Set the window width to .I W pixels, the height to .I H pixels, and the depth to .I D bpp (default: 640x480x24). . .TP .BI \-r \ r Use resolution .I r dpi (default: 72dpi). . .TP .BI \-e \ enc Specify encoding tag (default: no encoding). Common values: .B unic (Unicode), .B symb (symbol), .B ADOB (Adobe standard), .B ADBC (Adobe custom). . .TP .BI \-m \ text Use .I text for rendering. . .TP .BI \-k \ keys Emulate sequence of keystrokes upon start-up. If the keystrokes contain 'q', the program operates in batch mode. . .TP .B \-v Show version. . .\" eof ft2demos-2.10.1/src/ftvalid.10000644000175000001440000000466013506424316015473 0ustar00wlusers00000000000000.TH FTVALID 1 "May 2019" "FreeType 2.10.1" . . .SH NAME . ftvalid \- font layout table validator . . .SH SYNOPSIS . .B ftvalid .RI [ options ] .I fontfile . . .SH DESCRIPTION . .B ftvalid is an OpenType layout table validator. . .PP This program is part of the FreeType demos package. . . .SH OPTIONS . .TP .BI \-f \ index Select font index (default: 0). . .TP .BI \-t \ validator Select validator. Available validators are .BR ot , .BR gx , and .BR ckern . . .IP Note that the availability of validators depends on compile-time options of FreeType (this is, whether the modules `otvalid' and `gxvalid' are compiled into the library). . .TP .BI \-T \ tbls [ot, gx] Select sfnt table name tags to be validated. Use `:' to separate tags. . .IP Supported tables in ot validator are .BR BASE , .BR GDEF , .BR GPOS , .BR GSUB , .BR JSTF , and .BR MATH . . .IP Supported tables in gx validator are .BR feat , .BR mort , .BR morx , .BR bsln , .BR just , .BR kern , .BR opbd , .BR trak , .BR prop , and .BR lcar . . .IP Example: .B \-T \(dqfeat:morx\(dq . .TP .BI \-T \ dialect [ckern] Select classic kern dialect for validation. Use `:' to separate dialect names. If more than one dialect is specified, all dialects are accepted when validating. . .IP Supported dialects in ckern validator are .B ms and .BR apple . . .TP .BI \-l List the layout-related SFNT tables available in the font file. The selected validator (with option .BR \-t ) affects the list. . .IP ckern is applicable to `kern' table only. Option .B \-L lists dialects supported in ckern validator only if `kern' table is available in the font file. . .TP .BI \-V \ level Validation level. Possible values are .B 0 (default), .B 1 (tight), and .B 2 (paranoid). . .TP .B \-v Show version. . . .SH ENVIRONMENT VARIABLES . .TP .B FT2_DEBUG You can specify .RI ` component : level ' pairs for tracing. .I level must be in the range [1,7]. . .IP Available components for ot validator are .BR otvmodule , .BR otvcommon , .BR otvbase , .BR otvgdef , .BR otvgpos , .BR otvgsub , and .BR otvjstf . . .IP Available components for gx validator are .BR gxvmodule , .BR gxvcommon , .BR gxvfeat , .BR gxvmort , .BR gxvmorx , .BR gxvbsln , .BR gxvjust , .BR gxvkern , .BR gxvopbd , .BR gxvtrak , .BR gxvprop , and .BR gxvlcar . .IP Available component for ckern validator is .B gxvkern only. . .IP Example: .B FT2_DEBUG=\(dqotvcommon:5 gxvkern:7\(dq . .IP .B FT2_DEBUG only works if tracing support is compiled into FreeType. . .\" eof ft2demos-2.10.1/src/ftview.10000644000175000001440000000340613506424316015343 0ustar00wlusers00000000000000.TH FTVIEW 1 "May 2019" "FreeType 2.10.1" . . .SH NAME . ftview \- simple glyph viewer . . .SH SYNOPSIS . .B ftview .RI [ options ] .I pt font . . .SH DESCRIPTION . .B ftview displays all glyphs of a font, allowing changes of various rendering and hinting parameters interactively. . .TP .B pt The point size for the given resolution. If resolution is 72dpi, this directly gives the ppem value (pixels per EM). . .TP .B font The font file(s) to display. For Type 1 font files, ftview also tries to attach the corresponding metrics file (with extension `.afm' or `.pfm'). . .PP This program is part of the FreeType demos package. . . .SH OPTIONS . .TP .BI \-d \ W x H x D Set the window width to .I W pixels, the height to .I H pixels, and the depth to .I D bpp (default: 640x480x24). . .TP .BI \-r \ r Use resolution .I r dpi (default: 72dpi). . .TP .BI \-f \ index Specify first index to display (default: 0). . .TP .BI \-e \ enc Specify encoding tag (default: no encoding). Common values: .B unic (Unicode), .B symb (symbol), .B ADOB (Adobe standard), .B ADBC (Adobe custom). . .TP .BI \-m \ text Use .I text for rendering. . .TP .BI \-l \ mode Set start-up rendering mode (0 <= .I mode <= 6). . .TP .BI \-L \ W1 , W2 , W3 , W4 , W5 If there are five arguments, set LCD filter weights (as specified in function .BR FT_Library_SetLcdFilterWeights ). . .TP .BI \-L \ G1 , G2 , G3 , G4 , G5 , G6 If there are six arguments, set the subpixel geometry (as specified in function .BR FT_Library_SetLcdGeometry ) depending on the implemented subpixel rendering method. . .TP .B \-p Preload file in memory to simulate memory-mapping. . .TP .BI \-k \ keys Emulate sequence of keystrokes upon start-up. If the keystrokes contain 'q', the program operates in batch mode. . .TP .B \-v Show version. . .\" eof ft2demos-2.10.1/bin/0000755000175000001440000000000013506426605013736 5ustar00wlusers00000000000000ft2demos-2.10.1/bin/README0000644000175000001440000000010713434207203014603 0ustar00wlusers00000000000000This directory contains all executables for the FreeType demo programs ft2demos-2.10.1/Jamfile0000644000175000001440000000064413434207203014453 0ustar00wlusers00000000000000# FreeType2 demos top Jamfile (c) 2001 David Turner # if $(FT2DEMO_TOP) != $(DOT) { SubDir FT2DEMO_TOP ; } # compile FreeType library here! # FT2_TOP ?= ../freetype2 ; SubInclude FT2_TOP ; FT2DEMO_SRC = [ FT2DEMO_SubDir src ] ; FT2DEMO_GRAPH = [ FT2DEMO_SubDir graph ] ; # Include Graph sub-system rules # SubInclude FT2DEMO_GRAPH ; # Include demos rules # SubInclude FT2DEMO_SRC ; # end of top Jamfile ft2demos-2.10.1/Jamrules0000644000175000001440000000260613434207203014666 0ustar00wlusers00000000000000# FreeType 2 Demos JamRules (c) 2001 David Turner # # This file contains the Jam rules needed to build the FreeType 2 Demos. # It is shared by all Jamfiles and is included only once in the build # process. # # Determine prefix of library file. We must use "libxxxxx" on Unix systems, # while all other simply use the real name. # if $(UNIX) { LIBPREFIX ?= lib ; } else { LIBPREFIX ?= "" ; } FT2_TOP ?= [ FDirName $(DOTDOT) freetype2 ] ; # FT2_INCLUDE contains the location of the public FreeType 2 header files # it is ../freetype2/include by default # FT2_INCLUDE ?= [ FDirName $(FT2_TOP) include ] ; # FT2_LIB contains the path to the FreeType 2 library object # FT2_LIB ?= [ FDirName $(FT2_TOP) objs $(LIBPREFIX)freetype ] ; # X11_LINKLIBS is only used when compiling the X11 graphics back-end # this should be generated from a "configure" script on Unix # X11_LINKLIBS = -lX11 -L/usr/X11R6/lib ; # FT2DEMO_TOP contains the location of the FreeType demos directory. # FT2DEMO_TOP ?= $(DOT) ; # Define a new rule used to declare a sub directory of the Nirvana source # tree. # rule FT2DEMO_SubDir { if $(FT2DEMO_TOP) = $(DOT) { return [ FDirName $(<) ] ; } else { return [ FDirName $(FT2DEMO_TOP) $(<) ] ; } } # We also set ALL_LOCATE_TARGET in order to place all object and library # files in "objs". # ALL_LOCATE_TARGET ?= [ FT2DEMO_SubDir objs ] ; # end of Jamrules ft2demos-2.10.1/vms_make.com0000644000175000001440000002347113434207203015466 0ustar00wlusers00000000000000$!---------------vms_make.com for FreeType 2 demos ----------------------------- $! make FreeType 2 under OpenVMS $! $! In case of problems with the build you might want to contact me at $! zinser@zinser.no-ip.info (preferred) or $! zinser@sysdev.deutsche-boerse.com (Work) $! $!------------------------------------------------------------------------------ $! $ on error then goto err_exit $! $! Just some general constants $! $ Make = "" $ true = 1 $ false = 0 $! $! Setup variables holding "config" information $! $ name = "FT2demos" $ optfile = name + ".opt" $ ccopt = "/name=(as_is,short)/float=ieee" $ lopts = "" $! $! Check for MMK/MMS $! $ If F$Search ("Sys$System:MMS.EXE") .nes. "" Then Make = "MMS" $ If F$Type (MMK) .eqs. "STRING" Then Make = "MMK" $! $! Which command parameters were given $! $ gosub check_opts $! $! Create option file $! $ open/write optf 'optfile' $ If f$getsyi("HW_MODEL") .gt. 1024 $ Then $ write optf "[-.freetype2.lib]freetype2shr.exe/share" $ else $ write optf "[-.freetype2.lib]freetype.olb/lib" $ endif $ gosub check_create_vmslib $ write optf "sys$share:decw$xlibshr.exe/share" $ close optf $! $ gosub crea_mms $ 'Make' $ purge/nolog descrip.mms $! $ exit $! $ERR_LIB: $ write sys$output "Error reading config file [-.freetype2]vmslib.dat" $ goto err_exit $FT2_ERR: $ write sys$output "Could not locate FreeType 2 include files" $ goto err_exit $ERR_EXIT: $ set message/facil/ident/sever/text $ close/nolog optf $ close/nolog out $ close/nolog libdata $ write sys$output "Exiting..." $ exit 2 $!------------------------------------------------------------------------------ $! $! If MMS/MMK are available dump out the descrip.mms if required $! $CREA_MMS: $ write sys$output "Creating descrip.mms..." $ create descrip.mms $ open/append out descrip.mms $ copy sys$input: out $ deck # This file is part of the FreeType project. # # DESCRIP.MMS: Make file for OpenVMS using MMS or MMK # Created by Martin P.J. Zinser # (zinser@decus.de (preferred) or zinser@sysdev.deutsche-boerse.com (work)) $EOD $ write out "CCOPT = ", ccopt $ write out "LOPTS = ", lopts $ copy sys$input: out $ deck .FIRST define freetype [-.freetype2.include.freetype] CC = cc # location of src for Test programs SRCDIR = [.src] GRAPHSRC = [.graph] GRX11SRC = [.graph.x11] OBJDIR = [.objs] # include paths INCLUDES = /include=([-.freetype2.include],[.graph]) GRAPHOBJ = $(OBJDIR)grblit.obj, \ $(OBJDIR)grobjs.obj, \ $(OBJDIR)grfont.obj, \ $(OBJDIR)grinit.obj, \ $(OBJDIR)grdevice.obj,\ $(OBJDIR)grx11.obj, \ $(OBJDIR)gblender.obj, \ $(OBJDIR)gblblit.obj # C flags CFLAGS = $(CCOPT)$(INCLUDES)/obj=$(OBJDIR) ALL : ftchkwd.exe ftdump.exe ftlint.exe ftmemchk.exe ftmulti.exe ftview.exe \ ftstring.exe fttimer.exe ftbench.exe testname.exe ftbench.exe : $(OBJDIR)ftbench.obj,$(OBJDIR)common.obj link $(LOPTS) $(OBJDIR)ftbench.obj,$(OBJDIR)common.obj,- []ft2demos.opt/opt ftchkwd.exe : $(OBJDIR)ftchkwd.obj,$(OBJDIR)common.obj link $(LOPTS) $(OBJDIR)ftchkwd.obj,$(OBJDIR)common.obj,- []ft2demos.opt/opt ftdump.exe : $(OBJDIR)ftdump.obj,$(OBJDIR)common.obj link $(LOPTS) $(OBJDIR)ftdump.obj,common.obj,[]ft2demos.opt/opt ftlint.exe : $(OBJDIR)ftlint.obj link $(LOPTS) $(OBJDIR)ftlint.obj,[]ft2demos.opt/opt ftmemchk.exe : $(OBJDIR)ftmemchk.obj link $(LOPTS) $(OBJDIR)ftmemchk.obj,[]ft2demos.opt/opt ftmulti.exe : $(OBJDIR)ftmulti.obj,$(OBJDIR)common.obj,$(GRAPHOBJ) link $(LOPTS) $(OBJDIR)ftmulti.obj,common.obj,$(GRAPHOBJ),[]ft2demos.opt/opt ftview.exe : $(OBJDIR)ftview.obj,$(OBJDIR)common.obj,$(GRAPHOBJ) link $(LOPTS) $(OBJDIR)ftview.obj,common.obj,$(GRAPHOBJ),[]ft2demos.opt/opt ftstring.exe : $(OBJDIR)ftstring.obj,$(OBJDIR)common.obj,$(GRAPHOBJ) link $(LOPTS) $(OBJDIR)ftstring.obj,common.obj,$(GRAPHOBJ),[]ft2demos.opt/opt fttimer.exe : $(OBJDIR)fttimer.obj link $(LOPTS) $(OBJDIR)fttimer.obj,[]ft2demos.opt/opt testname.exe : $(OBJDIR)testname.obj link $(LOPTS) $(OBJDIR)testname.obj,[]ft2demos.opt/opt $(OBJDIR)common.obj : $(SRCDIR)common.c , $(SRCDIR)common.h $(OBJDIR)ftbench.obj : $(SRCDIR)ftbench.c $(OBJDIR)ftchkwd.obj : $(SRCDIR)ftchkwd.c $(OBJDIR)ftlint.obj : $(SRCDIR)ftlint.c $(OBJDIR)ftmemchk.obj : $(SRCDIR)ftmemchk.c $(OBJDIR)ftdump.obj : $(SRCDIR)ftdump.c $(OBJDIR)testname.obj : $(SRCDIR)testname.c $(OBJDIR)ftview.obj : $(SRCDIR)ftview.c $(OBJDIR)grblit.obj : $(GRAPHSRC)grblit.c $(OBJDIR)grobjs.obj : $(GRAPHSRC)grobjs.c $(OBJDIR)grfont.obj : $(GRAPHSRC)grfont.c $(OBJDIR)gblender.obj : $(GRAPHSRC)gblender.c $(OBJDIR)gblblit.obj : $(GRAPHSRC)gblblit.c $(OBJDIR)grinit.obj : $(GRAPHSRC)grinit.c set def $(GRAPHSRC) $(CC)$(CCOPT)/include=([.x11],[])/define=(DEVICE_X11)/obj=[-.objs] grinit.c set def [-] $(OBJDIR)grx11.obj : $(GRX11SRC)grx11.c set def $(GRX11SRC) $(CC)$(CCOPT)/obj=[--.objs]/include=([-]) grx11.c set def [--] $(OBJDIR)grdevice.obj : $(GRAPHSRC)grdevice.c $(OBJDIR)ftmulti.obj : $(SRCDIR)ftmulti.c $(OBJDIR)ftstring.obj : $(SRCDIR)ftstring.c $(OBJDIR)fttimer.obj : $(SRCDIR)fttimer.c CLEAN : delete $(OBJDIR)*.obj;*,[]ft2demos.opt;* # EOF $ eod $ close out $ return $!------------------------------------------------------------------------------ $! $! Check commandline options and set symbols accordingly $! $ CHECK_OPTS: $ i = 1 $ OPT_LOOP: $ if i .lt. 9 $ then $ cparm = f$edit(p'i',"upcase") $ if cparm .eqs. "DEBUG" $ then $ ccopt = ccopt + "/noopt/deb" $ lopts = lopts + "/deb" $ endif $! if cparm .eqs. "link $(LOPTS)" then link only = true $ if f$locate("LOPTS",cparm) .lt. f$length(cparm) $ then $ start = f$locate("=",cparm) + 1 $ len = f$length(cparm) - start $ lopts = lopts + f$extract(start,len,cparm) $ endif $ if f$locate("CCOPT",cparm) .lt. f$length(cparm) $ then $ start = f$locate("=",cparm) + 1 $ len = f$length(cparm) - start $ ccopt = ccopt + f$extract(start,len,cparm) $ endif $ i = i + 1 $ goto opt_loop $ endif $ return $!------------------------------------------------------------------------------ $! $! Take care of driver file with information about external libraries $! $! Version history $! 0.01 20040220 First version to receive a number $! 0.02 20040229 Echo current procedure name; use general error exit handler $! Remove xpm hack -> Replaced by more general dnsrl handling $! ---> Attention slightly changed version to take into account special $! situation for FreeType 2 demos $CHECK_CREATE_VMSLIB: $! $ if f$search("[-.freetype2]VMSLIB.DAT") .eqs. "" $ then $ write sys$output "FreeType 2 driver file [-.freetype2]vmslib.dat not found." $ write sys$output "Either Ft2demos have been installed in the wrong location" $ write sys$output "or FreeType 2 has not yet been configured." $ write sys$output "Exiting..." $ goto err_exit $ endif $! $! Init symbols used to hold CPP definitions and include path $! $ libdefs = "" $ libincs = "" $! $! Open data file with location of libraries $! $ open/read/end=end_lib/err=err_lib libdata [-.freetype2]VMSLIB.DAT $LIB_LOOP: $ read/end=end_lib libdata libline $ libline = f$edit(libline, "UNCOMMENT,COLLAPSE") $ if libline .eqs. "" then goto LIB_LOOP ! Comment line $ libname = f$edit(f$element(0,"#",libline),"UPCASE") $ write sys$output "Processing ''libname' setup ..." $ libloc = f$element(1,"#",libline) $ libsrc = f$element(2,"#",libline) $ testinc = f$element(3,"#",libline) $ cppdef = f$element(4,"#",libline) $ old_cpp = f$locate("=1",cppdef) $ if old_cpp.lt.f$length(cppdef) then cppdef = f$extract(0,old_cpp,cppdef) $ if f$search("''libloc'").eqs. "" $ then $ write sys$output "Can not find library ''libloc' - Skipping ''libname'" $ goto LIB_LOOP $ endif $ libsrc_elem = 0 $ libsrc_found = false $LIBSRC_LOOP: $ libsrcdir = f$element(libsrc_elem,",",libsrc) $ if (libsrcdir .eqs. ",") then goto END_LIBSRC $ if f$search("''libsrcdir'''testinc'") .nes. "" then libsrc_found = true $ libsrc_elem = libsrc_elem + 1 $ goto LIBSRC_LOOP $END_LIBSRC: $ if .not. libsrc_found $ then $ write sys$output "Can not find includes at ''libsrc' - Skipping ''libname'" $ goto LIB_LOOP $ endif $ if (cppdef .nes. "") then libdefs = libdefs + cppdef + "," $ libincs = libincs + "," + libsrc $ lqual = "/lib" $ libtype = f$edit(f$parse(libloc,,,"TYPE"),"UPCASE") $ if f$locate("EXE",libtype) .lt. f$length(libtype) then lqual = "/share" $ write optf libloc , lqual $ if (f$trnlnm("topt") .nes. "") then write topt libloc , lqual $! $! Nasty hack to get the FreeType includes to work $! $ ft2def = false $ if ((libname .eqs. "FREETYPE") .and. - (f$locate("FREETYPE2",cppdef) .lt. f$length(cppdef))) $ then $ if ((f$search("freetype:freetype.h") .nes. "") .and. - (f$search("freetype:[internal]ftobjs.h") .nes. "")) $ then $ write sys$output "Will use local definition of freetype logical" $ else $ ft2elem = 0 $FT2_LOOP: $ ft2srcdir = f$element(ft2elem,",",libsrc) $ if f$search("''ft2srcdir'''testinc'") .nes. "" $ then $ if f$search("''ft2srcdir'internal.dir") .nes. "" $ then $ ft2dev = f$parse("''ft2srcdir'",,,"device","no_conceal") $ ft2dir = f$parse("''ft2srcdir'",,,"directory","no_conceal") $ ft2conc = f$locate("][",ft2dir) $ ft2len = f$length(ft2dir) $ if ft2conc .lt. ft2len $ then $ ft2dir = f$extract(0,ft2conc,ft2dir) + - f$extract(ft2conc+2,ft2len-2,ft2dir) $ endif $ ft2dir = ft2dir - "]" + ".]" $ define freetype 'ft2dev''ft2dir','ft2srcdir' $ ft2def = true $ else $ goto ft2_err $ endif $ else $ ft2elem = ft2elem + 1 $ goto ft2_loop $ endif $ endif $ endif $ goto LIB_LOOP $END_LIB: $ close libdata $ return ft2demos-2.10.1/Makefile0000644000175000001440000004232113501434334014621 0ustar00wlusers00000000000000all: exes #################################################################### # # The `space' variable is used to avoid trailing spaces in defining # the `T' variable later. # empty := space := $(empty) $(empty) #################################################################### # # TOP_DIR is the directory where the main FreeType source is found, # as well as the `config.mk' file. # # TOP_DIR_2 is the directory is the top of the demonstration # programs directory. # # OBJ_DIR gives the objects directory of the FreeType library. # TOP_DIR ?= ../freetype2 TOP_DIR_2 ?= . OBJ_DIR ?= $(TOP_DIR)/objs ###################################################################### # # CONFIG_MK points to the current `config.mk' to use. It is defined # by default as $(TOP_DIR)/config.mk. # ifndef CONFIG_MK PROJECT := freetype CONFIG_MK := $(TOP_DIR)/config.mk endif ###################################################################### # # MODULES_CFG points to the current `modules.cfg' to use. It is defined # by default as $(TOP_DIR)/modules.cfg. # MODULES_CFG ?= $(TOP_DIR)/modules.cfg ifeq ($(wildcard $(MODULES_CFG)),) no_modules_cfg := 1 endif #################################################################### # # Check that we have a working `config.mk' in the above directory. # If not, issue a warning message, then stop there. # ifeq ($(wildcard $(CONFIG_MK)),) no_config_mk := 1 endif ifdef no_config_mk exes: $(info Please compile the library before the demo programs!) clean distclean: $(info I need a path to FreeType 2's `config.mk' to do that!) $(info Set the `TOP_DIR' variable to the correct value.) else #################################################################### # # Good, now include `config.mk' in order to know how to build # object files from sources, as well as other things (compiler # flags). # include $(CONFIG_MK) ifndef no_modules_cfg include $(MODULES_CFG) endif have_makefile := $(strip $(wildcard Makefile)) ifeq ($(PLATFORM),unix) ifdef DEVEL_DIR PLATFORM := unixdev endif endif #################################################################### # # Define a few important variables now. # ifeq ($(PLATFORM),unix) # without absolute paths libtool fails TOP_DIR := $(shell cd $(TOP_DIR); pwd) TOP_DIR_2 := $(shell cd $(TOP_DIR_2); pwd) ifneq ($(have_makefile),) BIN_DIR_2 ?= $(TOP_DIR_2)/bin OBJ_DIR_2 ?= $(TOP_DIR_2)/objs else BIN_DIR_2 ?= . OBJ_DIR_2 ?= . endif else ifneq ($(have_makefile),) BIN_DIR_2 ?= bin OBJ_DIR_2 ?= objs else BIN_DIR_2 ?= . OBJ_DIR_2 ?= . endif endif GRAPH_DIR := $(TOP_DIR_2)/graph ifeq ($(TOP_DIR),..) SRC_DIR := src else SRC_DIR := $(TOP_DIR_2)/src endif FT_INCLUDES := $(OBJ_BUILD) \ $(BUILD_DIR) \ $(DEVEL_DIR) \ $(TOP_DIR)/include \ $(SRC_DIR) COMPILE = $(CC) $(CPPFLAGS) \ $(CFLAGS) \ $(ANSIFLAGS) \ $(INCLUDES:%=$I%) \ $DFT_CONFIG_OPTIONS_H="" \ $DFT_CONFIG_MODULES_H="" # Enable C99 for gcc to avoid warnings. # Note that clang++ aborts with an error if we use `-std=C99', # so check for `++' in $(CC) also. ifneq ($(findstring -pedantic,$(COMPILE)),) ifeq ($(findstring ++,$(CC)),) COMPILE += -std=c99 endif endif FTLIB := $(LIB_DIR)/$(LIBRARY).$A # `-lm' is required to compile on some Unix systems. # ifeq ($(PLATFORM),unix) MATH := -lm endif ifeq ($(PLATFORM),unixdev) MATH := -lm endif # The default variables used to link the executables. These can # be redefined for platform-specific stuff. # # The first token of LINK_ITEMS must be the executable. # LINK_ITEMS = $T$(subst /,$(COMPILER_SEP),$@ $<) ifeq ($(PLATFORM),unix) CC = $(CCraw) LINK_CMD = $(subst /,$(SEP),$(OBJ_BUILD)/libtool) \ --mode=link $(CC) \ $(subst /,$(COMPILER_SEP),$(LDFLAGS)) LINK_LIBS = $(subst /,$(COMPILER_SEP),$(FTLIB) $(EFENCE)) $(LIB_CLOCK_GETTIME) else LINK_CMD = $(CC) $(subst /,$(COMPILER_SEP),$(LDFLAGS)) ifeq ($(PLATFORM),unixdev) LINK_LIBS = $(subst /,$(COMPILER_SEP),$(FTLIB) $(EFENCE)) -lm -lrt -lz -lbz2 LINK_LIBS += $(shell pkg-config --libs libpng) LINK_LIBS += $(shell pkg-config --libs harfbuzz) else LINK_LIBS = $(subst /,$(COMPILER_SEP),$(FTLIB) $(EFENCE)) endif endif LINK = $(LINK_CMD) \ $(LINK_ITEMS) \ $(LINK_LIBS) LINK_COMMON = $(LINK_CMD) \ $(LINK_ITEMS) $(subst /,$(COMPILER_SEP),$(COMMON_OBJ)) \ $(LINK_LIBS) LINK_GRAPH = $(LINK_COMMON) $(subst /,$(COMPILER_SEP),$(GRAPH_LIB)) \ $(GRAPH_LINK) $(MATH) LINK_NEW = $(LINK_CMD) \ $(LINK_ITEMS) $(subst /,$(COMPILER_SEP),$(COMMON_OBJ) \ $(FTCOMMON_OBJ)) \ $(LINK_LIBS) $(subst /,$(COMPILER_SEP),$(GRAPH_LIB)) \ $(GRAPH_LINK) $(MATH) .PHONY: exes clean distclean ################################################################### # # Include the rules needed to compile the graphics sub-system. # This will also select which graphics driver to compile to the # sub-system. # include $(GRAPH_DIR)/rules.mk #################################################################### # # Detect DOS-like platforms, currently DOS, Win 3.1, Win32 & OS/2. # ifneq ($(findstring $(PLATFORM),os2 win16 win32 dos),) DOSLIKE := 1 endif ################################################################### # # Clean-up rules. Because the `del' command on DOS-like platforms # cannot take a long list of arguments, we simply erase the directory # contents. # ifdef DOSLIKE clean_demo: -del objs\*.$(SO) 2> nul -del $(subst /,\,$(TOP_DIR_2)/src/*.bak) 2> nul distclean_demo: clean_demo -del objs\*.lib 2> nul -del bin\*.exe 2> nul else clean_demo: -$(DELETE) $(subst /,$(SEP),$(OBJ_DIR_2)/*.$(SO) $(OBJ_DIR_2)/*.$(O)) -$(DELETE) $(subst /,$(SEP),$(OBJ_DIR_2)/*.$(SA) $(OBJ_DIR_2)/*.$(A)) -$(DELETE) $(subst /,$(SEP),$(OBJ_DIR_2)/.libs/*) -$(DELETE) $(subst /,$(SEP),$(SRC_DIR)/*.bak graph/*.bak) -$(DELETE) $(subst /,$(SEP),$(SRC_DIR)/*~ graph/*~) distclean_demo: clean_demo -$(DELETE) $(subst /,$(SEP),$(EXES:%=$(BIN_DIR_2)/%$E)) -$(DELETE) $(subst /,$(SEP),$(GRAPH_LIB)) ifeq ($(PLATFORM),unix) -$(DELETE) $(BIN_DIR_2)/.libs/* -$(DELDIR) $(BIN_DIR_2)/.libs endif endif clean: clean_demo distclean: distclean_demo #################################################################### # # Compute the executable suffix to use, and put it in `E'. # It is ".exe" on DOS-ish platforms, and nothing otherwise. # ifdef DOSLIKE E := .exe else E := endif #################################################################### # # POSIX TERMIOS: Do not define if you use OLD U*ix like 4.2BSD. # ifeq ($(PLATFORM),unix) EXTRAFLAGS = $DUNIX $DHAVE_POSIX_TERMIOS endif ifeq ($(PLATFORM),unixdev) EXTRAFLAGS = $DUNIX $DHAVE_POSIX_TERMIOS endif ################################################################### # # The list of demonstration programs to build. # # Note that ttdebug only works if the FreeType's `truetype' driver has # been compiled with TT_CONFIG_OPTION_BYTECODE_INTERPRETER defined. # EXES := ftbench \ ftdump \ ftlint \ ttdebug # Comment out the next line if you don't have a graphics subsystem. EXES += ftdiff \ ftgamma \ ftgrid \ ftmulti \ ftstring \ ftview # ftvalid requires ftgxval.c and ftotval.c # ifneq ($(findstring ftgxval.c,$(BASE_EXTENSIONS)),) ifneq ($(findstring ftotval.c,$(BASE_EXTENSIONS)),) EXES += ftvalid endif endif # The following programs are not compiled automatically; either comment # out the affected line or use the program name as a Makefile target. # # EXES += ftchkwd # EXES += ftmemchk # EXES += ftpatchk # EXES += fttimer # EXES += testname exes: $(EXES:%=$(BIN_DIR_2)/%$E) INCLUDES := $(subst /,$(COMPILER_SEP),$(FT_INCLUDES)) # generic rule $(OBJ_DIR_2)/%.$(SO): $(SRC_DIR)/%.c $(FTLIB) $(COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) #################################################################### # # Rules for compiling object files for text-only demos. # $(OBJ_DIR_2)/common.$(SO): $(SRC_DIR)/common.c $(OBJ_DIR_2)/output.$(SO): $(SRC_DIR)/output.c $(OBJ_DIR_2)/mlgetopt.$(SO): $(SRC_DIR)/mlgetopt.c COMMON_OBJ := $(OBJ_DIR_2)/common.$(SO) \ $(OBJ_DIR_2)/output.$(SO) \ $(OBJ_DIR_2)/mlgetopt.$(SO) FTCOMMON_OBJ := $(OBJ_DIR_2)/ftcommon.$(SO) $(FTCOMMON_OBJ): $(SRC_DIR)/ftcommon.c $(SRC_DIR)/ftcommon.h $(COMPILE) $(GRAPH_INCLUDES:%=$I%) \ $T$(subst /,$(COMPILER_SEP),$@ $<) $(OBJ_DIR_2)/ftlint.$(SO): $(SRC_DIR)/ftlint.c $(COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) $(OBJ_DIR_2)/ftbench.$(SO): $(SRC_DIR)/ftbench.c $(COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) $(EXTRAFLAGS) $(OBJ_DIR_2)/ftpatchk.$(SO): $(SRC_DIR)/ftpatchk.c $(COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) $(EXTRAFLAGS) $(OBJ_DIR_2)/ftchkwd.$(SO): $(SRC_DIR)/ftchkwd.c $(COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) $(EXTRAFLAGS) $(OBJ_DIR_2)/compos.$(SO): $(SRC_DIR)/compos.c $(COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) $(OBJ_DIR_2)/ftmemchk.$(SO): $(SRC_DIR)/ftmemchk.c $(COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) $(OBJ_DIR_2)/fttimer.$(SO): $(SRC_DIR)/fttimer.c $(COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) $(OBJ_DIR_2)/fttry.$(SO): $(SRC_DIR)/fttry.c $(COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) $(OBJ_DIR_2)/testname.$(SO): $(SRC_DIR)/testname.c $(COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) # $(OBJ_DIR_2)/ftsbit.$(SO): $(SRC_DIR)/ftsbit.c # $(COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) # We simplify the dependencies on the graphics library by using # $(GRAPH_LIB) directly. $(OBJ_DIR_2)/ftgamma.$(SO): $(SRC_DIR)/ftgamma.c \ $(SRC_DIR)/ftcommon.h \ $(GRAPH_LIB) $(COMPILE) $(GRAPH_INCLUDES:%=$I%) \ $T$(subst /,$(COMPILER_SEP),$@ $<) $(OBJ_DIR_2)/ftmulti.$(SO): $(SRC_DIR)/ftmulti.c \ $(GRAPH_LIB) $(COMPILE) $(GRAPH_INCLUDES:%=$I%) \ $T$(subst /,$(COMPILER_SEP),$@ $<) $(OBJ_DIR_2)/ftstring.$(SO): $(SRC_DIR)/ftstring.c \ $(SRC_DIR)/ftcommon.h \ $(GRAPH_LIB) $(COMPILE) $(GRAPH_INCLUDES:%=$I%) \ $T$(subst /,$(COMPILER_SEP),$@ $<) #################################################################### # # Special rule to compile the `ftdump' program as it includes # internal header files. # $(OBJ_DIR_2)/ftdump.$(SO): $(SRC_DIR)/ftdump.c $(COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) $DFT2_BUILD_LIBRARY #################################################################### # # Special rule to compile the `t1dump' program as it includes # the Type1 source path. # $(OBJ_DIR_2)/t1dump.$(SO): $(SRC_DIR)/t1dump.c $(COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) #################################################################### # # Special rule to compile the `ftvalid' program as it includes # internal header files. # $(OBJ_DIR_2)/ftvalid.$(SO): $(SRC_DIR)/ftvalid.c $(COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) $DFT2_BUILD_LIBRARY #################################################################### # # Special rule to compile the `ftview' program as it includes # internal header files. # $(OBJ_DIR_2)/ftview.$(SO): $(SRC_DIR)/ftview.c \ $(SRC_DIR)/ftcommon.h \ $(GRAPH_LIB) $(COMPILE) $(GRAPH_INCLUDES:%=$I%) \ $T$(subst /,$(COMPILER_SEP),$@ $<) $DFT2_BUILD_LIBRARY #################################################################### # # Special rule to compile the `ftdiff' program as it includes # internal header files. # $(OBJ_DIR_2)/ftdiff.$(SO): $(SRC_DIR)/ftdiff.c \ $(SRC_DIR)/ftcommon.h \ $(GRAPH_LIB) $(COMPILE) $(GRAPH_INCLUDES:%=$I%) \ $T$(subst /,$(COMPILER_SEP),$@ $<) $DFT2_BUILD_LIBRARY #################################################################### # # Special rule to compile the `ftgrid' program as it includes # internal header files. # $(OBJ_DIR_2)/ftgrid.$(SO): $(SRC_DIR)/ftgrid.c \ $(SRC_DIR)/ftcommon.h \ $(GRAPH_LIB) $(COMPILE) $(GRAPH_INCLUDES:%=$I%) \ $T$(subst /,$(COMPILER_SEP),$@ $<) $DFT2_BUILD_LIBRARY #################################################################### # # Special rule to compile the `ttdebug' program as it includes # the TrueType source path and needs extra flags for correct keyboard # handling on Unix. $(OBJ_DIR_2)/ttdebug.$(SO): $(SRC_DIR)/ttdebug.c $(COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) \ $I$(subst /,$(COMPILER_SEP),$(TOP_DIR)/src/truetype) \ $(EXTRAFLAGS) $DFT2_BUILD_LIBRARY #################################################################### # # Rules used to link the executables. Note that they could be # overridden by system-specific things. # $(BIN_DIR_2)/ftlint$E: $(OBJ_DIR_2)/ftlint.$(SO) $(FTLIB) $(COMMON_OBJ) $(LINK_COMMON) $(BIN_DIR_2)/ftbench$E: $(OBJ_DIR_2)/ftbench.$(SO) $(FTLIB) $(COMMON_OBJ) $(LINK_COMMON) $(BIN_DIR_2)/ftpatchk$E: $(OBJ_DIR_2)/ftpatchk.$(SO) $(FTLIB) $(COMMON_OBJ) $(LINK_COMMON) $(BIN_DIR_2)/ftchkwd$E: $(OBJ_DIR_2)/ftchkwd.$(SO) $(FTLIB) $(COMMON_OBJ) $(LINK_COMMON) $(BIN_DIR_2)/ftmemchk$E: $(OBJ_DIR_2)/ftmemchk.$(SO) $(FTLIB) $(COMMON_OBJ) $(LINK_COMMON) $(BIN_DIR_2)/compos$E: $(OBJ_DIR_2)/compos.$(SO) $(FTLIB) $(COMMON_OBJ) $(LINK_COMMON) $(BIN_DIR_2)/ftvalid$E: $(OBJ_DIR_2)/ftvalid.$(SO) $(FTLIB) $(COMMON_OBJ) $(LINK_COMMON) $(BIN_DIR_2)/ftdump$E: $(OBJ_DIR_2)/ftdump.$(SO) $(FTLIB) $(COMMON_OBJ) $(LINK_COMMON) $(BIN_DIR_2)/fttimer$E: $(OBJ_DIR_2)/fttimer.$(SO) $(FTLIB) $(COMMON_OBJ) $(LINK_COMMON) $(BIN_DIR_2)/fttry$E: $(OBJ_DIR_2)/fttry.$(SO) $(FTLIB) $(LINK) # $(BIN_DIR_2)/ftsbit$E: $(OBJ_DIR_2)/ftsbit.$(SO) $(FTLIB) # $(LINK) $(BIN_DIR_2)/t1dump$E: $(OBJ_DIR_2)/t1dump.$(SO) $(FTLIB) $(LINK) $(BIN_DIR_2)/ttdebug$E: $(OBJ_DIR_2)/ttdebug.$(SO) $(FTLIB) $(COMMON_OBJ) $(LINK_COMMON) $(BIN_DIR_2)/testname$E: $(OBJ_DIR_2)/testname.$(SO) $(FTLIB) $(LINK) $(BIN_DIR_2)/ftview$E: $(OBJ_DIR_2)/ftview.$(SO) $(FTLIB) \ $(GRAPH_LIB) $(COMMON_OBJ) $(FTCOMMON_OBJ) $(LINK_NEW) $(BIN_DIR_2)/ftgrid$E: $(OBJ_DIR_2)/ftgrid.$(SO) $(FTLIB) \ $(GRAPH_LIB) $(COMMON_OBJ) $(FTCOMMON_OBJ) $(LINK_NEW) $(BIN_DIR_2)/ftgamma$E: $(OBJ_DIR_2)/ftgamma.$(SO) $(FTLIB) \ $(GRAPH_LIB) $(COMMON_OBJ) $(FTCOMMON_OBJ) $(LINK_NEW) $(BIN_DIR_2)/ftdiff$E: $(OBJ_DIR_2)/ftdiff.$(SO) $(FTLIB) \ $(GRAPH_LIB) $(COMMON_OBJ) $(FTCOMMON_OBJ) $(LINK_NEW) $(BIN_DIR_2)/ftmulti$E: $(OBJ_DIR_2)/ftmulti.$(SO) $(FTLIB) \ $(GRAPH_LIB) $(COMMON_OBJ) $(FTCOMMON_OBJ) $(LINK_NEW) $(BIN_DIR_2)/ftstring$E: $(OBJ_DIR_2)/ftstring.$(SO) $(FTLIB) \ $(GRAPH_LIB) $(COMMON_OBJ) $(FTCOMMON_OBJ) $(LINK_NEW) endif # This target builds the tarballs. # # Not to be run by a normal user -- there are no attempts to make it # generic. # we check for `dist', not `distclean' ifneq ($(findstring distx,$(MAKECMDGOALS)x),) FT_H := ../freetype2/include/freetype/freetype.h major := $(shell sed -n 's/.*FREETYPE_MAJOR[^0-9]*\([0-9]\+\)/\1/p' < $(FT_H)) minor := $(shell sed -n 's/.*FREETYPE_MINOR[^0-9]*\([0-9]\+\)/\1/p' < $(FT_H)) patch := $(shell sed -n 's/.*FREETYPE_PATCH[^0-9]*\([0-9]\+\)/\1/p' < $(FT_H)) # ifneq ($(findstring x0x,x$(patch)x),) # version := $(major).$(minor) # winversion := $(major)$(minor) # else version := $(major).$(minor).$(patch) winversion := $(major)$(minor)$(patch) # endif endif dist: -rm -rf tmp rm -f ft2demos-$(version).tar.gz rm -f ft2demos-$(version).tar.xz rm -f ftdmo$(winversion).zip for d in `find . -wholename '*/.git' -prune \ -o -type f \ -o -print` ; do \ mkdir -p tmp/$$d ; \ done ; currdir=`pwd` ; \ for f in `find . -wholename '*/.git' -prune \ -o -name .gitignore \ -o -name .mailmap \ -o -type d \ -o -print` ; do \ ln -s $$currdir/$$f tmp/$$f ; \ done cd tmp ; \ $(MAKE) distclean mv tmp ft2demos-$(version) tar -H ustar -chf - ft2demos-$(version) \ | gzip -c > ft2demos-$(version).tar.gz tar -H ustar -chf - ft2demos-$(version) \ | xz -c > ft2demos-$(version).tar.xz @# Use CR/LF for zip files. zip -lr ftdmo$(winversion).zip ft2demos-$(version) rm -fr ft2demos-$(version) # EOF ft2demos-2.10.1/ChangeLog0000644000175000001440000067277513506424237014767 0ustar00wlusers000000000000002019-07-01 Werner Lemberg * Version 2.10.1 released. ========================== Tag sources with `VER-2-10-1. * README: Updated. * src/*.1: Updated. * src/ftinspect/ftinspect.pro: Updated. 2019-07-01 Werner Lemberg * graph/x11/grx11.c (gr_x11_surface_init): Fix C++ warnings. 2019-06-25 Alexei Podtelezhnikov * src/ftgrid.c (bitmap_scale): Gray alternative to LCD bitmap... (Process_Event): ... after repeated bitmap toggles. 2019-06-20 Alexei Podtelezhnikov [ftgrid] Tweak direct rendering. * src/ftcommon.c (FT_Demo_Sketch_Glyph_Color): Redefine surface origin and clipping box instead of shifting outline. * src/ftgrid.c (grid_status_draw_outline): Tweaked. * graph/gblspans.h: Simplify. * graph/grobjs.h (grSurface): Introduce `origin' byte. * graph/gblblit.c: Silence compilation warning. 2019-06-19 Alexei Podtelezhnikov [ftgrid] Direct outline drawing. Now we can test `FT_RASTER_FLAG_DIRECT' and it is also faster because the glyph outline image is extremely sparse. * src/ftcommon.[hc] (FTDemo_Sketch_Glyph_Color): Implement rendering in direct mode. * src/ftgrid.c (grid_status_draw_outline): Use it. 2019-06-19 Alexei Podtelezhnikov [graph] Implement and register gray_span function. * graph/gblspans.h, graph/gblany.h (_gblender_spans_*): New functions. * graph/grobjs.h (grSurface): New fields `gray_spans' and `gcolor'. * graph/gblblit.c (grSetSurfaceGamma): Initialize `gray_spans'. * graph/rules.mk: Add new file. 2019-06-18 Alexei Podtelezhnikov [graph] Clearly separate two blenders. * graph/gblblit.[hc] (grBlitGlyphToSurface): Declare and define it. * graph/grblit.c (grBlitGlyphToBitmap): Call `grBlitGlyphToSurface'. * graph/gblender.c: Minor. 2019-06-17 Alexei Podtelezhnikov * src/ftmulti.c (bit): Surface bitmap must belong to surface. * graph/graph.h (grBlitGlyphToBitmap): Clarify documentation. * graph/grdevice.c (grNewSurface): Initialize default blender. 2019-06-17 Alexei Podtelezhnikov * graph/*/rules.mk: Add missing dependency. 2019-06-16 Alexei Podtelezhnikov * graph/grblit.c (grBlitGlyphToBitmap): Move code from here... * graph/gblblit.c (gblender_blit_init): ... to here. * graph/gblblit.h: Updated. 2019-06-15 Alexei Podtelezhnikov [graph] Relocate `gblender' to `grSurface'. This will be needed for direct rendering and simplifies gamma setting. * graph/grobjs.h (grSurface): Put `bitmap' on top, add `gblender'. * graph/graph.h: s/grSetGlyphGamma/grSetTargetGamma/. * graph/grblit.c (grSetTargetGamma): Move `gblender_init' here... (grBlitGlyphToBitmap): ...from here. * src/ftcommon.c (FTDemo_Display_New): Call `grSetTargetGamma'. * src/ft{diff,grid,string,view,multi}.c: Updated. 2019-06-14 Alexei Podtelezhnikov * graph/gblblit.c (gblender_blit_init): Switch to lookup table. * graph/gblany.h: Updated. 2019-06-12 Alexei Podtelezhnikov * src/ttdebug.c (RunIns): Return error like `TT_RunIns'. (Abort): Add error messages. 2019-06-11 Alexei Podtelezhnikov Fix compilation warnings. * src/ft{lint,dump}.c (main): Null-terminate `strncpy'. * src/ttdebug.c (main): Reluctantly ditto. * src/mlgetopt.c (getopt): Suppress the dropped `const' warning. 2019-06-10 Alexei Podtelezhnikov * src/mlgetopt.c (getopt): Permit merged option-argument pairs. 2019-06-09 Alexei Podtelezhnikov * src/ft{view,grid,string}.c (parse_cmdline): Generalize batch mode... (usage): ... and mention it. * src/ft{view,grid,string}.1: s/end/contain/. 2019-06-09 Alexei Podtelezhnikov * graph/batch/grbatch.c (gr_batch_surface_refresh_rect): Remove. 2019-06-09 Alexei Podtelezhnikov * src/ftcommon.[hc] (FTDemo_Display_Print): Use `const' qualifier. * src/ftdump.c (Print_Bytecode): Ditto. * src/ftmulti.c (new_header): Ditto. * src/ftstring.c (header): Ditto. * src/ft{view,grid,string}.c (Process_Event): Updated. 2019-06-07 Werner Lemberg Fix compilation warnings. Also do some minor formatting. * graph/batch/grbatch.c: Suppress warnings about unused variables. * src/*: Suppress warnings about dropping `const'. 2019-06-06 Alexei Podtelezhnikov [ftgrid,ftview,ftstring] Enable batch mode. * src/ftcommon.[hc] (FTDemo_Display_New): Pass `device' argument. * src/{ftview,ftstring,ftgrid}.c (status): New `device' field. (parse_cmdline): Enable batch mode if keys end with `q'. * src/{ftview,ftstring,ftgrid}.1: Document it. 2019-06-06 Alexei Podtelezhnikov [graph] New batch device. This driver maintains the image in memory without displaying it, useful for batch processing without GUI. * graph/batch/grbatch.[hc]: New implenetation files. * graph/batch/rules.mk: Makefile with unconditinal compilation. * graph/grinit.c (GR_INIT_DEVICE_CHAIN): Add the driver at the tail. 2019-06-05 Alexei Podtelezhnikov [graph] Stay true to linked lists. * graph/grinit.c (grInitDevices, grDoneDevices): Properly walk and delete entries from the linked list `gr_device_chain'. * graph/grdevice.c (find_device): Ditto. * graph/grdevice.h (gr_num_devices, gr_max_devices): Removed. * graph/grconfig.h (GR_MAX_DEVICES): Ditto. 2019-06-03 Alexei Podtelezhnikov [ftgrid,ftview,ftstring] Implement PNG printing. * src/ftcommon.[hc] (FT_Display_Print): New function. * src/{ftgrid,ftview,ftstring}.c (Process_Event): New event. * Makefile: Compile with appropriate so that FT_CONFIG_OPTION_USE_PNG status is inherited from the library build and based on the libPNG avalability. 2019-06-01 Alexei Podtelezhnikov [ftgrid,ftview,ftstring] Consolidate versioning. * src/ftcommon.[ch] (FTDemo_Version): New function. * src/{ftgrid,ftview,ftstring}.c (parse_cmdline, event_help): Use it. 2019-05-24 Werner Lemberg [ttdebug] Add option `-d' to select variation font instance. * src/ttdebug.c: Include `ctype.h'. (requested_pos, requested_cnt): New global variables. (parse_design_coords): New auxiliary function. (Usage): Updated. (main): Handle option`-d'. * src/ttdebug.1: Updated. 2019-05-22 Werner Lemberg [ttdebug] New key `O' to show opcode help string. Also add key `H' to show help on the formatting of data. * src/ttdebug.c (OpStrDoc): New global array. (RunIns) <'h'>: Move help on format of value changes to... <'H'>: ... this key. Also describe format of opcode syntax. <'O'>: Show opcode help string. 2019-05-22 Werner Lemberg [ttdebug] Add support for GETVARIATION and GETDATA opcodes. * src/ttdebug.c: Include FT_MULTIPLE_MASTERS_H. (multimaster): New global variable. (OpStr): Updated. (main): Call `FT_Get_MM_Var' to initialize MM support. 2019-05-22 Werner Lemberg * src/ttdebug.c (OpStr): Improve opcode mnemonics. 2019-05-22 Alexei Podtelezhnikov [ftview,ftstring,ftgrid] Add keystroke emulator. * src/{ftview,ftstring,ftgrid}.c (parse_cmdline): New option to pass keystroke sequence. (Process_Event): Consume keystrokes from buffer before listening. (usage): Document it. * src/{ftview,ftstring,ftgrid}.1: Document it. 2019-05-21 Alexei Podtelezhnikov Prepare for scripting. * src/{ftview.c,ftstring.c,ftgrid.c,ftmulti.c,ftgamma.c} (main, Process_Event): Consolidate event handling. 2019-04-28 Werner Lemberg [ftmulti] Add axis grouping. If axis grouping (key `A') is active, hidden axes that have the same name tag as a visible one are not displayed. Additionally they receive the same values as the corresponding visible axis. * src/ftmulti.c (grouping, hidden, shown_axes, num_shown_axes): New global variables. (set_up_axes): New function to group axes. (Render_All, Render_Text, Help): Updated. (Process_Event): Handle key `A'. Handle grouping of axis values. (main): Initialize `shown_axes' and `hidden'; call `set_up_axes'. Update code to display axes tags. 2019-04-26 Werner Lemberg * src/ftmulti.c (Help, main): Mark hidden axes with an asterisk. 2019-04-26 Werner Lemberg * src/ftmulti.c: Various minor clean-ups. 2019-04-06 Werner Lemberg For distribution, replace `.tar.bz2' with `.tar.xz' bundles. * Makefile (dist): Do it. 2019-03-15 Werner Lemberg * Version 2.10.0 released. ========================== Tag sources with `VER-2-10-0. * README: Updated. * src/*.1: Updated. * src/ftinspect/ftinspect.pro: Updated. * Makefile (version, winversion): Since the minor version number has two digits now, never omit the patch number. We would get ambiguous zip file names otherwise. * src/ftdump.c (main): Avoid compiler warning. 2019-03-07 Werner Lemberg * src/ttdebug.c (RunIns): Fix signature. 2019-02-24 Werner Lemberg [ftview] Fix LCD rendering of color-layered glyphs. * src/ftview.c (Render_All): Always use normal rendering for color-layered glyphs. 2019-02-23 Werner Lemberg [ftview] Add more control for color-layered glyphs. Key `z' toggles color-layered glyph usage. Keys `i' and `I' cycle through color palettes. * src/ftcommon.h (TFont): Add `palette_index' field. (FTDemo_Handle): Add `use_layers' field. * src/ftcommon.c (FTDemo_New, FTDemo_Install_Font): Initialize new structure elements. * src/ftview.c (Render_All): Select palette; use `use_layers'. (event_help): Updated. (event_palette_change): New function. (Process_Event): Handle keys `z', `i', and `I'. (write_header): Updated. 2019-02-22 Werner Lemberg Minor doc string fixes. * src/ftgrid.c (usage), src/ftstring.c (usage), src/ftview.c (event_help, usage): Improve. 2018-11-18 Alexei Podtelezhnikov [ftdiff] Tweak adjustment of spacing. Align with b82405eda. We want to avoid changing or adjusting usual rounding of advances. * src/ftdiff.c (render_state_draw): Tweak conditionals. 2018-10-28 Alexei Podtelezhnikov * src/ftdump.c (Print_Name): Ignore exuberant timestamps. 2018-10-28 Alexei Podtelezhnikov * src/ftdump.c (Print_Name): Use ISO 8601 datestamps. 2018-10-26 Alexei Podtelezhnikov * src/ftdump.c (Print_Name): Report `head' revision and timestamps. 2018-10-06 Alexei Podtelezhnikov * src/ftdump.c (Print_Charmaps): Rework without \b. 2018-10-06 Alexei Podtelezhnikov * src/ftcommon.c (FTDemo_String_Draw): Avoid endless loop. * src/ftstring.c (main): Don't disable sbits. 2018-10-04 Alexei Podtelezhnikov * src/ftstring.c (Render_Waterfall): Color the size marks. (event_color_change): Manipulate the warning color. 2018-10-03 Alexei Podtelezhnikov [ftdump] New compact charmap coverage format. * src/ftdump.c (Print_Charmaps): Implement it. (main): Change corresponding options. * src/ftdump.1, src/ftdump.c (usage): Document it. 2018-10-01 Alexei Podtelezhnikov * graph/x11/grx11.c: Remove unused fields and function. 2018-10-01 Alexei Podtelezhnikov * graph/x11/grx11.c (gr_x11_surface_init): Clean up window creation. 2018-09-29 Alexei Podtelezhnikov * src/ftstring.c (Render_Waterfall): Mark the status size. 2018-09-29 Alexei Podtelezhnikov * graph/grfill.c (grFillHLine): Fix cropping. (grFillVLine): Refactor in line with `grFillHLine'. 2018-09-26 Alexei Podtelezhnikov * src/ftstring.c (Process_Event, event_help): Implement flushing. 2018-09-14 Alexei Podtelezhnikov * src/ftstring.c: Polished. 2018-09-13 Alexei Podtelezhnikov [ftstring] Implement text carpeting mode. * src/ftstring.c (main): Add text-carpeting mode implemented in... (Render_Text): ... this new function. (Render_CmpKern, Render_Waterfall): Minor updates and refactoring. 2018-09-13 Alexei Podtelezhnikov Teach `FT_String_Draw' to recycle glyphs. * src/ftcommon.h (FTDemo_String_Context): New fields for offset glyph and extent to fill. (FTDemo_String_Draw): Return the number of glyphs drawn. * src/ftcommon.c (FTDemo_String_Draw): Implement glyph recycling until the extent is full. 2018-09-12 Alexei Podtelezhnikov [ftstring] Load glyphs and advances explicitly. * src/ftcommon.h (FTDemo_Handle): Remove `string_reload' flag. (TGlyph): Split `delta' into original `lsb_delta' and `rsb_delta'. (FTDemo_String_Load): Declare new function. * src/ftcommon.c (string_load, string_render_prepare): Merge into... (FTDemo_String_Load): ... this function. (FTDemo_String_Draw): Devoid of string loading. * src/ftstring.c (main, Process_Event,Render_{Waterfall,KernCmp}): Call `FTDemo_String_Load' explicitly. 2018-09-11 Alexei Podtelezhnikov [ftstring] Keep all advances together. * src/ftcommon.h (TGlyph): New `hadvance' field for kerned advance. * src/ftcommon.c (string_load): Initialize it here. (string_render_prepare): Modify it here. (FTDemo_String_Draw): Use it here. 2018-09-09 Alexei Podtelezhnikov [ftview] Draw warning box for zero-width glyphs. * src/ftview.c ({X,Y}_TOO_LONG): Reworked the macros. (Render_{Stroke,Fancy,All}): Fill the added space with a warning box for zero-width glyphs. (Render_{Waterfall,Text}): Updated accordingly. 2018-09-07 Alexei Podtelezhnikov [ftview] Extra space for zero-width glyphs. * src/ftview.c (Render_{Stroke,Fancy,All}): Add half ppem to zero-width glyphs. 2018-09-07 Alexei Podtelezhnikov [ftview] Handle extra space differently. * src/ftcommon.c (FTDemo_Draw_{Index,Glyph_Color}): Move extra pixel from here... * src/ftview.c (Render_{Stroke,Fancy,All}): ... to here. (Render_{Waterfall,Text}): Do not compensate. 2018-08-23 Werner Lemberg [ftdiff] New keys `A' to `E' to select hinting mode directly. * src/ftdiff.c (process_event): Handle keys `A' to `E'. (event_help): Updated. 2018-08-04 Werner Lemberg Fix clang warnings. * src/ftstring.c (Process_Event), src/ftview.c (Process_Event): Add cast. 2018-07-23 Hin-Tak Leung [ttdebug] Add option `-f' to access non-first member of TTC. * src/ttdebug.1, src/ttdebug.c: Add a `-f face_index' switch to access non-first member of a TTC, plus updating the man page. 2018-07-05 Alexei Podtelezhnikov * graph/grfont.c (grGotobitmap): Initialize color here... (grWrite): ... instead of here. 2018-07-03 Alexei Podtelezhnikov [ftstring] Implement waterfall as mode 2. * src/ftstring.c (Render_String, Render_KernCmp): Extracted from ... (main): ... here. (Render_Waterfall): New mode function based on ftview. (event_help): Updated. 2018-07-03 Werner Lemberg Fix some clang warnings. * graph/grfill.c (grFillRect): Use `int' for `size'. * src/ftstring.c (flower_init): Use `unsigned int' for `i'. Simplify some loops. * src/ftview.c (parse_cmdline) <'L'>: Use `unsigned char' casts. (main): Add `FT_LcdFilter' cast. 2018-07-02 Hugh McMaster Fix memory leak (patch #9666). * src/ftcommon.c (FTDemo_Install_Font): Always free `font->filepathname'. 2018-07-02 Werner Lemberg * src/ftview.c (Render_All): Update `FT_Get_Color_Glyph_Layer' call. The function's signature was changed on 2018-07-02. 2018-06-30 Alexei Podtelezhnikov [ftstring] Implement string shifts. * src/ftstring.c (event_center_change): New function. (Process_Event): Shift the string with left-right arrows, rotate it with F5-F6. (event_help): Document it. 2018-06-30 Alexei Podtelezhnikov * src/ftcommon.c (FTDemo_Get_Index): Handle `FT_ENCODING_ORDER'. * src/ftcommon.c (FTDemo_Draw_Header, FTDemo_String_Set), src/ftview.c (Render_{All,Stroke,Fancy}), src/ftgrid.c (grid_status_draw_outline): Simplified accordingly. 2018-06-28 Alexei Podtelezhnikov [ftstring] Ditch gamma ramp. * src/ftstring.c (status): `gamma_ramp' removed. (gamma_ramp_draw): Remove. (event_gamma_change): Remove setting `gamma_ramp'. * src/ftstring.1: Mention stress test glyphs. 2018-06-28 Alexei Podtelezhnikov [ftgrid, ftview, ftstring] Update font and encoding handling. * src/ftcommon.c (my_face_requester): Check `cmap_index' range. (FTDemo_Install_Font): `cmap_index' obeys `handle->encoding' here, and postpone setting `num_indices'. (FTDemo_Set_Current_Font): `handle->encoding' obeys `cmap_index' here, also set `num_indices' accordingly. * src/ftview.c (event_encoding_change): Simplify by calling `FTDemo_Set_Current_Font'. 2018-06-25 Alexei Podtelezhnikov [ftstring] Improve stress test glyphs. * src/ftstring.c (wheel_init): Integrate into... (flower_init): ...this function. (main): Improve appearance of stress test glyphs. 2018-06-17 Alexei Podtelezhnikov [ftstring] Display glyphs to stress test rendering. * src/ftstring.c (wheel_init, flower_init): New functions to initialize stress test glyphs. (main): Display them. 2018-06-17 Alexei Podtelezhnikov [ftgrid] Draw dots using `FT_New_Glyph'. * src/ftgrid.c (circle_init): Make a custom glyph with a circle. (circle_draw): Render it using `FTDemo_Draw_Glyph_Color'. (ft_bitmap_draw, ft_outline_draw, ft_outline_new_circle): Removed. 2018-06-16 Werner Lemberg [ftview] First shot at colored glyph layer support. This is basically a proof of concept. Still missing: Switching off color layers and controlling palette selection. Additionally, only `Render_All' handles color layers. Some code should be moved to `ftcommon' so that other demo programs can show colored glyph layers also. * src/ftview: Include FT_COLOR_H and FT_BITMAP_H. (Render_All): Handle colored glyph layers. 2018-06-07 Alexei Podtelezhnikov [ftview] Control subpixel rendering from command line. * src/ftview.c (parse_cmdline): New `-L' option to set subpixel filter weights or geometry depending on the implemented method. (write_header, Process_Event): Hide filtering if not implemented. (main): Set default filter only if command line is not used. (usage): Document it. * src/ftview.1: Document it. 2018-06-07 Alexei Podtelezhnikov * src/ftbench.c (benchmark): Output formatting. 2018-05-31 Alexei Podtelezhnikov * graph/x11/grx11.c (gr_x11_device_init): Organize logging. 2018-05-27 Werner Lemberg Separate color support from sbit handling. * src/ftcommon.h (FTDemo_Handle): New boolean field `use_color'. * src/ftcommon.c (FTDemo_New, FTDemo_Update_Current_Flags): Updated. * src/ftview.c (Process_Event): Use key `c' to toggle color support. (write_header, event_help): Updated. 2018-05-25 Werner Lemberg Update manpages. * src/ftgrid.1, src/ftstring.1, stc/ftview: Document option `-d'. 2018-05-24 Alexei Podtelezhnikov [graph] Implement grayscale target surface. * graph/grblit.c (grBlitGlyphToBitmap): Enable gray target. * graph/gblblit.c (gblender_blit_init, GRGB_TO_GRAY, GRGB24_TO_GRAY): Implement gray target. 2018-05-23 Alexei Podtelezhnikov [ftview, ftstring, ftgrid] Change dimension options. * src/ftcommon.[hc] (FTDemo_Dispay_New): Use single dimension string as an argument, parse it, and initialize accordingly. * src/ftgrid.c (usage, parse_cmdline, status): Use single dimension string option. * src/ftstring.c (usage, parse_cmdline, status): Ditto. * src/ftview.c (usage, parse_cmdline, status): Ditto, rename variable axis option. * src/ftdiff.c, src/ftgamma.c: Updated. 2018-05-23 Alexei Podtelezhnikov * Makefile [unixdev]: Uncouple harfbuzz and libpng. 2018-05-21 Alexei Podtelezhnikov * graph/gblbgra.h: Gamma-corrected variant (disabled). 2018-05-21 Alexei Podtelezhnikov * graph/gblbgra.h: Make it wotk for all destination targets. 2018-05-19 Alexei Podtelezhnikov [graph] Fast "powerless" gamma ramps. We calculate the lookup tables for the power function using finite differences. This is 10 times faster and accurate enough for gamma correction. * graph/gblender.c (gblender_set_gamma_table): Reimplement using finite differences. * src/ftstring.c (event_gamma_change): Ditto for the decoration ramp. 2018-05-15 Alexei Podtelezhnikov * src/ftgrid.c (bitmap_scale): Mark centers of mono pixels. 2018-05-13 Alexei Podtelezhnikov * graph/grfill.c (grFillRect): Thinko. 2018-05-10 Alexei Podtelezhnikov [ftgrid] Update FT_DEBUG_AUTOFIT mode. * src/ftgrid.c (grid_status_draw_outline) [FT_DEBUG_AUTOFIT]: Show active segments only when autohinter is forced. Minor tweaks. 2018-05-09 Alexei Podtelezhnikov [ftgrid] Accept bitmap fonts. * src/ftgrid.c (main): Accept bitmap fonts. (grid_status_draw_outline): Do bitmap for any font. (grid_status_rescale_initial): Bitmap-compatible improved layout. 2018-05-08 Alexei Podtelezhnikov * src/ftgrid.c (main): Fail to open font earlier. 2018-05-01 Werner Lemberg * Version 2.9.1 released. ========================= Tag sources with `VER-2-9-1. * README: Updated. * src/*.1: Updated. * src/ftinspect/ftinspect.pro: Updated. 2018-04-26 Alexei Podtelezhnikov * src/ftstring.c (main): Update initializations. 2018-04-25 Alexei Podtelezhnikov * src/ftstring.c (main): Use size metrics instead of resolution. * src/ftview.c (Render_Fancy, Render_Stroke): Ditto. 2018-04-25 Alexei Podtelezhnikov * src/ftgrid.c (gitd_status_init): Set default resolution here... (parse_cmdline): ... instead of here. 2018-04-23 Alexei Podtelezhnikov * src/ftcommon.c (FTDemo_Draw_Header): Hide redundant point size. 2018-04-22 Werner Lemberg * src/ftview.c (Render_Stroke): Avoid double-free in case of error. 2018-04-22 Alexei Podtelezhnikov * src/ftview.c (Render_Waterfall): Reformulate the step. 2018-04-20 Alexei Podtelezhnikov [ftview] Display more dramatic waterfalls. * src/ftview.c (Render_Waterfall): Start from a small size and increment so that the requested size is in the middle. 2018-04-19 Alexei Podtelezhnikov * graph/grobjs.c (grFindColor): Missing case added. 2018-04-19 Alexei Podtelezhnikov Recycle some code. * graph/grfill.c (grFillRect): Call `memcpy' to speed it up. * src/ftcommon.c (FTDemo_Display_Clear): Call `grFillRect'. 2018-04-18 Alexei Podtelezhnikov [ftdump] Special case for copyright sign. * src/output.c (put_ascii_string{,_size}): Implement it. 2018-04-18 Alexei Podtelezhnikov * Makefile: Use `info' function of make 3.81. 2018-04-18 Alexei Podtelezhnikov * src/gbench.c: Missing variable types. 2018-04-18 Alexei Podtelezhnikov * src/Jamfile: Mention `output.c'. * objs/.gitignore: Ignore almost everything. 2018-04-18 Werner Lemberg * Jamrules (FT2_LIB), src/Jamfile (COMMON_LIB): Don't use $(SUFLIB). Jam automatically uses them. 2018-04-17 Werner Lemberg Move `obj' directory to `objs'. This is both for consistency with the FreeType library tree and better jam support. * Makefile (OBJ_DIR_2, clean_demo, distclean_demo), mac/Makefile (OBJ_DIR_2), mac/ftoldmac.m68k_far.make.txt (ObjDir), mac/ftoldmac.ppc_classic.make.txt (ObjDir), vms_make.com (OBJDIR, grinit.obj, grx11.obj): Updated. 2018-01-26 Ben Wagner * src/ftmulti.c (LOG) [DEBUG]: Modernize. 2018-01-08 Werner Lemberg * Version 2.9 released. ======================= Tag sources with `VER-2-9. * README: Updated. * src/*.1: Updated. * src/ftinspect/ftinspect.pro: Updated. 2018-01-07 Werner Lemberg * Makefile (LINK_LIBS): Add `LIB_CLOCK_GETTIME' (#52824). 2018-01-06 Werner Lemberg Use new `FT_Done_Var_MM' function. * src/ftdump.c (Print_MM_Axes), src/ftgrid.c (main), src/ftmulti.c (main): Do it. 2017-12-31 Werner Lemberg [ttdebug] Fix compiler warnings and run-time errors. * src/ttdebug.c (Cur_U_Line): Remove useless casts to `unsigned' and fix the necessary ones. (RunIns): Protect `FT_MEM_COPY' calls. 2017-12-30 Werner Lemberg [ttdebug] Key `K' shows full stack. * src/ttdebug.c (RunIns): Update help display. Handle key `K'. 2017-12-30 Werner Lemberg [ttdebug] Key `I' toggles hexadecimal/decimal numbers display. * src/ttdebug.c (use_hex): New global variable. (Cur_U_Line): Use it. (RunIns): Use it. Update help display. Handle key `I'. 2017-12-27 Werner Lemberg Fix compiler warnings. * src/ftcommon.c, src/ftcommon.h (FTDemo_Event_{Cff,Type1,T1cid}_Hinting_Engine_Change): Change return type to `int'. * src/ftdiff.c (HINTING_ENGINE_MAX): Removed. * src/ftgrid.c, src/ftmulti.c, src/ftview.c (N_HINTING_ENGINES): Removed. 2017-12-16 Alexei Podtelezhnikov * bin/.gitignore: Ignore almost everything. 2017-12-14 Ewald Hew Werner Lemberg Finish hinting engine selection code for Type 1 and CID fonts. * src/ftview.c (event_cff_hinting_engine_change, event_type1_hinting_engine_change, event_t1cid_hinting_engine_change): Moved and renamed to... * src/ftcommon.c (FTDemo_Event_Cff_Hinting_Engine_Change, FTDemo_Event_Type1_Hinting_Engine_Change, FTDemo_Event_T1cid_Hinting_Engine_Change): ...these. Include FT_MODULE_H. * src/ftcommon.h: Declarations. * src/ftmulti.c: Forward declarations. * Makefile: Updated to link above. * src/ftview.c (event_tt_interpreter_version_change): Updated. (Process_Event) <'H'>: Updated. * src/ftbench.c: s/cff_hinting_/ps_hinting_/. (main): Set `hinting-engine' property for all PostScript format drivers. * src/ftdiff.c (ColumnStateRec): New fields `type1_hinting_engine' and `t1cid_hinting_engine'. (render_state_init): Initialize new fields. (render_state_draw): Use new fields. Update footer string. (process_event) <'H'>: Updated. * src/ftgrid.c (GridStatusRec): New fields `type1_hinting_engine' and `t1cid_hinting_engine'. (main): Initialize new fields. (event_cff_hinting_engine_change): Removed. (Process_Event) <'H'>: Updated. * src/ftmulti.c (type1_hinting_engine, t1cid_hinting_engine): New fields. (main): Initialize new fields. Update header string. (cff_hinting_engine_change): Removed. (Process_Event) <'H'>: Updated. 2017-12-08 Werner Lemberg [ftview] Allow hinting engine selection for Type 1 and CID fonts. * src/ftview.c (status): New fields `type1_hinting_engine' and `t1cid_hinting_engine'. (main): Initialize new fields. (event_type1_hinting_engine_change, event_t1cid_hinting_engine_change): New functions. (Process_Event) <'H'>: Use them. (write_header): Updated. 2017-12-08 Werner Lemberg Update to Freetype changes from 2017-12-08. * src/*.c: s/FT_{CFF,TRUETYPE}_DRIVER_H/FT_DRIVER_H/. s/FT_CFF_HINTING_/FT_HINTING_/. s/N_CFF_HINTING_ENGINES/N_HINTING_ENGINES/. 2017-12-02 Werner Lemberg [ftview] Fix `-l' option. * src/ftview.c (usage): Fix reported range. (parse_cmdline) : Fix range checking. Set `handle->lcd_mode'; without this, there is no effect at start-up. * src/ftview.1: Fix argument range of `-l'. 2017-10-21 Alexei Podtelezhnikov * src/ttdebug.c: Fix compilation on Windows. 2017-10-17 Alexei Podtelezhnikov * src/ftgrid.c: Use integer for `scale'. Other tweaks. 2017-10-16 Colin Fahey * src/output.c (put_unicode_be16_string): Fix UTF16 default. 2017-10-14 Werner Lemberg [ftbench] Add new test for creating face and loading glyph together. This will be test `k'. * src/ftbench.c (FT_BENCH_NEW_FACE_AND_LOAD_GLYPH): New enum value. (bench_desc): Updated. (test_new_face_and_load_glyph): New function. (main): Handle it. (test_image_cache, test_sbit_cache): Tag unused variables. * src/ftbench.1: Updated. 2017-10-14 Werner Lemberg [ftbench] New option `-j' to specify last glyph index. * src/ftbench.c (last_index): New global variable. (test_load, test_load_advances, test_render, test_embolden, test_get_glyph, test_get_cbox, test_get_bbox, test_image_cache, test_sbit_cache, get_charset): Use it. (usage): Updated. (main): Handle `-j'. Initialize `last_index'. Update test output. 2017-10-10 Alexei Podtelezhnikov * src/ftgrid.c (grid_status_draw_outline): Show ascender and descender. 2017-10-09 Alexei Podtelezhnikov * src/ftgamma.c (Render_Bitmap): Ignore target flow. 2017-10-09 Alexei Podtelezhnikov * graph/win32/grwin32.c (gr_win32_surface_set_title): Small fix. 2017-10-04 Werner Lemberg [ftgrid] Correctly handle MM data. We have to reload the MM data after the cache gets reset. * src/ftgrid.c (event_font_change): Move source code up in file. (event_cff_hinting_engine_change, event_tt_interpreter_version_change, event_warping_change, event_lcd_mode_change, Process_Event <'h'>): Call `event_font_change'. 2017-10-03 Werner Lemberg [ftgrid] Fix crash. * src/ftgrid.c (grid_status_draw_outline): Avoid a crash if a font can no longer be opened. 2017-10-03 Werner Lemberg Correctly handle Type1 font names without extension. * src/ftcommon.c (my_face_requester): Unset the suffix if the font file doesn't have an extension. 2017-09-21 Werner Lemberg * src/ftmulti.c (main): Fix memory leak. 2017-09-18 Werner Lemberg [ftgrid] New option `-n' suppresses display of named instances. * src/ftgrid.c (GridStatus): New field `no_named_instances'. (grid_status_init, usage): Updated. (parse_cmdline): Handle `-n'. (main): Use `no_named_instances'. * src/ftgrid.1: Document it. 2017-09-17 Werner Lemberg [ftgrid] Fix crash if MM and non-MM fonts are viewed together. * src/ftgrid.c (event_font_change): Reset `status.mm' after deallocation. 2017-09-16 Werner Lemberg * Version 2.8.1 released. ========================= Tag sources with `VER-2-8-1. * README: Updated. * src/*.1: Updated. * src/ftinspect/ftinspect.pro: Updated. 2017-09-10 Alexei Podtelezhnikov * src/ftdump.c (main): Remove unnecessary `printf'. 2017-09-10 Werner Lemberg [ftgrid] Key `C' now changes to a different color palette. This gives better support for color-blind people. * src/ftgrid.c (GridStatus): New member `do_alt_colors'. (grid_status_init, event_help): Updated. (grid_status_display): Move color code to... (grid_status_colors): ... this new function. (grof_status_alt_colors): New function. (Process_Event): Handle key `C'. (main): Updated. 2017-09-09 Werner Lemberg Fix clang compiler warnings. * src/ftcommon.c (PanicZ): Use `const'. (FTDemo_Draw_Header): Add a cast. * src/ftdump.c (PanicZ): Use `const'. 2017-09-09 Werner Lemberg [ftgrid] Key `G' now toggles the display of grid lines. * src/ftgrid.c (GridStatus): New member `do_grid'. (grid_status_init, event_help): Updated. (grid_status_draw_outline, main): Use `do_grid'. (Process_Event): Handle key `G'. 2017-09-09 Werner Lemberg [ftgrid] Fix display of segment lines. `af_glyph_hints_get_segment_offset' now returns values in font units. Previously, values were scaled to the device resolution but with x height correction applied, which caused a mismatch to the displayed unhinted outlines. * src/ftgrid.c (grid_hint_draw_segment): Add new argument for `FT_Size' object. Scale return values of `af_glyph_hints_get_segment_offset' manually. (grid_status_draw_outline): Updated. 2017-09-06 Alexei Podtelezhnikov * src/{ftdump.c,ftcommon.c} (PanicZ): Handle error messages. 2017-08-20 Alexei Podtelezhnikov * src/ftdump.c (Print_Charmaps): Decorate with glyph names. 2017-07-06 Alexei Podtelezhnikov [ftstring] Tweak adjustment of spacing. The advance width rounding in light hinting is reflected in `rsb_delta' and ranges from -31 to 32. These conventional limits should also define when the spacing adjustment is warranted. * src/ftcommon.c (string_load): Tweak conditionals. 2017-06-29 Werner Lemberg * src/ftview.c (Render_Stroke): Avoid memory leaks. 2017-06-24 Alexei Podtelezhnikov [ftdump] List SFNT tables. * src/ftdump.c (Print_Sfnt_Tables): New feature, list SFNT tables with their first 4 bytes with version for some tables. (usage, main): Updated. * src/ftdump.1: Updated 2017-06-22 Werner Lemberg [compos] Make it compile. * src/compos.c (FT2_BUILD_LIBRARY): Define; we need access to FT_SubGlyphRec. Include FT_INTERNAL_GLYPH_LOADER_H. (main): Updated. 2017-06-13 Alexei Podtelezhnikov * src/ftcommon.c (FTDemo_Draw_Header): Simplify. 2017-06-10 Werner Lemberg * src/ftcommon.c (FTDemo_Draw_Header): Fix compiler warning. 2017-06-10 Alexei Podtelezhnikov * src/ftview.c (event_encoding_change, main): Minor updates. 2017-06-10 Werner Lemberg * src/ftcommon.c (FTDemo_Draw_Header): Show gamma in second line. Otherwise it clashes with long file names. 2017-06-03 Alexei Podtelezhnikov [ftview] Merge gray and color sbits controls. * src/ftcommon.h (FTDemo_Handle): Merge `color' into `use_sbits'. * src/ftcommon.c (FTDemo_New, FTDemo_Update_Current_Flags): Updated. * src/ftview.c (Process_Event, event_help, write_header): Updated. 2017-06-03 Alexei Podtelezhnikov [ftgrid] Teach encodings. * src/ftgrid.c (grid_status_draw_outline): Use encoding. (parse_cmdline, usage): New option to specify encoding. (Process_Event): Use hexadecimal steps through index. 2017-06-03 Alexei Podtelezhnikov [ftgrid] Minor. * src/ftgrid.c (grid_status_draw_outline): Move the stroker initialization from here... (main): ... to here. 2017-06-03 Alexei Podtelezhnikov [ftview] Clean up charmap handling. * src/ftcommon.h (FT_ENCODING_ORDER): Introduce this special encoding for glyph order because `FT_ENCODING_NONE' has other meanings. * src/ftcommon.c (FTDemo_Install_Font): Fall back to `FT_ENCODING_ORDER' if encoding is not recognized. (FTDemo_Draw_Header): Updated. * src/ftview.c (status): Remove redundant `encoding' field and update all references. (FT_ENCODING_OTHER): Removed in favor of `FT_ENCODING_NONE'. 2017-06-01 Alexei Podtelezhnikov [ftgrid, ftstring, ftview] Further top header consolidation. * src/ftview.c (event_encoding_change): Update `handle'. (write_header): Move instance, encoding, and the first glyph code reporting from here... * src/ftgrid.c (write_header): ... and from here... * src/ftcommon.c (FTDemo_Draw_Header): ... to here. * src/ftcommon.h (FTDemo_Draw_Header): Update prototype. * src/ftstring.c (write_header): Updated. 2017-05-29 Alexei Podtelezhnikov [ftgrid, ftstring, ftview] Migrate gamma to `FTDemo_Display'. * src/ftcommon.h (FTDemo_Display): Add new field `gamma'. * src/ftcommon.c (FTDemo_Display_New): Initialize it. (FTDemo_Draw_Header): Updated. * src/ftgrid.c (GridStatusRec): Remove field `gamma'. (event_gamma_change): Updated. * src/ftstring.c (status): Remove field `gamma'. (event_gamma_change): Updated. * src/ftgrid.c (status): Remove field `gamma'. (event_gamma_change): Updated. 2017-05-28 Werner Lemberg * src/ftbench.c (BENCH_TIME): Use `double' literal. 2017-05-27 Philipp Kerling [ftinspect] Split sources; change face index type to `long'. * src/ftinspect.cpp, src/ftinspect.h: Split into... * src/ftinspect/*: ...these new files. Do face index type change. * src/ftinspect/.gitignore: New file. 2017-05-24 Werner Lemberg Minor `fread' coding issues. * src/ftbench.c (get_face), src/ftcommon.c (FTDemo_Install_Font): Make `nmemb' argument of `fread' equal 1; this allows a simplification of the return value test (you get either 0 or 1). * src/ftdiff.c (main): Handle `fread' errors. Problem reported by Kushal K S V S (కుషల్ కే ఎస్ వీ ఎస్) . 2017-05-18 Alexei Podtelezhnikov [ftgrid, ftstring, ftview] Unify top header lines. * src/ftcommon.[ch] (FTDemo_Draw_Header): New function that displays information about face, size, resolution, and gamma to be used in... * src/ftview.c (write_header): ... here. * src/ftstring.c (write_header): ... here. * src/ftgrid.c (write_header): ... and here. (event_gamma_change): Updated. 2017-05-15 Alexei Podtelezhnikov * src/ftgrid.c (main): Fix segmentation fault. 2017-05-15 Alexei Podtelezhnikov [ftdiff, ftgrid, ftview] Make autohint warping NORMAL option. * src/ftdiff.c (render_state_draw, event_help): Updated. * src/ftgrid.c (event_help, event_warping_change): Updated. * src/ftview.c (event_help, event_warping_change, write_header): Updated. 2017-05-14 Alexei Podtelezhnikov [ftstring, ftview] Loosely match bitmap font sizes. * src/ftcommon.c (FTDemo_Set_Current_Size, FTDemo_Set_Current_Charsize): Round requested size to the closest available ppem for bitmap fonts. * src/ftview.c (Render_Waterfall): Simplify accordingly. (write_header): Highlight ppem that does not match the point size. * src/ftstring.c (write_header): Report ppem. 2017-05-14 Alexei Podtelezhnikov * src/ftview.c (Render_Stroke): Fix segmentation fault. 2017-05-13 Werner Lemberg * Version 2.8 released. ======================= Tag sources with `VER-2-8. * README: Updated. * src/*.1: Updated. * src/ftinspect.pro: Updated. 2017-05-11 Werner Lemberg * src/ftinspect.cpp: Don't include `cstdint', which is C++11. Right now, we still want to be able to compile with older C++ compilers. 2017-05-11 Philipp Kerling [ftinspect] Check glyph index before discarding sign. * src/ftinspect.cpp (Engine:glyphName, Engine::loadOutline): Do it. 2017-05-11 Philipp Kerling * src/ftinspect.cpp (GlyphPointNumbers::paint): Fix `ptIdx' type. 2017-05-11 Philipp Kerling [ftinspect] Mark float literals as float. * src/ftinspect.cpp (GlyphPointNumbers::paint): Do it. 2017-05-11 Philipp Kerling [ftinspect] Insert explicit casts where warranted. This avoids compiler warnings. * src/ftinspect.cpp (Engine::numberOfNamedInstances, Engine::glyphName, Engine::loadOutline, GlyphBitmap::GlyphBitmap, GlyphBitmap::paint, QGraphicsViewx::resizeEvent): Do it. 2017-05-11 Philipp Kerling [ftinspect] Replace old-style casts with C++ casts. * src/ftinspect.cpp (Engine::update, GlyphPointNumbers::paint): Do it. 2017-05-11 Philipp Kerling [ftinspect] Make color tables and settings more readable. * src/ftinspect.cpp (MainGUI::setGraphicsDefaults): Use Qt constants and `qRgba'. 2017-05-11 Philipp Kerling [ftinspect] Use symbolic constant for TrueType interpreter v40. v40 is implemented meanwhile. * src/ftinspect.cpp (Engine::Engine, MainGUI::setDefaults): Use `TT_INTERPRETER_VERSION_40'. 2017-05-11 Philipp Kerling [ftinspect] Remove unneeded explicit array sizes. * src/ftinspect.cpp (Engine::Engine): Do it. 2017-05-11 Philipp Kerling [ftinspect] Make `ftcFaceID' conversion safe. * src/ftinspect.cpp: Include `stdint.h'. (faceRequester): Implement it. 2017-05-11 Philipp Kerling [ftinspect] Synchronize dpi, target, pxlMode types with FreeType. * src/ftinspect.h (Engine): Make `dpi' unsigned int. Make `loadFlags' unsigned long. (GlyphBitmap): Use `FT_Pixel_Mode' for `pixelMode' and constructor. * src/ftinspect.c: Include `cstdint', `cmath', `limits', `stdexcept', needed by forthcoming commits. (Engine::update, GlyphBitmap::GlyphBitmap, MainGUI::drawGlyph): Updated. 2017-05-11 Philipp Kerling [ftinspect] Change freetype2 include path to system include path. This avoids warnings. * src/ftinspect.pro: Do it. 2017-05-11 Philipp Kerling [ftinspect] Remove `const_cast'. * src/ftinspect.cpp (GlyphBitmap::paint): `const_cast' is potentially dangerous and should only be used as a last resort. Here, the mutable data can just be accessed with `.bits()' instead. 2017-05-11 Werner Lemberg Fix clang warnings. * src/ftbench.c (main): Use cast. * src/ftview.c (N_LCD_IDXS): Cast to `int'. (usage, parse_cmdline): Updated. 2017-05-09 Alexei Podtelezhnikov [ftview] Report fractional ppem for scalable fonts. * src/ftview.c (write_header): Updated, ppem and errors consolidated. 2017-05-08 Alexei Podtelezhnikov * src/ftview.c (write_header): Revert due to segmentation fault. 2017-05-02 Werner Lemberg Remove `slight' auto-hinting mode. Add sub-pixel `light' mode. * src/ftcommon.h (LCD_MODE_SLIGHT): Replace with... (LCD_MODE_LIGHT_SUBPIXEL): ...this new enum value. * src/ftcommon.c (FTDemo_Update_Current_Flags, FTDemo_Glyph_To_Bitmap): Updated. (string_load): Handle `LCD_MODE_LIGHT_SUBPIXEL'. Make integer delta support actually work. (string_render_prepare): Support `LCD_MODE_LIGHT_SUBPIXEL'. * src/ftdiff.c (HintMode): Replace HINT_MODE_AUTOHINT_SLIGHT with HINT_MODE_AUTOHINT_LIGHT_SUBPIXEL. (render_mode_names, render_state_draw, event_help): Updated. * src/ftgrid.c (grid_status_draw_outline): Show fractional advance width. (event_lcd_mode_change, Process_Event): Updated. * src/ftstring.c (event_lcdmode_change): Updated. * src/ftview.c (lcd_modes): New array to map indices (as produced by key presses) to LCD modes; we omit LCD_MODE_LIGHT_SUBPIXEL, which doesn't make much sense within ftview. (N_LCD_IDXS): New macro. (status): Replace `lcd_mode' with `lcd_idx'. (event_help): Revert change from 2017-04-19. (Process_Event): Updated to use `lcd_modes' array. Remove references to LCD_MODE_LIGHT. (write_header, usage, parse_cmdline, main): Updated. * src/ftinspect.h (AntiAliasing): Remove `AntiAliasing_Slight'. * src/ftinspect.cpp (Engine::update, MainGUI::checkHinting, MainGUI::checkAutoHinting, MainGUI::checkAntiAliasing, MainGUI::createLayout): Updated. 2017-04-19 Werner Lemberg Support new `slight' auto-hinting mode. Note that currently only `ftdiff' shows what the new mode really can do – `ftview' uses integer advance values, which doesn't work well with the `slight' mode. * src/ftcommon.h (LCD_MODE_SLIGHT): New enumeration. * src/ftcommon.c (FTDemo_Update_Current_Flags, FTDemo_Glyph_To_Bitmap): Handle `LCD_MODE_SLIGHT'. * src/ftdiff.c (HintMode): Add `HINT_MODE_AUTOHINT_SLIGHT'. (render_mode_names): Updated. (render_state_draw): Handle `HINT_MODE_AUTOHINT_SLIGHT'. * src/ftgrid.c (event_lcd_mode_change): Handle `LCD_MODE_SLIGHT'. (Process_Event): Updated. * src/ftstring.c (event_lcdmode_change): Handle `LCD_MODE_SLIGHT'. * src/ftview.c (event_help): Updated; we now have keys A-H to directly select rendering modes. (Process_Event, write_header): Updated. * src/ftinspect.h (AntiAliasing): Add `AntiAliasing_Light'. * src/ftinspect.cpp (Engine::update): Handle `AntiAliasing_Light', update `AntiAliasing_Slight'. (MainGUI::checkHinting, MainGUI::checkAutoHinting, MainGUI::checkAntiAliasing, MainGUI::createLayout): Updated. 2014-04-19 Werner Lemberg [ftgrid] Fix out-of-array memory access. * src/ftgrid.c (bitmap_scale) [gr_pixel_mode_lcd]: We handle input pixel by pixel, not the full line; consequently, we have to use `width', not `pitch'. 2017-04-17 Alexei Podtelezhnikov * src/ftview.c (write_header): Report fractional ppem differently. To convince Werner. 2017-04-16 Alexei Podtelezhnikov * src/ftview.c (write_header): Report fractional ppem. 2017-04-16 Werner Lemberg * src/ftdump.c (Print_Charmaps): Better show synthetic cmaps. 2017-04-09 Werner Lemberg * src/ftmulti.c (Render_All, Render_Text): Round advance widths. Problem spotted by Nikolaus. 2017-03-30 Werner Lemberg * src/ftview.c (write_header): Show current instance index. 2017-03-29 Alexei Podtelezhnikov Use `LCD_MODE_XXX' enum values. * src/ftcommon.c (FTDemo_New, FTDemo_Update_Current_Flags, FTDemo_Glyph_To_Bitmap, FTDemo_Index_To_Bitmap): Ditto. * src/ftgrid.c (event_lcd_filter_change): Ditto. * src/ftstring.c (event_lcdmode_change): Ditto. 2017-03-29 Werner Lemberg * src/ftview.c (INIT_SIZE): Improve vertical start position. 2017-03-27 Alexei Podtelezhnikov [ftview] Stuff right margin. * src/ftview.c (X_TOO_LONG): Rely on `horiAdvance' when available. (Render_All): Use `FTDemo_Draw_Slot' so that updated X_TOO_LONG works. (Render_Stroke, Render_Fancy): Updated. 2017-03-26 Alexei Podtelezhnikov [ftview] Hide LCD filter from grayscale modes. * src/ftview.c (Process_Event, write_header): Check the LCD mode before adjusting or reporting the LCD filter. 2017-03-26 Alexei Podtelezhnikov [ftview, ftstring, ftgrid] Remove anti-aliasing toggle. * src/ftcommon.h (FTDemo_Handle): Replace `antialias' field with `LCD_MODE_MONO' enumerator. * src/ftcommon.c (FTDemo_Update_Current_Flags, FTDemo_Glyph_To_Bitmap, FTDemo_Index_To_Bitmap): Updated. * src/ftgrid.c (Process_Event, event_help, event_lcd_mode_change, event_lcd_filter_change): Ditto. * src/ftstring.c (Process_Event, event_help, event_lcdmode_change): Ditto. * src/ftview.c (Process_Event, event_help, write_header): Ditto. 2017-03-24 Alexei Podtelezhnikov * src/ftview.c (Render_*): Improve readability. 2017-03-24 Alexei Podtelezhnikov [ftview] Consolidate emboldening and slanting modes. * src/ftview.c (Render_Slanted, Render_Embolden): Merged into... (Render_Fancy): ... this new function. (event_help, Process_Event, write_header, main): Updated. * src/ftview.1: Updated. 2017-03-23 Alexei Podtelezhnikov * src/ftmulti.c (Process_Event, main): Use `FT_RoundFix'. 2017-03-23 Werner Lemberg * src/ftmulti.c (Process_Event, main): Fix rounding. 2017-03-23 Werner Lemberg [ftmulti] Show PS name. * src/ftmulti.c (Render_All): Adjust vertical start position. (Render_Text): Make arguments similar to `Render_All'. Adjust vertical start position. (Process_Event): Round non-integer axis values to two decimal digits. (main): Updated. Print PostScript name. 2017-03-20 Brian Nixon [ftview] Improve waterfall mode (#50586). * src/ftview.c (Render_Waterfall): Stop repeating of the default glyph to the end of each line after the display text. 2017-03-20 Brian Nixon * graph/win32/grwin32.c(syskey_translators): Fix F10 key (#50585). `F10' does not work as advertised in the demos because the message-handling code expects it to arrive as a `normal' key but Windows sends it as a `system' key (because it is reserved for activating the menu bar, per the IBM Common User Access standard). Fix this by adding `F10' to the ‛syskey_translators’ table. (We also remove the existing handling of `F1' as a `system' key, because this does not appear to be necessary. `F1' is sent as a `normal' key and is correctly handled by the ‛key_translators’ table.) 2017-03-19 Alexei Podtelezhnikov * src/ftbench.c (main, usage): Add optional LCD filtering. 2017-03-19 Brian Nixon [graph] Make demo windows minimise-able on Win32 (#50582). * graph/win32/grwin32.c (gr_win32_surface_init): Implement it. 2017-03-13 Werner Lemberg [ftdump] Show ID numbers for standard `name' table entries. * src/ftdump.c (EXPAND, XEXPAND, NAME_ID): New macros. (name_id): Use new macros. 2017-02-07 Alexei Podtelezhnikov * src/ftgamma.c (main): Label images. 2017-02-03 Alexei Podtelezhnikov [ftgamma] Add box-filtered subpixel pattern. Two alternative patterns now demonstrate the importance of correct gamma for both grayscale and subpixel anti-aliasing, where it helps normalize thickness in the former and remove color fringes in the latter. * src/ftgamma.*: Updated. 2017-01-28 Alexei Podtelezhnikov [ftstring] Improve gamma ramp appearance. * src/ftstring.c (event_gamma_change, gamma_ramp_draw): Updated. 2017-01-28 Werner Lemberg [ftdump] Always finalize FreeType. * src/ftdump.c (PanicZ, usage): Add `library' argument so that we can call `FT_Done_FreeType'. (main): Updated. 2017-01-28 Werner Lemberg [ftdump] Sync with current FreeType. * src/ftdump.c (name_id): Use updated ID macros. Add new ID macros. 2017-01-27 Alexei Podtelezhnikov [ftview] Align with current FreeType. * src/ftview.c (write_header): s/GB2312/PRC/. (Process_Event): `FT_Library_SetLcdFilterWeights' now enables filtering without `FT_Library_SetLcdFilter'. 2016-12-30 Werner Lemberg * Version 2.7.1 released. ========================= Tag sources with `VER-2-7-1'. * README: Updated. * src/*.1: Updated. * src/ftinspect.pro: Updated. 2016-12-27 Werner Lemberg [ftmulti] Minor. * src/ftmulti.c (Process_Event, main): If MM, round design coordinates. 2016-12-25 Werner Lemberg Fixes for clang++. * Makefile (COMPILE): Don't add `-std=c99' if using a C++ compiler. * src/ftbench.c (_GNU_SOURCE): Declare only if not already defined. * src/ftcommon.c (_GNU_SOURCE): Declare only if not already defined. (FTDemo_Install_Font): Use proper case for `FT_Select_Charmap'. * src/ftmulti.c (main): Use proper case for `FT_Select_Charmap'. 2016-12-20 Werner Lemberg * src/ftmulti.c: Minor clang fixes. 2016-12-19 Werner Lemberg [ftmulti] Support multiple engines. Similar to other programs, use the `H' key to cycle through engines (if available). * src/ftmulti.c: Include FT_FONT_FORMATS_H, FT_MODULE_H, FT_TRUETYPE_DRIVER_H, FT_CFF_DRIVER_H. (N_CFF_HINTING_ENGINES): New macro. (cff_hinting_engine, tt_interpreter_versions, num_tt_interpreter_versions, tt_interpreter_version_idx, font_format): New global variables. (Help): Updated. (cff_hinting_engine_change, tt_interpreter_version_change): New functions. (Process_Event): Handle key `H'. (main): Set up selection of CFF and TrueType engine versions. Display selected engine. Force redisplay of current font if `H' key was pressed. 2016-11-06 Werner Lemberg * src/ftbench.c (main): Adjust size argument for bitmap strikes. For bitmap-only fonts we enforce the selection of the first bitmap strike size. This commit also fixes the `size' value itself. 2016-10-29 Werner Lemberg Minor compilation issues. * Makefile: Use ANSIFLAGS and select C99 for GNU-like compilers. * src/ftbench.c, src/ftcommon.c (_GNU_SOURCE): Define. We use functionality not covered by ANSI. 2016-10-29 Werner Lemberg Fix clang warnings. We now have a new `FT_ENCODING_OTHER' tag used for internal purposes. Since it is not possible to extend an enumeration after its definition, replace `FT_Encoding' types with `unsigned long'. * src/ftcommon.c (FTDemo_Make_Encoding_Tag): Updated. * src/ftcommon.h (FTDemo_Handle): Ditto. * src/ftmulti.c (encoding): Use `unsigned long'. (main): Updated. * src/ftstring.c (Sample): Make array of type `const char*'. (status): Use `unsigned long' for `encoding' field. Use `const char*' for `text' field. * src/ftview.c (status): Use `unsigned long' for `encoding'. (FT_ENCODING_OTHER): Use `unsigned long'. 2016-10-18 Alexei Podtelezhnikov [graph] Untested legacy 15/16-bit color fixes. Our tools do not use the legacy 15/16-bit color modes. This is mostly for the sake of correctness. We might also remove the code. * graph/grblit.c (blit_gray{8,}_to_{555,565}): Updated. * graph/x11/grx11.c (gr_x11_format_{bgr565,rgb555,bgr555}): Updated. 2016-10-13 Alexei Podtelezhnikov * graph/grblit.c (blit_lcd28_to_24): Typo. 2016-10-10 Alexei Podtelezhnikov * src/ftdump.c (Print_Charmaps): Dump format info. 2016-10-09 Alexei Podtelezhnikov [ftview] Recognize other charmaps. * src/ftview.c (event_change_encoding): Recognize when FT_ENCODING_NONE has special other meaning. (write_header): Default case for `status.encoding'. 2016-10-07 Alexei Podtelezhnikov [ftview] Fix charmap cycling. * src/ftview.c (event_change_encoding): Reimplement relying on `cmap_index' field in TFont structure. 2016-10-05 Alexei Podtelezhnikov [ftview] Implement cycling through available charmaps. * src/ftview.c (event_change_encoding): New function. (Process_Event): New [Tab] event to cycle through available charmaps, also increase index steps to 16, 256, and 4096. (event_help): Updated. 2016-10-03 Alexei Podtelezhnikov * graph/grevents.h (grKey): Typo. 2016-10-01 İsmail Dönmez * src/ftinspect.pro (LIBS): Fix default value. 2016-09-24 Alexei Podtelezhnikov [ftstring] Add LGC and CJK sample strings. * src/ftstring.c (event_text_change): New function. (Process_Event): New [Tab] event to cycle through sample strings. (event_help): Offer it. (status, event_font_change, main): Updated. 2016-09-16 Werner Lemberg * src/ftbench.1: Improve. 2016-09-08 Werner Lemberg * Version 2.7 released. ======================= Tag sources with `VER-2-7'. * README: Updated. * src/*.1: Updated. * src/ftinspect.pro: Updated. 2016-08-20 Alexei Podtelezhnikov * src/ftdump.c (Print_Programs): Use fewer casts. 2018-08-19 Werner Lemberg [ftdump] Fix clang compiler warnings. * src/ftdump.c (Print_Bytecode): Use cast instead of printf length modifier – we would need `hh', which only glibc offers. (Print_Programs): Use proper casts for constant strings and 16bit integer types. 2018-08-19 Werner Lemberg [ftgamma] Fix compiler warnings. * src/ftgamma.c (bit1, bit2, bit): Make them static. 2016-08-18 Alexei Podtelezhnikov [ftdump] Hexdump composite glyf instructions too. * src/ftdump.c (Print_Programs): Updated. (Print_Bytecode): Cleaned up. 2016-08-18 Alexei Podtelezhnikov [ftdump] Implement hexdump of TrueType instructions. This is useful when searching for interesting instructions. Pushed values come with underscore prefix to distinguish them from actual opcodes. * src/ftdump.c (Print_Bytecode, Print_Programs): Implement this. (usage): New option `-p' described. (main): Updated. * src/ftdump.1: Updated. 2016-08-06 Werner Lemberg Move Mark Leisher's `getopt' implementation to a separate file. We need this since `ftbench.c' now includes `unistd.h', which in turn declares `getopt'. * src/common.c, src/common.h: Move `getopt' stuff to... * src/mlgetopt.c, src/mlgetopt.h: ... these new files. Update all callers. * src/common.c, src/common.h: Use standard C only. Replace `CONST' with `const'. * Makefile (COMMON_OBJ): Add `mlgetopt'. 2016-08-02 Alexei Podtelezhnikov * src/ftbench.c (get_time, benchmark): Clean up timers. 2016-08-01 Alexei Podtelezhnikov [ftbench] Use POSIX timers when available. * src/ftbench.c (get_time): Use `clock_gettime' instead of obsolete and less accurate `gettimeofday'. (benchmark): Updated. 2016-07-14 Werner Lemberg [ftgrid] New option `-d' to give start-up design coordinates. This code is similar to the one from `ftmulti'. * src/ftgrid.c: Include `stdlib.h'. (GridStatusRec): Add `requested_pos' and `requested_cnt' to hold the design coordinate data from the command line. (event_font_change): Handle them. (parse_cmdline): Handle option `-d'. (usage): Document `-d'. (main): Don't load named instances if we have start-up design coordinates. * src/ftgrid.1: Updated. 2016-07-14 Werner Lemberg Prepare suppression of named instances. No functional change. * src/ftcommon.c (FTDemo_Install_Font): Add boolean parameter to avoid loading of instances. * src/ftcommon.h: Updated. * src/ftgrid.c (main), src/ftstring.c (main), src/ftview.c (main): Updated. 2016-07-14 Werner Lemberg [ftgrid] Properly handle named instances. * src/ftgrid.c (event_font_change): Properly initialize the design positions with the named instance's value, if appropriate. 2016-07-12 Werner Lemberg * Version 2.6.5 released. ========================= Tag sources with `VER-2-6-5'. * README: Updated. * src/*.1: Updated. * src/ftinspect.pro: Updated. 2016-07-05 Werner Lemberg * Version 2.6.4 released. ========================= Tag sources with `VER-2-6-4'. * README: Updated. * src/*.1: Updated. * src/ftinspect.pro: Updated. 2016-06-26 Werner Lemberg [ftinspect] Fix pixel box drawing. This commit circumvents a problem with Qt's `QPainter::drawImage' function; it seems that the alignment of the output becomes imprecise at high magnification values. * src/ftinspect.c (GlyphBitmap::paint): Manually draw pixel boxes with `fillRect'. 2016-05-29 Werner Lemberg * src/ftbench.c (main): Add cast to remove compiler warning. 2016-05-29 Werner Lemberg [ftinspect] Mark pixel centers in the grid with a cross. * src/ftinspect.c (Grid::paint): Implement it. 2016-05-29 Werner Lemberg [ftinspect] Prepare zoom for drawing pixel center. This change makes the zoom use only even values larger than a given threshold; it also implements (kind of) logarithmic zooming. * src/ftinspect.h (QSpinBoxx): New class, derived from `QSpinBox'. (MainGUI): Updated. * src/ftinspect.cpp (MainGUI::createLayout): Updated. (QSpinBoxx::valueFromText, QSpinBoxx::stepBy): New methods. 2016-05-26 Werner Lemberg [ftbench] Add support for third TrueType interpreter version. Option `-H' now takes an argument to select the CFF hinting engine, and new option `-I' selects the TT interpreter version. * src/ftbench.c (default_hinting_engine, default_interpreter_version): Replaced with... (tt_interpreter_versions, num_tt_interpreter_versions, dflt_tt_interpreter_version, cff_hinting_engines, num_cff_hinting_engines, dflt_cff_hinting_engine, cff_hinting_engine_names): ... these new global variables. (main): Expand check for alternative TrueType interpreter versions and CFF hinting engines. Add argument to option `-H'. Add new option `-I'. (usage): Updated. * src/ftbench.1: Updated. 2016-05-26 Werner Lemberg [ttdebug] Rename option `-H' to `-I'. This is for consistency with a forthcoming change to `ftbench'. * src/ttdebug.c (main): Implement it. (Usage): Updated. * src/ttdebug.1: Updated. 2016-05-26 Werner Lemberg [ttdebug] Add support for third TrueType interpreter version. Option `-H' now takes an argument. * src/ttdebug.c (default_version, alternative_version): Replaced with... (tt_interpreter_versions, num_tt_interpreter_versions, dflt_tt_interpreter_version): ... these new global variables. (main): Expand check for alternative TrueType interpreter versions. Add argument to option `-H'. (Usage): Updated. * src/ttdebug.1: Updated. 2016-05-21 Werner Lemberg [ftgrid] Add support for third TrueType interpreter version. * src/ftgrid.c (GridStatusRec): Replace `tt_interpreter_version' with `tt_interpreter_versions' array. Add `num_tt_interpreter_versions' and `tt_interpreter_version_idx'. (event_tt_interpreter_version_change): Updated. (main): Expand check for alternative TrueType interpreter versions. 2016-05-21 Werner Lemberg [ftdiff] Add support for third TrueType interpreter version. * src/ftdiff.c (ColumnStateRec): Replace `tt_interpreter_version' with `tt_interpreter_versions' array. Add `num_tt_interpreter_versions' and `tt_interpreter_version_idx'. (render_state_init): Expand check for alternative TrueType interpreter versions. (render_state_draw): Updated. (process_event) <'H'>: Updated. 2016-05-21 Werner Lemberg [ftview] Add support for third TrueType interpreter version. * src/ftview.c (status): Replace `tt_interpreter_version' with `tt_interpreter_versions' array. Add `num_tt_interpreter_versions' and `tt_interpreter_version_idx'. (event_tt_interpreter_version_change, write_header): Updated. (main): Expand check for alternative TrueType interpreter versions. 2016-05-21 Werner Lemberg Make compilation work with clang++. Also fix some warning messages. * src/ftcommon.c (FTDemo_Display_Clear): Use proper cast. (string_load): Replace shifts with multiplication. * src/ftgamma.c: (bit1, bit2): Complete initializer. (do_ptrn, do_fill): Use proper casts. (Render_Bitmap): s/bitmap/out/, s/bit/in/, to avoid shadowing global variable `bit'. * src/ftgrid.c (GridStatus): Make `lcd_filter' of type `FT_LcdFilter'. (bitmap_scale): Use proper casts. (grid_status_draw_outline): Fix int vs. short warnings. (event_cff_hinting_engine_change): Add initializer. (event_lcd_filter_change): Properly handle `status.lcd_filter'. * src/ftmulti.c (requested_cnt, used_num_axis): Make them `unsigned int'. (Process_Event, main): Updated. * src/ftstring.c (status): Complete initializer. * src/ftvalid.c (ValidatorType): Fix enum syntax. * src/ftview.c (event_cff_hinting_engine_change): Add initializer. (Process_Event) <'L'>: Fix call to FT_Library_SetLcdFilter. * src/output.c (put_ascii_string, put_unicode_be16_string): Add casts. 2016-05-19 Werner Lemberg [ftinspect] Use bottom left as the viewport anchor for resizing. We store the last bottom left corner point of the viewport rectangle and adjust the verticalScrollBar value by the delta relative to the current bottom left corner position. * src/ftinspect.h (QGraphicsViewx): New class, derived from `QGraphicsView'. (MainGUI): Updated. * src/ftinspect.cpp (MainGUI::createLayout): Updated. (QGraphicsViewx::QGraphicsViewx, QGraphicsViewx::scrollContentsBy, QGraphicsView::resizeEvent): New methods. 2016-05-18 Werner Lemberg [ftinspect] Re-implement file watching. * src/ftinspect.cpp (MainGUI::MainGUI): Initialize file watcher and timer. (MainGUI::closeFont): Updated. (MainGUI::watchCurrentFont): New method. (MainGUI::showFont): Handle file watching for both real files and softlinks. Display a softlink name as italic font. (MainGUI::createConnections): Updated. * src/ftinspect.h (MainGUI): Updated. 2016-05-15 Werner Lemberg [ftinspect] Redesign file/face/instance navigation. Instead of peeking into a font with a negative argument to `FT_Face_New', we now directly load appropriate (font, face, instance) triplets. The new code also tries a bit harder to separate the font stuff in the `Engine' class from the GUI navigation control in `MainGUI'. * src/ftinspect.h (Font): Removed. (MainGUI): Make `fontList' a `QStringList'. New members `currentNumberOfFaces' and `currentNumberOfNamedInstances'. Move `faceCounter' and `faceIDMap' members to... (Engine): ...this class. Make `faceRequester' a friend. * src/ftinspect.cpp (faceRequester): Check font index. Updated. (Engine::Engine): Updated. (Engine::numberOfFaces, Engine::numberOfNamedInstances, Engine::loadFont, Engine::removeFont): Rewritten. (MainGUI::loadFonts, MainGUI::closeFont, MainGUI::showFont, MainGUI::adjustGlyphIndex, MainGUI::checkCurrentFaceIndex, MainGUI::checkCurrentNamedInstanceIndex): Simplified. (MainGUI::nextFace, MainGUI::nextNamedInstance, MainGUI::drawGlyph, MainGUI::setDefaults): Updated. 2016-05-15 Werner Lemberg [ftinspect] Minor issues. * src/ftinspect.cpp (Engine::loadFont): More readable code. (MainGUI::showFont): Remove no longer needed argument. Updated. (MainGUI::checkCurrentFontIndex, MainGUI::checkCurrentFaceIndex, MainGUI::checkCurrentNamedInstanceIndex): Minor generalization. * src/ftinspect.h (MainGUI): Updated. 2016-05-15 Werner Lemberg [ftinspect] Replace face ID hash with a map. We need this for later changes that will rely on ordered data. * src/ftinspect.cpp (FaceID::operator==): Replace with... (FaceID::operator<): ... this method. (qHash): Removed. (faceRequester, Engine::loadFont, Engine::removeFont, MainGUI::closeFont, MainGUI::showFont): Updated. * src/ftinspect.h (FaceID): Updated. (Main): Rename member `faceIDHash' to `faceIDMap'. 2016-05-15 Werner Lemberg [ftinspect] More variable and function renamings. Mainly for consistency. * src/ftinspect.cpp (faceRequester): s/faceID/ftcFaceID/, s/id/faceID/. (Engine::numberOfFaces): s/result/numFaces/. (Engine::numberOfNamedInstances): s/result/numNamedInstances/. (Engine::loadFont): s/instanceIndex/namedInstanceIndex/. (Engine::removeFont): s/face_id/ftcFaceID/, s/instanceIndex/namedInstanceIndex/. (MainGUI::showFont): s/numberOfFaces/currentNumberOfFaces/, s/numberOfNamedInstances/currentNumberOfNamedInstances/. Updated. (MainGUI::checkCurrentFaceIndex): s/numberOfFaces/currentNumberOfFaces/. (MainGUI::checkCurrentInstanceIndex): Renamed to... (MainGUI::checkCurrentNamedInstanceIndex): ...this. s/numberOfNamedInstances/currentNumberOfNamedInstances/. Updated. (MainGUI::nextFace): s/numberOfFaces/currentNumberOfFaces/. (MainGUI::nextInstance): Renamed to... (MainGUI::nextNamedInstance): ... this. s/numberOfNamedInstances/currentNumberOfNamedInstances/. (MainGUI::previousInstance): Renamed to... (MainGUI::previousNamedInstance): ...this. (MainGUI::createLayout, MainGUI::createConnections, MainGUI::setDefaults): Updated. * src/ftinspect.h (Engine): Updated. (MainGUI): s/nextInstanceButton/nextNamedInstanceButton/ s/previousInstanceButton/previousNamedInstanceButton/. 2016-05-14 Werner Lemberg [ftinspect] Remove file watching. This approach doesn't work well. A new, improved implementation will follow. * src/ftinspect.h (Engine): Remove `currentFontFileInfo', `currentFontFileDate', `maxRetries', and `currentRetry'. Updated. (MainGUI): Remove `timer'. Updated. * src/ftinspect.cpp (Engine::watchCurrentFont): Removed. (Engine::loadFont, Engine::update): Updated. (MainGUI::MainGUI): Updated. (MainGUI::watchCurrentFont): Removed. (MainGUI::createConnections): Updated. 2016-05-14 Werner Lemberg [ftinspect] Variable renaming. * src/ftinspect.cpp, src/ftinspect.h (FaceID): s/instanceIndex/namedInstanceIndex/. 2016-05-12 Werner Lemberg [ftinspect] Variable renamings. For consistency. * src/ftinspect.cpp, src/ftinspect.h: s/numFaces/numberOfFaces/, s/numNamedInstancesList/numberOfNamedInstancesList/, s/numNamedInstances/numberOfNamedInstances/, s/currentInstanceIndex/currentNamedInstanceIndex/. s/currentNumGlyphs/currentNumberOfGlyphs/. 2016-05-12 Werner Lemberg [ftinspect] Display more glyph and font information. * src/ftinspect.cpp (Engine::loadFont): Update `curFamilyName' and `curStyleName'. (Engine::currentFamilyName, Engine::currentStyleName, Engine::glyphName): New methods. (MainGUI::closeFont, MainGUI::showFont, MainGUI::adjustGlyphIndex, MainGUI::createLayout): Updated. * src/ftinspect.h (Engine): New members `curFamilyName' and `curStyleName'. Updated. (MainGUI): New `fontFilenameLabel', `fontNameLabel', and `glyphNameLabel' members. Use `QGridLayout' for `infoRightLayout'. 2016-05-12 Werner Lemberg [ftinspect] Fix logical mistakes in font navigation. * src/ftinspect.cpp (Engine::Engine): Initialize `ftSize'. (MainGUI::showFont): Don't let exceed indices the number of available index values if `preserveIndices' is active. Always call `engine->loadFont' even for invalid fonts so that various font-global variables are set correctly. 2016-05-11 Werner Lemberg [ftinspect] Minor. * src/ftinspect.cpp, src/ftinspect.h: s/Instances/NamedInstances/. Also display `Previous/Next Named Instance' on the buttons. 2016-05-11 Werner Lemberg [ftinspect] Minor. * src/ftinspect.cpp, src/ftinspect.h: s/fonts/fontList/. 2016-05-11 Werner Lemberg [ftinspect] Display glyph index. * src/ftinspect.cpp (MainGUI::createLayout): Add `infoLeftLayout' and `infoRightLayout' at the top of the window; add `glyphIndexLabel' to the right. (MainGUI::adjustGlyphIndex): Set text for `glyphIndexLabel' (MainGUI::setDefaults): Call `adjustGlyphIndex'. * src/ftinspect.h: Updated. 2016-05-11 Werner Lemberg [ftinspect] Only use integer values for size if units are px. * src/ftinspect.cpp (MainGUI::checkUnits): Implement it. (MainGUI::createLayout): Updated. 2016-05-11 Werner Lemberg [ftinspect] Add file watching; remove watch button. * src/ftinspect.cpp (Engine::loadFont): Initialize file info. (Engine::watchCurrentFont): New method. (Engine::update): Updated. (MainGUI::MainGUI): Set up timer. (MainGUI::showFont): Add parameter to control updating of current indices. (MainGUI::watchCurrentFont): New method. (MainGUI::createLayout): Remove watch button code. (MainGUI::createConnections): Handle timer. * src/ftinspect.h (Engine): Add `currentFontFileInfo', `currentFontDateTime', `maxRetries', and `currentRetry'. Updated. (MainGUI): Updated. 2016-05-10 Werner Lemberg * src/ftinspect.cpp, src/ftinspect.h (MainGUI): Provide `aboutQt'. This removes a warning at start-up. 2016-05-10 Werner Lemberg [ftinspect] Display rendered glyph bitmaps. * src/ftinspect.cpp (Engine::update): Updated. (GlyphBitmap::GlyphBitmap, GlyphBitmap::~GlyphBitmap, GlyphBitmap::boundRect, GlyphBitmap::paint): New methods for constructing a rendered bitmap of the glyph. (MainGUI::checkAntiAliasing): Updated. (MainGUI::setGraphicsDefaults): Create color mapping tables for 8bit and 1bit pixmaps as needed by Qt. (MainGUI::drawGlyph): Honor `show bitmap' check box. (MainGUI::createLayout, MainGUI::setDefaults): Updated. (MainGUI::createConnections): Handle `showBitmapCheckBox'. * src/ftinspect.h (GlyphBitmap): New class, derived from `QGraphicsItem'. (MainGUI): Mew member `currentGlyphBitmapItem'. New members `grayColorTable' and `monoColorTable'. Updated. (Engine): Remove unused `showBitmap' member. 2016-05-10 Werner Lemberg [ftinspect] Make hinting mode selection work. * src/ftinspect.cpp (Engine::loadFont): Set font type. (Engine::setCFFHintingMode, Engine::setTTInterpreterVersion): New methods. (MainGUI::showFont): Updated. (MainGUI::checkHinting): Gray out hinting mode combo box items depending on font type. (MainGUI::checkHintingMode): Implemented. (MainGUI::checkAutoHinting): Updated. (MainGUI::setDefaults): Updated. * src/ftinspect.h: Include some internal FreeType header files. (Engine): New member `fontType'. New enumeration `FontType'. Updated. (MainGUI): New members `currentCFFHintingMode' and `currentTTInterpreterVersion'. * ftinspect.pro (DEFINES): Add `FT2_BUILD_LIBRARY' to enable access to internal FreeType headers. 2016-05-10 Werner Lemberg [ftinspect] Minor. * src/ftinspect.cpp, src/ftinspect.h: Rename `point indices' to `point numbers'. 2016-05-10 Werner Lemberg [ftinspect] Display glyph point numbers. * src/ftinspect.cpp (GlyphPointNumbers::GlyphPointNumbers, GlyphPointNumbers::boundRect, GlyphPointNumbers::paint): New methods for constructing the set of glyph point numbers. (MainGUI::drawGlyph): Honor `glyph point indices' check box. (MainGUI::createLayout): Updated. (MainGUI::createConnections): Handle `showPointIndicesCheckBox'. * src/ftinspect.h (GlyphPoints): New class, derived from `QGraphicsItem'. (MainGUI): Mew member `currentGlyphPointNumbersItem'. Updated. 2016-05-09 Werner Lemberg [ftinspect] Display glyph points. Also fix other minor issues. * src/ftinspect.cpp (GlyphPoints::GlyphPoints, GlyphPoints::boundRect, GlyphPoints::paint): New methods for constructing the set of glyph points. (MainGUI::checkShowPoints, MainGUI::setGraphicsDefaults): Updated. (MainGUI::drawGlyph): Honor `glyph outlines' and `glyph points' check boxes. (MainGUI::createLayout): Updated. (MainGUI::createConnections): Handle `showOutlinesCheckBox'. (GlyphOutline::GlyphOutline): Improve computation of bounding rectangle. (Engine::update): Updated. * src/ftinspect.h (Engine): Remove unused members which are handled in MainGUI. (GlyphPoints): New class, derived from `QGraphicsItem'. (MainGUI): Mew member `currentGlyphPointsItem'. 2016-05-09 Werner Lemberg [ftinspect] Minor. * src/ftinspect.cpp, src/ftinspect.h: s/loadGlyph/loadOutline/. s/Glyph/GlyphOutline/. s/drawGlyphOutline/drawGlyph/. 2016-05-09 Werner Lemberg [ftinspect] Display glyphs outlines. * src/ftinspect.cpp (Engine::loadGlyph): New method. (moveTo, lineTo, conicTo, cubicTo): New wrapper functions for `QPainterPath' methods. (outlineFuncs): New structure, used as an interface to `FT_Outline_Decompose'. (Glyph::Glyph, Glyph::boundRect, Glyph::paint): New methods for constructing a glyph object. (MainGUI::drawGlyphOutline): New method. (MainGUI::showFont, MainGUI::checkUnits, MainGUI::adjustGlyphIndex, MainGUI::createLayout): Updated. (MainGUI::createConnections): Handle `sizeDoubleSpinBox' and `dpiSpinBox'. * src/ftinspect.h (Engine): Updated. (Glyph): New class, derived from `QGraphicsItem'. (MainGUI): New member `currentGlyphOutlineItem'. Updated. 2016-05-09 Werner Lemberg [ftinspect] Fix a bunch of glitches. * src/ftinspect.cpp (FaceID::FaceID): Initialize members with `-1'. While not needed, it better indicates an invalid lookup in the hash for debugging purposes. (Engine::Engine): Don't call `update' here, since `MainGUI::setDefaults' wasn't called yet. (Engine::loadFont): Call `update'. Return -1 for an invalid face ID. (Engine::removeFont): Properly handle invalid face ID. (Engine::update): Fix code reversal for pixels vs. points. (MainGUI::MainGUI): Initialize `engine'. (MainGUI::closeFont): First remove the font, then the face ID. Handle invalid font also. (MainGUI::showFont): Handle invalid font also. (MainGUI::setGraphicsDefaults): Set width of outline pen. 2016-05-08 Werner Lemberg [ftinspect] Display axes. * src/ftinspect.cpp (Grid::Grid): Add second parameter to pass axis pen. (Grid::paint): Add axes. Increase grid size. (Grid::boundingRect):Updated. (MainGUI::createLayout): Updated. * src/ftinspect.h: Updated. 2016-05-08 Werner Lemberg [ftinspect] Display grid. The dimensions are still arbitrary, though. We now need Qt 4.6 or newer. * src/ftinspect.h (Engine): Remove `zoom' member. It doesn't belong here. (Grid): New class, derived from `QGraphicsItem'. We need this to disable drawing of the grid if the zoom factor is too small. (MainGUI): Add a `QGraphicsScene' member. Add a `zoom' method. * src/ftinspect.cpp (Engine::update): Updated. (Grid::Grid, Grid::boundingRect, Grid::paint): New methods. (MainGUI::createLayout): Initialize `glyphView' and `glyphScene'; add a grid object. Change zoomSpinBox to display an integer zoom factor instead of a percentage. This simplifies code since we don't have to bother with scaling values < 1. (MainGUI::createConnections, MainGUI::setDefaults): Updated. 2016-05-08 Werner Lemberg [ftinspect] Provide some drawing pens. * src/ftinspect.h (MainGUI): Provide colored pens for axes, blue zones, grid lines, on and off points, outlines, and segment lines. * src/ftinspect.cpp (MainGUI::setGraphicsDefaults): New method. (MainGUI::MainGUI): Updated. 2016-05-07 Werner Lemberg [ftinspect] Make glyph navigation work. * src/ftinspect.cpp (MainGUI::showFont): Don't use local variable. (MainGUI::adjustGlyphIndex): New method. (MainGUI::createConnections): Use `QSignalMapper' class to map all navigation button signals to a single receiver function (namely `adjustGlyphIndex'). (MainGUI::setDefaults): Updated. * src/ftinspect.h (MainGUI): New `currentGlyphIndex' member. Updated. 2016-05-07 Werner Lemberg [ftinspect] Really load fonts. * src/ftinspect.cpp (Engine::loadFont, Engine::removeFont): New methods. (Engine::update): Set font-independent scaler values. (MainGUI::closeFont): Remove font ID from hash and font from cache. (MainGUI::showFOnt): Call `loadFont'. (MainGUI::setDefaults): Set initial value of `faceCounter' to 1 to circumvent a FreeType buglet. * src/ftinspect.h (Engine): New `scaler' and `ftSize' members. Updated. (MainGUI): New member `currentNumGlyphs'. 2016-05-07 Werner Lemberg * src/ftinspect.cpp (MainGUI::showFont): Another logic fix. 2016-05-07 Werner Lemberg [ftinspect] s/maxFaces/faceCounter/. * src/ftinspect.cpp, src/ftinspect.h: Do it. 2016-05-07 Werner Lemberg [ftinspect] Another try to implement `faceRequester'. * src/ftinspect.h (FaceID): Extend structure to make it suitable as key to Qt's `QHash' class. (qHash): Also needed for `QHash'. (MainGUI): Provide running ID number in `maxFaces'. New `faceIDHash' to map between (font,face,instance) index triplets and IDs. * src/ftinspect.cpp (FaceID::FaceID, FaceID::operator==, qHash): Implement. (faceRequester): Use `faceIDHash'. (MainGUI::showFont): Fill `faceIDHash'. (MainGUI::setDefaults): Updated. 2016-05-06 Werner Lemberg * src/ftinspect.cpp (MainGUI::showFont): Fix logic. 2016-05-06 Werner Lemberg [ftinspect] Simplify code. * src/ftinspect.cpp (MainGUI::createConnections, MainGUI::createActions): Use `connect' variant that doesn't need `this' parameter. 2016-05-06 Werner Lemberg [ftinspect] Compute load flags for `FT_Load_Glyph'. * src/ftinspect.cpp (Engine::update): Compute `doHinting' and `doAutoHinting', and `loadFlags'. * src/ftinspect.h (Engine): Updated. 2016-05-06 Werner Lemberg [ftinspect] Add general hinting check button. * src/ftinspect.cpp (MainGUI::checkHinting): New method. (MainGUI::createLayout, MainGUI::createConnections, MainGUI::setDefaults): Updated. (MainGUI::checkAutoHinting): Also handle `hintingModeLabel'. * src/ftinspect.h: Updated. 2016-05-06 Werner Lemberg [ftinspect] More gamma slider settings. * src/ftinspect.cpp (MainGUI::createLayout): Set gamma slider tick intervals. (MainGUI::setDefaults): Set default value for gamma slider. Also move other spin box default values to this function. 2016-05-06 Werner Lemberg [ftinspect] Handle LCD filter change. * src/ftinspect.cpp (MainGUI::checkLcdFilter): New method. (MainGUI::setDefaults): Set up LCD filter mapping. Call `checkLcdFilter'. (MainGUI::createConnections): Register `checkLcdFilter'. * src/ftinspect.h (MainGUI): Updated. 2016-05-06 Werner Lemberg [ftinspect] Indent `show point indices' check box. * src/ftinspect.cpp (MainGUI::createLayout): Implement it. * src/ftinspect.h: Updated. 2016-05-06 Werner Lemberg [ftinspect] Minor. * src/ftinspect.cpp (MainGUI::checkAutoHinting): Fix logic for warping check box. 2016-05-06 Werner Lemberg [ftinspect] Add check box for auto-hinting. This allows easier hinting mode switch than having it in the hinting mode combo box. * src/ftinspect.cpp (MainGUI::checkAutoHinting): New method, containing almost stuff from ... (MainGUI::checkHintingMode): Updated. (MainGUI::createLayout): Updated; we also indent check boxes dependent on auto-hinting. (MainGUI::createConnections, MainGUI::setDefaults): Updated. * src/ftinspect.h: Updated. (HintingModes): Remove `HintingMode_AutoHinting' enum value. 2016-05-06 Werner Lemberg [ftinspect] Disable unavailable items in anti-aliasing combo box. * src/ftinspect.h (MainGUI): Make `setDefaults' public. (hintingModesTrueTypeHash, hintingModesCFFHash): New maps. (hintingModesAlwaysDisabled): New list. * src/ftinspect.cpp (MainGUI::setDefaults): Set up mappings between GUI enumerations and FreeType property values. Use them to create `hintingModesAlwaysDisabled', a list of enum values that gets fed to the anti-alias combo box's `setItemDisabled' method. (MainGUI::MainGUI): Don't call `setDefaults' here but... (main): ... here, after FreeType initialization. 2016-05-05 Werner Lemberg [ftinspect] Handle engine properties. * src/ftinspect.cpp (Engine::Engine): Handle CFF's `hinting-engine', TrueType's `interpreter-version', and the auto-hinter's `warping' properties. * src/ftinspect.h (Engine): Updated. 2016-05-05 Werner Lemberg [ftinspect] Start implementation of `showFont'. * src/ftinspect.cpp (MainGUI::loadFonts): Call `showFont'. (MainGUI:closeFont): Fix logic and call `showFont'. (MainGUI::showFont): New method. Doesn't display something yet, but font navigation buttons are fully functional now. (MainGUI::previousFont, MainGUI::nextFont, MainGUI::previousFace, MainGUI::nextFace, MainGUI::previousInstance, MainGUI::nextInstance): Call `showFont'. * src/ftinspect.h (MainGUI): Updated. 2016-05-05 Werner Lemberg [ftinspect] Add methods to get number of faces and instances. * src/ftinspect.cpp (Engine::numFaces, Engine::numInstances): New methods. * src/ftinspect.h (Engine): Updated. 2016-05-05 Werner Lemberg [ftinspect] Minor. * src/ftinspect.cpp (faceRequester): Use reference. (MainGUI::loadFonts): Simplify. 2016-05-05 Werner Lemberg [ftinspect] Make `MainGUI' and `Engine' classes more symmetric. Also avoid `const' issues. * src/ftinspect.h (Engine): Add `gui' field. Updated. (MainGUI): Don't use `const' for `engine'. Updated. * src/ftinspect.cpp (Engine::Engine, Engine::update): Updated. (MainGUI::update, main): Updated. 2016-05-04 Werner Lemberg [ftinspect] Add buttons for instances. * src/ftinspect.cpp (MainGUI::checkCurrentInstanceIndex, MainGUI::previousInstance, MainGUI::nextInstance): New methods. (MainGUI::createLayout): Updated. We now use a grid layout for the font buttons. (MainGUI::createConnections, MainGUI::setDefaults): Updated. * src/ftinspect.h: Updated. 2016-05-04 Werner Lemberg [ftinspect] Redesign font handling. At this early stage, it's not always clear to me how to do things correctly, so here's another try. * src/ftinspect.h (Font): Redesigned, using a list of instance numbers. (FaceID): New structure, for communication with the face requester. (Engine): We need the `MainGUI' structure for initializing the face requester. (MainGUI): Make `faceRequester' a friend. Replace string list `fontFileNames' with `fonts', which is a list of `Font' elements. Add `currentInstanceIndex'. * src/ftinspect.cpp (faceRequester): Replace dummy code with something more serious. (Engine::Engine, Engine::update): Updated. (MainGUI::loadFonts, MainGUI::closeFont, MainGUI::checkCurrentFontIndex, MainGUI::checkCurrentFaceIndex, MainGUI::nextFont, MainGUI::nextFace): Updated to use new `fonts' member. (MainGUI::setDefaults, main): Updated. 2016-05-04 Werner Lemberg [ftinspect] Minor. * src/ftinspect.h, src/ftinspect.cpp: s/checkCurrentFontFileIndex/checkCurrentFontIndex/, s/currentFontFileIndex/currentFontIndex/. 2016-05-04 Werner Lemberg [ftinspect] Minor. * src/ftinspect.h (Engine): Add destructor. (MainGUI): Use point to `engine'. * src/ftinspect.cpp (Engine::~Engine): Implement. (MainGUI::update): Updated. 2016-05-04 Werner Lemberg [ftinspect] Better intertwine `Engine' and `MainGUI'. * src/ftinspect.cpp (MainGUI::update): New method. (main): Use it. * src/ftinspect.h (Engine): Make it a friend of `MainGUI'. (MainGUI): New member `engine'. Updated. 2016-05-04 Werner Lemberg * src/ftinspect.cpp (MainGUI::loadFonts): Improve logic. 2016-05-04 Werner Lemberg [ftinspect] Make `previous face' and `next face' button logic work. It still does nothing, though. * src/ftinspect.h (MainGUI): New slots `checkCurrentFaceIndex', `previousFace, and `nextFace'. New members `numFaces' and `currentFaceIndex'. * src/ftinspect.cpp (MainGUI::checkCurrentFaceIndex, MainGUI::previousFace, MainGUI::nextFace): New methods. (MainGUI::createConnections): Register connections for `previousFaceButton' and `nextFaceButton'. (MainGUI::setDefaults): Updated. 2016-05-04 Werner Lemberg * src/ftinspect.cpp (MainGUI::checkCurrentFontFileIndex): Fix logic. 2016-05-04 Werner Lemberg [ftinspect] Add buttons for faces. * src/ftinspect.cpp (MainGUI::createLayout): New buttons for `previous face' and `next face'; they are put into a separate row (`fontLayout') together with the buttons for `previous font' and `next font'. s/fontSizeLayout/sizeLayout/. * src/ftinspect.h: Updated. 2016-05-04 Werner Lemberg [ftinspect] Don't use size in pixels for navigation buttons. Instead, derive the width from the displayed text. * src/ftinspect.h (QPushButtonx): New class, derived from `QPushButton'. * src/ftinspect.cpp (QPushButtonx::QPushButtonx): New constructor. (MainGUI::createLayout): Use `QPushButtonx' for navigation buttons. 2016-05-03 Werner Lemberg [ftinspect] Make `previous font' and `next font' button logic work. * src/ftinspect.h (MainGUI): New slots `checkCurrentFontFileIndex', `previousFont, and `nextFont'. * src/ftinspect.cpp (MainGUI::checkCurrentFontFileIndex, MainGUI::previousFont, MainGUI::nextFont): New methods. (MainGUI::createConnections): Register connections for `previousFontButton' and `nextFontButton'. (MainGUI::loadFonts, MainGUI::closeFont, MainGUI::setDefaults): Updated. 2016-05-03 Werner Lemberg [ftinspect] Add file dialogs. * src/ftinspect.h: Include some more Qt headers. (MainGUI): Add `fontFileNames' and `currentFontFileIndex'. Add actions to load and close font files. * src/ftinspect.cpp (MainGUI::loadFonts, MainGUI::closeFont): New methods. (MainGUI::createActions, MainGUI::createMenus, MainGUI::setDefaults): Updated. 2016-05-03 Werner Lemberg [ftinspect] Better code. * src/ftinspect.h (QComboBoxx): New class, derived from `QComboBox'; we add one method `setItemEnabled' to enable (or disable) an item with a given index. (MainGUI): Use `QComboBoxx' for `antiAliasingComboBoxx' (was: `antiAliasingComboBox') and `hintingModeComboBoxx' (was: `hintingModeComboBox'). Update all users. * src/ftinspect.cpp (MainGUI::checkHintingMode): Simplified. (QComboBoxx::setItemEnabled): New method. 2016-05-03 Werner Lemberg [ftinspect] Start with FreeType initialization. * src/ftinspect.h: Include some FreeType headers. (Font): New structure for holding a (physical) font. (Engine): New class for communication with FreeType library. (MainGUI): Make `engine' a friend. * src/ftinspect.cpp (faceRequester): New function for FreeType's cache manager. (Engine::Engine, Engine::update): Some basic functions; to be extensively revised in later commits. (main): Updated. * src/ftinspect.pro: Add support for FreeType and dependent libraries. Right now, you have to adjust paths manually. 2016-05-02 Werner Lemberg [ftinspect] Minor. * src/ftinspect.h, src/ftinspect.cpp: s/showBitmapsCheckBox/showBitmapCheckBox/. 2016-05-02 Werner Lemberg [ftinspect] Adjust layout. * src/ftinspect.cpp (MainGUI::createLayout): Move size, dpi, and zoom stuff one row down. s/fontLayout/fontSizeLayout/. * src/ftinspect.h: Updated. 2016-05-02 Werner Lemberg [ftinspect] Add DPI control. * src/ftinspect.cpp (MainGUI::createLayout): Add `unitsComboBox' to select between px and pt. Add `dpiLabel' and `dpiSpinBox' to select the DPI value. (MainGUI::checkUnits): New function. (MainGUI::createConnections, MainGUI::setDefaults): Updated. * src/ftinspect.h: Updated. 2016-05-01 Werner Lemberg [ftinspect] Some more GUI initialization defaults. * src/ftinspect.cpp (MainGUI::setDefaults): Updated. 2016-05-01 Werner Lemberg [ftinspect] Avoid parameters for signal functions. This makes the code a bit more elegant. * src/ftinspect.cpp (MainGUI::checkHintingMode, MainGUI::checkAntiAliasing): Implement. (MainGUI::createConnections, MainGUI::setDefaults): Updated. * src/ftinspect.h: Updated. 2016-05-01 Werner Lemberg [ftinspect] Rename some enum values. * src/ftinspect.cpp, src/ftinspect.h: Updated. 2016-05-01 Werner Lemberg [ftinspect] Provide dummy default values for GUI initialization. * src/ftinspect.cpp (MainGUI::setDefaults): Set some values. 2016-05-01 Werner Lemberg [ftinspect] Add signal for showPointsCheckBox. * src/ftinspect.cpp (MainGUI::checkShowPoints): New function. (MainGUI::createConnections): Add signal. * src/ftinspect.h: Updated. 2016-05-01 Werner Lemberg [ftinspect] Add signal for antiAliasingComboBox. * src/ftinspect.cpp (MainGUI::checkAntiAliasing): New function. (MainGUI::createConnections): Add signal. * src/ftinspect.h: Updated. 2016-05-01 Werner Lemberg [ftinspect] Refine signal for hintingModeComboBox. * src/ftinspect.cpp (MainGUI::checkHintingMode): Grey out `slight' hinting item in antiAliasingComboBox if not in auto-hinting mode. Also set a different anti aliasing value for this case if `slight' was the current value. * src/ftinspect.h: Updated. 2016-05-01 Werner Lemberg [ftinspect] Add signal for hintingModeComboBox. Also fix typo `hortizontal' -> `horizontal'. * src/ftinspect.cpp (MainGUI::checkHintingMode): New function. (MainGUI::createConnections): Add signal. * src/ftinspect.h: Updated. 2016-05-01 Werner Lemberg [ftinspect] Improve combo box setup. * src/ftinspect.h (MainGUI): New enums `AntiAliasing', `HintingModes', and `LCDFilter'. * src/ftinspect.cpp (MainGUI::createLayout): Use new enums to set items in combo boxes. Also simplify computation of maximum width. 2016-04-30 Werner Lemberg * src/ftinspect.cpp (MainGUI::createLayout): Fix memory leak. 2016-04-30 Werner Lemberg [ftinspect] A new Qt based variant for ftgrid. GUI draft only. The idea is to eventually integrate the functionality of ftview, ftkern, and ftdiff also. The code compiles fine with both Qt4 and Qt5; it doesn't do anything yet beyond showing how the GUI looks like. * src/ftinspect.cpp, src/ftinspect.h: New source code files. * src/ftinspect.pro: New qmake input file. 2016-04-08 Werner Lemberg [ftview] Avoid hangs with bitmap only fonts. Problem reported by Hin-Tak Leung . * src/ftview.c (Render_Text, Render_Waterfall): Escape loop if not a single glyph could be rendered. 2016-03-18 Werner Lemberg * graph/x11/rules.mk (X11_LIB): Also append `/lib64'. 2016-03-02 Werner Lemberg [ftgrid] Use colors for dot numbers. We now have bitmap rendering also, and black numbers on a black background are ... not optimal. * src/ftgrid.c (grid_status_draw_outline): Implement it. 2016-03-01 Werner Lemberg [ftgrid] Exchange movement directions of `i' and `k' keys. This synchronizes the actions with its descriptions in the help screen. * src/ftgrid.c (Process_Event): Implement it. 2016-03-01 Werner Lemberg * src/ftgrid.c (grid_status_draw_outline): Fix memory leak. 2016-02-21 Alexei Podtelezhnikov [ftgrid] Touch up. * src/ftgrid.c (status): Initialize `header' as NULL to display font name initially. Use bits of new field `work' to control... (grid_status_draw_outline, main, Process_Event): Updated accordingly. * src/ftgrid.1: Updated. 2016-02-21 Werner Lemberg * src/ftgrid.c (event_grid_zoom): Make zoom up always work. 2016-02-21 Alexei Podtelezhnikov [ftgrid] Enable LCD filtering. * src/ftgrid.c (event_lcd_filter_change): New function. (status, main, Process_Event, event_help): Updated. 2016-02-20 Alexei Podtelezhnikov [ftgrid] Improve stroked path appearance. * src/ftgrid.c (grid_status_draw_outline): Hint scaled outline to follow gridlines and cover entire pixels. 2016-02-20 Alexei Podtelezhnikov [ftgrid] Display monochrome and LCD bitmaps. * src/ftgrid.c (grid_status_draw_outline): Rework to use... (bitmap_scale): New function that implements bitmap scaling. 2016-02-13 Alexei Podtelezhnikov [graph] Actually clear cache when full. * graph/gblender.c (gblender_lookup, gblender_lookup_channel): Updated. 2016-02-12 Alexei Podtelezhnikov [ftgrid] Display rendered bitmap (new feature). * src/ftgrid.c (status): New field to control new feature. (grid_status_draw_outline): Implement new feature here. (Process_Event, usage): Updated. 2016-02-10 Alexei Podtelezhnikov * src/ftgrid.c (grid_status_draw_outline): Use simpler line join. 2016-02-10 Alexei Podtelezhnikov [ftgrid] Use fixed-point scale and integer origin. * src/ftgrid.c (status): Change field types. (grid_status_init, grid_status_rescale_initial, grid_status_draw_grid, grid_hint_draw_segment, grid_status_draw_outline): Updated. 2016-02-07 Werner Lemberg * Version 2.6.3 released. ========================= Tag sources with `VER-2-6-3'. * README: Updated. * src/*.1: Updated. 2016-02-04 Alexei Podtelezhnikov * src/ftcommon.c (FTDemo_String_Draw): Typo. 2016-02-02 Alexei Podtelezhnikov * src/ftgrid.c, src/ftview.c, src/testname.c: Remove math.h. 2016-02-02 Alexei Podtelezhnikov [ftgrid] Fix dot position and shape. * src/ftgrid.c (circle_draw): Correct subpixel positioning. (ft_outline_new_circle): Correct circle approximation. 2016-02-01 Nikolaus Waxweiler [ftview] Fix toggling of `force auto-hinter' in light mode. Light mode does not imply auto-hinter anymore. * src/ftview.c (Process event) <'f'>: Update code. 2016-01-17 Alexei Podtelezhnikov * src/ftdiff.c (render_state_init): Update default LCD filter. 2016-01-14 Werner Lemberg Don't use macro names that start with `_[A-Z]' or contain `__'. Such macro names are reserved for both C and C++. * *.h: Harmonize ID macros so that file `foo.h' uses `FOO_H_'. * *.c: s/_Translator/Translator_'. * graph/x11/grx11.c (gr_x11_surface_init): s/_NET_WM_PID/NET_WM_PID/. * src/ftdiff.c: Replace structure names `_foo' with `foo_'. 2016-01-13 Alexei Podtelezhnikov [ftview] Cycle through available LCD filtering. * src/ftview.c (status, Process_Event): Implement cycle through `FT_LcdFilter'. 2016-01-11 Alexei Podtelezhnikov * src/ftview.c (status, Process_Event): Update default LCD filter. 2016-01-09 Alexei Podtelezhnikov [ftgamma] Provide alternative pattern. * src/ftgamma.c (do_ptrn, GammaPtrn): Implement slightly slanted anti-aliased lines. (Process_Event, event_help, main): Updated. * src/ftgamma.1: Updated. 2016-01-04 Alexei Podtelezhnikov [ftgamma] Enable color. * src/ftgamma.c (Render_GammaGrid): Split into... (Render_Bitmap): ... this renderer with color controls. (GammaGrid): ... and this grayscale bitmap builder. (event_color_change): New function. (Process_Event, event_help, main): Updated. * src/ftgamma.1: Updated. 2015-12-22 Alexei Podtelezhnikov [ftgamma] Minor refactoring. * src/ftgamma.c (Render_GammaGrid): Move labels from here... (main): ... to here. 2015-12-20 Alexei Podtelezhnikov Relocate gamma grid display from [ftview] to [ftgamma]. * src/ftview.c (Process_Event): Remove event `G'. (event_help): Update. (event_gamma_grid): Move to... * src/ftgamma.c (event_gamma_grid): ... here. (Process_Event): New function. (event_help): New function. (main): Update to handle events. 2015-12-18 Alexei Podtelezhnikov [ftstring, ftview] Auxiliary gamma rounding fixes. * src/ftstring.c (event_gamma_change): Updated. * src/ftview.c (event_gamma_grid): Updated. 2015-12-18 Alexei Podtelezhnikov * graph/gblender.c (gblender_set_gamma_table): Rounding, formatting. 2015-12-15 Werner Lemberg * src/ftgamma.c (do_fill): Fix compiler warning. 2015-12-14 Alexei Podtelezhnikov [ftgamma] Modernize appearance. * src/ftgamma.c: Major renovations. * src/ftgamma.1: Update. 2015-12-10 Werner Lemberg * src/ftcommon.c (FTDemo_Install_Font): Handle alloc/file errors. Problem reported by Alexei. 2015-12-09 Alexei Podtelezhnikov * src/ftstring.c (event_angle_change): Wrap angle differently. 2015-12-07 Alexei Podtelezhnikov [ftstring] Miscellaneous updates. * src/ftstring.c (event_gamma_change): Do not report gamma updates. (write_header): Permanently display gamma. (gamma_ramp_draw): Brighten the curve. 2015-12-06 Alexei Podtelezhnikov [graph] Small improvements. * graph/gblender.h (GBLENDER_SHADE_INDEX): Round to nearest grid. * graph/gblender.c (gblender_lookup, gblender_lookup_channel): Minor. 2015-12-05 Alexei Podtelezhnikov [graph] Unravel blending, part 2. * graph/gblender.c (gblender_reset_key, gblender_reset_channel_key): Set alpha grid values explicitly. 2015-12-03 Alexei Podtelezhnikov [graph] Unravel blending. * graph/gblender.c (gblender_reset_key, gblender_reset_channel_key): Entrust optimizations to modern compilers, remove unused variables. 2015-11-30 Werner Lemberg [graph] Initialize local variables after checking channel change. This fixes a crash if foreground color == background color. Problem reported by Alexei. * graph/gblender.h (GBLENDER_VARS): Split off initialization to... (GBLENDER_VARS_SET): ...this new macro. (GBLENDER_CHANNEL_VARS): Split off initialization to... (GBLENDER_CHANNEL_VARS_SET): ...this new macro. * graph/gblcolor.h, graph/gblhbgr.h, graph/gblhrgb.h, graph/gblvbgr.h, graph/gblvrgb.h: Updated. 2015-11-29 Alexei Podtelezhnikov * graph/gblender.c (gblender_clear): Fix typo. 2015-11-29 Alexei Podtelezhnikov * src/fttimer.c (main): Remove unused variable. 2015-11-28 Alexei Podtelezhnikov * src/ftcommon.c (FTDemo_Display_Clear): Speed up. 2015-11-28 Werner Lemberg * Version 2.6.2 released. ========================= Tag sources with `VER-2-6-2'. * README: Updated. * src/*.1: Updated. 2015-11-25 Alexei Podtelezhnikov [ftstring, ftview] Small clean-ups. * src/ftstring.c (event_lcdmode_change): Robustify the switch. * src/ftview.c (write_header): Ditto. 2015-11-25 Werner Lemberg * src/ftstring.c: Fix compilation warnings. 2015-11-24 Alexei Podtelezhnikov [ftstring] Enable sub-pixel rendering. * src/ftstring.c (event_lcdmode_change): New function. (Process_Event): New event to change LCD mode. (event_help): Offer it. (main): Select light LCD filter. 2015-11-22 Alexei Podtelezhnikov * src/ftstring.c (main): Move gamma curve in the background. 2015-11-22 Alexei Podtelezhnikov [ftstring] Enable changing display color. * src/ftstring.c (event_color_change): New function. (Process_Event) [grKeySpace]: New event to change color. (event_help): Offer it. (main): Updated. * src/ftstring.1: Updated. 2015-11-22 Alexei Podtelezhnikov [ftstring] Use shared `grSetGlyphGamma'. * src/ftcommon.h (FTDemo_String_Context): Remove `gamma_ramp'. * src/ftcommon.c (apply_gamma_ramp): Remove. (FTDemo_String_Draw): Do not apply gamma correction here. * src/ftstring.c (event_gamma_change): Call `grSetGlyphGamma' here. (main): Switch from gray to rgb24; update. 2015-11-22 Alexei Podtelezhnikov [ftstring] Remove gamma toggle. * src/ftstring.c (event_help, Process_Event): Updated. 2015-11-21 Alexei Podtelezhnikov Copy-paste typos. * src/ftstring.1: Updated. * src/ftstring.c: Updated. 2015-11-19 Alexei Podtelezhnikov Cosmetic improvements. * src/ftdiff.c (write_global_info): Do not display zero gamma. * src/ftgrid.c (event_gamma_change): Ditto. * src/ftview.c (write_header): Ditto. 2015-11-12 Alexei Podtelezhnikov * graph/gblender.c (gblender_reset_key): Fix typo. 2015-11-12 Alexei Podtelezhnikov Define and use GAMMA. * src/ftcommon.h (GAMMA): Define new macro. * src/ftdiff.c (adisplay_init): Use it. * src/ftgrid.c (grid_status_init): Use it. * src/ftstring.c (status): Use it. * src/ftview.c (status): Use it. 2015-11-11 Alexei Podtelezhnikov [ftdiff,ftgrid] Default to gamma = 1.8. * src/ftcommon.c (FTDemo_Display_New): Do not set gamma. * graph/grblit.c (gr_glyph_gamma): Updated. * src/ftdiff.c (adisplay_init): Updated. * src/ftgrid.c (grid_status_init): Updated. 2015-11-06 Alexei Podtelezhnikov [graph] Minor sRGB accuracy update. * graph/gblender.c (gblender_set_gamma_table): Updated. 2015-11-06 Alexei Podtelezhnikov [ftview,ftstring] Default to gamma = 1.8. * src/ftview.c (status): Updated. * src/ftstring.c (status, main): Updated. 2015-10-16 Werner Lemberg Don't use `aux' as a file name. This should be avoided under Windows. Problem reported by Dave Arnold . * src/aux.c, src/aux.h: Renamed to... * src/output.c, src/output.h: ... these file names. * Makefile, src/ftdump.c, src/ftgrid.c: Updated. 2015-10-04 Werner Lemberg * Version 2.6.1 released. ========================= Tag sources with `VER-2-6-1'. * README: Updated. * src/*.1: Updated. 2015-09-13 Werner Lemberg * Makefile (FT_H): Updated to recent directory changes (#45954). The patch is taken from the anonymous Savannah bug report. 2015-08-13 Werner Lemberg [ftcommon] Support named instances of GX variation fonts. * src/ftcommon.c (FTDemo_Install_Font): Add inner loop for named instances. 2015-08-05 Werner Lemberg [ftgrid] Avoid invalid left-shift of negative values. * src/ftgrid.c (grid_status_draw_outline): Don't use left-shift but multiplication. 2015-08-04 Werner Lemberg * src/ftmulti.c (main): Fix double-free in case of invalid font. 2015-07-08 Werner Lemberg [ftcommon] Improve loading of font collections. * src/ftcommon.c (FTDemo_Install_Font): Don't exit if first face of a font is invalid. Don't exit if we want outline fonts only and the first face isn't. Don't exit if there are problems with the cmap. In all three cases, simply skip the font face. 2015-06-07 Werner Lemberg * Version 2.6 released. ======================= Tag sources with `VER-2-6'. * README: Updated. * src/*.1: Updated. * Makefile: Omit a zero patch level in computation of `version'. 2015-06-06 Werner Lemberg [ftgrid] Key `D' now toggles display of point numbers. * src/ftgrid.c: Include FT_TRIGONOMETRY_H. (GridStatusRec): Add field `do_dotnumbers'. (grid_status_init): Updated. (grid_status_draw_outline): Implement point number display. (event_help): Updated. (Process_Event): Handle `D' key. (main): Updated. 2015-04-22 Werner Lemberg * src/ftdiff.c (process_event): Add missing `break' statement. 2015-04-21 Werner Lemberg [ftview] Key `w' now toggles warper (if compiled-in). * src/ftview.c (status): Add `warping' field. (event_help): Updated. (event_warping_change): New function. (Process_Event): Handle `w' key. (write_header, main): Updated. 2015-04-21 Werner Lemberg [ftgrid] Key `w' now toggles warper (if compiled-in). This replaces the no longer existing debugging hook with a generic solution that uses the `warping' auto-hinter module property. * src/ftgrid.c (_af_debug_disable_warper): Removed. (GridStatusRec): s/do_warp/warping/. (grid_status_init, grid_status_draw_outline, event_help): Updated. (event_warping_change): New function. (Process_Event): Handle `w', not `W', and use `event_warping_change'. (main): Updated. 2015-04-21 Werner Lemberg [ftdiff] Key `w' now toggles warper (if compiled-in). * src/ftdiff.c (render_mode_names): Updated. (ColumnStateRec): Add `warping' field. (render_state_init, render_state_draw, event_help): Updated. (process_event): Handle `w' key. 2015-04-19 Werner Lemberg [ftdiff] Correctly reload face after changing hinting engine. In most cases, calling `FT_Property_Set' acts globally on the FT_Library object. * src/ftdiff.c (RenderStateRec): Remove `need_rescale', since we always rescale now after reloading the face. Update all users. (render_state_set_face_index): New function. (render_state_set_file): Remove `idx' argument. Instead, (re)load font with index `state->face_index'. (render_state_draw): Call `render_state_set_file'. (event_change_face_index): New function. (process_event): s/render_state_set_file/event_change_face_index/. (main): Updated. 2015-04-18 Werner Lemberg [ftgrid] Show advance width. * src/ftgrid.c (grid_status_draw_outline): Display vertical line at advance width position. 2015-04-16 Werner Lemberg [ftgrid] Key `W' now toggles warper (if compiled-in). * src/ftgrid.c [FT_DEBUG_AUTOFIT]: New extern variable `_af_debug_disable_warper'. (GridStatusRec): Add `do_warp' member. (grid_status_init): Updated. (grid_status_draw_outline): Set `_af_debug_disable_warper'. (event_help): Updated. (Process_Event): Handle `W' key. 2015-04-16 Werner Lemberg [ftgrid] Make blue zone toggling actually work. * src/ftgrid.c (grid_status_draw_outline) [FT_DEBUG_AUTOFIT]: Set `_af_debug_disable_blue_hints'. 2015-04-16 Werner Lemberg * src/ftgrid.c (Process_Event) <' '>: Don't reset debugging flags. 2015-04-16 Werner Lemberg [ftgrid] Cycle through AA rendering modes with F5 and F6. * src/ftgrid.c (event_lcd_mode_change): New function. (Process_Event) [FT_DEBUG_AUTOFIT]: Enable debug stuff for light AA mode also. Handle `F5' and `F6' keys. (event_help): Updated. 2015-04-14 Werner Lemberg [ftgrid] Fix memory leak. * src/ftgrid.c (event_font_change): Free `status.mm' before calling `FT_Get_MM_Var' (again). 2015-04-14 Werner Lemberg [ftgrid] Show proper names for GX axes. * src/ftgrid.c: Include `aux.h', FT_SFNT_NAMES_H, and FT_TRUETYPE_IDS_H. (GridStatusRec): Add `axis_name' array. (event_font_change): Set GX axis name if possible. (write_header): Use `axis_name' if non-NULL. (main): Add clean-up code for `axis_name' array. 2015-04-14 Werner Lemberg [aux] Add functions for outputting strings. * src/aux.c (hexdigit): New static array. (put_ascii_string, put_ascii_string_size, put_unicode_be16_string, put_unicode_be16_string_size): New functions. (put_ascii, put_unicode_be16): Use new functions to implement it. * src/aux.h: Updated. 2015-04-14 Werner Lemberg Move some output functions to a separate file. * src/aux.c, src/aux.h: New files, holding `put_ascii' and `put_unicode_be16' from... * src/ftdump.c: ... this file, which now includes `aux.h'. * Makefile (COMMON_OBJ): Add `aux.c'. Fix rule. 2015-04-11 Werner Lemberg [ftbench] Check unscaled advance widths also. * src/ftbench.c (main) : Add test. 2015-04-05 Werner Lemberg [ftdump] Simplify code. * src/ftdump.c (put_unicode_be16_as_utf8): Fold into... (put_unicode_be16): This function, with an additional argument. Update all callers. 2015-04-03 Werner Lemberg [ftdump] Remove dead code. * src/ftdump.c (debug, trace_level): Remove. (usage): Remove #ifdef'ed code. (main): Don't handle obsolete options `-d' and `-l'. Remove #ifdef'ed code. 2015-04-03 Werner Lemberg [ftdump] Add option `-u' to emit data in UTF-8 encoding. * src/ftdump.c (utf8): New global variable. (usage): Updated. (put_unicode_be16): Only emit characters < 0x80 as-is. (put_unicode_be_as_utf8): New function. (Print_Sfnt_Names, Print_MM_Axes): Use it. (main): Handle new option `-u'. * src/ftdump.1: Updated. 2015-04-02 Werner Lemberg [ftmulti] Make the first six axes accessible. We now use keys F1-F6 and 1-6. F7 and F8 get its original function back (this is, adjusting the glyph index by 10). * src/ftmulti.c (MAX_MM_AXES): New macro. Replaces `T1_MAX_MM_AXIS' everywhere. (Render_All): Adjust vertical position depending on number of axes. (Help): Updated. (Process_Event): Handle new keys. (main): Use two lines for axes if we have more than three. 2015-04-01 Werner Lemberg [ftgrid] Fix minor memory leak. * src/ftgrid.c (GridStatusRec): Add `stroker' field. (grid_status_draw_outline): Updated. (main): Call `FT_Stroker_Done'. 2015-03-30 Werner Lemberg [ftdump] Show proper names for GX axes. * src/ftdump.c (Print_MM_Axes): Try to find and display English versions of the GX axis names (stored in the `name' table) instead of 4-letter tags. 2015-03-29 Werner Lemberg [ftgrid, ftmulti]: Handle GX fonts with more than 4 axes. ftgrid now handles up to 32 axes, while ftmulti will ignore all axes but the first four. * src/ftgrid.c (MAX_MM_AXES): New macro. (GridStatusRec): New field `used_num_axis'. (event_axis_change, event_font_change, Process_Event): Use it. * src/ftmulti.c (used_num_axis): New global variable. (Process_Event, main): Use it. 2015-03-29 Werner Lemberg [ftdump] Display info about MM axes. * src/ftdump.c: Include FT_MULTIPLE_MASTERS_H. (Print_MM_Axes): New function. (main): Use it. 2015-03-19 Werner Lemberg [ftdump] Various minor improvements. * src/ftdump.c (name_id): Handle WWS entries also. Return NULL for not pre-defined entries. (put_ascii): Display characters >= 0x80 as hex escape sequence. (Print_Sfnt_Names): Improve output. 2015-03-11 Werner Lemberg Update to latest FreeType library changes. * src/ftcommon.c: s/FT_XFREE86_H/FT_FONT_FORMATS_H/. (my_face_requester): s/FT_Get_X11_Font_Format/FT_Get_Font_Format/. 2015-03-07 Werner Lemberg * src/ftvalid.c: Various minor compiler warning fixes. 2015-03-07 Werner Lemberg * src/ftview.c: Various minor compiler warning fixes. * src/ftcommon.c, src/ftcommon.h (FTDemo_Draw_Index): Change type of `gindex' to unsigned. 2015-03-07 Werner Lemberg * src/ftstring.c: Various minor compiler warning fixes. 2015-03-07 Werner Lemberg [ftmulti] Various minor compiler warning fixes. * src/ftmulti.c: Fix signedness issues. Add `static' keyword where appropriate. (CENTER_X, CENTER_Y, autorun, use_grays, raster_buff, FLOOR, CEIL, TRUNC): Removed. Unused. 2015-03-06 Werner Lemberg [ftgrid] Various minor compiler warning fixes. * src/ftgrid.c: Fix signedness issues. (event_axis_change, event_font_change): Avoid variable shadowing. (CEIL, X_TOO_LONG, Y_TOO_LONG): Removed. Unused. 2015-03-06 Werner Lemberg * src/ftgamma.c: Various minor compiler warning fixes. 2015-03-06 Werner Lemberg [ftcommon] Various minor compiler warning fixes. * src/ftcommon.c: Fix signedness issues. (my_face_requester): Remove dead code. (FTDemo_Install_Font): Protect against stream failure. (string_render_prepare): Add `static' keyword. * src/ftcommon.h: Updated. 2015-03-05 Werner Lemberg * src/ftdiff.c: Various minor compiler warning fixes. 2015-03-05 Werner Lemberg [graph] Many compiler warning fixes. * graph/*, graph/x11/*: Fix signedness issues. Unified handling of unused variables. Add `static' keyword where appropriate. Include `foo.h' into `foo.c' where appropriate. * graph/grobjs.c, graph/grobjs.h (grRealloc): Removed. Unused. 2015-03-04 Werner Lemberg [ttdebug] Various compiler warning fixes. * src/ttdebug.c: Decorate global variables/functions with `static'. Signedness fixes. (main): Protect various command line arguments against invalid values. 2015-03-04 Werner Lemberg * src/ftlint.c: Various minor compiler warning fixes. 2015-03-04 Werner Lemberg * src/ftdump.c: Various minor compiler warning fixes. 2015-03-04 Werner Lemberg [ftbench] Various compiler warning fixes. * src/ftbench.c: Decorate global variables/functions with `static'. Signedness fixes. (main): Protect various command line arguments against invalid values. 2015-03-03 Werner Lemberg [ftgrid] Add support for MM (and GX) fonts. F2 selects the axis, F3 and F4 change the axis value. The new code is adapted from `ftmulti.c'. * src/ftgrid.c: Include FT_MULTIPLE_MASTERS_H. (GridStatusRec): Add `mm', `design_pos', and `current_axis' fields. (grid_status_init): Initialize new fields. (event_help): Updated. (event_axis_change): New function. (event_font_change): Handle MM data. (Process_Event): Handle new keys. (write_header, main): Updated. 2015-03-03 Werner Lemberg [ftgrid] Less verbose header line. * src/ftgrid.c (BUFSIZE): New macro. (GridStatusRec, event_help): Use it. (write_header): Use it. Emit more compact header line. 2015-03-03 Werner Lemberg * src/ftmulti.c (main): Always display 1/100ths for axis values. 2015-03-03 Werner Lemberg [ftmulti] Use F1-F8 keys to handle four axes. Previously, we used F1 for help and F3-F8 for three axes. * src/ftmulti.c (Process_Event): Implement. (Help): Updated. 2015-03-03 Werner Lemberg Recommend `?' instead of `F1' for help. Usually, both `F1' and `?' map to the help screen. However, not all display managers provide the F1 key to the application. * src/ftdiff.c (main), src/ftgrid.c (main), src/ftmulti.c (main), src/ftstring.c (main), src/ftview.c (main): Apply. 2014-12-30 Werner Lemberg * Version 2.5.5 released. ========================= Tag sources with `VER-2-5-5'. * README: Updated. * src/*.1: Updated. * Makefile (dist): Fix typos. 2014-12-11 Werner Lemberg * Makefile (dist): Use older POSIX standard for `tar'. Apparently, BSD tar isn't capable yet of handling POSIX-1.2001 (contrary to GNU tar), so force the POSIX-1.1988 format. Problem reported by Stephen Fisher . 2014-12-06 Werner Lemberg * Version 2.5.4 released. ========================= Tag sources with `VER-2-5-4'. * README: Updated. * src/*.1: Updated. 2014-11-22 Werner Lemberg Show FreeType version in demo program help screens. * src/ftdiff.c (event_help), src/ftgrid.c (event_help), src/ftmulti.c (Help), src/ftstring.c (event_help), src/ftview.c (event_help): Implement it. 2014-05-11 Werner Lemberg Fix Savannah bug #42182. * src/ttdebug.c (main): Fix typos. 2014-03-06 Werner Lemberg * Version 2.5.3 released. ========================= Tag sources with `VER-2-5-3'. * README: Updated. * src/*.1: Updated. 2014-03-04 Werner Lemberg * Makefile (LINK_LIBS) [unixdev]: Don't use pkg-config for bzip2. Not all platforms have `bzip2.pc'. We also add `-lz' just for completeness. 2014-01-30 Werner Lemberg [ftbench] Allow `-s 0' for better testing of FT_LOAD_NO_SCALE. * src/ftbench.c (main) <'s'>: Don't alter value 0. Don't call `FT_Set_Pixel_Sizes' for size == 0. Don't call tests for size == 0 that need valid scaling factors. (usage): Updated. (benchmark): Return meaningful timer value for error-only calls. (test_embolden): Enable test. I think there is no longer a reason to not run it. * src/ftbench.1: Updated. 2014-01-28 Werner Lemberg * src/ftgrid.c (grid_status_rescale_initial): Avoid NaN values. Remove forgotten debug message. 2014-01-28 Werner Lemberg * graph/grblit.c (grBlitGlyphToBitmap): Don't crash on empty glyphs. Problem reported by Dave Arnold . 2014-01-03 Werner Lemberg [ftgrid] Show (some) blue zones. * src/ftgrid.c (af_glyph_hints_get_segment_offset): Update prototype. (GridStatusRec): New member `blue_color'. (grid_status_display): Change `on' color to red. Set `blue' color. (grid_hint_draw_segment): Show associated blue zones. (event_help): Updated. 2014-01-03 Werner Lemberg [ftgrid] Minor. * src/ftgrid.c (GridStatusRec): Rename `conic_color' to `off_color'. Remove unused `cubic_color' member. (grid_status_display, grid_status_draw_outline): Updated. 2013-12-22 Werner Lemberg * Makefile (LINK_LIBS) [unixdev]: Use pkg-config to get link flags. This corresponds to a similar change in current FreeType to link with HarfBuzz in development mode. 2013-12-08 Werner Lemberg * Version 2.5.2 released. ========================= Tag sources with `VER-2-5-2'. * README: Updated. * src/*.1: Updated. 2013-11-27 Werner Lemberg [ftgrid] Fix compilation in non-debug mode. * src/ftgrid.c: Guard autofit dump functions with FT_DEBUG_AUTOFIT clause. Update prototypes. (grid_hint_draw_segment): Guard with FT_DEBUG_AUTOFIT clause. (grid_status_draw_outline): Guard call to `grid_hint_draw_segment' with FT_DEBUG_AUTOFIT clause. (Process_Event) <'1'>, <'2'>, <'3'>: Don't mess around with trace levels, which should always stay internal to the FreeType library. Update calls to dump functions. 2013-11-25 Werner Lemberg * Version 2.5.1 released. ========================= Tag sources with `VER-2-5-1'. * README: Updated. * src/*.1: Updated. 2013-11-21 Werner Lemberg [ftgrid] Make keys `1', `2', and `3' work again. * src/ftgrid.c (Process_Event) <'1'>, <'2'>, <'3'>: Set `trace_afhints' trace level to value 7 temporarily since the autofit dumping functions use `FT_TRACE7' since 2012-07-06. 2013-11-21 Werner Lemberg [ftgrid] Fix compilation with C++. * src/ftgrid.c (_af_debug_*): Add `extern' keyword. 2013-11-20 Werner Lemberg Increase file path size. * src/compos.c (main), src/ftchkwd.c (main), src/ftdump.c (main), src/ftlint.c (main), src/ftmemchk.c (main), src/ftsbit.c (main), src/fttimer.c (main), src/fttry.c (main): Increase array size of `filename' and `alt_filename' to 1024. 2013-11-13 Werner Lemberg * Makefile (FT_H): Update to new header layout of FreeType. 2013-11-05 Werner Lemberg [ttdebug] Improve display of point tags. * src/ttdebug.c (old_tag_to_new): Removed, no longer used. (display_changed_points, show_points_table): Display tags with mnemonic characters instead of ORed numbers. (RunIns) <'h'>: Updated. 2013-11-05 Werner Lemberg [ttdebug] Enable debugging of composite glyphs (again). This was lost while improving key handling. * src/ttdebug.c (RunIns): Introduce variable `really_leave' to insert one stop before really leaving the current glyph range. Without that, inspecting the current data right after finishing the hinting of a subglyph wouldn't be possible. (main): Stay in loop even if `FT_Load_Glyph' returns zero. 2013-11-04 Werner Lemberg [ttdebug] Provide man page and compile program by default. * Makefile (EXES): Add `ttdebug'. * src/ttdebug.1: New file. 2013-11-01 Werner Lemberg [ttdebug] Make `B' emit a function backtrace. This needs the today's version of the FreeType library. * src/ttdebug (RunIns) <'h'>: Updated. <'B'>: Print backtrace. 2013-11-01 Werner Lemberg [ttdebug] Make `p' set a breakpoint at previous position. * src/ttdebug.c (RunIns): Store information about last position in `last_IP' and `last_range'. <'h'>, <'c'>, <'f'>, <'n'>, <'s'>: Updated. <'p'>: Set breakpoint at previous instruction. 2013-10-31 Werner Lemberg [ttdebug] Minor. * src/ttdebug.c: Make full-sentence messages where appropriate. (RunIns): Make help screen more compact vertically. 2013-10-31 Werner Lemberg [ttdebug] Make `b' set a breakpoint. * src/ttdebug.c (Breakpoint): New structure. (RunIns): Handle breakpoint. <'h'>, <'c'>, <'f'>, <'n'>: Updated. <'b'>: Set breakpoint. 2013-10-31 Werner Lemberg [ttdebug] Improve help; add key `h' to show it. * src/ttdebug.c (RunIns) <'?'>: Update and redesign help screen. <'h'>: Same as key `?'. (main): Show version string and help info at start-up. 2013-10-31 Werner Lemberg [ttdebug] Make key `R' restart the debugger. * src/ttdebug.c (Restart): New macro. (RunIns) <'Q'>: Set `pedantic_hinting' flag. <'R'>: Set error to `Restart'. (main): Add loop. 2013-10-30 Werner Lemberg [ttdebug] Make key `f' finish current function. Change old `f' key to `F'. * src/ttdebug.c (RunIns) <'f'>: Renamed to ... <'F'>: ... this. <'f'>: Loop until current function is finished. <'?'>: Updated. 2013-10-28 Werner Lemberg Add manual pages. Originally contributed (but heavily modified) by Nis Martensen . * src/ftbench.1, src/ftdiff.1, src/ftdump.1, src/ftgamma.1, src/ftgrid.1, src/ftlint.1, src/ftmulti.1, src/ftstring.1, src/ftvalid.1, src/ftview.1: New files. 2013-10-28 Werner Lemberg [ftbench, ftmulti, ftvalid] Improve and correct usage output. This commit also changes key mappings in ftvalid ('L' -> 'l', 'v' -> 'V'), adds option -v to display the version, and removes dead code. * src/ftbench.c (bench_desc): Fix typo. * src/ftmulti.c (usage): Do it. * src/ftvalid.c (validators, print_usage): Do it. (main): Updated. 2013-10-27 Werner Lemberg * src/ttdebug.c (main, RunIns): Fix memory leaks. 2013-10-26 Werner Lemberg [ttdebug] Display storage are data; key 'S' shows all of them. * src/ttdebug.c (Storage): New structure. We need to handle storage area data specially since we have to make a distinction between initialized and uninitialized values. (handle_WS): New function. Since it is not necessary for the bytecode interpreter to trace whether a value is uninitialized or not, we have to do it manually right before every debugging step. (RunIns): After executing a step, storage area data different to before is displayed. <'?'>: Help updated. <'S'>: Show storage area data. <'c'>, <'s'>, <'n'>: Call `handle_WS'. 2013-10-26 Werner Lemberg [ttdebug] Fix code range detection. * src/ttdebug.c (RunIns): The `code_range' string identifies the code range where `RunIns' has been called, so it's best to use it throughout the code for this purpose. <'C'>, <'P'>, <'S'>: Updated accordingly. (show_points_table): Updated accordingly. 2013-10-25 Werner Lemberg [ttdebug] Display CVT data; key `C' shows all Control Values. * src/ttdebug.c (RunIns): New array `save_cvt'. After executing a step, CVT data different to before is displayed. <'C'>: Show CVT data. <'?'>: Help updated. 2013-10-25 Werner Lemberg [ttdebug] Change some key assignments from lowercase to uppercase. * src/ttdebug.c (RunIns) <'v'>: Use 'V' instead. <'g'>: Use 'G' instead. <'p'>: Use 'P' instead. <'t'>: Use 'T' instead. <'q'>: Use 'Q' instead. <'?'>: Help updated. 2013-10-25 Werner Lemberg * src/ttdebug.c (RunIns) <'n'>: Handle ranges correctly. 2013-10-16 Werner Lemberg * src/ttdebug.c (RunIns): Handle `Enter' key correctly. 2013-10-16 Werner Lemberg [ttdebug] Display twilight data; key `t' shows twilight point table. * src/ttdebug.c (display_changed_points, show_points_table): Pass flag for twilight zone and handle it accordingly. (RunIns): Track twilight data. Handle key `t'. Update help. 2013-10-16 Werner Lemberg [ttdebug] Some refactorization. * src/ttdebug.c (display_changed_points, show_points_table): New functions, extracted from... (RunIns): ... this one. 2013-10-16 Werner Lemberg * src/ttdebug.c: s/save/save_pts/. 2013-10-16 Werner Lemberg [ttdebug] Display improvements. * src/ttdebug.c (exec): Removed, unused. (RunIns): Increase size of `temp' buffer. Display negative hex numbers. Correctly display hex numbers with more than 4 digits. (RunIns) <'g'>: Display interpreter version. 2013-10-09 Werner Lemberg * src/ftview.c (Render_Waterfall): Avoid `%n' in `snprintf'. MSVC disables this by default, and compilation would fail otherwise. 2013-09-28 Dave Arnold * src/ftdiff.c (Process_Event) <'H'>: Fix typo. If FT_DEBUG_AUTOFIT is false, then the command `H' had a side-effect of decrementing the glyph index. 2013-09-23 Werner Lemberg [ftdiff] Improve text display at small sizes. * src/ftdiff.c (render_state_draw): Loop over the text. This also avoids problems if the .notdef character has zero width (for whatever reasons). 2013-07-21 Behdad Esfahbod * src/ftcommon.c (FTDemo_Index_To_Bitmap): Add BGRA support. 2013-07-21 Werner Lemberg * graph/rules.mk (GRAPH_H): Add missing files. 2013-07-21 Behdad Esfahbod * src/ftcommon.c (FTDemo_Index_To_Bitmap): Remove unneeded code. 2013-07-21 Behdad Esfahbod [graph] Fix BGRA blending. * graph/gblbgra.h: Simplify and correct blending operation. 2013-07-20 Werner Lemberg Fix Savannah bug #39537. */* s/FALSE/0/, s/TRUE/1/. 2013-07-20 Werner Lemberg Improve font loading. In particular, avoid a crash in ftgrid for fonts without outlines. * src/ftcommon.c (FTDemo_Install_Font): Provide argument to load fonts with outlines only. * src/ftcommon.h, src/ftview.c, src/ftstring.c: Updated. * src/ftgrid.c (main): Updated. Emit warning message for skipped fonts. 2013-07-05 Werner Lemberg [ftbench] Be more verbose in reporting results. * src/ftbench.c (benchmark): Indent trace output. (usage): Minor improvement. (main): Add some option value guards. Print information on test setup. 2013-07-02 Werner Lemberg [ftbench] Improve `usage' text. * src/ftbench.c (default_hinting_engine, default_interpreter_version): New global variables. (usage): Improve text for `-H' and `-f'. (main): Updated. 2013-06-26 Werner Lemberg [ftgrid] Implement CFF and TTF engine change support. Key `H' toggles this. * src/ftgrid.c: Include FT_MODULE_H, FT_INTERNAL_OBJECTS_H, FT_INTERNAL_DRIVER_H, FT_CFF_DRIVER_H, and FT_TRUETYPE_DRIVER_H. (N_CFF_HINTING_ENGINES): Define macro. (GridStatusRec): Add `cff_hinting_engine' and `tt_interpreter_version'. (event_help): New layout similar to ftview. (event_cff_hinting_engine_change, event_tt_interpreter_version_change): New functions. (Process_Event): Extend handling of `H' key. (main): Get default properties of CFF and TTF drivers. 2013-06-26 Werner Lemberg * src/ftview.c (event_help): Mention `q' and `ESC' keys. 2013-06-19 Werner Lemberg * Version 2.5.0 released. ========================= Tag sources with `VER-2-5-0'. * README: Updated. 2013-06-12 Werner Lemberg [ftbench] Allow arbitrary sizes. * src/ftbench.c (main): Remove size limit. 2013-06-10 Werner Lemberg [ftview] Use key `K' for toggling small cache. Key `C' is already in use. * src/ftview.c (Process_Event) <'C'>: Replace with... <'K'>: This key. Add missing `break'. (event_help): Updated. 2013-06-09 Werner Lemberg [ttdebug] Add command `f' to select number format. * src/ttdebug.c (use_float): New global variable. (RunIns): Add `f' key to toggle between floating and fixed point number formats. Update all affected print commands. 2013-06-09 Werner Lemberg [ttdebug] Add command `l', improve help and output. * src/ttdebug.c (RunIns): Display message if entering a new code range. Improve output of `?' and `p' keys. Add `l' key to show last bytecode instruction. 2013-06-09 Werner Lemberg [ttdebug] Add command line option `-H' to select hinting engine. * src/ttdebug.c: Include FT_TRUETYPE_DRIVER_H. (default_version, alternative_version): New global variables. (Usage): Updated. (main): Handle option `-H'. 2013-06-09 Werner Lemberg [ftview] Fix cache handling. * src/ftview.c (event_cff_hinting_engine_change, event_tt_interpreter_version_change): Reset the cache to flush the glyph image cache. Otherwise, the cache lookup functions get confused since info about module properties is not stored in the glyph cache nodes. 2013-06-03 Werner Lemberg [ftview, ftdiff, ftbench] Update CFF and TT property handling. * src/ftbench.c (main): Make option `-H' use the non-default properties and warning if there is a problem. * src/ftdiff (render_state_init): At startup, use default properties. (process_event) <'H'>: Do nothing if non-default `hinting-engine' property is not available. * src/ftview.c (event_cff_hinting_engine_change): Do nothing if non-default `hinting-engine' property is not available. (Process_Event) <'H'>: Updated. (main): At startup, use default properties. 2013-05-22 Behdad Esfahbod Add support for color glyphs. In ftview, key `c' toggles color, while use of sbits cache is now mapped to key `C'. The premultiplied bgra blending is still off. * graph/gblany.h (_gblender_blit_bgra_): New template. * graph/graph.h (grPixelMode): Add gr_pixel_mode_bgra. * graph/gblblit.h (GBlenderSourceFormat): Add GBLENDER_SOURCE_BGRA. * graph/gblblit.c (gblender_blit_init): Handle GBLENDER_SOURCE_BGRA. * graph/grblit.c (grBlitGlyphToBitmap): Updated. * graph/gblbgra.h: New header file. * src/ftcommon.h (FTDemo_Handle): New member `color'. * src/ftcommon.c (FTDemo_New, FTDemo_Update_Current_Flags): Updated. (FTDemo_Glyph_To_Bitmap): Handle FT_PIXEL_MODE_BGRA. * src/ftview.c (Process_Event) <'c'>: Handle color. <'C'>: Handle sbits cache. (help): Updated. (write_header): Updated. * Makefile (LINK_LIBS): Add -lpng. 2013-05-17 Werner Lemberg [ftview, ftdiff, ftbench] Support `interpreter-version' property. * src/ftbench.c: Include FT_TRUETYPE_DRIVER_H. (usage): Updated. (main): Update `-H' option. * src/ftdiff.c: Include FT_TRUETYPE_DRIVER_H. s/hinting_engine/cff_hinting_engine/. (ColumnStateRec): Add `tt_interpreter_version' member. (render_state_init, render_state_draw): Updated. (event_help): Updated. (process_event) <'H'>: Handle new property. * src/ftview.c: Include FT_TRUETYPE_DRIVER_H. s/hinting_engine/cff_hinting_engine/. s/HINTING_ENGINES/CFF_HINTING_ENGINES/. (status): Add `tt_interpreter_version' member. (event_tt_interpreter_version_change): New function. (Process_Event) <'H'>: Use it. (write_header): Updated. (main): Set default value for `interpreter-version'. 2013-05-13 Sebastien Bacher * src/ftview.c (write_header): Fix uninitialized variables. 2013-05-08 Werner Lemberg * Version 2.4.12 released. ========================== Tag sources with `VER-2-4-12'. * README: Updated. * src/x11/grx11.c: s/read/lread/, s/write/lwrite/ where appropriate to avoid variable shadow warnings. 2013-05-03 Werner Lemberg [ftbench] New command line option `-H' to select Adobe's CFF engine. * src/ftbench.c: Include FT_MODULE_H and FT_CFF_DRIVER_H. (main): Handle `H' key. (usage): Updated. 2013-04-27 Werner Lemberg [ftview] Don't show encoding in `text' and `waterfall' modes. Those two modes always use UTF-8 (or rather, they use FTDemo_Get_Index). * src/ftview.c (write_header): Implement it. 2013-04-26 Werner Lemberg [ftview] Allow engine change for non-hinted modes also. This is useful to demonstrate the stem darkening of the Adobe's CFF engine. * src/ftview.c (Process_Event) <'H'>, (write_header): Adjust conditions. 2013-04-23 Werner Lemberg [ftview] Improve waterfall and text mode. * src/ftview.c (status): New member `topleft'. (Text): Convert string to UTF-8 encoding. Now the whole string is displayed again. (Render_Stroke, Render_Slanted, Render_Embolden, Render_All): Set `status.topleft' to the first offset which gets really displayed. (Render_Text, Render_Waterfall): Set `status.topleft' to the first offset which gets really displayed. If characters from the `Text' string have been exhausted, start again from the beginning. (write_header): Always assume UTF-8 encoding for displaying header in `text' and `waterfall' modes. 2013-04-23 Werner Lemberg [ftview] Rename some variables. * src/ftview.c (status): s/font_index/font_idx/. s/Num/offset/. s/Fail/num_fails/. s/fw_index/fw_idx/. Update all callers. (Render_Stroke, Render_Slanted, Render_Embolden, Render_All, Render_Text, Render_Waterfall): s/first_index/offset/. (event_index_change): s/old_Num/old_offset/. (write_header): s/gindex/glyph_idx/. 2013-04-20 Werner Lemberg [ftdiff] New `x' key to toggle layout modes. (cbox vs. adv. width). Using the advance width is the new default. * src/ftdiff.c (ColumnStateRec): New member `use_cboxes'. (render_state_init): Updated. (render_state_draw): Use advance width instead of the maximum x value of the cbox if `use_cboxes' is set to 0. (event_help): Updated. (process_event): Handle `x' key. 2013-04-18 Werner Lemberg [ftdiff] Implement key `H' to select CFF hinting engine. * src/ftdiff.c: Include FT_CFF_DRIVER_H. Include FT_MODULE_H, FT_INTERNAL_OBJECTS_H, and FT_INTERNAL_DRIVER_H. (HINTING_ENGINE_MAX): New macro. (ColumnStateRec): New member `hinting_engine'. (render_state_init): Updated. (render_state_draw): Select hinting engine. Display hinting engine if we have CFF font. (event_help): Updated. (process_event): Handle `H' key. * Makefile (ftdiff.$(SO)): Enable inclusion of internal header files. 2013-04-17 Werner Lemberg Support display of no anti-aliasing, no hinting. * src/ftcommon.c (FTDemo_Update_Current_Flags): Handle this by setting FT_LOAD_MONOCHROME for this combination. 2013-04-17 Werner Lemberg [ftview] Be more intelligent in updating the display. This improves readability of tracing messages. * src/ftview.c (event_bold_change, event_change_radius, event_slant_change, event_size_change, event_index_change, event_font_change): Return update status. (Process_Event): Update display only if an event causes a change. 2013-04-17 Werner Lemberg [ftview] Minor GUI improvements. * src/ftview.c (event_hinting_engine_change, event_render_mode_change): Simplify. (Process_Event): Make keys `A'-`F' work only if AA is active. Disable keys `f' and `H' if in light hinting mode. (write_header): Ditto for header messages. 2013-04-17 Werner Lemberg [ftview] Key `H' should be active only if we have a CFF. * src/ftview.c (Process_Event): Do it. 2013-04-13 Werner Lemberg [ftview] Add keys `A'-`F' to select LCD mode. * src/ftview.c (event_help): Updated and rewritten to provide a two-column layout. (Process_Event): Handle `A'-`F'; former key `F' is now mapped to `L'. 2013-04-13 Werner Lemberg [ftview] Key `H' switches CFF hinting engines. * src/ftview.c: Include FT_MODULE_H, FT_INTERNAL_OBJECTS_H, FT_INTERNAL_DRIVER_H, and FT_CFF_DRIVER_H. (N_HINTING_ENGINES): New macro. (status): New member `hinting_engine'. (event_help): Updated. (event_hinting_engine_change): New function. (Process_Event): Handle `H' key. (main): Set default CFF engine. 2013-04-21 Werner Lemberg [graph/x11] Set _NET_WM_PID property. * graph/X11/x11/grx11.c: Include `sys/types.h', `unistd.h', and `XAtom.h'. (gr_x11_surface_init): Get process ID and set _NET_WM_PID property. 2013-03-27 Werner Lemberg Makefile (COMPILE): Add `CPPFLAGS'. Two reasons: (a) for orthogonality with freetype.mk (b) users can pass additional stuff to the compiler 2013-03-24 Werner Lemberg [ftview] Improve rendering mode switching. * src/ftview.c (status): Add `update' field. (Process_Event): Set `update' to 1 only if we really have to do an update. (main): Updated. 2013-03-24 Werner Lemberg [ftview] Use `l' and `k' keys instead of `L' and `K'. * src/ftview.c (event_help, Process_Event): Implement it. 2013-03-24 Werner Lemberg Don't try to handle rendering precision. This is a non-functional remnant of FreeType 1. All font drivers using B/W rendering activate this at ppem < 24. * src/ftcommon.h (FTDemo_Handle): Remove `low_prec' field. * src/ftcommon.c (FTDemo_New): Updated. * src/ftmulti.c (low_prec): Removed. (Help, Process_Event): Updated. * src/ftstring.c (event_help, Process_Event): Updated. * src/ftview.c (event_help, Process_Event, write_header): Updated. 2013-03-17 Werner Lemberg [ftview] Remove options -d and -L. Not documented and no longer working. This functionality is now available via FreeType's FT2_DEBUG environment variable. * src/ftview.c (status): Remove `debug' and `trace_level'. (parse_cmdline, main): Updated. 2013-03-17 Werner Lemberg [ftview] Remove option -D. This no longer works because the used cache values are now internal. * src/ftview.c (status): Remove `dump_cache_stats'. (usage, parse_cmdline, main): Updated. 2013-02-16 Alexei Podtelezhnikov [ftbench] Make BBox test harder. Rotating an outline puts more off-points outside of its bounding box. * src/ftbench.c: Include FT_OUTLINE_H. (test_get_bbox): Rotate outline by 30 degrees. 2013-02-12 Werner Lemberg [ftbench] Add test for `FT_Outline_Get_BBox'. * src/ftbench.c: Include FT_BBOX_H. (FT_BENCH_GET_BBOX): New enumeration value. (bench_desc): Updated. (test_get_bbox): New function. (main): Handle FT_BENCH_GET_BBOX. 2013-02-08 Werner Lemberg Implement `-v' to show version. Rename ftdump's `verbose' option to `-V'. Beautify and harmonize usage strings. * src/ftbench.c (bench_desc): Improve. (usage): Updated. (main): Handle `-v'. * src/ftdiff.c (usage): Updated. (render_state_init): Pass `library' argument. Move FreeType initialization to... (main): Here. Handle `-v'. * src/ftdump.c (usage): Updated. (main): Handle `-v', rename old `-v' to `-V'. * src/ftmulti.c (usage): Updated. (main): Handle `-v'. * src/ftgrid.c, src/ftstring.c, src/ftview (usage): Updated. (parse_cmdline): Handle `-v'. (main): Updated. 2013-02-08 Werner Lemberg [ftdiff] Simplify option handling. * src/ftdiff.c (get_option_arg): Removed. (main): Use `getopt'. 2013-02-08 Werner Lemberg * src/ftcommon.c, src/ftcommon.h (FTDemo_New): Take no parameter. * src/ftgrid.c, src/ftstring.c, src/ftview.c: Updated. 2013-02-06 Werner Lemberg [ttdebug] Remove options `-n' and `d'; add `-v' to show version. * src/ttdebug.c: Include `common.h'. (Panic): Renamed to... (Abort): This to avoid name clash. (dump_mode, non_interactive_mode): Removed. Unused. (main): Use `getopt'. Implement `-v' to show FreeType version. (Usage): Updated and synchronized with other usage messages from FreeType demo programs. * Makefile (ttdebug$E): Updated to use `common.c'. 2013-02-06 Werner Lemberg [ttdebug] Make `q' work correctly. * src/ttdebug.c (Quit): New macro. (RunIns, main): Handle `Quit'. 2013-02-06 Werner Lemberg * src/ttdebug.c (RunIns): Slightly beautify output. (Usage): Mention help key. 2013-02-06 Werner Lemberg [ttdebug] Make it work again (partially). Since we now have lazy execution of the `prep' bytecode, the old ttdebug code no longer could debug it. The new code debugs `fpgm', `prep', and the glyph's bytecode in one run. To facilitate it, it also adds a new `c' key to continue to the next code range. * src/ttdebug.c (debug_coderange): Removed. (RunIns): Always run debugger. Report `end of program' only after glyph program. Update output of `?' key. Handle `c' key to loop until end of code range is reached. (Usage): Updated. (main): Don't handle negative glyph indices. 2013-02-06 Werner Lemberg * src/ttdebug.c: s/exc->/CUR./. 2013-02-05 Werner Lemberg * src/ttdebug.c (OpStr): Oops! Add commas back. 2013-02-05 Werner Lemberg [ttdebug] Fix compilation warnings. * src/ttdebug.c (Cur_U_Line): Use `CUR' macro. (RunIns): Use global `error' variable. Use a const `temp' pointer locally. (Usage): Fix declaration. 2013-02-05 Werner Lemberg * src/ttdebug.c: Formatting, improving messages. 2013-01-28 Werner Lemberg [ftview] Make waterfall display -m string. Also make leftArrow key and friends functional. * src/ftview.c (Text): Make it `const char*'. (Render_Waterfall): Add argument to pass first index. Use -m option if given, and handle it as UTF-8. (Render_Text, parse_cmdline, main): Updated. 2013-01-28 Werner Lemberg * src/ftview.c (write_header): Show rendering mode number. 2013-01-03 Werner Lemberg [ftdiff] Slightly redesign layout to display all options. Also some other, minor changes. * src/ftdiff.c: Include . (RenderStateRec): Remove `message' and `message0'. Update all users. (render_state_draw): Display one more line for status information. (write_message): Renamed to... (write_global_info): This. Also display family and style name; we thus no longer need to display the number of subfonts. Also display dpi, ppem, and gamma. (main): Slightly improve column layout. (event_help): Minor improvement. (adisplay_change_gamma): Use epsilons. (render_state_set_file): Don't loop around the start or end of the face list. Other FreeType demo programs don't do this either. 2013-01-03 Werner Lemberg [ftdiff] Store family and style name of loaded fonts. To be used in a following commit. * src/ftdiff.c (FontFaceRec): New members `family_name' and `style_name'. (render_state_set_files): Fill new FontFaceRec members. 2013-01-03 Werner Lemberg * src/ftdiff (event_help): Improve text. 2013-01-03 Werner Lemberg [ftgrid] Make it work again. * src/ftgrid.c (grid_status_init): Don't initialize variables related to `display'. Do this... (grid_status_display): ... in this new function instead. (main): Use new function to handle command line arguments before initializing the display. 2013-01-02 Werner Lemberg Increase line height in help texts. * src/ftview.c (event_help): Increase line height. Improve text. * src/ftdiff.c (event_help), src/ftgrid.c (event_help), src/ftmulti.c (Help), src/ftstring.c (event_help): Increase line height. 2013-01-02 Werner Lemberg [graph] Implement adjustable line height. * graph/grfont.c (gr_line_height): New global variable. (grSetLineHeight): New function. (grWrite): Use gr_line_height. * graph/grfont.h: Updated. 2013-01-02 Werner Lemberg * src/ftview.c (write_header): Improve displayed strings. 2013-01-02 Werner Lemberg [ftview] Better input key handling. * src/ftview.c (Process_Event): Don't handle key events if not in a mode where they change something visible. 2013-01-02 Werner Lemberg * src/ftdiff.c (render_state_set_files): Skip non-scalable fonts. 2013-01-02 Werner Lemberg * src/ftview.c (main) Remove redundant code. 2013-01-02 Werner Lemberg [ftview] Redesign layout. It now displays all options, not only the changes, in a structured way. * src/ftview.c (START_X, START_Y): New macros. (INIT_SIZE): Use them. (status): Remove `header' and `header_buffer' members. (Render_Waterfall): Use START_X and START_Y. (event_gamma_change, event_bold_change, event_radius_change, event_slant_change, event_render_mode_change, Process_Event): Don't set `status.header'. (write_header): Display all options. (main): Updated. 2012-12-31 Werner Lemberg Introduce a warn color. * src/ftcommon.h (FTDemo_Display): Add `warn_color' member. * src/ftcommon.c (FTDemo_Display_New): Initialize it. 2012-12-31 Werner Lemberg * src/ftdiff.c (render_state_draw, main): Use HEADER_HEIGHT. 2012-12-27 Werner Lemberg Increase header line distances. * src/ftgrid.c, src/ftview.c (HEADER_HEIGHT): Move to... * src/ftcommon.h: ... this file. Set it to value 12. 2012-12-27 Werner Lemberg * Makefile: Add dependencies on `ftcommon.h'. 2012-12-26 Werner Lemberg Implement -w and -h options to specify window width and height. * src/ftcommon.c (FTDemo_Display_New): Two new parameters to pass width and height. (DIM_X, DIM_Y): Moved to ... * src/ftcommon.h: ... this. * src/ftdiff.c (usage): Updated. (ADisplayRec): Add `width' and `height' elements. (adisplay_init): Two new parameters to pass width and height. (write_message): Updated. (main): Handle `-w' and `-h' options. * src/ftgamma.c (DIM_X, DIM_Y): Removed. * src/ftgrid.c (GridStatusRec): Add `width' and `height' elements. (grid_status_init): Updated. (usage): Updated. (parse_cmdline): Handle `-w' and `-h' options. (main): Updated. * src/ftmulti.c (DIM_X, DIM_Y): Use the same (new) values as in other demo programs. (width, height): New global variables. (Init_Display): Updated. (usage): Updated. (main): Handle `-w' and `-h' options. * src/ftstring.c (status): Add `width' and `height' elements. (usage): Updated. (parse_cmdline): Handle `-w' and `-h' options. (main): Updated. * src/ftview.c (status): Add `width' and `height' elements. (usage): Updated. (parse_cmdline): Handle `-w' and `-h' options. (main): Updated. 2012-12-20 Werner Lemberg * bin/.cvsignore: Renamed to... * bin/.gitignore: ... this. * Makefile (dist): Don't include `.mailmap' and `.gitignore' 2012-12-19 Werner Lemberg * Version 2.4.11 released. ========================== Tag sources with `VER-2-4-11'. * README: Updated. 2012-11-27 Werner Lemberg * src/ftdiff.c (usage): Updated. 2012-11-26 Werner Lemberg [ftdiff] Accept UTF-8 encoded input files. * src/ftdiff.c (default_text): Use `char*' instead of `unsigned char*'. (main): Ditto for `text' variable. (RenderStateRec): Ditto for `text' member. (render_state_draw): Ditto for `text' argument. Use `utf8_next' to parse UTF-8 encoded text. 2012-11-04 Werner Lemberg [ftdump] Improve output of cmap tables. * src/ftdump.c (Print_Charmaps): Indicate Unicode Variation Sequences. 2012-10-20 Werner Lemberg * src/ftdump.c: (main): Minor output formatting. 2012-09-01 Alexei Podtelezhnikov [ftview] Use pixel size calculation that works for bitmap fonts too. * src/ftview.c (Render_Stroke, Render_Embolden): Rely on the status point size and resolution to get the pixel size. 2012-08-19 Alexei Podtelezhnikov [ftview] Implement adjustable stroker radius. * src/ftview.c (status): New field 'radius'. (Render_Stroke): Updated. (Process_Event): Add the keys `r' and `R' to handle the change. (event_radius_change): Implement it. (event_help): Updated. 2012-08-18 Alexei Podtelezhnikov [ftview] Use more readable loop. * src/ftview.c (main): use do-while instead of for-break. 2012-07-20 Alexei Podtelezhnikov [ftview] Clean up the code. * src/ftview.c (Render_Slanted): Move the shear matrix setup out of the loop. * src/ftview.c (Render_Embolden): Move the emboldening strength calculation out of the loop. 2012-07-12 Alexei Podtelezhnikov [ftview] Further code homogenization. * src/ftview.c (Render_Stroke): Stroker constructor and destructor are moved to... * src/ftcommon.c (FTDemo_New, FTDemo_Done): Here. * src/ftcommon.h (FTDemo_Handle): New field `stroker'. 2012-07-11 Werner Lemberg Avoid crashes in case of failure. * src/ftcommon.c (FTDemo_Draw_Slot), src/ftgrid.c (grid_status_draw_outline), src/ftview.c (Render_Stroke): Only call `FT_Done_Glyph' in case of success. 2012-07-10 Alexei Podtelezhnikov [ftview] Clean up and homogenize the code. * src/ftview.c (Render_Stroke): Replace while-loop with for-loop. (Render_Slanted): Ditto. (Render_Embolden): Ditto. (Render_All): Ditto. (Render_Waterfall): Ditto. (Render_Stroke): Homogenize with other similar functions. (Render_Text): Code cleanup. (event_gamma_grid): Ditto. 2012-06-15 Werner Lemberg * Version 2.4.10 released. ========================== Tag sources with `VER-2-4-10'. * README: Updated. 2012-05-28 Alexei Podtelezhnikov [ftview] Implement handling of FT_Outline_EmboldenXY. * src/ftview.c (status): Replace `bold_factor' with `xbold_factor' and `ybold_factor'. (Render_Embolden): Updated. (Process_Event): Replacing handling of `e', `E' keys with `x', `X', `y', and `Y'. (event_bold_change): Implement it. (event_help): Updated. 2012-03-14 Alexei Podtelezhnikov [ftview] Improve spacing for bold rendering mode. * src/ftview.c (Render_Embolden): Fix algorithm to reduce spacing. 2012-03-08 Werner Lemberg * Version 2.4.9 released. ========================= Tag sources with `VER-2-4-9' (the previous commit has this tag). * README: Updated. 2012-03-03 Werner Lemberg [ftstring] Fix display of kern compare mode. * src/ftstring.c (main) : Fix scaling of `height'. 2012-03-03 Werner Lemberg Fix handling of track kerning. * src/ftcommon.c (string_render_prepare): Fix scaling for `FT_Get_Track_Kerning'. 2012-03-03 Werner Lemberg Remove unused function. * src/ftcommon.[ch] (FTDemo_Set_Current_Pointsize): Remove. 2012-03-02 Werner Lemberg Fix Savannah bug #33660. * src/ftcommon.c: Include `FT_XFREE86_H'. (file_suffixes): Remove. (my_face_requester): Check whether font driver is `Type 1' instead of relying on the file suffix. Additionally, prefer `.afm' over `.pfm'. (FTDemo_Install_Font): Don't try various suffixes. Allocate more memory for `font->filepathname' as needed by `my_face_requester'. * src/ftdiff.c: Include `ftcommon.h' and `common.h'. Remove declaration of `error' everywhere. (usage): Updated. Add argument for binary name. Update all callers. (event_help): Updated. * src/ftgrid.c (usage): Updated. * src/ftstring.c (event_help, usage): Updated. * src/ftview.c (usage): Updated. 2012-03-02 Werner Lemberg * src/ftstring.c: Remove redundant code; formatting. 2012-03-02 Werner Lemberg * src/ftdiff.c: Formatting. 2012-03-02 Werner Lemberg * src/ftgrid.c: Remove redundant code; formatting. 2012-03-02 Werner Lemberg * src/ftcommon.c: Remove dead code; formatting. 2012-02-13 Peter Grandi [ftview] Implement cycling backwards for rendering and LCD modes. * src/ftview.c (Process_Event): Handle keys `K' and `backspace'. (event_help): Updated. 2012-02-13 Werner Lemberg Fix X11 keyboard handling. * graph/grevents.h (grKey): Shift special keys to a higher range, otherwise it can happen that they are processed twice. For example, `grKeyBackSpace' also returns key code 8 under X11, and this was previously mapped to `grKeyF8'. 2011-12-07 Antoine Leca Fix printf specifications and parameters. * src/ttdebug.c (Cur_U_Line, RunIns): Use "%hu" for FT_UShort, "%ld" for FT_Pos; drop the "h" in "%hx" for FT_Byte parameters and cast the parameters to (unsigned) ("%hhx" is C99 only, and often unimplemented). Noticed by clang. 2011-12-02 suzuki toshiya Use $(LIBTOOL) to make graph.a, if it is defined. If configure script in FreeType2 library directory creates GNU Libtool, using it is better than using raw `ar'. For example, Mac OS X archive library is required to be processed by ranlib. See discussion in http://lists.gnu.org/archive/html/freetype-devel/2011-10/msg00034.html * graph/rules.mk: Change the object suffix $(SO) to $(O) for the sake of GNU Libtool. If $(LIBTOOL) is defined, use it to compile the objects and make the library. * graph/x11/rules.mk: Ditto. * graph/beos/rules.mk: Ditto. * Makefile: `clean' target erases the object, the library and GNU Libtool related files in .libs/ directory. 2011-11-15 Werner Lemberg * Version 2.4.8 released. ========================= Tag sources with `VER-2-4-8'. * README: Updated. 2011-10-18 Werner Lemberg * Version 2.4.7 released. ========================= Tag sources with `VER-2-4-7'. * README: Updated. 2011-08-14 Werner Lemberg Improve usage messages. This should fix Savannah bug #33660. * src/ftgrid.c, src/ftstring.c, src/ftview.c (usage): Reword and extend. 2011-07-29 Werner Lemberg * Version 2.4.6 released. ========================= Tag sources with `VER-2-4-6'. * README: Updated. 2011-06-24 Werner Lemberg * Version 2.4.5 released. ========================= Tag sources with `VER-2-4-5'. * README: Updated. 2011-06-01 Werner Lemberg Fix gcc 4.6 warnings. * graph/grblit.c (blit_gray_to_gray): Remove unused variables. (blit_gray_to_gray_simple): Declare and set `max' conditionally. * src/ftcommon.c (FTDemo_Index_To_Bitmap): Remove unused variable. * src/ftmulti.c (Render_All, Render_Text): Ditto. * src/ftview.c (INIT_SIZE, Render_Stroke, Render_Slanted, Render_Embolden, Render_All, Render_Text, Render_Waterfall): Ditto. 2011-05-01 Just Fill Bugs Werner Lemberg [ftgrid] Show autohinter segments. Toggle with key `s'. * src/ftgrid.c: Add declarations for `af_glyph_hints_get_num_segments' and `af_glyph_hints_get_segments_offset'. (GridStatus): Add `segment_color' and `do_segment'. (grid_status_init): Updated. (grid_hint_draw_segment): New function. (grid_status_draw_outline): Call it. (Process_Event) <'s'>: Toggle display of segment lines. (event_help): Updated. 2011-04-24 Werner Lemberg * src/ftgrid.c (event_grid_zoom): Fix status message. 2011-04-21 Werner Lemberg FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH is deprecated and ignored. * src/ftchkwd.c (check_face): Update load flags. * src/ftcommon.h (FTDemo_Handle): Remove `use_global_advance_width'. * src/ftcommon.c (FTDemo_New, FTDemo_Update_Current_Flags): Updated. * src/ftmulti.c (LoadChar): Update load flags. * src/ftdiff.c (ColumnStateRec): Remove `use_global_advance_width'. (render_state_init, render_state_draw): Updated. (process_event): No longer handle key `a'. (event_help): Updated. * src/ftview.c (Process_Event): No longer handle key `A'. (event_help): Updated. 2011-04-20 Werner Lemberg [ftgrid]: Prevent incorrect output of `1', `2', and `3' keys. * src/ftgrid.c (Process_Event) <'1', '2', '3'>: Ensure that hinting is active, otherwise old table data could be emitted. 2011-04-19 Werner Lemberg * Makefile (FT_INCLUDES): Simplify. 2011-04-18 Werner Lemberg [ftgrid]: Limit autofit control even more. * src/ftgrid.c (Process_Event) <'H', 'V', 'B'> [FT_DEBUG_AUTOFIT]: Limit visibility and improve status messages. (event_help): Updated. 2011-04-18 Werner Lemberg [ftgrid] Add forced autohinting and limit autofit dumping. * src/ftgrid.c (_af_debug): Remove, unused. (Process_Event) <'f'>: Toggle autohinting. [FT_DEBUG_AUTOFIT] <'1', '2', '3'>: Limit visibility and improve status messages. (event_help): Updated. (main): Updated. 2011-04-18 Werner Lemberg Honor DEVEL_DIR. * Makefile (FT_INCLUDES) [DEVEL_DIR]: Add $DEVEL_DIR. 2011-03-19 Werner Lemberg C++ compilation fixes. * src/ftcommon.c, src/ftdiff.c: `strrchr' returns `const char *'. * src/ftview.c (status): Fix initialization. 2011-01-30 Werner Lemberg Add flag `A' to ftview for toggling the global advance width flag. * src/ftcommon.h (FTDemo_Handle): New field `use_global_advance_width'. * src/ftcommon.c (FTDemo_New): Set it. (FTDemo_Update_Current_Flags): Handle it. * src/ftview.c (Process_Event): Handle key `A'. (event_help): Updated. 2010-12-31 Werner Lemberg * Makefile: Add -lbz2 for development builds. 2010-11-28 Werner Lemberg * Version 2.4.4 released. ========================= Tag sources with `VER-2-4-4'. * README: Updated. 2010-10-03 Werner Lemberg * Version 2.4.3 released. ========================= Tag sources with `VER-2-4-3'. * README: Updated. 2010-08-29 Steve Langasek Make `grKey' enum comprehensive for gcc 4.5 compatibility. * graph/grevents.h (grKey): Avoid the situation of trying to compare an enum variable with a value not included in that enum in a case statement. An enum needs to be declared to include the list of all possible values (which in the case of keypresses is quite a few), not just the most convenient ones. 2010-08-17 Werner Lemberg [ftbench] Add option `-i' to specify first used glyph index. * src/ftbench.c (first_index): New global variable. (test_load, test_load_advances, test_render, test_embolden, test_get_cbox, test_get_glyph, test_image_cache, test_sbit_cache, get_charset): Use it. (usage): Updated. (main): Handle `-i'. 2010-08-06 Werner Lemberg * Version 2.4.2 released. ========================= Tag sources with `VER-2-4-2'. * README: Updated. 2010-07-23 Werner Lemberg ftmulti: Oops! Patch has been applied incorrectly. * src/ftmulti.c (main): Really limit axis name length. 2010-07-19 Werner Lemberg * Version 2.4.1 released. ========================== Tag sources with `VER-2-4-1'. * README: Updated. 2010-07-17 Werner Lemberg ftmulti: Fix possible buffer overflow. Based on a patch from Marek Kašík . * src/ftmulti.c (main): Limit axis name length in `Header'. 2010-07-13 suzuki toshiya ftdump: Show language ID for all cmap subtables. * src/ftdump.c (Print_Charmaps): Print the language IDs obtained by FT_Get_CMap_Language_ID(). The language IDs is cast to FT_UInt, so broken IDs (> 0xFFFF) will not be shown correctly. 2010-07-12 Werner Lemberg * Version 2.4.0 released. ========================== Tag sources with `VER-2-4-0'. * README: Updated. 2010-06-28 Werner Lemberg ftbench: Fix suboptions of `-b'. * src/ftbench.c (bench_desc): Add missing description for FT_BENCH_LOAD_ADVANCES. 2010-06-07 Werner Lemberg Fix Savannah bug #30054. * src/ftdiff.c, src/ftgrid.c, src/ftmulti.c, src/ftstring.c, src/ftview.c: Use precision for `%s' where appropriate to avoid buffer overflows. 2010-04-14 Werner Lemberg ftdiff: Add support for LCD filter control. Key `l' cycles through the filter modes, `[' and `]' select the custom filter weight, `-' and `+' (or `=') adjust the selected filter weight. This is based on code written by Lifter . * src/ftdiff.c (ColumnStateRec): Add members for LCD filter control. (render_state_init): Updated. (render_state_draw): Add support for custom LCD filter. (event_help): Document new keys. Make help screen more compact. (process_event): Handle new keys. 2010-04-14 Werner Lemberg ftview: Add support for LCD filter control. Key `F' toggles custom LCD filter mode, `[' and `]' select the custom filter weight, `-' and `+' (or `=') adjust the selected filter weight. This is based on code written by Lifter . * src/ftview.c (INIT_SIZE, Render_Waterfall): Add space for a third header line. (status_): Add members for LCD filter control. (event_help): Document new keys. Make help screen more compact. (Process_Event): Handle new keys. Use FTC_Manager_RemoveFaceID to flush the bitmap caches, forcing a redraw. I'm not sure whether this is the right thing, but it seems to work... (write_header): Display custom filter weights. 2010-02-11 Werner Lemberg * Version 2.3.12 released. ========================== Tag sources with `VER-2-3-12'. * README: Updated. 2009-10-10 Werner Lemberg * Version 2.3.11 released. ========================== Tag sources with `VER-2-3-11'. * README: Updated. 2009-10-06 Werner Lemberg * Version 2.3.10 released. ========================== Tag sources with `VER-2-3-10'. * README: Updated. * Makefile (major, minor, patch): Fix regexp to allow more than a single digit. (dist): We now use git. 2009-07-30 Boris Letocha [graph] Fix rendering on Windows. * graph/win32/grwin32.c (gr_win32_surface_refresh_rectangle): Handle `gr_pixel_mode_gray' correctly. 2009-06-17 Werner Lemberg Reduce number of automatically compiled programs. Many GNU/Linux distributions install those programs, and most of them are completely useless or very specialized. * Makefile (LINK): Define. (EXES): Reduce list to retain only generally useful programs. (ftsbit): Comment out. Program doesn't compile (but may be useful). (ttdebug.o): Make it compile again. 2009-06-17 Werner Lemberg * Makefile: Handle `EXTRAFLAGS' for platform `unixdev' also. 2009-04-30 Werner Lemberg ftview: Make slant and boldness controllable. Keys `e' and `E' adjust emboldening, keys `s' and `S' the slant. * src/ftview.c (status): Add `bold_factor' and `slant' members. (Render_Slanted): Use `status.slant'. (Render_Embolden): Copy code from `FT_GlyphSlot_Embolden' and use `status.bold_factor'. (event_bold_change, event_slant_change): New functions. (Process_Event): Handle keys `s', `S', `e', and `E'. (event_help): Updated. 2009-04-26 Werner Lemberg * graph/grblit.c (blit_lcd8_to_24): Fix typo. Reported by suyu@cooee.cn. 2009-04-22 Werner Lemberg Fix crash in ftgrid. * src/ftgrid.c (grid_status_draw_outline): Handle return value of FT_Load_Glyph. 2009-03-12 Werner Lemberg * Version 2.3.9 released. ========================= Tag sources with `VER-2-3-9'. * README: Updated. 2009-03-10 Werner Lemberg * src/common.c (CONST): New macro, defined depending on __STDC__. Use it where necessary. 2009-03-10 Werner Lemberg Fix C++ compilation. * src/ftbench.c (test_load_advances): Use cast. * src/ftgrid.c: Protect `extern' declarations with `extern "C"'. 2009-03-03 Werner Lemberg Fix signedness issues. * src/ftcommon.c (FTDemo_String_Set): Fix signedness. Update callers. Include `common.h'. Use __STDC__ macro. * src/ftcommon.h (FTDemo_String_Set): Fix signedness. * src/common.h, src/common.c: Use __STDC__ macro. 2009-03-03 David Turner Add utf-8 support to ftview. Fixes Savannah BUG #18225. * src/common.h, src/common.c: Add `utf8_next' function. * src/ftcommon.c (FTDemo_String_Set), src/ftview.c (Render_Text): Use `utf8_next'. 2009-01-14 Werner Lemberg * Version 2.3.8 released. ========================= Tag sources with `VER-2-3-8'. * README: Updated. 2009-01-07 Werner Lemberg ftdiff: Add `a' key to toggle global advance width. * src/ftdiff.c (ColumnStateRec): Add `use_global_advance_width' field. (render_state_init): Updated. (render_state_draw): Control FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH. Update screen output. (event_help): Document `a' key. Sort output. (process_keys): Handle `a' key. Sort entries in `case' block. 2008-12-05 Werner Lemberg * src/ftbench.c: Remove #if FT_ADVANCES_H ... conditionals. 2008-09-02 David Turner * src/ftbench.c: Include FT_ADVANCES_H. (FT_BENCH_LOAD_ADVANCES): New enumeration value. (test_load_advances): New function. (main) : New case. 2008-06-29 Werner Lemberg * Version 2.3.7 released. ========================= Tag sources with `VER-2-3-7'. * README: Updated. 2008-06-10 Werner Lemberg * Version 2.3.6 released. ========================= Tag sources with `VER-2-3-6'. * README: Updated. 2008-05-18 Werner Lemberg * src/ftdiff.c (render_mode_names): Use better strings. 2008-05-13 Werner Lemberg * src/ftcommon.c (string_render_prepare): Always set extent in last slot. 2008-01-10 Allan Yang, Jian Hua - SH * graph/grfill.c: Include . 2007-12-29 Allan Yang, Jian Hua - SH Werner Lemberg * src/ftview.c: Implement slanting. 2007-08-08 Werner Lemberg * src/ftvalid.c (print_usage): Add option `-f'. 2007-08-08 George Williams * src/ftvalid.c (ot_table_spec): Handle `MATH' table also. (main): Add option `-f' to select font index. 2007-07-07 Werner Lemberg * src/ftview.c (parse_cmdline): Remove C++ compiler warning. * src/ftcommon.c (my_file_requester), src/ftgrid.c (grid_status_draw_grid, ft_outline_draw, ft_outline_new_circle, grid_status_draw_outline, _af_debug_hints), src/ftdiff.c (_render_state_rescale, render_state_set_files, render_state_set_file, adisplay_draw_glyph, adisplay_draw_text, event_help, event_change_gamma, process_event, write_message, main): Fix compilation with C++ compiler. 2007-07-02 Werner Lemberg * Version 2.3.5 released. ========================= Tag sources with `VER-2-3-5'. * README: Updated. 2007-06-19 Werner Lemberg * src/ftview.c (usage): Make it more readable. 2007-06-16 Werner Lemberg * src/ftpatentcheck.c: Renamed to... * src/ftpatchk.c: This. Minor fixes. * src/Jamfile (PROGRAMS), Makefile: Updated. 2007-06-10 David Turner Add the new `ftpatentcheck' program; it is a simple wrapper of the new FT_Face_CheckTrueTypePatents function. * src/ftpatentcheck.c: New file. * src/Jamfile (PROGRAMS), Makefile: Updated. 2007-06-09 Werner Lemberg * src/ftgrid.c (Process_Event): Assign usual actions to keys F7-F12. (event_help): Updated. (main): Don't expect a Unicode encoded font -- we are only working with glyph indices currently. 2007-06-01 Werner Lemberg * src/ftcommon.c (FTDemo_Index_To_Bitmap): Initialize `*x_advance'. 2007-05-28 David Turner * src/ftcommon.h: fix compilation warning * src/ftview.c: fix size bugs in waterfall mode 2007-05-11 David Turner * src/ftcommon.h, src/ftcommon.c, src/ftview.c, src/ftgrid.c, src/ftstring.c: adapt test programs to use the new FTC_ImageCache_LookupScaler and FTC_SBitCache_LookupScaler functions. This allows you to specify fractional pixel/point sizes on the command line (e.g. ftview 13.5 ~/fonts/*) 2007-05-09 Ryan Hill * Makefile: Fix rules for fttimer which doesn't use graphical output. Fix rule for ftdump to make it work with parallel builds. 2007-04-09 Werner Lemberg * Version 2.3.4 released. ========================= Tag sources with `VER-2-3-4'. * README: Updated. * src/ftdiff.c (process_event): Handle `?' key. 2007-04-04 Werner Lemberg * Version 2.3.3 released. ========================= Tag sources with `VER-2-3-3'. * README: Updated. 2007-04-03 Werner Lemberg * src/ftdiff.c (usage): Make message similar to other ftdemo programs. 2007-04-02 David Turner * graph/win32/grwin32.c (gr_win32_surface_init): Fix the Win32 window size computations to properly adjust border thickness and other extras. Fix by Sébastien Leix . * src/ftdiff.c (render_state_draw): Fix small bug that prevented unhinted rendering from working as expected with embedded bitmaps. (adisplay_init): Fix small bug that occurred when the call to grNewSurface() failed. Reported by Sébastien Leix . (usage): Move up in file. (FontFaceRec): New structure. (RenderStateRec): Integrate it. Update all users. (render_state_set_files, render_state_set_file): Handle all faces in a multi-face font file. (write_message): Handle multi-face font files. 2007-04-01 Werner Lemberg * src/ftdiff.c: Remove compiler warnings. Formatting. 2007-03-30 David Turner Change interface keys to allow you to change settings for a single column only. Press F1 for details. * src/ftdiff.c: Include FT_LCD_FILTER_H. (DisplayMode): Add DISPLAY_MODE_LCD. (Display_textFunc): New function pointer. (DisplayRec): Add it. (RenderMode): Replace it with... (HintMode): This. Update all users. (render_mode_names): New array. (ColumnStateRec): New struct. (RenderStateRec): Use it. (render_state_init): Initialize it. (render_state_draw): Pass index as argument. Use ColumnStateRec. Implement sub-pixel positioning for unhinted mode. Add column footers, showing current rendering state. (adisplay_draw_glyph): Handle DISPLAY_MODE_LCD. (adisplay_draw_text): New function. (event_help): Updated. (process_event): Add many keys to control rendering modes in more detail. (main): Updated. 2007-03-28 Werner Lemberg * src/ftdiff.c: Remove many compiler warnings. Fix some typos. Improve and fix help texts. Formatting. 2007-03-26 David Turner * src/ftdiff.c: New proofing program that displays text in three columns: bytecode-hinted, auto-hinted with rsb/lsb delta adjustments, and unhinted/subpixel-positioned. For comparison purposes. * Makefile, Jamfile: Add ftdiff. 2007-03-22 suzuki toshiya * src/ftvalid.c (print_usage): Fix a typo in the help message. 2007-03-09 Werner Lemberg * Version 2.3.2 released. ========================= Tag sources with `VER-2-3-2'. * README: Updated. 2007-02-14 David Turner * src/ttdebug.c: another refresh of the debugger. Minor improvements to be able to display more useful information during debugging 2007-02-12 David Turner * src/ttdebug.c: refresh the TrueType debugger code 2007-02-06 Alexei Podtelezhnikov * src/ftstring.c (event_render_mode_change): Fix spelling. 2007-01-31 Werner Lemberg * Version 2.3.1 released. ========================= Tag sources with `VER-2-3-1-FINAL'. * README: Updated. 2007-01-17 Werner Lemberg * Version 2.3.0 released. ========================= Tag sources with `VER-2-3-0-FINAL'. 2007-01-11 Masatake YAMATO * src/ftvalid.c (run_ot_validator, run_gx_validator, run_ckern_validator): Return FT_Error value instead of int value. (main): Return value returned from validator's run method. (report_result): Don't show `invalid' message if there is no target table. 2006-12-15 suzuki toshiya * mac/ftoldmac.c: Fix conditional macros of FSSpec/FSRef and QuickDraw/ATS functionalities. 2006-12-10 Werner Lemberg * Makefile (dist): Extract version number from freetype.h. 2006-11-15 David Turner * graph/x11/rules.mk (X11_PATH): Check /usr also. Search for `Xlib.h'. 2006-11-03 Werner Lemberg * src/ftgrid.c: Fix external function declarations. (event_help): Document `1', `2', and `3' keys. (grid_status_init, grid_status_rescale_initial, grid_status_draw_grid, grid_status_draw_outline, event_grid_reset): s/status/st/, s/error/err/ where appropriate to avoid shadowed variables. (GridStatusRec): Add `const' to `header'. Update all assignments. * Makefile: Add ftgrid. 2006-11-02 David Turner Add `B' key to ftgrid for toggling blue zone hinting. Add `1', `2', and `3' keys to dump hints for edges, segments, and points, respectively. * src/ftgrid.c: Add some externs. (_af_debug, _af_debug_disable_blue_hints, _af_debug_hints): New global variables. (GridStatusRec): Add `do_blue_hints' variable. (grid_status_init): Set do_blue_hints. (event_help): Updated. (Process_Event): Updated. (main): Set _af_debug. 2006-10-23 Zhe Su Add a benchmark for the emboldening algorithm. * src/ftbench.c: Include FT_SYNTHESIS_H. (FT_BENCH_EMBOLDEN): New enumeration value. (bench_desc): Add `Embolden'. (test_embolden): New function. (main): Add it. 2006-10-23 David Turner * src/ftgrid.c: Make the file compile again. 2006-10-11 suzuki toshiya * mac/ftoldmac.c (print_help): Renamed to... (print_help_and_exit): This. Update callers. Improve the conditionals in source to separate Toolbox QuickDraw and Carbon QuickDraw. (reserveToolBoxQuickDrawFontName, test_face_quickdraw, test_font_list_quickdraw_old, test_font_list_quickdraw, test_font_list_ats): Ditto. 2006-10-11 suzuki toshiya * mac/Makefile: Synchronize with the changes of top-level Makefile on 2006-02-01. 2006-09-27 David Turner Add support for LCD color filtering to ftview. * src/ftview.c: Include FT_LCD_FILTER_H. (status): Initialize it completely. (main): Call FT_Library_SetLcdFilter. * src/ftcommon.c (FT_Demo_Draw_Glyph): Renamed to... (FT_Demo_Draw_Glyph_Color): This. Add an argument to pass the colour. (FT_Demo_Draw_Glyph): New function, calling FT_Demo_Draw_Glyph_Color. * src/ftcommon.h (FT_Demo_Draw_Glyph_Color): New declaration. * src/ftgrid.c: New file, implementing an auto-fitter debugger. This is a very preliminary version. It only compiles with Jam at the moment, and you must have AF_DEBUG defined in your `src/autofit/aftypes.h' file to be able to link it. * src/Jamfile (GRAPHIC_PROGRAMS): Add ftgrid. * graph/graph.h (grFindColor, grFillHLine, grFillVLine, grFillRect): New declarations. * graph/grfill.c: New file which implements `grFillHLine', `grFillVLine', and `grFillRect'. They are mainly used by the auto-fitter debugger. * graph/grobjs.c (grFindColor): New function for the auto-fitter debugger. * graph/gblender.c (gblender_set_gamma_table): Set `gamma_ramp_inv[gmax]'. * graph/gblender.h (GBLENDER_STAT_HIT, GBLENDER_LOOKUP): Move them up in source file. * graph/Jamfile (graph_sources), graph/rules.mk (GRAPH_OBJS): Add `grfill'. 2006-09-11 David Turner Add support for OLPC swizzle simulation (must define SWIZZLE at compile time for this to work). * graph/grswizzle.c, graph/grswizzle.h: New files. * graph/grdevice.h (gr_swizzle_rgb24): Declare. * graph/Jamfile (graph_sources): Add `grswizzle'. * graph/win32/grwin32.c [SWIZZLE]: Include `grswizzle.h'. (gr_win32_surface_refresh_rectangle) [SWIZZLE]: Don't call gr_swizzle_rgb24 but gr_rect_swizzle_rgb24. Remove unused variables. 2006-09-01 David Turner Fix various bugs in the glyph blender/blitter. * graph/gblcolor.h, graph/gblhbgr.h, graph/gblhrgb.h, graph/gblvbgr.h, graph/gblvrgb.h: Fix off-by-one error. * graph/gblender.c (gblender_lookup): Fix computation of key->cells. (gblender_lookup_channel): Fix computation of key->index. * graph/win32/grwin32.c: Fix RGB/BGR ordering -- Win32 uses BGR ordering for its 24-bit bitmaps. (SWIZZLE): New macro (set to undefined). (grWin32SurfaceRec): Add `bgrBitmap'. [SWIZZLE]: Add `swizzle_bitmap'. (gr_win32_surface_done) [SWIZZLE]: Handle `swizzle_bitmap'. (gr_win32_surface_refresh_rectangle): Do conversion RGB->BGR. (gr_win32_surface_init): Initialize `bgrBitmap'. [SWIZZLE]: Initialize `swizzle_bitmap'. 2006-07-03 Masatake YAMATO * src/ftvalid.c (library): Move this global variable to main as a local variable. (print_usage): Introduce function static variable `library'. Add one argument for initializing the static variable. (main): Call print_usage with `library'. (main, else, parse_table_specs, find_validation_flag): Call print_usage with NULL. 2006-06-17 Masatake YAMATO * src/ftvalid.c: Rearrange code. (library): Make variable having global scope. (OT_VALIDATOR_SYMBOL): Remove. (GX_VALIDATOR_SYMBOL): Remove. (CKERN_VALIDATOR_SYMBOL): Remove. (validator_symbols): Remove. (ValidatorType::LAST_VALIDATE): New enum element used in loop sentinel. (ot_table_spec): Remove const modifier. (gx_table_spec): Remove const modifier. (Validator): New data type. (validators): New variable. (print_usage): Use validators. (report_header, report_result): Use validators. (is_ot_validator_implemented): New function. (is_gx_validator_implemented): New function. (is_ckern_validator_implemented): New function. (run_ckern_validator): Use validators. (main): Initialize library at the beginning of main. Use validators. Report messages and exit if the validator specified by command line is not implemented in libfreetype2 linked to ftvalid. Suggested by George Williams. 2006-06-09 Werner Lemberg * src/ftcommon.c (FTDemo_Install_Font): Fix index range for MS Symbol. 2006-06-07 Werner Lemberg * src/ftcommon.c (FTDemo_Display_Done, FTDemo_Done): Protect against NULL argument. * src/ftview.c (Fatal): New function to finalize FreeType library. This allows using FreeType's memory debugger in case of errors. s/PanicZ/Fatal/. 2006-06-04 David Turner * src/ftbench.c (main): fixed a subtle memory corruption bug at program exit. Reported by . 2006-05-21 Werner Lemberg * src/ftdump.c (Print_Type): Fix type for `module'. Reported by Mark Wang. 2006-05-17 Werner Lemberg * src/ftcommon.c, src/ftview.c [_WIN32]: Define `strcasecmp' and `snprintf'. 2006-05-17 yi luo * graph/win32/rules.mk: Add support for icl compiler. * src/ftcommon.c (strcasecmp): Define to `_stricmp' if not available. * src/ftview.c (snprintf): Define to `_snprintf' if not available. 2006-05-12 Werner Lemberg * Version 2.2.1 released. ========================= 2006-05-10 Werner Lemberg * Makefile (clean distclean) [no_config_mk]: Fix warning message. (dist): New target to build .tar.bz2, .tar.gz, and .zip bundles. Note that there are still many hard-coded version strings. 2006-05-06 Werner Lemberg * src/ftdump.c (main): Fix compiler warning. 2006-05-02 David Turner Add support for font preloading with the `-p' flag, simulating memory-mapped file access. * src/ftcommon.h (TFont): New elements `file_address' and `file_size'. (FTDemo_Handle): New element `preload'. (FTDemo_Set_Preload): New prototype. * src/ftcommon.c (my_face_requester): Use FT_New_Memory_Face for preloaded font. Handle PFM files also. (FTDemo_Install_Font): Handle preloading (this is, load font into a buffer). (FTDemo_Set_Preload): New function. * src/ftview.c (status): Add `preload' field. (parse_cmdline): Handle `-p' command line option. (usage): Updated. (main): * src/ftdump.c (main): Add glyph count dump. 2006-04-26 David Turner * Version 2.2 released. ======================= 2006-04-24 Werner Lemberg * src/ftview.c (Render_Stroke): Update parameters in call to FT_Stroker_New. 2006-03-20 David Turner Disable cache statistics dump, since the cache internals are not available anymore. Rename `-l' to `-L'. Add new command line options `-m text' and `-l render_mode'. * src/ftview.c (status): Add member `lcd_mode'. (Render_Text): Compensate the additional empty pixels inserted by Draw_Index. Handle number of glyph indices better. (parse_cmdline): Handle `-m' and `-l'. Updated. (usage): Updated. (main): Handle `status.lcd_mode'. Updated. Print cache statistics only conditionally (for FreeType versions lower than 2.2). 2006-03-02 Chia-I Wu * src/ftcommon.c (string_render_prepare): Fix a possible crash. 2006-02-28 suzuki toshiya * Makefile: include modules.cfg to reflect module configuration, and ftvalid is built when required stubs (ftgxval and ftotval) are built in libfreetype. 2006-02-27 suzuki toshiya * mac/ftoldmac.m68k_far.make.txt, mac/ftoldmac.ppc_classic.make.txt: Update to new header inclusion introduced on 2006-02-16. 2006-02-27 Chia-I Wu * src/ftcommon.c (my_face_requester): Attach the AFM only for PFA and PFB. 2006-02-25 Werner Lemberg * src/ftbench.c, src/ftcommon.c, src/ftvalid.c: Add proper casts where necessary to allow compilation with C++. Other minor fixes to remove compiler warnings. 2006-02-01 Werner Lemberg * Makefile (PLATFORM): Define to `unixdev' if PLATFORM=unix and DEVEL_DIR is defined. (BIN_DIR, OBJ_DIR): Replaced with... (BIN_DIR_2, OBJ_DIR_2): New variables, set with `?='. Update all callers. (BIN_DIR): Set also. (COMPILE): Add definition for FT_CONFIG_MODULES_H since we always build with an uninstalled FreeType version. (ftdump.$(SO), ftvalid.$(SO), ftview.$(SO)): Add -DFT2_BUILD_LIBRARY since these programs use internal headers. * graph/rules.mk, graph/*/rules.mk: s/OBJ_DIR/OBJ_DIR_2/. * src/ftcommon.c (string_render_prepare): Fix compiler warnings. 2006-01-16 Chia-I Wu Add support for track kerning and a new rendering mode for kerning comparison to ftstring. * src/ftcommon.c (my_face_requester): Try to attach the file having the same name as the font, but with suffix `.afm'. (FTDemo_New): Updated. (FTDemo_String_Set_Kerning, FTDemo_String_Set_Vertical): Removed. (string_load): Rewritten. (string_render_prepare): New function. (FTDemo_String_Draw): Rewritten to have more flexibility. For example, we can now draw the string twice with different kerning modes without reloading the glyphs. * src/ftcommon.h (TGlyph): Add more data, mainly taken from FTDemo_Handle structure. (KERNING_DEGREE_XXX): New enumerations. (FTDemo_String_Context): New structure. (FTDemo_Handle): Updated. (FTDemo_String_Set_Kerning, FTDemo_String_Set_Vertical): Removed. (FTDemo_String_Draw): Updated. * src/ftstring.c: Updated along with many cleanups. (CELLSTRING_HEIGHT): New macro. (RENDER_MODE_XXX): New enumeration values. (status): Add more fields. (event_help, event_angle_change): Updated. (event_render_mode_change): New function. (Process_Event): Handle `1', `2', and `t' events. Update handling of `g', `k', and `V' events. (error_message): Renamed to... (write_header): This. Display point size and rotation angle. (main): Handle new render mode. 2006-01-12 suzuki toshiya Add `ftoldmac' commandline program to test MacOS specific feature: font file access by FSSpec, font file search by old/new QuickDraw, and font name or ATS font name. * mac/ftoldmac.c: Added. * mac/Makefile: Unix Makefile for MacOS X. * mac/ftoldmac.m68k_far.make.txt: MPW Makefile skeleton. * mac/ftoldmac.ppc_carbon.make.txt: MPW Makefile skeleton. * mac/ascii2mpw.py: Python script to generate MPW Makefile from the skeletons. * mac/README: Add note about ftoldmac, because ft2demos/mac was originally for demos built by CodeWarrior. 2005-12-08 Chia-I Wu * src/ftview.c (error_message): Renamed to write_header. Also write face size, first glyph index. Write glyph name if available. (main): Updated to use write_header. 2005-12-04 Chia-I Wu * src/ftbench.c: Update copyright date. Use `getopt' from `common.h'. 2005-12-04 Chia-I Wu * src/ftbench.c: Formatting. Make `face' and `charset' local variables. (btest_t): Use `const' qualifier for `title'. (bcharset_t): Change the type of `size' to `FT_Int'. (face_requester, benchmark): Updated because `face' is no longer global. (test_get_char_index, test_cmap_cache, get_charset): Updated because `charset' is no longer global. (main): New variables, `face' and `charset'. Updated because `face' and `charset' are local now. `get_charset' only when perform FT_BENCH_CMAP. 2005-12-02 Chia-I Wu Overhaul `ftbench.' Now it can perform tests with arbitrary load flags and render mode. Testing `Render' instead of `Load + Render', for example, is also possible now. * src/ftbench.c: Overhauled. 2005-11-30 Werner Lemberg Replace flag `-c' with `-v' to indicate verbosity. * src/ftdump.c (verbose): New global variable. (usage): Updated. (Print_Charmaps): Only take a single argument. Update caller. Always show some charmap info. Use `verbose'. (main): Remove verbose_cmap. Handle `-v' instead of `-c'. * src/common.c (getopt): s/illegal/invalid/. 2005-11-30 Chia-I Wu * src/ftdump.c (Print_Charmaps): face->charmap might be NULL. 2005-11-30 Chia-I Wu * src/ftdump.c (main): New command line option `c' to show the contents of charmaps. (Print_Charmaps): Take one more argument: `verbose'. (usage): Updated. 2005-11-21 Werner Lemberg * graph/grinit.c (grDoneDevices): New function. * graph/graph.h (grInit, grDone): Remove unused declarations. (grDoneDevices): New declaration. * src/ftcommon.c (FTDemo_Display_Done): Call grDoneDevices. (FTDemo_Done): Free `handle'. * src/ftmulti.c (main): Call grDoneSurface and grDoneDevices. 2005-11-18 Werner Lemberg * src/ftvalid.c (run_ot_validator, run_gx_validator, run_ckern_validator): Remove unused variable `memory'. 2005-11-18 suzuki toshiya * src/ftvalid.c: Use FT_TrueTypeGX_Validate, FT_ClassicKern_Validate and FT_OpenType_Validate instead of FT_FREE (it calls FT_Free_Debug of libfreetype, which is not a public function). 2005-11-16 David Turner * graph/graph.h: Updated. * graph/grdevice.c (grSurfaceDone): New function to free surface correctly. This was commented out previously. * graph/x11/grx11.c (gr_x11_device_done): Call XFreeCursor. (gr_x11_surface_done): Call XFreeGC to fix memory leak. * src/ftcommon.c (FTDemo_Display_Done): Call `grDoneSurface' instead of `free' to fix memory leak. * src/ftbench.c (main): Add the `-c' flag to specify maximum iteration count. Useful for repeat profiling. (usage): Updated. 2005-09-29 Werner Lemberg * src/ftcommon.c (FTDemo_Update_Current_Flags): Fix variable shadowing. 2005-09-27 David Turner Fix gamma handling, mainly for LCD modes. * graph/gblgblit.c (GRGB_TO_RGB565): Protect arguments correctly. * graph/gblcolor.h, graph/gblhbgr.h, graph/gblhrgb.h, graph/gblvbgr.h, graph/gblvrgb.h: Call gblender_use_channels. * graph/gblender.c (gblender_clear, gblender_reset): Handle blender cache. (gblender_use_channels): New function. (gblender_reset_key): Improve. (gblender_lookup, gblender_lookup_channel): Comment possible call to gblender_reset. Fix computation of `idx'. (gblender_reset_channel_key): Fix computation of `a' and `r'. * graph/gblender.h (GBLENDER_SHADE_INDEX): Corrected definition. (gblender_use_channels): New declaration. * src/Jamfile: Include ftcommon.c. Fix order of link libraries. 2005-09-22 David Turner * src/ftcommon.c (FTDemo_Update_Current_Flags): Fix load flags computation to mimic libXft's behaviour. 2005-08-30 Werner Lemberg * graph/graph.h (grFillRectangle): Comment out -- we don't have an implementation. 2005-08-23 Masatake YAMATO * src/ftvalid.c: Add gxvalid support. (GX_VALIDATOR_SYMBOL): New definition. (CKERN_VALIDATOR_SYMBOL): New definition. (ValidatorType::GX_VALIDATE): New enum member. (ValidatorType::CKERN_VALIDATE): New enum member. (validator_symbols): Added GX_VALIDATOR_SYMBOL and CKERN_VALIDATOR_SYMBOL. (gx_table_spec): New const. (N_GX_TABLE_SPEC): New definition. (print_usage): Write about gxvalid and ckern valid. (run_gx_validator): New function. (list_gx_tables): Ditto. (run_ckern_validator): Ditto. (list_ckern_tables): Ditto. (main): Call new validators. * src/ftvalid.c: Following are misc modifications. (report_result): Use printf instead fprintf. Fix incorrect message. (main): Use switch/case instead of if/else when calling per validator functions. Call FT_Done_Face. Use a loop to set validator. (print_usage): Insert empty line in usage strings. (validator_symbols): Added NULL as the last array element. 2005-07-04 Chia I Wu * src/ftcommon.i: Removed. * src/ftgamma.c: Updated to use api provided by ftcommon.c. * Makefile: Make ftgamma depend on ftcommon.c. Remove dependency of ftmulti.c on ftcommon.i. 2005-06-17 Werner Lemberg * Makefile: Update rules for ftview and ftstring which no longer depend on ftcommon.i but on ftcommon.c. (LINK_ITEMS, LINK_CMD, LINK_LIBS): New variables. (GRAPH_LINK2): Removed. (COMMON_LINK, GRAPH_LINK): Replace with... (LINK_COMMON, LINK_GRAPH): This. Use LINK_ITEMS, LINK_CMD, and LINK_LIBS. Update all affected targets. (LINK_NEW): Temporary new link command to handle executables which use ftcommon.c. (FTCOMMON_OBJ): New variable to handle ftcommon.c. 2005-06-17 Chia I Wu * src/ftcommon.c, src/ftcommon.h: New files. * src/ftstring.c: Rewritten. Make the function keys more compatible with ftview.c. New key 'V' for vertical rendering. * src/ftview.c: Rewritten. Now we can use number keys (i.e. 1, 2, ...) to select rendering mode. 2005-06-08 Werner Lemberg * Version 2.1.10 released. ========================== 2005-05-26 Werner Lemberg * src/ftcommon.i (get_glyph_bitmap, glyph_to_bitmap): Initialize `target->grays' even for FT_PIXEL_MODE_MONO since it is tested in grBlitGlyphToBitmap. * graph/x11/grx11.c (gr_x11_surface_init): Initialize `xswa.border_pixel'. 2005-05-25 Chia I Wu * src/ftcommon.i: Include FT_SYNTHESIS_H. Make `render_mode' an enumeration. * src/ftview.c (Render_Embolden): New function. (Process_Event, main): Update to `render_mode' enumeration. 2005-05-23 Werner Lemberg * src/ftvalid (main) <'v'>: Add cast to make it compile with C++. 2005-04-24 YAMATO Masatake * src/ftvalid.c: New file. * Makefile, src/Jamfile: Add ftvalid. 2005-03-04 Werner Lemberg * src/ftgamma.c (Render_GammaGrid), src/ftmulti.c (parse_design_coords), src/ftview.c (Render_GammaGrid): Fix compiler warnings. 2005-02-28 David Turner * src/ftbench.c (preload, memory_file, memory_size): New global variables. (bench_open_close): Handle `preload' by using `FT_New_Memory_Face'. (main): Remove `preload', `memory_file', and `memory_size'. 2005-02-23 David Turner * src/ftbench.c (fetch_test, cbox_test): Fix memory leaks. 2005-02-12 Werner Lemberg Make ft2demos support a separate build directory. * Makefile (have_makefile): New variable. Set if the build directory is the same as the source directory. (GRAPH_DIR): Give full path. (BIN_DIR, OBJ_DIR): Updated. (FT_INCLUDES): Include $(OBJ_BUILD). (LINK) : Fix path to `libtool'. * README: Updated. 2004-12-15 Werner Lemberg * src/ftcommon.i (glyph_to_bitmap): Don't convert 1bpp bitmaps. 2004-12-14 Werner Lemberg * src/ftcommon.i: Include new FT_BITMAP_H. Remove dead code. (ft_bitmap): New global variable. (init_freetype): Call FT_Bitmap_New. (done_freetype): Call FT_Bitmap_Done. (glyph_to_bitmap, get_glyph_bitmap): Handle 2bpp and 4bpp bitmaps using FT_Bitmap_Convert. 2004-12-12 Steve Hartwell * graph/grblit.c (blit_mono_to_rgb32): Advance read buffer properly. 2004-11-26 Jouk Jansen * vms_make.com: Don't assume that the ft2demos package is a subdirectory of freetype2. Fix `ccopt'. 2004-11-19 Werner Lemberg * src/ftview.c (Render_Waterfall): Handle size as points, not as pixels. * src/ftstring.c (layout_glyphs), src/ftmulti.c (LoadChar), src/ftcommon.i (set_current_image_type): Always use FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH. 2004-11-16 Dr. Martin P.J. Zinser * vms_make.com: Updated to be in sync with vms_make.com from FT2. 2004-10-18 Werner Lemberg * graph/gblblit.c (gblender_blit_init): Fix blit test. 2004-09-08 Jouk Jansen * graph/x11/grx11.c [__VMS]: Include vms_x_fix.h. * vms_make.com: Updated. 2004-08-29 Werner Lemberg * graph/gblender.c (gblender_lookup, gblender_lookup_channel): s/index/idx/ to avoid compiler warnings. 2004-08-19 Werner Lemberg * src/ftstring.c (prepare_text): Handle encoding = 0. 2004-07-14 Werner Lemberg * src/ftcommon.i (get_glyph_bitmap): Don't accept a `missing' character with zero or negative width. 2004-07-13 David Turner * graph/x11/grx11.c (gr_x11_device_init): Fix memory leak. * src/ftbench.c (bench_cmap_parse): New function, assigned to key `j'. (usage, main): Updated. * src/ftcommon.i (install_font_file): Initialize `cmap_index' here. (my_face_requester): Don't initialize `cmap_index'. (glyph_to_bitmap): Add new argument to get glyph reference. (get_glyph_bitmap): Updated. * src/ftview.c (Render_Stroke): Increase stroker limit. Fix glyph indices. Fix memory leaks. 2004-06-24 David Turner * Version 2.1.9 released. ========================= 2004-06-24 Werner Lemberg * Makefile (GRAPH_LINK): Add $(MATH). Remove $(MATH) from link rule for ftstring. 2004-06-23 Werner Lemberg * src/ftbench.c: Fix compiler warnings. (usage): Updated. 2004-06-23 David Turner * src/ftbench.c (bench_open_close): New benchmark to measure face open/close performance (controlled by the `i' flag for the `-b' command-line option flag). (main): Use it. 2004-06-11 Werner Lemberg * src/ftstring.c (layout_glyphs): Updated to latest FreeType library changes. 2004-06-03 Werner Lemberg Add autohinting toggling (using the `f' key) to ftstring. Handle new inter-letter spacing support for autohinting. * src/ftstring.c (autohint): New global variable. (layout_glyphs): Handle `autohint' variable. Handle new `lsb_delta' and `rsb_delta' elements of face->glyph->metrics. Remove some dead code. (Help): Updated. (Process_Event): Handle key `f'. Extend key `k'. 2004-05-23 Werner Lemberg * graph/gblender_blit.c: Renamed to... * graph/gblblit.c: This. Updated to use new include file names. (gblender_blit_init): Change 11th argument to `unsigned char*' * graph/gblender_blit.h: Renamed to... * graph/gblblit.h: This. Updated. * graph/gblender_blit_any.h: Renamed to... * graph/gblany.h: This. Updated to use new include file names. * graph/gblender_blit_hbgr.h: Renamed to... * graph/gblhbgr.h: This. * graph/gblender_blit_hrgb.h: Renamed to... * graph/gblhrgb.h: This. * graph/gblender_blit_vbgr.h: Renamed to... * graph/gblvbgr.h: This. * graph/gblender_blit_vrgb.h: Renamed to... * graph/gblvrgb.h: This. * graph/gblender.h (GBLENDER_CHANNEL_VARS): Remove final `;'. * graph/grblit.c: Updated to use new include file names. * graph/rules.mk, graph/Jamfile: Updated. * Makefile: Build `ftgamma'. * src/ftview.c (Render_GammaGrid): Fix compiler warnings. (Help): Updated. * src/ftgamma.c: Fix compiler warnings. 2004-05-20 David Turner Adding support for fast gamma-corrected alpha-blending. New test program `ftgamma'. * graph/grblit.c: Include gblender_blit.h. (GRAY8): New macro. (blit_gray8_to_555, blit_gray8_to_565, blit_gray8_to_24, blit_lcd8_to_24, blit_lcd28_to_24) [GRAY8]: New functions. (blit_gray8_to_32): New function. (gr_gray8_blitters) [GRAY8]: New function table. (grSetGlyphGamma): New function. (grBlitGlyphToBitmap): Implement blending. * graph/graph.h (grSetGlyphGamma): New declaration. * graph/grfont.c, graph/grfont.h (grSetPixelMargin): New function. * graph/gblender.c, graph/gblender.h, graph/gblender_blit.c, graph/gblender_blit.h, graph/gblender_blit_any.h, gblender_blit_color.h, gblender_blit_hbgr.h, gblender_blit_hrgb.h, gblender_blit_vbgr.h, gblender_blit_vrgb.h: New files. * graph/Jamfile (graph_sources): Add gblender and gblender_bnit. * graph/rules.mk (GRAPH_H, GRAPH_OBJS): Updated. * src/ftcommon.i (the_gamma): New global variable. (Init_Display): Call grSetGlyphGamma. * src/ftgamma.c: New demo program. * src/ftview.c: Include math.h. (Render_GammaGrid): New function. (Help): Updated. (Process_Event): Assign increase and decrease of gamma value to keys `g' and `G'. Assign gamma grid rendering mode to key `K'. (main): Updated. * src/Jamfile (LINKLIBS): Add -lm. (GRAPHIC_PROGRAMS): Add ftgamma.c. Add LINKLIBS for all GRAPHIC_PROGRAMS. * vms_make.com: Updated. 2004-05-19 George Williams * src/ftmulti.c (main): Use default axis values. 2004-05-09 Werner Lemberg * src/ftdump.c (put_unicode_be16): Initialize `ch'. 2004-04-29 Flavio Stanchina Parse SFNT `name' table in ftdump if new option -n is given. * src/ftdump.c: Include FT_SFNT_NAMES_H and FT_TRUETYPE_IDS_H. (name_tables): New global variable. (usage): Show -d and -i info conditionally. Add -n info. (platform_id, name_id, put_ascii, put_unicode_be16, Print_Sfnt_Names): New functions. (main): Handle -n. 2004-04-24 George Williams Add GX var font support to ftmulti. Add command line option `-d' to ftmulti to select design coordinates. * src/ftmulti.c: New global variables `requested_pos' and `requested_cnt'. Make `multimaster' a pointer. (parse_design_coords): New function. (Help, usage): Updated. (Process_Event) : Don't use fixed 20 unit steps but a proportional granularity. Use FT_Set_Var_Design_Coordinates instead of FT_Set_MM_Design_Coordinates. (main): Handle new option `-d'. Use FT_Get_MM_Var and FT_Set_Var_Design_Coordinates instead of FT_Get_Multi_Master and FT_Set_MM_Design_Coordinates. 2004-04-23 Werner Lemberg * src/ftcommon.i (TFont): Add `cmap_index'. (my_face_requester): Set `font->cmap_index'. (get_glyph_index): Properly set third argument. 2004-04-21 David Turner * Version 2.1.8 released. ========================= 2004-04-10 Werner Lemberg * src/ftbench.c (cmap_cache_test, main): Use proper cast for `face_id'. 2004-03-26 Ulrich * graph/x11/grx11.c (grX11DeviceRec): Add `visual' member. (gr_x11_device_init): Directly manipulate `x11dev'. Use XGetVisualInfo. (gr_x11_surface_init): Directly use `x11dev'. Fix other visual selection problems. 2004-03-20 Steve Hartwell Updated to make it compile with newer MacOS versions. * graph/mac: Don't include Windows.h but MacWindows.h. Include SIOUX.h only if __MWERKS__ is defined. (refresh_rectangle): Updated. (listen_event): Remove `theEventMask'. Updated. Make code conditional to __MWERKS__ which is related to SIOUX. (init_surface): Handle gr_pixel_mode_rgb24. Updated. 2004-02-20 Werner Lemberg Add `light' render mode to ftview (using key `L'). * src/ftcommon.i (set_current_image_type): Handle FT_LOAD_TARGET_LIGHT. (glyph_to_bitmap, get_glyph_bitmap): Updated. * src/ftview.c (Process_Event): Provide proper header for `light' render mode. (Help): Updated. 2004-02-18 Werner Lemberg * src/ftcommon.i: Include FT_CACHE_MANAGER_H and FT_STROKER_H. Don't include obsolete FT_CACHE_* macros. (glyph_to_bitmap): Remove declaration of `error'. * src/ftview.c: Don't include FT_CACHE_MANAGER_H. (Render_Stroke): Remove declaration of `error'. Fix other compiler warnings. (Render_Waterfall): Remove declaration of `face'. 2004-01-29 David Turner * src/ftcommon.i (get_glyph_bitmap): Rewritten for new cache code. (glyph_to_bitmap): New function. * src/ftview.c (Render_Stroke): New function. (Render_Waterfall): Use FTC_Manager_LookupFace. (Process_Event) <' '>: Provide header text for stroked text. (main): Add Render_Stroke. 2003-12-26 Werner Lemberg * src/ftcommon.i (set_current_size): Don't allow values larger than 0xFFFF. * src/ftview.c (main): Set `face'. (Render_Waterfall): Don't set `face'. use precomputed value instead. (main): Don't use `face->' but `size->face->'. Use `exit' in case of fatal error. Don't test `face' but `size' for printing error messages. Print proper error message for FT_Err_Invalid_PPem. 2003-12-21 David Turner * graph/graph.h (grPixelMode): Add `gr_pixel_mode_lcd2' and `gr_pixel_mode_lcdv2' modes. (grBlitGlyphToBitmap): Remove `is_bgr' argument. Updated all callers. * graph/grblit.c (blit_mono_to_pal8): Speed up loop. (blit_lcd_to_24, blit_lcdv_to_24): Remove `is_bgr' argument. (blit_lcd2_to_24, blit_lcdv2_to_24): New functions. (compute_clips): Updated. (grBlitGlyphToBitmap): Remove `is_bgr' argument. Use new blitter functions for the two new modes. * graph/win32/Jamfile: s/TOOLSET/JAM_TOOLSET/. * src/gbench.c, src/gbench.h: New files. * src/Jamfile: Handle `gbench'. * src/ftbench.c, src/ftcommon.i, src/ftview.c: Updated to use new FreeType cache implementation and new blitter modes. 2003-11-10 Werner Lemberg Add display of bitmap fonts to ftstring. * src/ftstring.c (layout_glyphs): Call FT_Vector_Transform for scalable fonts only. (render_string): Handle bitmap fonts. 2003-11-07 Werner Lemberg * Version 2.1.7 released. ========================= 2003-11-06 David Turner * Version 2.1.6 released. ========================= 2003-11-01 Werner Lemberg * src/testname.c: Include ft2build.h. 2003-10-22 Werner Lemberg * src/ftdump.c (usage): Fix typo. 2003-10-17 Werner Lemberg * src/ftmulti.c (main): Call `FT_Done_Face'. * src/ftstring.c (main): Clean up glyph and face objects, then finish FreeType library. 2003-10-10 Werner Lemberg * src/ftmulti.c (Help): Document all keys. (main): Call FT_Done_FreeType. 2003-09-02 David Turner * Version 2.1.5 released. ========================= 2003-06-30 Werner Lemberg * src/ftdump.c (Print_Fixed): Print all elements of face->available_sizes. 2003-06-17 Werner Lemberg * src/*.c: s/ft_glyph_format_*/FT_GLYPH_FORMAT_*/. s/ft_pixel_mode_*/FT_PIXEL_MODE_*/. s/ft_glyph_bbox_*/FT_GLYPH_BBOX_*/. 2003-06-16 YAMANO-UCHI Hidetoshi * graph/x11/rules.mk (GRAPH_LINK): Add run-time search path on Unix systems. 2003-06-16 Werner Lemberg * src/ftcheckfixedwidth.c: Renamed to... * src/ftchkwd.c: This. * src/testnames.c: Renamed to... * src/testname.c: This. * src/Jamfile, Makefile: Updated. 2003-06-15 Werner Lemberg * *.mk: Updated and revised to latest changes in FreeType 2. 2003-06-13 Werner Lemberg * src/ftdump.c (Print_Type): Don't emit bbox, ascender, descender, and height for non-scalable fonts. 2003-06-08 Werner Lemberg * graph/x11/grx11.c (gr_x11_surface_init): Add proper cast in call to grAlloc. * src/ftbench.c (main): Add proper cast in call to malloc. Use FT_ENCODING_NONE, not 0. 2003-06-01 Werner Lemberg * src/ftview.c (Render_Waterfall): Handle fixed-sized fonts better. 2003-05-27 Martin Zinser * vms_make.com: Handle ftbench. 2003-05-21 Werner Lemberg * src/ftcommon.i (install_font_file): Initialize new elements of reallocated `fonts' array with zero bytes. 2003-05-20 Martin Zinser * descrip.mms: Removed. Now created by... * vms_make.com: New file. 2003-05-19 Werner Lemberg * src/ftcommon.i (install_font_file): Use calloc to allocate `fonts'. (done_freetype): Deallocate `fonts'. 2003-04-28 Werner Lemberg * src/ftcheckfixedwidth.c: Remove unused global variables; make global variables local to `main' if possible. Fixed compiler warnings (s/index/idx/). 2003-04-25 Davor Buvinic * Makefile: Add rules to build ftcheckfixedwidth. 2003-04-24 Anthony Fok * src/ftcommon.i: Replace `ft_encoding_*' with `FT_ENCODING_*'. (file_suffixes): Add `.otf'. (install_font_file): Set font->num_indices depending on encoding. * src/ftmulti.c, src/ftstring.c, src/fttimer.c, src/ftview.c: Replace `ft_encoding_*' with `FT_ENCODING_*'. * src/testnames.c: Replace `ft_render_mode_mono' with `FT_RENDER_MODE_MONO'. 2003-04-09 David Turner * Jamfile: Set FT2_TOP. * src/ftbench.c (main): Use `long' for `max_bytes'. * src/ftcheckfixedwidth.c: New test program. * src/ftstring.c: (prepare_text): Remove unused variable `codepoint'. (apply_gamma): Fix initialization of `buffer'. * src/ftview.c (Render_Waterfall): Print more characters. 2003-04-08 David Turner * Version 2.1.4 released. ========================= 2002-12-02 Antoine Leca * src/ftstring.c: Use `FT_ENCODING_*' everywhere instead of deprecated lowercase variants. (prepare_text): 'message' for the -m option is now expected to be encoded with UTF-8. This allows testing of Unicode chars, including non-BMP characters. 2002-12-01 Antoine Leca * graph/win32/rules.mk: Adding link rules for Borland C++. 2002-11-18 David Turner * Version 2.1.3 released. ========================= 2002-11-10 David Turner * src/Jamfile (PROGRAMS): Add `ftcheckfixedwidth'. 2002-09-25 David Turner * graph/win32/grwin32.c: Removing compiler warnings. * descrip.mms: Removing 'ftmemchk' and 'testnames' from the list of programs to compile, these are now obsolete. 2002-09-25 Anthony Fok * src/ftbench.c: The program did perform out-of-bound memory writes with certain fonts containing a buggy charmap. 2002-09-18 Werner Lemberg Add LCD BGR support. * graph/grblit.c (blit_lcd_to_24, blit_lcdv_to_24): Add parameter `is_bgr' to assign color components in reversed order. (grBlitGlyphToBitmap): Add parameter `is_bgr' passed on to `blit_lcd_lcd*'. Updated all callers. Remove unused label. * graph/graph.h, graph/grfont.c: Updated. * src/ftcommon.i (set_current_image_type), src/ftview.c (Render_All, Render_Text, Render_Waterfall, Process_Event): Handle LCD modes 3 and 4. * src/ftstring.c, src/ftmulti.c: Updated. * graph/x11/grx11.c (gr_x11_device_init, gr_x11_surface_init): Remove unused variables. (gr_x11_format_rgb555): Fix typos. 2002-09-08 David Turner Add support for sub-pixel rendering. * graph/x11/grx11.c, graph/win32/grwin32.c: Completely rewritten to support 24-bits RGB surfaces. This is needed to test sub-pixel rendering. Note that other drivers haven't been touched yet. The X11 driver doesn't work with 8-bit displays for now, but a reduced mode will probably be introduced in the near future. * graph/graph.h (grPixelMode): Add `gr_pixel_mode_lcd' and `gr_pixel_mode_lcdv'. * graph/grblit.c (compute_clips): Use `gr_pixel_mode_lcd' and `gr_pixel_mode_lcdv'. (compose_pixel_full): New macro. (compose_pixel): Use it. (blit_lcd_to_24, blit_lcdv_to_24): New functions. for RGB-decimated modes (BGR not yet implemented). (gr_color_blitters): Updated. (grBlitGlyphToBitmap): Support new pixel modes. * src/Jamfile (PROGRAMS): Don't include fttimer, fttry, and testnames. * src/ftbench.c: Updated to latest changes in FreeType library. * src/ftcommon.i (Init_Display): New default mode is `gr_pixel_mode_rgb24'. (set_current_image_type, get_glyph_bitmap): Add support for LCD modes (horizontal and vertical). * src/ftview.c (Render_Waterfall): Call `set_current_size'. (Help): Document new `L' key for cycling through the pixel modes. (Process_Event): Handle `L' key. 2002-08-04 Vincent Caron * src/ftcommon.i (Text), src/ftmulti.c (Text): s/jumped/jumps/. * src/ftview.c (Render_Waterfall): Remove unused variable. 2002-07-03 David Turner * src/ftview.c (Render_Waterfall): New function, adding a "waterfall" rendering mode (accessible by cycling modes with the space bar). (Process_Event, main): Use it. 2002-07-01 David Turner * src/ftbench.c: Adding the "-p" option to pre-load font files in memory. This is a very useful thing to quantify the performance improvements achieved by many of FreeType internal optimizations regarding stream i/o. * src/ftstring.c (reset_transform): Fix Werner's incorrect fix. 2002-06-25 Werner Lemberg * src/ftstring.c (reset_transform): Fix transformation matrix. 2002-06-23 Vincent Caron Adding support for gamma-corrected display to ftstring (assigned to `g', F9, and F10 keys). * src/ftstring.c (use_gamma, gamma_value, gamma_ramp): New global variables. (init_gamma, apply_gamma, draw_gamma_ramp): New functions. (render_string): Use apply_gamma. (Help): Updated. (Process_Event): Handle `g', F9, and F10 keys. (main): Call init_gamma and draw_gamma_ramp. 2002-06-21 David Turner * Version 2.1.2 released. ========================= 2002-06-14 Werner Lemberg * Makefile, graph/rules.mk: s/TOP/TOP_DIR/, s/TOP2/TOP_DIR_2/. 2002-06-10 Werner Lemberg * src/ftbench.c: s/index/idx/. Fixed more gcc compiler warnings. 2002-06-10 David Turner * src/ftbench.c: Removing compiler warnings. * src/ttdebug.c: Updating to latest internal changes. 2002-06-09 David Turner * Version 2.1.1 released. ========================= 2002-06-07 David Turner Adding Vincent Caron's benchmark program. * src/ftbench.c: New file. * Makefile, src/Jamfile: Updated. Other minor fixes. * src/ftview.c (Render_Text): Call get_glyph_index() conditionally. 2002-05-20 Werner Lemberg * src/ftcommon.i (get_glyph_bitmap): Use `sbit->num_grays'. Handle `sbit->buffer == 0' correctly. 2002-05-17 Michael Pfeiffer * graph/beos/Jamfile: New file. 2002-05-12 Werner Lemberg * README: Updated. 2002-05-12 Michael Pfeiffer * graph/Jamfile: Add support for BeOS. 2002-04-28 Werner Lemberg * src/ftview.c (Render_Text): Don't call `get_glyph_index'. This is done in `get_glyph_bitmap'. * src/ftstring.c (encoding): New global variable, initialized to `ft_encoding_unicode'. (render_mode): Removed. (make_tag): New utility function (copied from ftcommon.i). (prepare_text): Call `FT_Select_Charmap'. (Process_Event): Don't handle ` '. (main): Add option -e to select encoding. (usage): Document it. * src/ftmulti.c (encoding): New global variable. (make_tag): New utility function (copied from ftcommon.i). (main): Add option -e to select encoding. (usage): Document it. 2002-04-28 Martin Zinser * descrip.mms: Add clean target. Handle compiler options better. 2002-04-17 David Turner * Version 2.1.0 released. ========================= 2002-04-01 Werner Lemberg * graph/x11/grx11.c: Use `c_class' instead of `class' if compiling with C++. * src/ftcommon.i (encoding): Use `FT_Encoding' type. Update all using code. (done_glyph_bitmap): Use cast. * src/ftview.c: Updated to changes in `ftcommon.i'. (main): Use cast for `encoding'. 2002-03-30 Werner Lemberg * src/ftdump.c (Print_Type): Use `%ld' for some fields. * src/testnames.c (main): Exit if no parameter. 2002-03-21 David Turner * graph/grblit.c, graph/win32/grwin32.c, src/common.c, src/ftcommon.i, src/ftdump.c: Getting rid of compiler warnings. 2002-03-08 David Turner * Version 2.0.9 released. ========================= 2002-03-06 David Turner * src/ftdump.c: Added display of ascender/descender/text height. * Jamfile: Support the FT2_TOP environment variable to indicate where the FreeType 2 sources are located. This is very useful for switching between the STABLE and HEAD branches of the library. 2002-03-05 David Turner * src/ftdump.c: Added the display of a font's Postscript name, EM size and global Bbox. Now supports the debugging mode of 2.1.x. * src/ftview.c: Minor change to support debugging mode of 2.1.x. 2002-02-14 Detlef Würkner * src/fttimer.c (ConvertRaster): Handle embedded bitmaps properly. * src/ftstring.c (use_sbits): Default value is no 0. (layout_glyphs): Handle `use_sbits'. (Process_Event): Make friendlier error messages. 2002-02-09 David Turner * Version 2.0.8 released. ========================= 2002-02-02 David Turner * Version 2.0.7 released. ========================= 2002-01-25 Martin Zinser * src/common.h ([VMS]): Alias stuff specific to getopt. * graph/grinit.c ([DEVICE_X11]): Handle VMS. * descrip.mms: New file for compiling the demo programs with OpenVMS. 2002-01-07 David Turner * Version 2.0.6 released. ========================= 2001-12-31 Werner Lemberg * graph/x11/rules.mk: Fix typo (wilcard -> wildcard). 2001-12-30 David Turner * README: Updated to version 2.0.6. * graph/x11/rules.mk: Updated X11 detection rules: "/usr/X11R6" and "/usr/local/X11R6" are now probed as a fallback. This allows the test programs to work automatically on Debian Linux systems (which only use "/usr/bin/X11" in the path). 2001-12-21 David Turner * src/ftcommon.i (get_glyph_bitmap): Added a missing error check. Make the function return an error code if necessary. * src/testnames.c (main): Fix typo. 2001-12-15 Werner Lemberg * Makefile: Add `testnames' program. * src/testnames.c (main): Remove unused variable. First command line parameter is now used as the font to be tested instead of a fixed string. 2001-12-14 David Turner * src/ftstring.c (layout_glyphs): Fix centering bug. 2001-12-12 David Turner * src/testnames.c: New test program. 2001-12-08 David Turner Use new charmap cache. * src/ftcommon.i: Include FT_CACHE_CHARMAP_H. (cmap_cache): New global variable. (encoding): Change type to FT_UInt32. (init_freetype): Initialize charmap cache. (get_glyph_index): New function. (get_glyph_bitmap): Use it. Increase pixel dimensions to 48 for sbit cache. Add ftc_image_format_outline flag if not a bitmap glyph. * src/ftview.c: Use `get_glyph_index'. 2001-12-06 David Turner An update to use the new cache manager code. * src/ftcommon.i: s/FTC_Image_Cache/FTC_ImageCache/. s/FTC_SBit_Cache/FTC_SBitCache/. s/FTC_Image_Desc/FTC_ImageDesc/. s/image_type/type/. (done_glyph_bitmap): New function. (get_glyph_bitmap): Add new argument. Use sbits cache only of pixel size <= 32. Other fixes. * src/ftview.c (Render_All, Render_Text): Updated to changes in ftcommon.i. 2001-12-05 Werner Lemberg * src/ftcommon.i, src/ftview.c: s/manager/cache_manager/ to avoid compiler warnings. 2001-12-05 Taiji Yamada * src/graph/x11/grx11.c (done_surface): Free and reset color map. (init_surface): Use private colormap if there are no more shared colormap entries. 2001-10-27 David Turner * src/ftcommon.i (use_sbits_cache): Set to 1. 2001-10-26 Leonard Rosenthol * mac/codewarrior/carbonprefix.h: New file to define building the demos Carbonized. * mac/codewarrior/ftview.prj: Updated for CW7 and to build a Carbonized version. * mac/getargv.c: Updated to build Carbonized. * mac/ftview_m.c: Updated to build Carbonized. 2001-10-18 David Turner * Jamrules: Define X11_LINKLIBS. * README: Updated. * graph/os2/Jamfile: Define GROS2_PATH and GRAPH_LINKLIBS. * src/Jamfile (PROGRAMS): Add fttry. Fix order of libraries. * src/ftview.c (main): Update cache dump code. * src/ftlint.c (main) [TEST_PSNAMES]: Add some debugging code. * src/fttry.c (main) [DUMP_NAME]: Add some glyph name debugging code. 2001-10-17 David Turner * Version 2.0.5 released. ========================= 2001-09-21 Eric Olson * graph/os2/gros2pm.c: Remove global variable `window_created'. (LOCK): Fix typo. (refresh_rectangle): Use LOCK() and UNLOCK(). (init_surface): Don't use `window_created'. Use LOCK() and UNLOCK(). (RunPMWindow): Use LOCK() and UNLOCK(). Fix typo. Don't use `window_created'. (Message_Process): Allow F9, F10, and others keys to pass through the application. Use LOCK() and UNLOCK(). 2001-09-10 Werner Lemberg * README: Slight update. 2001-08-25 Werner Lemberg Added CMap support to ftview: The new flag `-e' accepts an encoding tag as defined in freetype.h (e.g. `unic') to select a character map. Only fonts with a valid character map are selected. * src/ftcommon.i: s/num_glyphs/num_indices/. (encoding): New global variable. (make_tag): New function. (install_font_file): If a cmap tag has been specified, load functions only which have a valid cmap. (my_face_requester): Select cmap also if `encoding' is non-zero. (get_glyph_bitmap): Map char index to glyph if `encoding' is non-zero. * src/ftview.c: s/first_glyph/first_index/. (Help): Adjust help text. (usage): Document -e switch. (main): Implement -e switch. Adjust `Header'. * Version 2.0.4 released. ========================= 2001-06-27 Werner Lemberg * src/ftmemchk.c: s/memtest/ftmemchk/. 2001-06-27 David Turner * src/ftcommon.i, src/ftmemchk.c: Changes due to the modification of the FT_CALLBACK_DEF macro definition. 2001-06-24 David Turner Renamed the test program "memtest" to "ftmemchk". * src/memtest.c: Renamed to ... * src/ftmemchk.c: This file. * Makefile, src/Jamfile: Updated. * Version 2.0.3 released. ========================= 2001-05-28 David Turner * Jamfile, src/Jamfile, graph/os2/Jamfile, graph/win32/Jamfile, graph/x11/Jamfile: Updating Jamfiles to correctly link the graphics programs on all platforms with Jam. * src/ftstring.c: Removing debugging output. 2001-04-25 David Turner * graph/beos/grbeos.cpp, graph/beos/grbeos.h, graph/beos/rules.mk, graph/grinit.c: added BeOS graphics driver to MiGS. 2001-04-04 Werner Lemberg * graph/allegro/gralleg.c, graph/mac/grmac.c, graph/os2/gros2pm.c, graph/x11/grx11.c: Don't include system-specific header but `grobjs.h'. * graph/x11/grx11.c: Some structural reorderings. Include `grdevice.h'. * graph/grinit.c: Use subdirectories for #include. * graph/rules.mk, graph/*/rules.mk (DEVICE_INCLUDE): Removed. * Jamrules, Jamfile, */Jamfile: Updated. It now compiles with X11 also (no checking for X header and lib locations yet). 2001-04-04 David Turner * Jamrules, Jamfile, graph/Jamfile, graph/x11/Jamfile, graph/win32/Jamfile, graph/os2/Jamfile, src/Jamfile: Added Jamfiles to build the FreeType 2 demos with Jam. Be careful, they probably don't work on Unix and OS/2 yet. 2000-03-24 David Turner * Version 2.0.2 released. ========================= 2001-03-23 David Turner * Makefile, src/*.c: Changed to new header inclusion scheme. 2001-03-13 Werner Lemberg * graph/x11/grx11.c: Increase MAX_PIXEL_MODES to 100. 2001-03-06 Werner Lemberg * src/memtest.c (my_memory): Add cast to remove C++ compiler error. 2001-02-22 David Turner * src/memtest.c: Fixed the debug memory allocator. The constant "my_memory" was replaced by a function that allocates a new "memory allocator through "my_alloc()" and returns it. 2001-02-06 James H. Cloos Jr. * src/ftview.c (Render_Text): Fix rendering of test string. 2001-01-31 Werner Lemberg * src/ftstring.c (Help): Added `void' type. 2000-12-09 Werner Lemberg * Makefile: Added $(LDFLAGS) variable for `unix' link target. 2000-12-01 David Turner * Version 2.0.1 released. ========================= 2000-11-09 David Turner * Version 2.0 released. ======================= Local Variables: version-control: never coding: utf-8 End: ft2demos-2.10.1/README0000644000175000001440000000556313506424316014054 0ustar00wlusers00000000000000This package contains example programs for the FreeType 2 library. WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING The Makefile and Jamfile contained in this directory assume that the FreeType 2 library sources are located in `../freetype2'. If you downloaded one of the stable FreeType 2 source packages from our server, you most probably have to rename its directory, for example: mv freetype-2.10.1 freetype2 on Unix rename freetype-2.10.1 freetype2 on Windows WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING First compile the FreeType 2 library, then say `make'. However, you must rename the directory of the FreeType 2 library to `freetype2' (or create a symlink) before doing this. Note that the demonstration programs include a tiny graphics sub-system that includes `drivers' to display Windows on Win32, X11, BeOS, Mac, and OS/2. The build system should automatically detect which driver to use based on the current platform. UNIX USERS ========== X11 issues ---------- When building the demos, the build system tries to detect your X11 path by looking for the patterns `X11/bin', `X11R6/bin', and `X11R5/bin' in your current path (in this order). If no X11 path is found, some demo programs will not be able to display graphics and will fail. If you have X11 in an unusual place, use the X11_PATH make variable. More than one directory, if necessary, must be separated with spaces. Example: make X11_PATH="/usr/openwin /usr/local/X11R6" The build system then derives the X11_INCLUDE include file path from X11_PATH by appending `/include' to all path components. It also derives the X11_LIB library path from X11_PATH by appending `/lib64' and `/lib' to all components (in that order). You might override those variables similar to X11_PATH as arguments to `make'. If you don't have X11 at all, fix the definition of the EXES variable as described in the top-level Makefile. Recent versions of Mac OS X no longer deliver X11 by default; you have to install XQuartz, see https://support.apple.com/en-us/HT201341 for more details. Using a different build directory --------------------------------- If the `configure' script of the FreeType 2 library is run from a separate build directory, it creates a dummy Makefile which sets some variables before including the top-level Makefile of the source directory. This dummy Makefile can also be used for the ft2demos package to be compiled in a different build directory: make FT2DEMOS=1 -f /path/to/freetype2/build-dir/Makefile If necessary, adapt the `TOP_DIR_2' variable to make it point to the ft2demos source directory. --- end of README ---