| @@ -33,7 +33,7 @@ | |||||
| <PackageName Value="LCL"/> | <PackageName Value="LCL"/> | ||||
| </Item1> | </Item1> | ||||
| </RequiredPackages> | </RequiredPackages> | ||||
| <Units Count="10"> | |||||
| <Units Count="15"> | |||||
| <Unit0> | <Unit0> | ||||
| <Filename Value="TextSuiteTest.lpr"/> | <Filename Value="TextSuiteTest.lpr"/> | ||||
| <IsPartOfProject Value="True"/> | <IsPartOfProject Value="True"/> | ||||
| @@ -59,6 +59,7 @@ | |||||
| <Unit4> | <Unit4> | ||||
| <Filename Value="old\TextSuiteImports.pas"/> | <Filename Value="old\TextSuiteImports.pas"/> | ||||
| <IsPartOfProject Value="True"/> | <IsPartOfProject Value="True"/> | ||||
| <UnitName Value="TextSuiteImports"/> | |||||
| </Unit4> | </Unit4> | ||||
| <Unit5> | <Unit5> | ||||
| <Filename Value="old\TextSuiteWideUtils.pas"/> | <Filename Value="old\TextSuiteWideUtils.pas"/> | ||||
| @@ -77,11 +78,34 @@ | |||||
| <Unit8> | <Unit8> | ||||
| <Filename Value="old\TextSuiteTTFUtils.pas"/> | <Filename Value="old\TextSuiteTTFUtils.pas"/> | ||||
| <IsPartOfProject Value="True"/> | <IsPartOfProject Value="True"/> | ||||
| <UnitName Value="TextSuiteTTFUtils"/> | |||||
| </Unit8> | </Unit8> | ||||
| <Unit9> | <Unit9> | ||||
| <Filename Value="old\TextSuiteVersion.pas"/> | <Filename Value="old\TextSuiteVersion.pas"/> | ||||
| <IsPartOfProject Value="True"/> | <IsPartOfProject Value="True"/> | ||||
| </Unit9> | </Unit9> | ||||
| <Unit10> | |||||
| <Filename Value="new\utsFontCreatorGDI.pas"/> | |||||
| <IsPartOfProject Value="True"/> | |||||
| <UnitName Value="utsFontCreatorGDI"/> | |||||
| </Unit10> | |||||
| <Unit11> | |||||
| <Filename Value="new\utsTtfUtils.pas"/> | |||||
| <IsPartOfProject Value="True"/> | |||||
| </Unit11> | |||||
| <Unit12> | |||||
| <Filename Value="new\utsTypes.pas"/> | |||||
| <IsPartOfProject Value="True"/> | |||||
| </Unit12> | |||||
| <Unit13> | |||||
| <Filename Value="new\utsUtils.pas"/> | |||||
| <IsPartOfProject Value="True"/> | |||||
| </Unit13> | |||||
| <Unit14> | |||||
| <Filename Value="new\utsRendererOpenGL.pas"/> | |||||
| <IsPartOfProject Value="True"/> | |||||
| <UnitName Value="utsRendererOpenGL"/> | |||||
| </Unit14> | |||||
| </Units> | </Units> | ||||
| </ProjectOptions> | </ProjectOptions> | ||||
| <CompilerOptions> | <CompilerOptions> | ||||
| @@ -92,10 +116,13 @@ | |||||
| </Target> | </Target> | ||||
| <SearchPaths> | <SearchPaths> | ||||
| <IncludeFiles Value="$(ProjOutDir);old"/> | <IncludeFiles Value="$(ProjOutDir);old"/> | ||||
| <OtherUnitFiles Value="old;..\bitSpace\_projects\MassiveUniverseOnline\bitSpaceEngine\src\OpenGLCore;new"/> | |||||
| <OtherUnitFiles Value="old;new;..\bitSpace\_projects\MassiveUniverseOnline\bitSpaceEngine\src\OpenGLCore"/> | |||||
| <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> | <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> | ||||
| </SearchPaths> | </SearchPaths> | ||||
| <Linking> | <Linking> | ||||
| <Debugging> | |||||
| <UseHeaptrc Value="True"/> | |||||
| </Debugging> | |||||
| <Options> | <Options> | ||||
| <Win32> | <Win32> | ||||
| <GraphicApplication Value="True"/> | <GraphicApplication Value="True"/> | ||||
| @@ -7,8 +7,9 @@ uses | |||||
| cthreads, | cthreads, | ||||
| {$ENDIF}{$ENDIF} | {$ENDIF}{$ENDIF} | ||||
| Interfaces, // this includes the LCL widgetset | Interfaces, // this includes the LCL widgetset | ||||
| Forms, uMainForm, TextSuite, TextSuiteClasses, TextSuiteImports, TextSuitePostProcess, | |||||
| TextSuiteTTFUtils, TextSuiteVersion, TextSuiteWideUtils, utsTextSuite; | |||||
| Forms, uMainForm, TextSuite, TextSuiteClasses, TextSuiteImports, TextSuitePostProcess, TextSuiteTTFUtils, | |||||
| TextSuiteVersion, TextSuiteWideUtils, utsTextSuite, utsFontCreatorGDI, utsTtfUtils, utsTypes, utsUtils, | |||||
| utsRendererOpenGL; | |||||
| {$R *.res} | {$R *.res} | ||||
| @@ -4,13 +4,13 @@ | |||||
| <PathDelim Value="\"/> | <PathDelim Value="\"/> | ||||
| <Version Value="9"/> | <Version Value="9"/> | ||||
| <BuildModes Active="Default"/> | <BuildModes Active="Default"/> | ||||
| <Units Count="19"> | |||||
| <Units Count="42"> | |||||
| <Unit0> | <Unit0> | ||||
| <Filename Value="TextSuiteTest.lpr"/> | <Filename Value="TextSuiteTest.lpr"/> | ||||
| <IsPartOfProject Value="True"/> | <IsPartOfProject Value="True"/> | ||||
| <EditorIndex Value="-1"/> | <EditorIndex Value="-1"/> | ||||
| <CursorPos X="45" Y="17"/> | <CursorPos X="45" Y="17"/> | ||||
| <UsageCount Value="60"/> | |||||
| <UsageCount Value="92"/> | |||||
| </Unit0> | </Unit0> | ||||
| <Unit1> | <Unit1> | ||||
| <Filename Value="uMainForm.pas"/> | <Filename Value="uMainForm.pas"/> | ||||
| @@ -19,9 +19,9 @@ | |||||
| <HasResources Value="True"/> | <HasResources Value="True"/> | ||||
| <ResourceBaseClass Value="Form"/> | <ResourceBaseClass Value="Form"/> | ||||
| <UnitName Value="uMainForm"/> | <UnitName Value="uMainForm"/> | ||||
| <TopLine Value="79"/> | |||||
| <CursorPos Y="97"/> | |||||
| <UsageCount Value="60"/> | |||||
| <IsVisibleTab Value="True"/> | |||||
| <CursorPos X="3" Y="5"/> | |||||
| <UsageCount Value="92"/> | |||||
| <Loaded Value="True"/> | <Loaded Value="True"/> | ||||
| <LoadedDesigner Value="True"/> | <LoadedDesigner Value="True"/> | ||||
| </Unit1> | </Unit1> | ||||
| @@ -29,58 +29,59 @@ | |||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <IsPartOfProject Value="True"/> | <IsPartOfProject Value="True"/> | ||||
| <UnitName Value="utsTextSuite"/> | <UnitName Value="utsTextSuite"/> | ||||
| <IsVisibleTab Value="True"/> | |||||
| <EditorIndex Value="2"/> | <EditorIndex Value="2"/> | ||||
| <TopLine Value="1988"/> | |||||
| <CursorPos X="22" Y="2002"/> | |||||
| <UsageCount Value="59"/> | |||||
| <TopLine Value="1886"/> | |||||
| <CursorPos X="33" Y="1904"/> | |||||
| <UsageCount Value="91"/> | |||||
| <Loaded Value="True"/> | <Loaded Value="True"/> | ||||
| </Unit2> | </Unit2> | ||||
| <Unit3> | <Unit3> | ||||
| <Filename Value="old\TextSuite.pas"/> | <Filename Value="old\TextSuite.pas"/> | ||||
| <IsPartOfProject Value="True"/> | <IsPartOfProject Value="True"/> | ||||
| <UnitName Value="TextSuite"/> | <UnitName Value="TextSuite"/> | ||||
| <EditorIndex Value="1"/> | |||||
| <EditorIndex Value="6"/> | |||||
| <WindowIndex Value="1"/> | <WindowIndex Value="1"/> | ||||
| <TopLine Value="207"/> | |||||
| <CursorPos X="3" Y="223"/> | |||||
| <TopLine Value="391"/> | |||||
| <CursorPos X="13" Y="408"/> | |||||
| <ExtraEditorCount Value="1"/> | <ExtraEditorCount Value="1"/> | ||||
| <ExtraEditor1> | <ExtraEditor1> | ||||
| <EditorIndex Value="-1"/> | <EditorIndex Value="-1"/> | ||||
| <TopLine Value="232"/> | <TopLine Value="232"/> | ||||
| <CursorPos X="3" Y="302"/> | <CursorPos X="3" Y="302"/> | ||||
| </ExtraEditor1> | </ExtraEditor1> | ||||
| <UsageCount Value="54"/> | |||||
| <UsageCount Value="86"/> | |||||
| <Loaded Value="True"/> | <Loaded Value="True"/> | ||||
| </Unit3> | </Unit3> | ||||
| <Unit4> | <Unit4> | ||||
| <Filename Value="old\TextSuiteImports.pas"/> | <Filename Value="old\TextSuiteImports.pas"/> | ||||
| <IsPartOfProject Value="True"/> | <IsPartOfProject Value="True"/> | ||||
| <EditorIndex Value="-1"/> | |||||
| <TopLine Value="662"/> | |||||
| <CursorPos X="3" Y="664"/> | |||||
| <UsageCount Value="54"/> | |||||
| <UnitName Value="TextSuiteImports"/> | |||||
| <EditorIndex Value="5"/> | |||||
| <WindowIndex Value="1"/> | |||||
| <TopLine Value="656"/> | |||||
| <CursorPos X="20" Y="635"/> | |||||
| <UsageCount Value="86"/> | |||||
| <Loaded Value="True"/> | |||||
| </Unit4> | </Unit4> | ||||
| <Unit5> | <Unit5> | ||||
| <Filename Value="old\TextSuiteWideUtils.pas"/> | <Filename Value="old\TextSuiteWideUtils.pas"/> | ||||
| <IsPartOfProject Value="True"/> | <IsPartOfProject Value="True"/> | ||||
| <UnitName Value="TextSuiteWideUtils"/> | <UnitName Value="TextSuiteWideUtils"/> | ||||
| <EditorIndex Value="2"/> | |||||
| <EditorIndex Value="7"/> | |||||
| <WindowIndex Value="1"/> | <WindowIndex Value="1"/> | ||||
| <TopLine Value="1243"/> | <TopLine Value="1243"/> | ||||
| <CursorPos X="18" Y="1257"/> | <CursorPos X="18" Y="1257"/> | ||||
| <UsageCount Value="54"/> | |||||
| <UsageCount Value="86"/> | |||||
| <Loaded Value="True"/> | <Loaded Value="True"/> | ||||
| </Unit5> | </Unit5> | ||||
| <Unit6> | <Unit6> | ||||
| <Filename Value="old\TextSuiteClasses.pas"/> | <Filename Value="old\TextSuiteClasses.pas"/> | ||||
| <IsPartOfProject Value="True"/> | <IsPartOfProject Value="True"/> | ||||
| <UnitName Value="TextSuiteClasses"/> | <UnitName Value="TextSuiteClasses"/> | ||||
| <IsVisibleTab Value="True"/> | |||||
| <WindowIndex Value="1"/> | <WindowIndex Value="1"/> | ||||
| <TopLine Value="4487"/> | |||||
| <CursorPos X="28" Y="4439"/> | |||||
| <UsageCount Value="54"/> | |||||
| <TopLine Value="654"/> | |||||
| <CursorPos X="25" Y="673"/> | |||||
| <UsageCount Value="86"/> | |||||
| <Loaded Value="True"/> | <Loaded Value="True"/> | ||||
| </Unit6> | </Unit6> | ||||
| <Unit7> | <Unit7> | ||||
| @@ -90,16 +91,18 @@ | |||||
| <WindowIndex Value="1"/> | <WindowIndex Value="1"/> | ||||
| <TopLine Value="163"/> | <TopLine Value="163"/> | ||||
| <CursorPos X="61" Y="141"/> | <CursorPos X="61" Y="141"/> | ||||
| <UsageCount Value="54"/> | |||||
| <UsageCount Value="86"/> | |||||
| </Unit7> | </Unit7> | ||||
| <Unit8> | <Unit8> | ||||
| <Filename Value="old\TextSuiteTTFUtils.pas"/> | <Filename Value="old\TextSuiteTTFUtils.pas"/> | ||||
| <IsPartOfProject Value="True"/> | <IsPartOfProject Value="True"/> | ||||
| <EditorIndex Value="-1"/> | |||||
| <WindowIndex Value="-1"/> | |||||
| <TopLine Value="-1"/> | |||||
| <CursorPos X="-1" Y="-1"/> | |||||
| <UsageCount Value="54"/> | |||||
| <UnitName Value="TextSuiteTTFUtils"/> | |||||
| <EditorIndex Value="4"/> | |||||
| <WindowIndex Value="1"/> | |||||
| <TopLine Value="83"/> | |||||
| <CursorPos X="3" Y="91"/> | |||||
| <UsageCount Value="86"/> | |||||
| <Loaded Value="True"/> | |||||
| </Unit8> | </Unit8> | ||||
| <Unit9> | <Unit9> | ||||
| <Filename Value="old\TextSuiteVersion.pas"/> | <Filename Value="old\TextSuiteVersion.pas"/> | ||||
| @@ -108,243 +111,386 @@ | |||||
| <WindowIndex Value="-1"/> | <WindowIndex Value="-1"/> | ||||
| <TopLine Value="-1"/> | <TopLine Value="-1"/> | ||||
| <CursorPos X="-1" Y="-1"/> | <CursorPos X="-1" Y="-1"/> | ||||
| <UsageCount Value="54"/> | |||||
| <UsageCount Value="86"/> | |||||
| </Unit9> | </Unit9> | ||||
| <Unit10> | <Unit10> | ||||
| <Filename Value="..\bitSpace\_projects\MassiveUniverseOnline\bitSpaceEngine\src\OpenGLCore\uglcTypes.pas"/> | |||||
| <UnitName Value="uglcTypes"/> | |||||
| <EditorIndex Value="1"/> | |||||
| <TopLine Value="264"/> | |||||
| <CursorPos X="3" Y="273"/> | |||||
| <UsageCount Value="30"/> | |||||
| <Filename Value="new\utsFontCreatorGDI.pas"/> | |||||
| <IsPartOfProject Value="True"/> | |||||
| <UnitName Value="utsFontCreatorGDI"/> | |||||
| <EditorIndex Value="4"/> | |||||
| <TopLine Value="655"/> | |||||
| <CursorPos X="53" Y="662"/> | |||||
| <UsageCount Value="50"/> | |||||
| <Loaded Value="True"/> | <Loaded Value="True"/> | ||||
| </Unit10> | </Unit10> | ||||
| <Unit11> | <Unit11> | ||||
| <Filename Value="..\bitSpace\_projects\MassiveUniverseOnline\bitSpaceEngine\src\OpenGLCore\dglOpenGL.pas"/> | |||||
| <UnitName Value="dglOpenGL"/> | |||||
| <EditorIndex Value="5"/> | |||||
| <TopLine Value="11398"/> | |||||
| <CursorPos X="3" Y="11232"/> | |||||
| <UsageCount Value="30"/> | |||||
| <Loaded Value="True"/> | |||||
| <Filename Value="new\utsTtfUtils.pas"/> | |||||
| <IsPartOfProject Value="True"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <TopLine Value="128"/> | |||||
| <CursorPos X="17" Y="144"/> | |||||
| <UsageCount Value="42"/> | |||||
| </Unit11> | </Unit11> | ||||
| <Unit12> | <Unit12> | ||||
| <Filename Value="new\uglctextsuite.pas"/> | |||||
| <Filename Value="new\utsTypes.pas"/> | |||||
| <IsPartOfProject Value="True"/> | |||||
| <EditorIndex Value="-1"/> | <EditorIndex Value="-1"/> | ||||
| <CursorPos X="3" Y="13"/> | |||||
| <UsageCount Value="15"/> | |||||
| <TopLine Value="152"/> | |||||
| <CursorPos X="5" Y="168"/> | |||||
| <UsageCount Value="42"/> | |||||
| </Unit12> | </Unit12> | ||||
| <Unit13> | <Unit13> | ||||
| <Filename Value="new\utsUtils.pas"/> | |||||
| <IsPartOfProject Value="True"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <CursorPos Y="20"/> | |||||
| <UsageCount Value="42"/> | |||||
| </Unit13> | |||||
| <Unit14> | |||||
| <Filename Value="new\utsRendererOpenGL.pas"/> | |||||
| <IsPartOfProject Value="True"/> | |||||
| <UnitName Value="utsRendererOpenGL"/> | |||||
| <EditorIndex Value="3"/> | |||||
| <TopLine Value="356"/> | |||||
| <CursorPos X="20" Y="376"/> | |||||
| <UsageCount Value="39"/> | |||||
| <Loaded Value="True"/> | |||||
| </Unit14> | |||||
| <Unit15> | |||||
| <Filename Value="..\bitSpace\_projects\MassiveUniverseOnline\bitSpaceEngine\src\OpenGLCore\uglcTypes.pas"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <WindowIndex Value="1"/> | |||||
| <TopLine Value="261"/> | |||||
| <CursorPos X="3" Y="277"/> | |||||
| <UsageCount Value="37"/> | |||||
| </Unit15> | |||||
| <Unit16> | |||||
| <Filename Value="..\bitSpace\_projects\MassiveUniverseOnline\bitSpaceEngine\src\OpenGLCore\dglOpenGL.pas"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <TopLine Value="1066"/> | |||||
| <CursorPos X="27" Y="1082"/> | |||||
| <UsageCount Value="32"/> | |||||
| </Unit16> | |||||
| <Unit17> | |||||
| <Filename Value="new\uglctextsuite.pas"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <CursorPos X="3" Y="13"/> | |||||
| <UsageCount Value="13"/> | |||||
| </Unit17> | |||||
| <Unit18> | |||||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\ustringh.inc"/> | <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\ustringh.inc"/> | ||||
| <EditorIndex Value="4"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <TopLine Value="110"/> | <TopLine Value="110"/> | ||||
| <CursorPos X="10" Y="126"/> | <CursorPos X="10" Y="126"/> | ||||
| <UsageCount Value="28"/> | |||||
| <Loaded Value="True"/> | |||||
| </Unit13> | |||||
| <Unit14> | |||||
| <UsageCount Value="27"/> | |||||
| </Unit18> | |||||
| <Unit19> | |||||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\ustrings.inc"/> | <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\ustrings.inc"/> | ||||
| <EditorIndex Value="-1"/> | <EditorIndex Value="-1"/> | ||||
| <TopLine Value="1819"/> | <TopLine Value="1819"/> | ||||
| <CursorPos X="37" Y="2066"/> | <CursorPos X="37" Y="2066"/> | ||||
| <UsageCount Value="6"/> | |||||
| </Unit14> | |||||
| <Unit15> | |||||
| <UsageCount Value="4"/> | |||||
| </Unit19> | |||||
| <Unit20> | |||||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\systemh.inc"/> | <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\systemh.inc"/> | ||||
| <EditorIndex Value="-1"/> | <EditorIndex Value="-1"/> | ||||
| <TopLine Value="756"/> | <TopLine Value="756"/> | ||||
| <CursorPos X="32" Y="774"/> | <CursorPos X="32" Y="774"/> | ||||
| <UsageCount Value="27"/> | |||||
| </Unit15> | |||||
| <Unit16> | |||||
| <UsageCount Value="25"/> | |||||
| </Unit20> | |||||
| <Unit21> | |||||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\heaph.inc"/> | <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\heaph.inc"/> | ||||
| <EditorIndex Value="3"/> | |||||
| <TopLine Value="69"/> | |||||
| <CursorPos X="10" Y="94"/> | |||||
| <UsageCount Value="27"/> | |||||
| <Loaded Value="True"/> | |||||
| </Unit16> | |||||
| <Unit17> | |||||
| <EditorIndex Value="-1"/> | |||||
| <TopLine Value="71"/> | |||||
| <CursorPos X="10" Y="95"/> | |||||
| <UsageCount Value="26"/> | |||||
| </Unit21> | |||||
| <Unit22> | |||||
| <Filename Value="old\TextSuiteCPUUtils.pas"/> | <Filename Value="old\TextSuiteCPUUtils.pas"/> | ||||
| <EditorIndex Value="-1"/> | <EditorIndex Value="-1"/> | ||||
| <WindowIndex Value="1"/> | <WindowIndex Value="1"/> | ||||
| <CursorPos X="23" Y="20"/> | <CursorPos X="23" Y="20"/> | ||||
| <UsageCount Value="18"/> | |||||
| </Unit17> | |||||
| <Unit18> | |||||
| <UsageCount Value="16"/> | |||||
| </Unit22> | |||||
| <Unit23> | |||||
| <Filename Value="..\glBitmap\glBitmap\glBitmap.pas"/> | <Filename Value="..\glBitmap\glBitmap\glBitmap.pas"/> | ||||
| <EditorIndex Value="-1"/> | <EditorIndex Value="-1"/> | ||||
| <CursorPos X="14" Y="14"/> | <CursorPos X="14" Y="14"/> | ||||
| <UsageCount Value="6"/> | |||||
| </Unit18> | |||||
| <UsageCount Value="4"/> | |||||
| </Unit23> | |||||
| <Unit24> | |||||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\objpas\math.pp"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <TopLine Value="1011"/> | |||||
| <CursorPos X="47" Y="1015"/> | |||||
| <UsageCount Value="8"/> | |||||
| </Unit24> | |||||
| <Unit25> | |||||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\mathh.inc"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <TopLine Value="84"/> | |||||
| <CursorPos X="14" Y="101"/> | |||||
| <UsageCount Value="8"/> | |||||
| </Unit25> | |||||
| <Unit26> | |||||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\genmath.inc"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <TopLine Value="152"/> | |||||
| <CursorPos X="10" Y="155"/> | |||||
| <UsageCount Value="8"/> | |||||
| </Unit26> | |||||
| <Unit27> | |||||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\dynlibs.pas"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <TopLine Value="41"/> | |||||
| <CursorPos X="10" Y="58"/> | |||||
| <UsageCount Value="13"/> | |||||
| </Unit27> | |||||
| <Unit28> | |||||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\win\dynlibs.inc"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <TopLine Value="9"/> | |||||
| <CursorPos X="3" Y="26"/> | |||||
| <UsageCount Value="13"/> | |||||
| </Unit28> | |||||
| <Unit29> | |||||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\win\sysosh.inc"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <TopLine Value="11"/> | |||||
| <CursorPos X="3" Y="19"/> | |||||
| <UsageCount Value="13"/> | |||||
| </Unit29> | |||||
| <Unit30> | |||||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\objpash.inc"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <TopLine Value="177"/> | |||||
| <CursorPos X="22" Y="195"/> | |||||
| <UsageCount Value="17"/> | |||||
| </Unit30> | |||||
| <Unit31> | |||||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\objpas\sysutils\sysunih.inc"/> | |||||
| <EditorIndex Value="3"/> | |||||
| <WindowIndex Value="1"/> | |||||
| <TopLine Value="25"/> | |||||
| <CursorPos X="34" Y="43"/> | |||||
| <UsageCount Value="21"/> | |||||
| <Loaded Value="True"/> | |||||
| </Unit31> | |||||
| <Unit32> | |||||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\packages\fcl-base\src\syncobjs.pp"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <TopLine Value="113"/> | |||||
| <CursorPos X="25" Y="115"/> | |||||
| <UsageCount Value="18"/> | |||||
| </Unit32> | |||||
| <Unit33> | |||||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\objpas\classes\classesh.inc"/> | |||||
| <EditorIndex Value="1"/> | |||||
| <WindowIndex Value="1"/> | |||||
| <TopLine Value="311"/> | |||||
| <CursorPos X="14" Y="327"/> | |||||
| <UsageCount Value="18"/> | |||||
| <Loaded Value="True"/> | |||||
| </Unit33> | |||||
| <Unit34> | |||||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\objpas.inc"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <TopLine Value="516"/> | |||||
| <CursorPos X="9" Y="525"/> | |||||
| <UsageCount Value="16"/> | |||||
| </Unit34> | |||||
| <Unit35> | |||||
| <Filename Value="C:\Zusatzprogramme\Lazarus\lcl\include\control.inc"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <TopLine Value="2843"/> | |||||
| <CursorPos Y="2858"/> | |||||
| <UsageCount Value="15"/> | |||||
| </Unit35> | |||||
| <Unit36> | |||||
| <Filename Value="C:\Users\Erik\Desktop\RectPacking\unit1.pas"/> | |||||
| <UnitName Value="Unit1"/> | |||||
| <IsVisibleTab Value="True"/> | |||||
| <EditorIndex Value="2"/> | |||||
| <WindowIndex Value="1"/> | |||||
| <TopLine Value="376"/> | |||||
| <CursorPos X="7" Y="390"/> | |||||
| <UsageCount Value="16"/> | |||||
| <Loaded Value="True"/> | |||||
| </Unit36> | |||||
| <Unit37> | |||||
| <Filename Value="..\bitSpace\_projects\MassiveUniverseOnline\bitSpaceEngine\src\OpenGLCore\uglcArrayBuffer.pas"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <WindowIndex Value="1"/> | |||||
| <TopLine Value="102"/> | |||||
| <CursorPos X="37" Y="112"/> | |||||
| <UsageCount Value="12"/> | |||||
| </Unit37> | |||||
| <Unit38> | |||||
| <Filename Value="..\bitSpace\_projects\MassiveUniverseOnline\bitSpaceEngine\src\OpenGLCore\uglcBitmap.pas"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <WindowIndex Value="1"/> | |||||
| <TopLine Value="1047"/> | |||||
| <CursorPos X="15" Y="1043"/> | |||||
| <UsageCount Value="10"/> | |||||
| </Unit38> | |||||
| <Unit39> | |||||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\objpas\objpas.pp"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <TopLine Value="19"/> | |||||
| <CursorPos X="8" Y="35"/> | |||||
| <UsageCount Value="10"/> | |||||
| </Unit39> | |||||
| <Unit40> | |||||
| <Filename Value="C:\Zusatzprogramme\Lazarus\lcl\include\application.inc"/> | |||||
| <EditorIndex Value="-1"/> | |||||
| <TopLine Value="966"/> | |||||
| <CursorPos Y="981"/> | |||||
| <UsageCount Value="10"/> | |||||
| </Unit40> | |||||
| <Unit41> | |||||
| <Filename Value="..\bitSpace\_projects\MassiveUniverseOnline\bitSpaceEngine\src\SpaceEngine\uengFrameLimiter.pas"/> | |||||
| <UnitName Value="uengFrameLimiter"/> | |||||
| <EditorIndex Value="1"/> | |||||
| <TopLine Value="14"/> | |||||
| <CursorPos X="13" Y="14"/> | |||||
| <UsageCount Value="10"/> | |||||
| <Loaded Value="True"/> | |||||
| </Unit41> | |||||
| </Units> | </Units> | ||||
| <JumpHistory Count="30" HistoryIndex="29"> | |||||
| <JumpHistory Count="30" HistoryIndex="28"> | |||||
| <Position1> | <Position1> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="1979" TopLine="1967"/> | |||||
| <Caret Line="1797" TopLine="1781"/> | |||||
| </Position1> | </Position1> | ||||
| <Position2> | <Position2> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="1980" TopLine="1967"/> | |||||
| <Caret Line="1683" TopLine="1657"/> | |||||
| </Position2> | </Position2> | ||||
| <Position3> | <Position3> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="1981" TopLine="1967"/> | |||||
| <Caret Line="1679" TopLine="1657"/> | |||||
| </Position3> | </Position3> | ||||
| <Position4> | <Position4> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="1982" TopLine="1967"/> | |||||
| <Caret Line="1680" TopLine="1657"/> | |||||
| </Position4> | </Position4> | ||||
| <Position5> | <Position5> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="1983" TopLine="1967"/> | |||||
| <Caret Line="1681" TopLine="1657"/> | |||||
| </Position5> | </Position5> | ||||
| <Position6> | <Position6> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="1984" TopLine="1967"/> | |||||
| <Caret Line="1683" TopLine="1658"/> | |||||
| </Position6> | </Position6> | ||||
| <Position7> | <Position7> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="1987" TopLine="1967"/> | |||||
| <Caret Line="1797" TopLine="1781"/> | |||||
| </Position7> | </Position7> | ||||
| <Position8> | <Position8> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="2032" TopLine="2015"/> | |||||
| <Caret Line="1799" TopLine="1781"/> | |||||
| </Position8> | </Position8> | ||||
| <Position9> | <Position9> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="2037" TopLine="2015"/> | |||||
| <Caret Line="1800" TopLine="1781"/> | |||||
| </Position9> | </Position9> | ||||
| <Position10> | <Position10> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="1970" TopLine="1954"/> | |||||
| <Caret Line="1801" TopLine="1781"/> | |||||
| </Position10> | </Position10> | ||||
| <Position11> | <Position11> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="1973" TopLine="1954"/> | |||||
| <Caret Line="1803" TopLine="1781"/> | |||||
| </Position11> | </Position11> | ||||
| <Position12> | <Position12> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="1974" TopLine="1954"/> | |||||
| <Caret Line="1804" TopLine="1781"/> | |||||
| </Position12> | </Position12> | ||||
| <Position13> | <Position13> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="1975" TopLine="1967"/> | |||||
| <Caret Line="1805" TopLine="1781"/> | |||||
| </Position13> | </Position13> | ||||
| <Position14> | <Position14> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="1977" TopLine="1967"/> | |||||
| <Caret Line="1679" TopLine="1663"/> | |||||
| </Position14> | </Position14> | ||||
| <Position15> | <Position15> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="1991" TopLine="1967"/> | |||||
| <Caret Line="1465" Column="3" TopLine="1460"/> | |||||
| </Position15> | </Position15> | ||||
| <Position16> | <Position16> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="1995" TopLine="2008"/> | |||||
| <Caret Line="288" Column="101" TopLine="274"/> | |||||
| </Position16> | </Position16> | ||||
| <Position17> | <Position17> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="1997" TopLine="1982"/> | |||||
| <Caret Line="1470" Column="28" TopLine="1459"/> | |||||
| </Position17> | </Position17> | ||||
| <Position18> | <Position18> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="2008" TopLine="1982"/> | |||||
| <Caret Line="1471" Column="73" TopLine="1459"/> | |||||
| </Position18> | </Position18> | ||||
| <Position19> | <Position19> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="2054" TopLine="2037"/> | |||||
| <Caret Line="1723" Column="29" TopLine="1713"/> | |||||
| </Position19> | </Position19> | ||||
| <Position20> | <Position20> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="2032" TopLine="2016"/> | |||||
| <Caret Line="1685" TopLine="1670"/> | |||||
| </Position20> | </Position20> | ||||
| <Position21> | <Position21> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="2037" Column="36" TopLine="2013"/> | |||||
| <Caret Line="1686" TopLine="1670"/> | |||||
| </Position21> | </Position21> | ||||
| <Position22> | <Position22> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="2011" TopLine="1995"/> | |||||
| <Caret Line="1687" TopLine="1670"/> | |||||
| </Position22> | </Position22> | ||||
| <Position23> | <Position23> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="2032" TopLine="2016"/> | |||||
| <Caret Line="1689" TopLine="1670"/> | |||||
| </Position23> | </Position23> | ||||
| <Position24> | <Position24> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="1991" Column="51" TopLine="2005"/> | |||||
| <Caret Line="1686" Column="20" TopLine="1670"/> | |||||
| </Position24> | </Position24> | ||||
| <Position25> | <Position25> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="2011" TopLine="2006"/> | |||||
| <Caret Line="290" Column="52" TopLine="281"/> | |||||
| </Position25> | </Position25> | ||||
| <Position26> | <Position26> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | <Filename Value="new\utsTextSuite.pas"/> | ||||
| <Caret Line="2034" TopLine="2012"/> | |||||
| <Caret Line="1761" Column="23" TopLine="1742"/> | |||||
| </Position26> | </Position26> | ||||
| <Position27> | <Position27> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | |||||
| <Caret Line="2035" TopLine="2012"/> | |||||
| <Filename Value="uMainForm.pas"/> | |||||
| <Caret Line="5" Column="2"/> | |||||
| </Position27> | </Position27> | ||||
| <Position28> | <Position28> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | |||||
| <Caret Line="2051" TopLine="2035"/> | |||||
| <Filename Value="uMainForm.pas"/> | |||||
| <Caret Line="21" Column="18" TopLine="5"/> | |||||
| </Position28> | </Position28> | ||||
| <Position29> | <Position29> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | |||||
| <Caret Line="1993" Column="28" TopLine="1991"/> | |||||
| <Filename Value="uMainForm.pas"/> | |||||
| <Caret Line="57" Column="40" TopLine="50"/> | |||||
| </Position29> | </Position29> | ||||
| <Position30> | <Position30> | ||||
| <Filename Value="new\utsTextSuite.pas"/> | |||||
| <Caret Line="2011" TopLine="1990"/> | |||||
| <Filename Value="uMainForm.pas"/> | |||||
| <Caret Line="23" Column="21" TopLine="22"/> | |||||
| </Position30> | </Position30> | ||||
| </JumpHistory> | </JumpHistory> | ||||
| </ProjectSession> | </ProjectSession> | ||||
| <Debugging> | <Debugging> | ||||
| <BreakPoints Count="4"> | |||||
| <Item1> | |||||
| <Kind Value="bpkSource"/> | |||||
| <WatchScope Value="wpsLocal"/> | |||||
| <WatchKind Value="wpkWrite"/> | |||||
| <Source Value="new\utsTextSuite.pas"/> | |||||
| <Line Value="2011"/> | |||||
| </Item1> | |||||
| <Item2> | |||||
| <Kind Value="bpkSource"/> | |||||
| <WatchScope Value="wpsLocal"/> | |||||
| <WatchKind Value="wpkWrite"/> | |||||
| <Source Value="new\utsTextSuite.pas"/> | |||||
| <Line Value="2058"/> | |||||
| </Item2> | |||||
| <Item3> | |||||
| <Kind Value="bpkSource"/> | |||||
| <WatchScope Value="wpsLocal"/> | |||||
| <WatchKind Value="wpkWrite"/> | |||||
| <Source Value="new\utsTextSuite.pas"/> | |||||
| <Line Value="2037"/> | |||||
| </Item3> | |||||
| <Item4> | |||||
| <Kind Value="bpkSource"/> | |||||
| <WatchScope Value="wpsLocal"/> | |||||
| <WatchKind Value="wpkWrite"/> | |||||
| <Source Value="new\utsTextSuite.pas"/> | |||||
| <Line Value="1991"/> | |||||
| </Item4> | |||||
| </BreakPoints> | |||||
| <Watches Count="4"> | |||||
| <Watches Count="3"> | |||||
| <Item1> | <Item1> | ||||
| <Expression Value="Text"/> | |||||
| <Expression Value="aItem"/> | |||||
| </Item1> | </Item1> | ||||
| <Item2> | <Item2> | ||||
| <Expression Value="p^.Text"/> | |||||
| <Expression Value="aItem^.children[0]"/> | |||||
| </Item2> | </Item2> | ||||
| <Item3> | <Item3> | ||||
| <Expression Value="TextBegin"/> | |||||
| <Expression Value="aItem^.children[1]"/> | |||||
| </Item3> | </Item3> | ||||
| <Item4> | |||||
| <Expression Value="aText"/> | |||||
| </Item4> | |||||
| </Watches> | </Watches> | ||||
| </Debugging> | </Debugging> | ||||
| </CONFIG> | </CONFIG> | ||||
| @@ -0,0 +1,918 @@ | |||||
| unit utsFontCreatorGDI; | |||||
| {$mode objfpc}{$H+} | |||||
| interface | |||||
| uses | |||||
| Classes, SysUtils, syncobjs, dynlibs, | |||||
| utsTextSuite, utsTypes; | |||||
| type | |||||
| HDC = Cardinal; | |||||
| TFixed = packed record | |||||
| fract: Word; | |||||
| value: Smallint; | |||||
| end; | |||||
| TMat2 = packed record | |||||
| eM11: TFixed; | |||||
| eM12: TFixed; | |||||
| eM21: TFixed; | |||||
| eM22: TFixed; | |||||
| end; | |||||
| PMat2 = ^TMat2; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| TtsFontGDI = class(TtsFont) | |||||
| private | |||||
| fHandle: THandle; | |||||
| fMat2: TMat2; | |||||
| protected | |||||
| constructor Create(const aRenderer: TtsRenderer; const aCreator: TtsFontGenerator; const aProperties: TtsFontProperties; const aHandle: THandle); | |||||
| public | |||||
| destructor Destroy; override; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| TtsFontRegistration = class(TObject) | |||||
| protected | |||||
| fIsRegistered: Boolean; | |||||
| fFontname: String; | |||||
| procedure UnregisterFont; virtual; abstract; | |||||
| public | |||||
| property IsRegistered: Boolean read fIsRegistered; | |||||
| property Fontname: String read fFontname; | |||||
| destructor Destroy; override; | |||||
| end; | |||||
| TtsFontRegistrationFile = class(TtsFontRegistration) | |||||
| private | |||||
| fFilename: String; | |||||
| protected | |||||
| procedure UnregisterFont; override; | |||||
| public | |||||
| constructor Create(const aFilename: String); | |||||
| end; | |||||
| TtsFontRegistrationStream = class(TtsFontRegistration) | |||||
| private | |||||
| fHandle: THandle; | |||||
| protected | |||||
| procedure UnregisterFont; override; | |||||
| public | |||||
| constructor Create(const aStream: TStream); | |||||
| end; | |||||
| TtsRegistredFontGDI = class(TtsFontGDI) | |||||
| private | |||||
| fRegistration: TtsFontRegistration; | |||||
| public | |||||
| constructor Create(const aRenderer: TtsRenderer; const aCreator: TtsFontGenerator; | |||||
| const aRegistration: TtsFontRegistration; const aProperties: TtsFontProperties; const aHandle: THandle); | |||||
| destructor Destroy; override; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| TtsFontGeneratorGDI = class(TtsFontGenerator) | |||||
| private | |||||
| function ConvertFont(const aFont: TtsFont): TtsFontGDI; | |||||
| function GetGlyphIndex(const aFont: TtsFontGDI; const aCharCode: WideChar): Integer; | |||||
| procedure GetCharImageAANone(const aDC: HDC; const aFont: TtsFontGDI; const aCharCode: WideChar; const aImage: TtsImage); | |||||
| procedure GetCharImageAANormal(const aDC: HDC; const aFont: TtsFontGDI; const aCharCode: WideChar; const aImage: TtsImage); | |||||
| function CreateFont(const aFontname: String; const aSize: Integer; const aStyle: TtsFontStyles; const aAntiAliasing: TtsAntiAliasing; out aProperties: TtsFontProperties): THandle; | |||||
| protected | |||||
| function GetGlyphMetrics(const aFont: TtsFont; const aCharCode: WideChar; out aGlyphOrigin, aGlyphSize: TtsPosition; out aAdvance: Integer): Boolean; override; | |||||
| procedure GetCharImage(const aFont: TtsFont; const aCharCode: WideChar; const aCharImage: TtsImage); override; | |||||
| public | |||||
| function GetFontByName(const aFontname: String; const aRenderer: TtsRenderer; const aSize: Integer; const aStyle: TtsFontStyles; const aAntiAliasing: TtsAntiAliasing): TtsFont; overload; | |||||
| function GetFontByFile(const aFilename: String; const aRenderer: TtsRenderer; const aSize: Integer; const aStyle: TtsFontStyles; const aAntiAliasing: TtsAntiAliasing): TtsFont; overload; | |||||
| function GetFontByStream(const aStream: TStream; const aRenderer: TtsRenderer; const aSize: Integer; const aStyle: TtsFontStyles; const aAntiAliasing: TtsAntiAliasing): TtsFont; overload; | |||||
| constructor Create; | |||||
| destructor Destroy; override; | |||||
| end; | |||||
| implementation | |||||
| uses | |||||
| math, utsTtfUtils; | |||||
| const | |||||
| LIB_GDI32 = 'gdi32.dll'; | |||||
| LIB_KERNEL32 = 'kernel32.dll'; | |||||
| GDI_ERROR = DWORD($FFFFFFFF); | |||||
| FW_NORMAL = 400; | |||||
| FW_BOLD = 700; | |||||
| DEFAULT_CHARSET = 1; | |||||
| NONANTIALIASED_QUALITY = 3; | |||||
| ANTIALIASED_QUALITY = 4; | |||||
| GGO_METRICS = 0; | |||||
| GGO_BITMAP = 1; | |||||
| GGO_GRAY8_BITMAP = 6; | |||||
| GGO_GLYPH_INDEX = $80; | |||||
| FR_PRIVATE = $10; | |||||
| FR_NOT_ENUM = $20; | |||||
| LOCALE_USER_DEFAULT = $0400; | |||||
| LOCALE_ILANGUAGE = $1; | |||||
| GCP_MAXEXTENT = $100000; | |||||
| TMPF_FIXED_PITCH = 1; | |||||
| type | |||||
| HFONT = Cardinal; | |||||
| HGDIOBJ = Cardinal; | |||||
| TLogFontA = record | |||||
| lfHeight: Longint; | |||||
| lfWidth: Longint; | |||||
| lfEscapement: Longint; | |||||
| lfOrientation: Longint; | |||||
| lfWeight: Longint; | |||||
| lfItalic: Byte; | |||||
| lfUnderline: Byte; | |||||
| lfStrikeOut: Byte; | |||||
| lfCharSet: Byte; | |||||
| lfOutPrecision: Byte; | |||||
| lfClipPrecision: Byte; | |||||
| lfQuality: Byte; | |||||
| lfPitchAndFamily: Byte; | |||||
| lfFaceName: array[0..31] of AnsiChar; | |||||
| end; | |||||
| PLogFontA = ^TLogFontA; | |||||
| TTextMetricW = record | |||||
| tmHeight: Longint; | |||||
| tmAscent: Longint; | |||||
| tmDescent: Longint; | |||||
| tmInternalLeading: Longint; | |||||
| tmExternalLeading: Longint; | |||||
| tmAveCharWidth: Longint; | |||||
| tmMaxCharWidth: Longint; | |||||
| tmWeight: Longint; | |||||
| tmOverhang: Longint; | |||||
| tmDigitizedAspectX: Longint; | |||||
| tmDigitizedAspectY: Longint; | |||||
| tmFirstChar: WideChar; | |||||
| tmLastChar: WideChar; | |||||
| tmDefaultChar: WideChar; | |||||
| tmBreakChar: WideChar; | |||||
| tmItalic: Byte; | |||||
| tmUnderlined: Byte; | |||||
| tmStruckOut: Byte; | |||||
| tmPitchAndFamily: Byte; | |||||
| tmCharSet: Byte; | |||||
| end; | |||||
| PTextMetricW = ^TTextMetricW; | |||||
| TGlyphMetrics = record | |||||
| gmBlackBoxX: Cardinal; | |||||
| gmBlackBoxY: Cardinal; | |||||
| gmptGlyphOrigin: TtsPosition; | |||||
| gmCellIncX: Smallint; | |||||
| gmCellIncY: Smallint; | |||||
| end; | |||||
| PGlyphMetrics = ^TGlyphMetrics; | |||||
| TGCPResultsW = record | |||||
| lStructSize: DWORD; | |||||
| lpOutString: PWideChar; | |||||
| lpOrder: PDWORD; | |||||
| lpDx: PInteger; | |||||
| lpCaretPos: PInteger; | |||||
| lpClass: PChar; | |||||
| lpGlyphs: PCardinal; | |||||
| nGlyphs: Cardinal; | |||||
| nMaxFit: Cardinal; | |||||
| end; | |||||
| PGCPResultsW = ^TGCPResultsW; | |||||
| TPanose = record | |||||
| bFamilyType: Byte; | |||||
| bSerifStyle: Byte; | |||||
| bWeight: Byte; | |||||
| bProportion: Byte; | |||||
| bContrast: Byte; | |||||
| bStrokeVariation: Byte; | |||||
| bArmStyle: Byte; | |||||
| bLetterform: Byte; | |||||
| bMidline: Byte; | |||||
| bXHeight: Byte; | |||||
| end; | |||||
| PPanose = ^TPanose; | |||||
| TOutlineTextmetricW = record | |||||
| otmSize: LongWord; | |||||
| otmTextMetrics: TTextMetricW; | |||||
| otmFiller: Byte; | |||||
| otmPanoseNumber: TPanose; | |||||
| otmfsSelection: LongWord; | |||||
| otmfsType: LongWord; | |||||
| otmsCharSlopeRise: Integer; | |||||
| otmsCharSlopeRun: Integer; | |||||
| otmItalicAngle: Integer; | |||||
| otmEMSquare: LongWord; | |||||
| otmAscent: Integer; | |||||
| otmDescent: Integer; | |||||
| otmLineGap: LongWord; | |||||
| otmsCapEmHeight: LongWord; | |||||
| otmsXHeight: LongWord; | |||||
| otmrcFontBox: TtsRect; | |||||
| otmMacAscent: Integer; | |||||
| otmMacDescent: Integer; | |||||
| otmMacLineGap: LongWord; | |||||
| otmusMinimumPPEM: LongWord; | |||||
| otmptSubscriptSize: TtsPosition; | |||||
| otmptSubscriptOffset: TtsPosition; | |||||
| otmptSuperscriptSize: TtsPosition; | |||||
| otmptSuperscriptOffset: TtsPosition; | |||||
| otmsStrikeoutSize: LongWord; | |||||
| otmsStrikeoutPosition: Integer; | |||||
| otmsUnderscoreSize: Integer; | |||||
| otmsUnderscorePosition: Integer; | |||||
| otmpFamilyName: PWideChar; | |||||
| otmpFaceName: PWideChar; | |||||
| otmpStyleName: PWideChar; | |||||
| otmpFullName: PWideChar; | |||||
| end; | |||||
| POutlineTextmetricW = ^TOutlineTextmetricW; | |||||
| TCreateFontIndirectA = function (const p1: TLogFontA): HFONT; stdcall; | |||||
| TAddFontResourceA = function(Filename: PAnsiChar): Integer; stdcall; | |||||
| TAddFontResourceExA = function(Filename: PAnsiChar; Flag: DWORD; pdv: Pointer): Integer; stdcall; | |||||
| TAddFontMemResourceEx = function(pbFont: Pointer; cbFont: DWORD; pdv: Pointer; pcFonts: PDWORD): THandle; stdcall; | |||||
| TRemoveFontResourceA = function(Filename: PAnsiChar): Boolean; stdcall; | |||||
| TRemoveFontResourceExA = function(filename: PAnsiChar; Flag: DWORD; pdv: Pointer): Boolean; stdcall; | |||||
| TRemoveFontMemResourceEx = function(fh: THandle): Boolean; stdcall; | |||||
| TGetTextMetricsW = function(DC: HDC; var TM: TTextMetricW): Boolean; stdcall; | |||||
| TGetGlyphOutlineA = function(DC: HDC; uChar, uFormat: Cardinal; lpgm: PGlyphMetrics; cbBuffer: DWORD; lpvBuffer: Pointer; lpmat2: PMat2): DWORD; stdcall; | |||||
| TGetCharacterPlacementW = function(DC: HDC; Str: PWideChar; Count, MaxExtent: Integer; Result: PGCPResultsW; Flags: DWORD): DWORD; stdcall; | |||||
| TGetFontData = function(DC: HDC; TableName, Offset: DWORD; Buffer: Pointer; Data: DWORD): DWORD; stdcall; | |||||
| TCreateCompatibleDC = function(DC: HDC): HDC; stdcall; | |||||
| TDeleteDC = function(DC: HDC): Boolean; stdcall; | |||||
| TSelectObject = function(DC: HDC; p2: HGDIOBJ): HGDIOBJ; stdcall; | |||||
| TDeleteObject = function(p1: HGDIOBJ): Boolean; stdcall; | |||||
| TGetOutlineTextMetricsW = function(DC: HDC; p2: LongWord; var OTMetricStructs: TOutlineTextmetricW): LongWord; stdcall; | |||||
| TGetLocaleInfoA = function(Locale: DWORD; LCType: DWORD; lpLCData: pAnsiChar; cchData: Integer): Integer; stdcall; | |||||
| var | |||||
| gdiRefCount: Integer; | |||||
| gdiCritSec: TCriticalSection; | |||||
| gdiInitialized: Boolean; | |||||
| gdiLibHandle: TLibHandle = 0; | |||||
| kernel32LibHandle: TLibHandle = 0; | |||||
| CreateFontIndirectA: TCreateFontIndirectA; | |||||
| AddFontResourceA: TAddFontResourceA; | |||||
| AddFontResourceExA: TAddFontResourceExA; | |||||
| AddFontMemResourceEx: TAddFontMemResourceEx; | |||||
| RemoveFontResourceA: TRemoveFontResourceA; | |||||
| RemoveFontResourceExA: TRemoveFontResourceExA; | |||||
| RemoveFontMemResourceEx: TRemoveFontMemResourceEx; | |||||
| GetTextMetricsW: TGetTextMetricsW; | |||||
| GetGlyphOutlineA: TGetGlyphOutlineA; | |||||
| GetCharacterPlacementW: TGetCharacterPlacementW; | |||||
| GetFontData: TGetFontData; | |||||
| CreateCompatibleDC: TCreateCompatibleDC; | |||||
| DeleteDC: TDeleteDC; | |||||
| SelectObject: TSelectObject; | |||||
| DeleteObject: TDeleteObject; | |||||
| GetOutlineTextMetricsW: TGetOutlineTextMetricsW; | |||||
| GetLocaleInfoA: TGetLocaleInfoA; | |||||
| procedure InitGDI; | |||||
| function GetProcAddr(const aLibHandle: TLibHandle; const aName: String): Pointer; | |||||
| begin | |||||
| result := GetProcAddress(aLibHandle, aName); | |||||
| if not Assigned(result) then | |||||
| raise EtsException.Create('unable to load procedure from library: ' + aName); | |||||
| end; | |||||
| begin | |||||
| try | |||||
| if (gdiLibHandle = 0) then begin | |||||
| gdiLibHandle := LoadLibrary(LIB_GDI32); | |||||
| if (gdiLibHandle = 0) then | |||||
| raise EtsException.Create('unable to load gdi lib: ' + LIB_GDI32); | |||||
| end; | |||||
| if (kernel32LibHandle = 0) then begin | |||||
| kernel32LibHandle := LoadLibrary(LIB_KERNEL32); | |||||
| if (kernel32LibHandle = 0) then | |||||
| raise EtsException.Create('unable to load kernel lib: ' + LIB_KERNEL32); | |||||
| end; | |||||
| CreateFontIndirectA := TCreateFontIndirectA( GetProcAddr(gdiLibHandle, 'CreateFontIndirectA')); | |||||
| AddFontResourceA := TAddFontResourceA( GetProcAddr(gdiLibHandle, 'AddFontResourceA')); | |||||
| AddFontResourceExA := TAddFontResourceExA( GetProcAddr(gdiLibHandle, 'AddFontResourceExA')); | |||||
| AddFontMemResourceEx := TAddFontMemResourceEx( GetProcAddr(gdiLibHandle, 'AddFontMemResourceEx')); | |||||
| RemoveFontResourceA := TRemoveFontResourceA( GetProcAddr(gdiLibHandle, 'RemoveFontResourceA')); | |||||
| RemoveFontResourceExA := TRemoveFontResourceExA( GetProcAddr(gdiLibHandle, 'RemoveFontResourceExA')); | |||||
| RemoveFontMemResourceEx := TRemoveFontMemResourceEx(GetProcAddr(gdiLibHandle, 'RemoveFontMemResourceEx')); | |||||
| GetTextMetricsW := TGetTextMetricsW( GetProcAddr(gdiLibHandle, 'GetTextMetricsW')); | |||||
| GetGlyphOutlineA := TGetGlyphOutlineA( GetProcAddr(gdiLibHandle, 'GetGlyphOutlineA')); | |||||
| GetCharacterPlacementW := TGetCharacterPlacementW( GetProcAddr(gdiLibHandle, 'GetCharacterPlacementW')); | |||||
| GetFontData := TGetFontData( GetProcAddr(gdiLibHandle, 'GetFontData')); | |||||
| CreateCompatibleDC := TCreateCompatibleDC( GetProcAddr(gdiLibHandle, 'CreateCompatibleDC')); | |||||
| DeleteDC := TDeleteDC( GetProcAddr(gdiLibHandle, 'DeleteDC')); | |||||
| SelectObject := TSelectObject( GetProcAddr(gdiLibHandle, 'SelectObject')); | |||||
| DeleteObject := TDeleteObject( GetProcAddr(gdiLibHandle, 'DeleteObject')); | |||||
| GetOutlineTextMetricsW := TGetOutlineTextMetricsW( GetProcAddr(gdiLibHandle, 'GetOutlineTextMetricsW')); | |||||
| GetLocaleInfoA := TGetLocaleInfoA(GetProcAddr(kernel32LibHandle, 'GetLocaleInfoA')); | |||||
| gdiInitialized := true; | |||||
| except | |||||
| gdiInitialized := false; | |||||
| FreeLibrary(gdiLibHandle); | |||||
| FreeLibrary(kernel32LibHandle); | |||||
| end; | |||||
| end; | |||||
| procedure QuitGDI; | |||||
| begin | |||||
| CreateFontIndirectA := nil; | |||||
| AddFontResourceA := nil; | |||||
| AddFontResourceExA := nil; | |||||
| RemoveFontResourceA := nil; | |||||
| RemoveFontResourceExA := nil; | |||||
| GetTextMetricsW := nil; | |||||
| GetGlyphOutlineA := nil; | |||||
| GetCharacterPlacementW := nil; | |||||
| GetFontData := nil; | |||||
| CreateCompatibleDC := nil; | |||||
| DeleteDC := nil; | |||||
| SelectObject := nil; | |||||
| DeleteObject := nil; | |||||
| GetLocaleInfoA := nil; | |||||
| if (gdiLibHandle <> 0) then begin | |||||
| FreeLibrary(gdiLibHandle); | |||||
| gdiLibHandle := 0; | |||||
| end; | |||||
| if (kernel32LibHandle <> 0) then begin | |||||
| FreeLibrary(kernel32LibHandle); | |||||
| kernel32LibHandle := 0; | |||||
| end; | |||||
| gdiInitialized := false; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| //TtsFontGDI//////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| constructor TtsFontGDI.Create(const aRenderer: TtsRenderer; const aCreator: TtsFontGenerator; const aProperties: TtsFontProperties; const aHandle: THandle); | |||||
| begin | |||||
| inherited Create(aRenderer, aCreator, aProperties); | |||||
| FillByte(fMat2, SizeOf(fMat2), 0); | |||||
| fMat2.eM11.value := 1; | |||||
| fMat2.eM22.value := 1; | |||||
| fHandle := aHandle; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| destructor TtsFontGDI.Destroy; | |||||
| begin | |||||
| DeleteObject(fHandle); | |||||
| inherited Destroy; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| //TtsFontRegistration/////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| destructor TtsFontRegistration.Destroy; | |||||
| begin | |||||
| if fIsRegistered then | |||||
| UnregisterFont; | |||||
| inherited Destroy; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| //TtsFontRegistrationFile/////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| procedure TtsFontRegistrationFile.UnregisterFont; | |||||
| begin | |||||
| if Assigned(RemoveFontResourceExA) then | |||||
| RemoveFontResourceExA(PAnsiChar(fFilename), 0, nil) | |||||
| else if Assigned(RemoveFontResourceA) then | |||||
| RemoveFontResourceA(PAnsiChar(fFilename)); | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| constructor TtsFontRegistrationFile.Create(const aFilename: String); | |||||
| var | |||||
| lang: AnsiString; | |||||
| begin | |||||
| inherited Create; | |||||
| fFilename := aFilename; | |||||
| // get Fontname | |||||
| SetLength(lang, 4); | |||||
| GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ILANGUAGE, @lang[1], 4); | |||||
| fFontname := GetTTFontFullNameFromFile(aFilename, StrToInt('$' + String(lang))); | |||||
| // register font | |||||
| if Assigned(AddFontResourceExA) then | |||||
| fIsRegistered := (AddFontResourceExA(PAnsiChar(fFilename), 0, nil) > 0) | |||||
| else if Assigned(AddFontResourceA) then | |||||
| fIsRegistered := (AddFontResourceA(PAnsiChar(fFilename)) > 0) | |||||
| else | |||||
| fIsRegistered := false; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| //TtsFontRegistrationStream///////////////////////////////////////////////////////////////////////////////////////////// | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| procedure TtsFontRegistrationStream.UnregisterFont; | |||||
| begin | |||||
| if Assigned(RemoveFontMemResourceEx) then | |||||
| RemoveFontMemResourceEx(fHandle); | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| constructor TtsFontRegistrationStream.Create(const aStream: TStream); | |||||
| var | |||||
| lang: AnsiString; | |||||
| ms: TMemoryStream; | |||||
| cnt: DWORD; | |||||
| begin | |||||
| inherited Create; | |||||
| fHandle := 0; | |||||
| fIsRegistered := false; | |||||
| // get Fontname | |||||
| SetLength(Lang, 4); | |||||
| GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ILANGUAGE, @lang[1], 4); | |||||
| fFontname := GetTTFontFullNameFromStream(aStream, StrToInt('$' + String(Lang))); | |||||
| // register font | |||||
| ms := TMemoryStream.Create; | |||||
| try | |||||
| ms.CopyFrom(aStream, 0); | |||||
| if Assigned(AddFontMemResourceEx) then | |||||
| fHandle := AddFontMemResourceEx(ms.Memory, ms.Size, nil, @cnt); | |||||
| fIsRegistered := (fHandle > 0); | |||||
| finally | |||||
| FreeAndNil(ms); | |||||
| end; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| //TtsRegistredFontGDI/////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| constructor TtsRegistredFontGDI.Create(const aRenderer: TtsRenderer; const aCreator: TtsFontGenerator; | |||||
| const aRegistration: TtsFontRegistration; const aProperties: TtsFontProperties; const aHandle: THandle); | |||||
| begin | |||||
| inherited Create(aRenderer, aCreator, aProperties, aHandle); | |||||
| fRegistration := aRegistration; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| destructor TtsRegistredFontGDI.Destroy; | |||||
| begin | |||||
| FreeAndNil(fRegistration); | |||||
| inherited Destroy; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| //TtsFontCreatorGDIFontFace///////////////////////////////////////////////////////////////////////////////////////////// | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function TtsFontGeneratorGDI.ConvertFont(const aFont: TtsFont): TtsFontGDI; | |||||
| begin | |||||
| if not (aFont is TtsFontGDI) then | |||||
| raise EtsException.Create('aFont need to be a TtsFontGDI object'); | |||||
| result := (aFont as TtsFontGDI); | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function TtsFontGeneratorGDI.GetGlyphIndex(const aFont: TtsFontGDI; const aCharCode: WideChar): Integer; | |||||
| var | |||||
| DC: HDC; | |||||
| GCPRes: TGCPResultsW; | |||||
| begin | |||||
| result := -1; | |||||
| DC := CreateCompatibleDC(0); | |||||
| try | |||||
| SelectObject(DC, aFont.fHandle); | |||||
| if Assigned(GetCharacterPlacementW) then begin | |||||
| FillByte(GCPRes, SizeOf(GCPRes), 0); | |||||
| GetMem(GCPRes.lpGlyphs, SizeOf(Cardinal)); | |||||
| try | |||||
| GCPRes.lStructSize := SizeOf(GCPRes); | |||||
| GCPRes.lpGlyphs^ := 0; | |||||
| GCPRes.nGlyphs := 1; | |||||
| if (GetCharacterPlacementW(DC, @aCharCode, 1, GCP_MAXEXTENT, @GCPRes, 0) <> GDI_ERROR) and | |||||
| (GCPRes.nGlyphs = 1) and | |||||
| (GCPRes.lpGlyphs <> nil) then | |||||
| begin | |||||
| result := GCPRes.lpGlyphs^; | |||||
| end; | |||||
| finally | |||||
| FreeMem(GCPRes.lpGlyphs); | |||||
| end; | |||||
| end; | |||||
| finally | |||||
| DeleteDC(DC); | |||||
| end; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| procedure TtsFontGeneratorGDI.GetCharImageAANone(const aDC: HDC; const aFont: TtsFontGDI; const aCharCode: WideChar; const aImage: TtsImage); | |||||
| var | |||||
| Metric: TGlyphMetrics; | |||||
| GlyphIndex, srcW, srcX, w, h, x, y: Integer; | |||||
| Size, OutlineRes: Cardinal; | |||||
| Buffer, pSrc, pDst: PByte; | |||||
| procedure ExpandByte; | |||||
| var | |||||
| i, cnt, srcCnt: Integer; | |||||
| c: TtsColor4f; | |||||
| begin | |||||
| srcCnt := min(8, srcX); | |||||
| cnt := min(8, x); | |||||
| for i := 1 to cnt do begin | |||||
| c := tsColor4f(1, 1, 1, 1); | |||||
| if ((pSrc^ and $80) > 0) then | |||||
| c.a := 1 | |||||
| else | |||||
| c.a := 0; | |||||
| pSrc^ := (pSrc^ and not $80) shl 1; | |||||
| tsFormatMap(aFont.Renderer.Format, pDst, c); | |||||
| end; | |||||
| dec(srcX, srcCnt); | |||||
| dec(x, cnt); | |||||
| inc(pSrc); | |||||
| end; | |||||
| begin | |||||
| if (aFont.fMat2.eM11.value <> 1) then | |||||
| raise EtsException.Create('invalid value'); | |||||
| FillByte(Metric, SizeOf(Metric), 0); | |||||
| GlyphIndex := GetGlyphIndex(aFont, aCharCode); | |||||
| if (GlyphIndex < 0) then | |||||
| exit; | |||||
| Size := GetGlyphOutlineA(aDC, GlyphIndex, GGO_BITMAP or GGO_GLYPH_INDEX, @Metric, 0, nil, @aFont.fMat2); | |||||
| if (Size = GDI_ERROR) or (Size = 0) then | |||||
| exit; | |||||
| GetMem(Buffer, Size); | |||||
| try | |||||
| OutlineRes := GetGlyphOutlineA(aDC, GlyphIndex, GGO_BITMAP or GGO_GLYPH_INDEX, @Metric, Size, Buffer, @aFont.fMat2); | |||||
| if (OutlineRes = GDI_ERROR) then | |||||
| exit; | |||||
| w := Metric.gmBlackBoxX; | |||||
| h := Metric.gmBlackBoxY; | |||||
| srcW := (Size div h) * 8; | |||||
| if (w <= 0) or (h <= 0) then | |||||
| exit; | |||||
| aImage.CreateEmpty(aFont.Renderer.Format, w, h); | |||||
| pSrc := Buffer; | |||||
| for y := 0 to h-1 do begin | |||||
| pDst := aImage.Scanline[y]; | |||||
| srcX := srcW; | |||||
| while (srcX > 0) do | |||||
| ExpandByte; | |||||
| end; | |||||
| finally | |||||
| Freemem(Buffer); | |||||
| end; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| procedure TtsFontGeneratorGDI.GetCharImageAANormal(const aDC: HDC; const aFont: TtsFontGDI; const aCharCode: WideChar; const aImage: TtsImage); | |||||
| var | |||||
| Metric: TGlyphMetrics; | |||||
| GlyphIndex, OutlineRes, tmp, Spacer, x, y, w, h: Integer; | |||||
| Size: Cardinal; | |||||
| Buffer, pSrc, pDst: PByte; | |||||
| procedure CopyPixel; | |||||
| var | |||||
| i: Integer; | |||||
| tmp, cnt: Cardinal; | |||||
| c: TtsColor4f; | |||||
| begin | |||||
| cnt := min(x, aFont.fMat2.eM11.value); | |||||
| tmp := 0; | |||||
| for i := 0 to cnt-1 do begin | |||||
| tmp := tmp + pSrc^; | |||||
| inc(pSrc, 1); | |||||
| end; | |||||
| dec(x, cnt); | |||||
| c := tsColor4f(1, 1, 1, tmp / ($40 * Cardinal(aFont.fMat2.eM11.value))); | |||||
| tsFormatMap(aFont.Renderer.Format, pDst, c); | |||||
| end; | |||||
| begin | |||||
| FillByte(Metric, SizeOf(Metric), 0); | |||||
| GlyphIndex := GetGlyphIndex(aFont, aCharCode); | |||||
| if (GlyphIndex < 0) then | |||||
| exit; | |||||
| Size := GetGlyphOutlineA(aDC, GlyphIndex, GGO_GRAY8_BITMAP or GGO_GLYPH_INDEX, @Metric, 0, nil, @aFont.fMat2); | |||||
| if (Size = GDI_ERROR) or (Size = 0) then | |||||
| exit; | |||||
| GetMem(Buffer, Size); | |||||
| try | |||||
| OutlineRes := GetGlyphOutlineA(aDC, GlyphIndex, GGO_GRAY8_BITMAP or GGO_GLYPH_INDEX, @Metric, Size, Buffer, @aFont.fMat2); | |||||
| if (OutlineRes = GDI_ERROR) then | |||||
| exit; | |||||
| w := Integer(Metric.gmBlackBoxX) div aFont.fMat2.eM11.value; | |||||
| h := Metric.gmBlackBoxY; | |||||
| tmp := Integer(Metric.gmBlackBoxX) mod aFont.fMat2.eM11.value; | |||||
| if (tmp <> 0) then | |||||
| w := w + aFont.fMat2.eM11.value - tmp; | |||||
| if (w <= 0) or (h <= 0) then | |||||
| exit; | |||||
| // spacer | |||||
| Spacer := Metric.gmBlackBoxX mod 4; | |||||
| if (Spacer <> 0) then | |||||
| Spacer := 4 - Spacer; | |||||
| // copy image | |||||
| aImage.CreateEmpty(aFont.Renderer.Format, w, h); | |||||
| pSrc := Buffer; | |||||
| for y := 0 to h-1 do begin | |||||
| pDst := aImage.Scanline[y]; | |||||
| x := Metric.gmBlackBoxX; | |||||
| while (x > 0) do | |||||
| CopyPixel; | |||||
| inc(pSrc, Spacer); | |||||
| end; | |||||
| finally | |||||
| FreeMem(Buffer); | |||||
| end; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function TtsFontGeneratorGDI.CreateFont(const aFontname: String; const aSize: Integer; const aStyle: TtsFontStyles; | |||||
| const aAntiAliasing: TtsAntiAliasing; out aProperties: TtsFontProperties): THandle; | |||||
| var | |||||
| LogFont: TLogFontA; | |||||
| i: Integer; | |||||
| DC: HDC; | |||||
| TableName, BufSize: Cardinal; | |||||
| Buffer: PByte; | |||||
| Lang: AnsiString; | |||||
| TextMetric: TTextMetricW; | |||||
| OutlineMetric: TOutlineTextmetricW; | |||||
| function _(e: Boolean; a, b: Integer): Integer; | |||||
| begin | |||||
| if e then | |||||
| result := a | |||||
| else | |||||
| result := b; | |||||
| end; | |||||
| begin | |||||
| result := 0; | |||||
| FillByte(aProperties, SizeOf(aProperties), 0); | |||||
| aProperties.Size := aSize; | |||||
| aProperties.Style := aStyle; | |||||
| aProperties.AntiAliasing := aAntiAliasing; | |||||
| aProperties.Fontname := aFontname; | |||||
| // prepare font attribs | |||||
| FillByte(LogFont, SizeOf(LogFont), 0); | |||||
| for i := 1 to min(Length(aFontname), Length(LogFont.lfFaceName)) do | |||||
| LogFont.lfFaceName[i-1] := aFontname[i]; | |||||
| LogFont.lfCharSet := DEFAULT_CHARSET; | |||||
| LogFont.lfHeight := -aSize; | |||||
| LogFont.lfWeight := _(tsStyleBold in aStyle, FW_BOLD, FW_NORMAL); | |||||
| LogFont.lfItalic := _(tsStyleItalic in aStyle, 1, 0); | |||||
| LogFont.lfUnderline := _(tsStyleUnderline in aStyle, 1, 0); | |||||
| LogFont.lfQuality := _(aAntiAliasing = tsAANormal, ANTIALIASED_QUALITY, NONANTIALIASED_QUALITY); | |||||
| result := CreateFontIndirectA(LogFont); | |||||
| DC := CreateCompatibleDC(0); | |||||
| try try | |||||
| SelectObject(DC, result); | |||||
| TableName := MakeTTTableName('n', 'a', 'm', 'e'); | |||||
| BufSize := GetFontData(DC, TableName, 0, nil, 0); | |||||
| if (BufSize <> GDI_ERROR) then begin | |||||
| GetMem(Buffer, BufSize); | |||||
| try | |||||
| if (GetFontData(DC, TableName, 0, Buffer, BufSize) <> GDI_ERROR) then begin | |||||
| SetLength(Lang, 4); | |||||
| GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ILANGUAGE, @Lang[1], 4); | |||||
| GetTTString(Buffer, BufSize, NAME_ID_COPYRIGHT, StrToInt('$' + String(Lang)), aProperties.Copyright); | |||||
| GetTTString(Buffer, BufSize, NAME_ID_FACE_NAME, StrToInt('$' + String(Lang)), aProperties.FaceName); | |||||
| GetTTString(Buffer, BufSize, NAME_ID_STYLE_NAME, StrToInt('$' + String(Lang)), aProperties.StyleName); | |||||
| GetTTString(Buffer, BufSize, NAME_ID_FULL_NAME, StrToInt('$' + String(Lang)), aProperties.FullName); | |||||
| end; | |||||
| finally | |||||
| FreeMem(Buffer); | |||||
| end; | |||||
| end; | |||||
| if GetTextMetricsW(DC, TextMetric) then begin | |||||
| aProperties.Ascent := TextMetric.tmAscent; | |||||
| aProperties.Descent := TextMetric.tmDescent; | |||||
| aProperties.ExternalLeading := TextMetric.tmExternalLeading; | |||||
| aProperties.DefaultChar := TextMetric.tmDefaultChar; | |||||
| end; | |||||
| if (GetOutlineTextMetricsW(DC, SizeOf(OutlineMetric), OutlineMetric) > 0) then begin | |||||
| aProperties.UnderlinePos := OutlineMetric.otmsUnderscorePosition; | |||||
| aProperties.UnderlineSize := Min(1, OutlineMetric.otmsUnderscoreSize); | |||||
| aProperties.StrikeoutPos := OutlineMetric.otmsStrikeoutPosition; | |||||
| aProperties.StrikeoutSize := Min(1, OutlineMetric.otmsStrikeoutSize); | |||||
| end; | |||||
| except | |||||
| DeleteObject(result); | |||||
| result := 0; | |||||
| end; | |||||
| finally | |||||
| DeleteDC(DC); | |||||
| end; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function TtsFontGeneratorGDI.GetGlyphMetrics(const aFont: TtsFont; const aCharCode: WideChar; out aGlyphOrigin, aGlyphSize: TtsPosition; out aAdvance: Integer): Boolean; | |||||
| var | |||||
| GlyphIndex: Integer; | |||||
| font: TtsFontGDI; | |||||
| DC: HDC; | |||||
| Metric: TGlyphMetrics; | |||||
| Size: Cardinal; | |||||
| begin | |||||
| result := false; | |||||
| aGlyphOrigin.x := 0; | |||||
| aGlyphOrigin.x := 0; | |||||
| aGlyphSize.x := 0; | |||||
| aGlyphSize.y := 0; | |||||
| aAdvance := 0; | |||||
| font := ConvertFont(aFont); | |||||
| GlyphIndex := GetGlyphIndex(font, aCharCode); | |||||
| if (GlyphIndex < 0) then | |||||
| exit; | |||||
| DC := CreateCompatibleDC(0); | |||||
| try | |||||
| SelectObject(DC, font.fHandle); | |||||
| case font.Properties.AntiAliasing of | |||||
| tsAANone: begin | |||||
| Size := GetGlyphOutlineA(DC, GlyphIndex, GGO_BITMAP or GGO_GLYPH_INDEX, @Metric, 0, nil, @font.fMat2); | |||||
| end; | |||||
| tsAANormal: begin | |||||
| Size := GetGlyphOutlineA(DC, GlyphIndex, GGO_GRAY8_BITMAP or GGO_GLYPH_INDEX, @Metric, 0, nil, @font.fMat2); | |||||
| end; | |||||
| else | |||||
| Size := GDI_ERROR; | |||||
| end; | |||||
| if (Size = GDI_ERROR) then | |||||
| Size := GetGlyphOutlineA(DC, GlyphIndex, GGO_METRICS or GGO_GLYPH_INDEX, @Metric, 0, nil, @font.fMat2); | |||||
| if (Size <> GDI_ERROR) then begin | |||||
| aGlyphOrigin.x := Round(Metric.gmptGlyphOrigin.x / font.fMat2.eM11.value); | |||||
| aGlyphOrigin.y := Metric.gmptGlyphOrigin.y; | |||||
| aGlyphSize.x := Round(Metric.gmBlackBoxX / font.fMat2.eM11.value); | |||||
| aGlyphSize.y := Metric.gmBlackBoxY; | |||||
| aAdvance := Round(Metric.gmCellIncX / font.fMat2.eM11.value); | |||||
| result := true; | |||||
| end; | |||||
| finally | |||||
| DeleteDC(DC); | |||||
| end; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| procedure TtsFontGeneratorGDI.GetCharImage(const aFont: TtsFont; const aCharCode: WideChar; const aCharImage: TtsImage); | |||||
| var | |||||
| DC: HDC; | |||||
| font: TtsFontGDI; | |||||
| begin | |||||
| font := ConvertFont(aFont); | |||||
| DC := CreateCompatibleDC(0); | |||||
| try | |||||
| SelectObject(DC, font.fHandle); | |||||
| case font.Properties.AntiAliasing of | |||||
| tsAANone: | |||||
| GetCharImageAANone(DC, font, aCharCode, aCharImage); | |||||
| tsAANormal: | |||||
| GetCharImageAANormal(DC, font, aCharCode, aCharImage); | |||||
| end; | |||||
| finally | |||||
| DeleteDC(DC); | |||||
| end; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function TtsFontGeneratorGDI.GetFontByName(const aFontname: String; const aRenderer: TtsRenderer; | |||||
| const aSize: Integer; const aStyle: TtsFontStyles; const aAntiAliasing: TtsAntiAliasing): TtsFont; | |||||
| var | |||||
| handle: THandle; | |||||
| prop: TtsFontProperties; | |||||
| begin | |||||
| handle := CreateFont(aFontname, aSize, aStyle, aAntiAliasing, prop); | |||||
| if (handle = 0) then | |||||
| raise EtsException.Create('unable to create font from name: ' + aFontname); | |||||
| result := TtsFontGDI.Create(aRenderer, self, prop, handle); | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function TtsFontGeneratorGDI.GetFontByFile(const aFilename: String; const aRenderer: TtsRenderer; | |||||
| const aSize: Integer; const aStyle: TtsFontStyles; const aAntiAliasing: TtsAntiAliasing): TtsFont; | |||||
| var | |||||
| reg: TtsFontRegistrationFile; | |||||
| handle: THandle; | |||||
| prop: TtsFontProperties; | |||||
| begin | |||||
| reg := TtsFontRegistrationFile.Create(aFilename); | |||||
| if not reg.IsRegistered then | |||||
| raise EtsException.Create('unable to register font file: ' + aFilename); | |||||
| handle := CreateFont(reg.Fontname, aSize, aStyle, aAntiAliasing, prop); | |||||
| if (handle = 0) then | |||||
| raise EtsException.Create('unable to create font from file: ' + aFilename); | |||||
| result := TtsRegistredFontGDI.Create(aRenderer, self, reg, prop, handle); | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function TtsFontGeneratorGDI.GetFontByStream(const aStream: TStream; const aRenderer: TtsRenderer; | |||||
| const aSize: Integer; const aStyle: TtsFontStyles; const aAntiAliasing: TtsAntiAliasing): TtsFont; | |||||
| var | |||||
| reg: TtsFontRegistrationStream; | |||||
| handle: THandle; | |||||
| prop: TtsFontProperties; | |||||
| begin | |||||
| reg := TtsFontRegistrationStream.Create(aStream); | |||||
| if not reg.IsRegistered then | |||||
| raise EtsException.Create('unable to register font from stream'); | |||||
| handle := CreateFont(reg.Fontname, aSize, aStyle, aAntiAliasing, prop); | |||||
| if (handle = 0) then | |||||
| raise EtsException.Create('unable to create font from stream: ' + reg.Fontname); | |||||
| result := TtsRegistredFontGDI.Create(aRenderer, self, reg, prop, handle); | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| constructor TtsFontGeneratorGDI.Create; | |||||
| begin | |||||
| inherited Create; | |||||
| gdiCritSec.Enter; | |||||
| try | |||||
| inc(gdiRefCount, 1); | |||||
| if not gdiInitialized then | |||||
| InitGDI; | |||||
| finally | |||||
| gdiCritSec.Leave; | |||||
| end; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| destructor TtsFontGeneratorGDI.Destroy; | |||||
| begin | |||||
| gdiCritSec.Enter; | |||||
| try | |||||
| dec(gdiRefCount, 1); | |||||
| if (gdiRefCount <= 0) then | |||||
| QuitGDI; | |||||
| finally | |||||
| gdiCritSec.Leave; | |||||
| end; | |||||
| inherited Destroy; | |||||
| end; | |||||
| initialization | |||||
| gdiRefCount := 0; | |||||
| gdiInitialized := false; | |||||
| gdiCritSec := TCriticalSection.Create; | |||||
| finalization | |||||
| if gdiInitialized then | |||||
| QuitGDI; | |||||
| FreeAndNil(gdiCritSec); | |||||
| end. | |||||
| @@ -0,0 +1,521 @@ | |||||
| unit utsRendererOpenGL; | |||||
| {$mode objfpc}{$H+} | |||||
| interface | |||||
| uses | |||||
| Classes, SysUtils, syncobjs, dglOpenGL, | |||||
| utsTextSuite, utsTypes; | |||||
| type | |||||
| TtsQuadPosF = array[0..3] of TtsPositionF; | |||||
| TtsCharRenderRefOpenGL = class(TtsCharRenderRef) | |||||
| private | |||||
| TextureID: GLint; // ID of OpenGL texture where the char is stored in | |||||
| TexCoordSize: TtsPositionF; // size of the char in texture coords (0.0 - 1.0) | |||||
| TexCoordPos: TtsPositionF; // position of the char in texture coords (0.0 - 1.0) | |||||
| VertexSize: TtsPositionF; // size of the char in world coords | |||||
| VertexPos: TtsPositionF; // size of the char in world coords | |||||
| public | |||||
| constructor Create; | |||||
| end; | |||||
| PtsTextureUsageItem = ^TtsTextureUsageItem; | |||||
| TtsTextureUsageItem = packed record | |||||
| children: array[0..3] of PtsTextureUsageItem; | |||||
| end; | |||||
| PtsTextureTreeItem = ^TtsTextureTreeItem; | |||||
| TtsTextureTreeItem = packed record | |||||
| value: SmallInt; | |||||
| children: array[0..1] of PtsTextureTreeItem; | |||||
| ref: TtsCharRenderRefOpenGL; | |||||
| end; | |||||
| PtsFontTexture = ^TtsFontTexture; | |||||
| TtsFontTexture = packed record | |||||
| ID: GLint; // OpenGL texture ID | |||||
| Usage: PtsTextureTreeItem ; // tree of used texture space | |||||
| Next: PtsFontTexture; // next texture in list | |||||
| Prev: PtsFontTexture; // previouse texture in list | |||||
| Size: Integer; // size of this texture | |||||
| Count: Integer; // number of chars stored in this texture | |||||
| end; | |||||
| TtsRendererOpenGL = class(TtsRenderer) | |||||
| private | |||||
| fVBO: GLuint; | |||||
| fTextureSize: Integer; | |||||
| fColor: TtsColor4f; | |||||
| fRenderPos: TtsPosition; | |||||
| fIsRendering: Boolean; | |||||
| fFirstTexture: PtsFontTexture; | |||||
| fLastTexture: PtsFontTexture; | |||||
| function CreateNewTexture: PtsFontTexture; | |||||
| procedure FreeTexture(var aTexture: PtsFontTexture); | |||||
| procedure FreeTextures(var aTexture: PtsFontTexture); | |||||
| procedure FreeTextureTreeItem(var aItem: PtsTextureTreeItem); | |||||
| protected | |||||
| function CreateRenderRef(const aChar: TtsChar; const aCharImage: TtsImage): TtsCharRenderRef; override; | |||||
| procedure FreeRenderRef(const aCharRef: TtsCharRenderRef); override; | |||||
| procedure BeginRender; override; | |||||
| procedure EndRender; override; | |||||
| procedure SetDrawPos(const X, Y: Integer); override; | |||||
| function GetDrawPos: TtsPosition; override; | |||||
| procedure MoveDrawPos(const X, Y: Integer); override; | |||||
| procedure SetColor(const aColor: TtsColor4f); override; | |||||
| procedure Render(const aCharRef: TtsCharRenderRef); override; | |||||
| public | |||||
| property TextureSize: Integer read fTextureSize write fTextureSize; | |||||
| constructor Create(const aContext: TtsContext; const aFormat: TtsFormat); | |||||
| destructor Destroy; override; | |||||
| end; | |||||
| EtsRendererOpenGL = class(EtsRenderer); | |||||
| implementation | |||||
| type | |||||
| TVertex = packed record | |||||
| pos: array[0..1] of GLfloat; | |||||
| tex: array[0..1] of GLfloat; | |||||
| end; | |||||
| const | |||||
| FORMAT_TYPES: array[TtsFormat] of packed record | |||||
| InternalFormat: GLenum; | |||||
| Format: GLenum; | |||||
| DataFormat: GLenum; | |||||
| end = ( | |||||
| ( //tsFormatEmpty | |||||
| InternalFormat: 0; | |||||
| Format: 0; | |||||
| DataFormat: 0), | |||||
| ( //tsFormatRGBA8 | |||||
| InternalFormat: GL_RGBA8; | |||||
| Format: GL_RGBA; | |||||
| DataFormat: GL_UNSIGNED_BYTE), | |||||
| ( //tsFormatLumAlpha8 | |||||
| InternalFormat: GL_LUMINANCE8_ALPHA8; | |||||
| Format: GL_LUMINANCE_ALPHA; | |||||
| DataFormat: GL_UNSIGNED_BYTE), | |||||
| ( //tsFormatAlpha8 | |||||
| InternalFormat: GL_ALPHA8; | |||||
| Format: GL_ALPHA; | |||||
| DataFormat: GL_UNSIGNED_BYTE) | |||||
| ); | |||||
| VBO_DATA: array[0..3] of TVertex = ( | |||||
| (pos: (0.0, 0.0); tex: (0.0, 0.0)), | |||||
| (pos: (0.0, 1.0); tex: (0.0, 1.0)), | |||||
| (pos: (1.0, 1.0); tex: (1.0, 1.0)), | |||||
| (pos: (1.0, 0.0); tex: (1.0, 0.0)) | |||||
| ); | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| //TtsCharRenderRefOpenGL//////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| constructor TtsCharRenderRefOpenGL.Create; | |||||
| begin | |||||
| inherited Create; | |||||
| TextureID := 0; | |||||
| FillByte(TexCoordPos, SizeOf(TexCoordPos), 0); | |||||
| FillByte(TexCoordSize, SizeOf(TexCoordSize), 0); | |||||
| FillByte(VertexPos, SizeOf(VertexPos), 0); | |||||
| FillByte(VertexSize, SizeOf(VertexSize), 0); | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| //TtsRendererOpenGL///////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function TtsRendererOpenGL.CreateNewTexture: PtsFontTexture; | |||||
| begin | |||||
| new(result); | |||||
| try | |||||
| FillByte(result^, SizeOf(result^), 0); | |||||
| new(result^.Usage); | |||||
| FillByte(result^.Usage^, SizeOf(result^.Usage^), 0); | |||||
| result^.Size := TextureSize; | |||||
| glGenTextures(1, @result^.ID); | |||||
| glBindTexture(GL_TEXTURE_2D, result^.ID); | |||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |||||
| glTexImage2D( | |||||
| GL_TEXTURE_2D, | |||||
| 0, | |||||
| FORMAT_TYPES[Format].InternalFormat, | |||||
| result^.Size, | |||||
| result^.Size, | |||||
| 0, | |||||
| FORMAT_TYPES[Format].Format, | |||||
| FORMAT_TYPES[Format].DataFormat, | |||||
| nil); | |||||
| result^.Prev := fLastTexture; | |||||
| if Assigned(fLastTexture) then | |||||
| fLastTexture^.Next := result | |||||
| else | |||||
| fFirstTexture := result; | |||||
| fLastTexture := result; | |||||
| except | |||||
| if Assigned(result^.Usage) then | |||||
| Dispose(result^.Usage); | |||||
| Dispose(result); | |||||
| end; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| procedure TtsRendererOpenGL.FreeTexture(var aTexture: PtsFontTexture); | |||||
| begin | |||||
| if not Assigned(aTexture) then | |||||
| exit; | |||||
| glDeleteTextures(1, @aTexture^.ID); | |||||
| FreeTextureTreeItem(aTexture^.Usage); | |||||
| if Assigned(aTexture^.Prev) then | |||||
| aTexture^.Prev^.Next := aTexture^.Next; | |||||
| if Assigned(aTexture^.Next) then | |||||
| aTexture^.Next^.Prev := aTexture^.Prev; | |||||
| Dispose(aTexture); | |||||
| aTexture := nil; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| procedure TtsRendererOpenGL.FreeTextures(var aTexture: PtsFontTexture); | |||||
| begin | |||||
| if not Assigned(aTexture) then | |||||
| exit; | |||||
| FreeTextures(aTexture^.Next); | |||||
| FreeTexture(aTexture); | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| procedure TtsRendererOpenGL.FreeTextureTreeItem(var aItem: PtsTextureTreeItem); | |||||
| begin | |||||
| if not Assigned(aItem) then | |||||
| exit; | |||||
| FreeTextureTreeItem(aItem^.children[0]); | |||||
| FreeTextureTreeItem(aItem^.children[1]); | |||||
| Dispose(aItem); | |||||
| aItem := nil; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function TtsRendererOpenGL.CreateRenderRef(const aChar: TtsChar; const aCharImage: TtsImage): TtsCharRenderRef; | |||||
| var | |||||
| GlyphWidth, GlyphHeight: Integer; | |||||
| function InsertToTree(const aItem: PtsTextureTreeItem; const X1, Y1, X2, Y2: SmallInt; out X, Y: Integer): PtsTextureTreeItem; | |||||
| var | |||||
| w, h: Integer; | |||||
| begin | |||||
| result := nil; | |||||
| w := X2 - X1; | |||||
| h := Y2 - Y1; | |||||
| if not Assigned(aItem) or | |||||
| Assigned(aItem^.ref) or | |||||
| (w < GlyphWidth) or | |||||
| (h < GlyphHeight) then | |||||
| exit; | |||||
| if (aItem^.value > 0) then begin | |||||
| result := InsertToTree(aItem^.children[0], X1, Y1, X2, aItem^.value, X, Y); | |||||
| if not Assigned(result) then | |||||
| result := InsertToTree(aItem^.children[1], X1, aItem^.value, X2, Y2, X, Y); | |||||
| end else if (aItem^.value < 0) then begin | |||||
| result := InsertToTree(aItem^.children[0], X1, Y1, -aItem^.value, Y2, X, Y); | |||||
| if not Assigned(result) then | |||||
| result := InsertToTree(aItem^.children[1], -aItem^.value, Y1, X2, Y2, X, Y); | |||||
| end else if (w = GlyphWidth) and (h = GlyphHeight) then begin | |||||
| X := X1; | |||||
| Y := Y1; | |||||
| result := aItem; | |||||
| end else begin | |||||
| new(aItem^.children[0]); | |||||
| new(aItem^.children[1]); | |||||
| FillByte(aItem^.children[0]^, SizeOf(aItem^.children[0]^), 0); | |||||
| FillByte(aItem^.children[1]^, SizeOf(aItem^.children[1]^), 0); | |||||
| if (w - GlyphWidth) < (h - GlyphHeight) then begin | |||||
| aItem^.value := Y1 + GlyphHeight; | |||||
| result := InsertToTree(aItem^.children[0], X1, Y1, X2, aItem^.value, X, Y); | |||||
| end else begin | |||||
| aItem^.value := -(X1 + GlyphWidth); | |||||
| result := InsertToTree(aItem^.children[0], X1, Y1, -aItem^.value, Y2, X, Y) | |||||
| end; | |||||
| end; | |||||
| end; | |||||
| function AddToTexture(const aTexture: PtsFontTexture): TtsCharRenderRefOpenGL; | |||||
| var | |||||
| x, y: Integer; | |||||
| item: PtsTextureTreeItem; | |||||
| begin | |||||
| item := InsertToTree(aTexture^.Usage, 0, 0, aTexture^.Size, aTexture^.Size, x, y); | |||||
| if not Assigned(item) then | |||||
| raise EtsRendererOpenGL.Create('unable to add glyph to texture'); | |||||
| item^.ref := TtsCharRenderRefOpenGL.Create; | |||||
| result := item^.ref; | |||||
| // Text Coords | |||||
| result.TextureID := aTexture^.ID; | |||||
| result.TexCoordPos.x := x / aTexture^.Size; | |||||
| result.TexCoordPos.y := y / aTexture^.Size; | |||||
| result.TexCoordSize.x := aCharImage.Width / aTexture^.Size; | |||||
| result.TexCoordSize.y := aCharImage.Height / aTexture^.Size; | |||||
| // Vertex Coords | |||||
| result.VertexPos.x := -aChar.GlyphRect.Left; | |||||
| result.VertexPos.y := -aChar.GlyphRect.Top - aChar.GlyphOrigin.y; | |||||
| result.VertexSize.x := aCharImage.Width; | |||||
| result.VertexSize.y := aCharImage.Height; | |||||
| glBindTexture(GL_TEXTURE_2D, result.TextureID); | |||||
| glTexSubImage2D(GL_TEXTURE_2D, 0, | |||||
| x, y, aCharImage.Width, aCharImage.Height, | |||||
| FORMAT_TYPES[aCharImage.Format].Format, | |||||
| FORMAT_TYPES[aCharImage.Format].DataFormat, | |||||
| aCharImage.Data); | |||||
| end; | |||||
| var | |||||
| tex: PtsFontTexture; | |||||
| begin | |||||
| result := nil; | |||||
| if aCharImage.IsEmpty then | |||||
| exit; | |||||
| GlyphWidth := aCharImage.Width + 1; | |||||
| GlyphHeight := aCharImage.Height + 1; | |||||
| // try to add to existing texture | |||||
| tex := fFirstTexture; | |||||
| while Assigned(tex) and not Assigned(result) do begin | |||||
| result := AddToTexture(tex); | |||||
| tex := tex^.Next; | |||||
| end; | |||||
| // create new texture | |||||
| if not Assigned(result) then begin | |||||
| if (aCharImage.Width > TextureSize) or (aCharImage.Height > TextureSize) then | |||||
| raise EtsRendererOpenGL.Create('char is to large to fit into a texture: ' + aChar.CharCode + ' (0x' + IntToHex(Ord(aChar.CharCode), 4) + ')'); | |||||
| tex := CreateNewTexture; | |||||
| result := AddToTexture(tex); | |||||
| end; | |||||
| if not Assigned(result) then | |||||
| raise EtsRendererOpenGL.Create('unable to creat render reference for char: ' + aChar.CharCode + ' (0x' + IntToHex(Ord(aChar.CharCode), 4) + ')'); | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| procedure TtsRendererOpenGL.FreeRenderRef(const aCharRef: TtsCharRenderRef); | |||||
| var | |||||
| ref: TtsCharRenderRefOpenGL; | |||||
| tex: PtsFontTexture; | |||||
| function IsEmtpy(const aItem: PtsTextureTreeItem): Boolean; | |||||
| begin | |||||
| result := | |||||
| Assigned(aItem) and | |||||
| not Assigned(aItem^.children[0]) and | |||||
| not Assigned(aItem^.children[1]) and | |||||
| not Assigned(aItem^.ref); | |||||
| end; | |||||
| function RemoveFromTree(const aItem: PtsTextureTreeItem; const X1, Y1, X2, Y2: Integer): Boolean; | |||||
| var | |||||
| w, h: Integer; | |||||
| begin | |||||
| w := X2 - X1; | |||||
| h := Y2 - Y1; | |||||
| if not Assigned(aItem) or | |||||
| (w < ref.VertexSize.x) or | |||||
| (h < ref.VertexSize.y) then | |||||
| exit; | |||||
| result := (aItem^.ref = ref); | |||||
| if not result then begin | |||||
| if (aItem^.value > 0) then begin | |||||
| result := result or RemoveFromTree(aItem^.children[0], X1, Y1, X2, aItem^.value); | |||||
| result := result or RemoveFromTree(aItem^.children[1], X1, aItem^.value, X2, Y2); | |||||
| end else if (aItem^.value < 0) then begin | |||||
| result := result or RemoveFromTree(aItem^.children[0], X1, Y1, -aItem^.value, Y2); | |||||
| result := result or RemoveFromTree(aItem^.children[1], -aItem^.value, Y1, X2, Y2); | |||||
| end; | |||||
| end else | |||||
| aItem^.ref := nil; | |||||
| if result and | |||||
| IsEmtpy(aItem^.children[0]) and | |||||
| IsEmtpy(aItem^.children[1]) then | |||||
| begin | |||||
| FreeTextureTreeItem(aItem^.children[0]); | |||||
| FreeTextureTreeItem(aItem^.children[1]); | |||||
| FillByte(aItem^, SizeOf(aItem^), 0); | |||||
| end; | |||||
| end; | |||||
| begin | |||||
| try | |||||
| if not Assigned(aCharRef) or not (aCharRef is TtsCharRenderRefOpenGL) then | |||||
| exit; | |||||
| ref := (aCharRef as TtsCharRenderRefOpenGL); | |||||
| tex := fFirstTexture; | |||||
| while Assigned(tex) do begin | |||||
| if (tex^.ID = ref.TextureID) then begin | |||||
| if not RemoveFromTree(tex^.Usage, 0, 0, tex^.Size, tex^.Size) then | |||||
| raise EtsRendererOpenGL.Create('unable to remove render ref from texture'); | |||||
| if IsEmtpy(tex^.Usage) then begin | |||||
| if (tex = fFirstTexture) then | |||||
| fFirstTexture := nil; | |||||
| FreeTexture(tex); | |||||
| end; | |||||
| tex := nil; | |||||
| end else | |||||
| tex := tex^.Next; | |||||
| end; | |||||
| finally | |||||
| if Assigned(aCharRef) then | |||||
| aCharRef.Free; | |||||
| end; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| procedure TtsRendererOpenGL.BeginRender; | |||||
| begin | |||||
| inherited BeginRender; | |||||
| fIsRendering := true; | |||||
| fRenderPos.x := 0; | |||||
| fRenderPos.y := 0; | |||||
| glPushMatrix; | |||||
| glColor4fv(@fColor.arr[0]); | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| procedure TtsRendererOpenGL.EndRender; | |||||
| begin | |||||
| if fIsRendering then begin | |||||
| glPopMatrix; | |||||
| fIsRendering := false; | |||||
| end; | |||||
| inherited EndRender; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| procedure TtsRendererOpenGL.SetDrawPos(const X, Y: Integer); | |||||
| begin | |||||
| fRenderPos.x := X; | |||||
| fRenderPos.y := Y; | |||||
| glPopMatrix; | |||||
| glPushMatrix; | |||||
| glTranslatef(X, Y, 0); | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function TtsRendererOpenGL.GetDrawPos: TtsPosition; | |||||
| begin | |||||
| result := fRenderPos; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| procedure TtsRendererOpenGL.MoveDrawPos(const X, Y: Integer); | |||||
| begin | |||||
| fRenderPos.x := fRenderPos.x + X; | |||||
| fRenderPos.y := fRenderPos.y + Y; | |||||
| glTranslatef(X, Y, 0); | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| procedure TtsRendererOpenGL.SetColor(const aColor: TtsColor4f); | |||||
| begin | |||||
| fColor := aColor; | |||||
| glColor4fv(@fColor.arr[0]); | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| procedure TtsRendererOpenGL.Render(const aCharRef: TtsCharRenderRef); | |||||
| var | |||||
| ref: TtsCharRenderRefOpenGL; | |||||
| procedure RenderTreeItem(const aItem: PtsTextureTreeItem; const X1, Y1, X2, Y2: Integer); | |||||
| begin | |||||
| glBegin(GL_LINE_LOOP); | |||||
| glVertex2f(X1, Y1); | |||||
| glVertex2f(X2, Y1); | |||||
| glVertex2f(X2, Y2); | |||||
| glVertex2f(X1, Y2); | |||||
| glEnd; | |||||
| if (aItem^.value > 0) then begin | |||||
| RenderTreeItem(aItem^.children[0], X1, Y1, X2, aItem^.value); | |||||
| RenderTreeItem(aItem^.children[1], X1, aItem^.value, X2, Y2); | |||||
| end else if (aItem^.value < 0) then begin | |||||
| RenderTreeItem(aItem^.children[0], X1, Y1, -aItem^.value, Y2); | |||||
| RenderTreeItem(aItem^.children[1], -aItem^.value, Y1, X2, Y2); | |||||
| end; | |||||
| end; | |||||
| begin | |||||
| if Assigned(aCharRef) and (aCharRef is TtsCharRenderRefOpenGL) then begin | |||||
| ref := (aCharRef as TtsCharRenderRefOpenGL); | |||||
| glEnable(GL_TEXTURE_2D); | |||||
| glBindTexture(GL_TEXTURE_2D, ref.TextureID); | |||||
| glMatrixMode(GL_TEXTURE); | |||||
| glPushMatrix; | |||||
| glLoadIdentity; | |||||
| glTranslatef(ref.TexCoordPos.x, ref.TexCoordPos.y, 0); | |||||
| glScalef(ref.TexCoordSize.x, ref.TexCoordSize.y, 1); | |||||
| glMatrixMode(GL_MODELVIEW); | |||||
| glPushMatrix; | |||||
| glTranslatef(ref.VertexPos.x, ref.VertexPos.y, 0); | |||||
| glScalef(ref.VertexSize.x, ref.VertexSize.y, 1); | |||||
| glBindBuffer(GL_ARRAY_BUFFER, fVBO); | |||||
| glEnableClientState(GL_VERTEX_ARRAY); | |||||
| glVertexPointer(2, GL_FLOAT, SizeOf(TVertex), Pointer(0)); | |||||
| glEnableClientState(GL_TEXTURE_COORD_ARRAY); | |||||
| glTexCoordPointer(2, GL_FLOAT, SizeOf(TVertex), Pointer(8)); | |||||
| glDrawArrays(GL_QUADS, 0, 4); | |||||
| glDisableClientState(GL_TEXTURE_COORD_ARRAY); | |||||
| glDisableClientState(GL_VERTEX_ARRAY); | |||||
| glMatrixMode(GL_TEXTURE); | |||||
| glPopMatrix; | |||||
| glMatrixMode(GL_MODELVIEW); | |||||
| glPopMatrix; | |||||
| end; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| constructor TtsRendererOpenGL.Create(const aContext: TtsContext; const aFormat: TtsFormat); | |||||
| begin | |||||
| inherited Create(aContext, aFormat); | |||||
| fIsRendering := false; | |||||
| fFirstTexture := nil; | |||||
| fLastTexture := nil; | |||||
| fTextureSize := 2048; | |||||
| fColor := tsColor4f(1, 1, 1, 1); | |||||
| fRenderPos := tsPosition(0, 0); | |||||
| glGenBuffers(1, @fVBO); | |||||
| glBindBuffer(GL_ARRAY_BUFFER, fVBO); | |||||
| glBufferData(GL_ARRAY_BUFFER, SizeOf(TVertex) * Length(VBO_DATA), @VBO_DATA[0].pos[0], GL_STATIC_DRAW); | |||||
| glBindBuffer(GL_ARRAY_BUFFER, 0); | |||||
| end; | |||||
| destructor TtsRendererOpenGL.Destroy; | |||||
| begin | |||||
| glDeleteBuffers(1, @fVBO); | |||||
| FreeTextures(fFirstTexture); | |||||
| inherited Destroy; | |||||
| end; | |||||
| end. | |||||
| @@ -0,0 +1,323 @@ | |||||
| unit utsTtfUtils; | |||||
| {$mode objfpc}{$H+} | |||||
| interface | |||||
| uses | |||||
| Classes, SysUtils; | |||||
| const | |||||
| NAME_ID_COPYRIGHT = 0; | |||||
| NAME_ID_FACE_NAME = 1; | |||||
| NAME_ID_STYLE_NAME = 2; | |||||
| NAME_ID_FULL_NAME = 4; | |||||
| function MakeTTTableName(const ch1, ch2, ch3, ch4: Char): Cardinal; | |||||
| function GetTTString(pBuffer: Pointer; BufferSize: Integer; NameID, LanguageID: Cardinal; var Text: AnsiString): Boolean; | |||||
| function GetTTFontFullNameFromStream(Stream: TStream; LanguageID: Cardinal): AnsiString; | |||||
| function GetTTFontFullNameFromFile(Filename: AnsiString; LanguageID: Cardinal): AnsiString; | |||||
| implementation | |||||
| uses | |||||
| utsUtils; | |||||
| type | |||||
| TT_OFFSET_TABLE = packed record | |||||
| uMajorVersion: Word; | |||||
| uMinorVersion: Word; | |||||
| uNumOfTables: Word; | |||||
| uSearchRange: Word; | |||||
| uEntrySelector: Word; | |||||
| uRangeShift: Word; | |||||
| end; | |||||
| TT_TABLE_DIRECTORY = packed record | |||||
| TableName: Cardinal; // table name | |||||
| uCheckSum: Cardinal; // Check sum | |||||
| uOffset: Cardinal; // Offset from beginning of file | |||||
| uLength: Cardinal; // length of the table in bytes | |||||
| end; | |||||
| TT_NAME_TABLE_HEADER = packed record | |||||
| uFSelector: Word; //format selector. Always 0 | |||||
| uNRCount: Word; //Name Records count | |||||
| uStorageOffset: Word; //Offset for strings storage, from start of the table | |||||
| end; | |||||
| TT_NAME_RECORD = packed record | |||||
| uPlatformID: Word; | |||||
| uEncodingID: Word; | |||||
| uLanguageID: Word; | |||||
| uNameID: Word; | |||||
| uStringLength: Word; | |||||
| uStringOffset: Word; //from start of storage area | |||||
| end; | |||||
| const | |||||
| PLATFORM_ID_APPLE_UNICODE = 0; | |||||
| PLATFORM_ID_MACINTOSH = 1; | |||||
| PLATFORM_ID_MICROSOFT = 3; | |||||
| function SWAPWORD(x: Word): Word; | |||||
| begin | |||||
| Result := x and $FF; | |||||
| Result := Result shl 8; | |||||
| Result := Result or (x shr 8); | |||||
| end; | |||||
| function SWAPLONG(x: Cardinal): Cardinal; | |||||
| begin | |||||
| Result := (x and $FF) shl 24; | |||||
| x := x shr 8; | |||||
| Result := Result or ((x and $FF) shl 16); | |||||
| x := x shr 8; | |||||
| Result := Result or ((x and $FF) shl 8); | |||||
| x := x shr 8; | |||||
| Result := Result or x; | |||||
| end; | |||||
| function GetTTTableData(Stream: TStream; TableName: Cardinal; pBuff: Pointer; var Size: Integer): Boolean; | |||||
| var | |||||
| Pos: Int64; | |||||
| OffsetTable: TT_OFFSET_TABLE; | |||||
| TableDir: TT_TABLE_DIRECTORY; | |||||
| Idx: Integer; | |||||
| begin | |||||
| Result := False; | |||||
| Pos := Stream.Position; | |||||
| // Reading table header | |||||
| Stream.Read(OffsetTable, sizeof(TT_OFFSET_TABLE)); | |||||
| OffsetTable.uNumOfTables := SWAPWORD(OffsetTable.uNumOfTables); | |||||
| OffsetTable.uMajorVersion := SWAPWORD(OffsetTable.uMajorVersion); | |||||
| OffsetTable.uMinorVersion := SWAPWORD(OffsetTable.uMinorVersion); | |||||
| //check is this is a true type font and the version is 1.0 | |||||
| if (OffsetTable.uMajorVersion <> 1) or (OffsetTable.uMinorVersion <> 0) then | |||||
| Exit; | |||||
| // seaching table with name | |||||
| for Idx := 0 to OffsetTable.uNumOfTables -1 do begin | |||||
| Stream.Read(TableDir, sizeof(TT_TABLE_DIRECTORY)); | |||||
| if (TableName = TableDir.TableName) then begin | |||||
| TableDir.uOffset := SWAPLONG(TableDir.uOffset); | |||||
| TableDir.uLength := SWAPLONG(TableDir.uLength); | |||||
| // copying tabledata | |||||
| if (pBuff <> nil) and (Size >= Integer(TableDir.uLength)) then begin | |||||
| Stream.Seek(TableDir.uOffset, soBeginning); | |||||
| Size := Stream.Read(pBuff^, TableDir.uLength); | |||||
| Result := Size = Integer(TableDir.uLength); | |||||
| end else | |||||
| begin | |||||
| // restoring streamposition | |||||
| Stream.Position := Pos; | |||||
| Size := TableDir.uLength; | |||||
| Result := True; | |||||
| end; | |||||
| break; | |||||
| end; | |||||
| end; | |||||
| end; | |||||
| function MakeTTTableName(const ch1, ch2, ch3, ch4: Char): Cardinal; | |||||
| begin | |||||
| Result := ord(ch4) shl 24 or ord(ch3) shl 16 or ord(ch2) shl 8 or ord(ch1); | |||||
| end; | |||||
| function GetTTString(pBuffer: Pointer; BufferSize: Integer; NameID, LanguageID: Cardinal; var Text: AnsiString): Boolean; | |||||
| var | |||||
| pActBuffer: pByte; | |||||
| ttNTHeader: TT_NAME_TABLE_HEADER; | |||||
| ttRecord: TT_NAME_RECORD; | |||||
| Idx: Integer; | |||||
| Prio: Integer; | |||||
| procedure ExtractName; | |||||
| var | |||||
| pTempBuffer: pByte; | |||||
| pTemp: pWideChar; | |||||
| uStringLengthH2: Word; | |||||
| procedure SwapText(pText: pWideChar; Length: Word); | |||||
| begin | |||||
| while Length > 0 do begin | |||||
| pWord(pText)^ := SWAPWORD(pWord(pText)^); | |||||
| Inc(pText); | |||||
| Dec(Length); | |||||
| end; | |||||
| end; | |||||
| begin | |||||
| Result := True; | |||||
| ttRecord.uStringLength := SWAPWORD(ttRecord.uStringLength); | |||||
| ttRecord.uStringOffset := SWAPWORD(ttRecord.uStringOffset); | |||||
| uStringLengthH2 := ttRecord.uStringLength shr 1; | |||||
| pTempBuffer := pBuffer; | |||||
| Inc(pTempBuffer, ttNTHeader.uStorageOffset + ttRecord.uStringOffset); | |||||
| // Unicode | |||||
| if ((ttRecord.uPlatformID = PLATFORM_ID_MICROSOFT) and (ttRecord.uEncodingID in [0, 1])) or | |||||
| ((ttRecord.uPlatformID = PLATFORM_ID_APPLE_UNICODE) and (ttRecord.uEncodingID > 0)) then begin | |||||
| pTemp := tsStrAlloc(uStringLengthH2); | |||||
| try | |||||
| // uStringLengthH2 * 2 because possible buffer overrun | |||||
| Move(pTempBuffer^, pTemp^, uStringLengthH2 * 2); | |||||
| SwapText(pTemp, uStringLengthH2); | |||||
| WideCharLenToStrVar(pTemp, uStringLengthH2, Text); | |||||
| finally | |||||
| tsStrDispose(pTemp); | |||||
| end; | |||||
| end else | |||||
| // none unicode | |||||
| begin | |||||
| SetLength(Text, ttRecord.uStringLength); | |||||
| Move(pTempBuffer^, Text[1], ttRecord.uStringLength); | |||||
| end; | |||||
| end; | |||||
| begin | |||||
| Result := False; | |||||
| pActBuffer := pBuffer; | |||||
| Move(pActBuffer^, ttNTHeader, sizeof(TT_NAME_TABLE_HEADER)); | |||||
| inc(pActBuffer, sizeof(TT_NAME_TABLE_HEADER)); | |||||
| ttNTHeader.uNRCount := SWAPWORD(ttNTHeader.uNRCount); | |||||
| ttNTHeader.uStorageOffset := SWAPWORD(ttNTHeader.uStorageOffset); | |||||
| Prio := -1; | |||||
| for Idx := 0 to ttNTHeader.uNRCount -1 do begin | |||||
| Move(pActBuffer^, ttRecord, sizeof(TT_NAME_RECORD)); | |||||
| Inc(pActBuffer, sizeof(TT_NAME_RECORD)); | |||||
| ttRecord.uNameID := SWAPWORD(ttRecord.uNameID); | |||||
| if ttRecord.uNameID = NameID then begin | |||||
| ttRecord.uPlatformID := SWAPWORD(ttRecord.uPlatformID); | |||||
| ttRecord.uEncodingID := SWAPWORD(ttRecord.uEncodingID); | |||||
| ttRecord.uLanguageID := SWAPWORD(ttRecord.uLanguageID); | |||||
| // highest priority | |||||
| if (ttRecord.uPlatformID = PLATFORM_ID_MICROSOFT) then begin | |||||
| // system language | |||||
| if (ttRecord.uLanguageID = languageID) then begin | |||||
| if Prio <= 7 then begin | |||||
| ExtractName; | |||||
| Prio := 7; | |||||
| end; | |||||
| end else | |||||
| // english | |||||
| if (ttRecord.uLanguageID = 1033) then begin | |||||
| if Prio <= 6 then begin | |||||
| ExtractName; | |||||
| Prio := 6; | |||||
| end; | |||||
| end else | |||||
| // all else | |||||
| if Prio <= 5 then begin | |||||
| ExtractName; | |||||
| Prio := 5; | |||||
| end; | |||||
| end else | |||||
| // apple unicode | |||||
| if (ttRecord.uPlatformID = PLATFORM_ID_APPLE_UNICODE) then begin | |||||
| ExtractName; | |||||
| Prio := 4; | |||||
| end else | |||||
| // macintosh | |||||
| if (ttRecord.uPlatformID = PLATFORM_ID_MACINTOSH) then begin | |||||
| // english | |||||
| if (ttRecord.uLanguageID = 0) then begin | |||||
| if Prio <= 3 then begin | |||||
| ExtractName; | |||||
| Prio := 3; | |||||
| end; | |||||
| end else | |||||
| // all other | |||||
| begin | |||||
| ExtractName; | |||||
| Prio := 2; | |||||
| end; | |||||
| end else | |||||
| begin | |||||
| if Prio <= 1 then begin | |||||
| ExtractName; | |||||
| Prio := 1; | |||||
| end; | |||||
| end; | |||||
| end; | |||||
| end; | |||||
| end; | |||||
| function GetTTFontFullNameFromStream(Stream: TStream; LanguageID: Cardinal): AnsiString; | |||||
| var | |||||
| TableName: Cardinal; | |||||
| Buffer: Pointer; | |||||
| BufferSize: Integer; | |||||
| begin | |||||
| TableName := MakeTTTableName('n', 'a', 'm', 'e'); | |||||
| if GetTTTableData(Stream, TableName, nil, BufferSize) then begin | |||||
| GetMem(Buffer, BufferSize); | |||||
| try | |||||
| if GetTTTableData(Stream, TableName, Buffer, BufferSize) then begin | |||||
| if not GetTTString(Buffer, BufferSize, NAME_ID_FULL_NAME, LanguageID, Result) then | |||||
| if not GetTTString(Buffer, BufferSize, NAME_ID_FACE_NAME, LanguageID, Result) then | |||||
| Result := ''; | |||||
| end; | |||||
| finally | |||||
| FreeMem(Buffer); | |||||
| end; | |||||
| end; | |||||
| end; | |||||
| function GetTTFontFullNameFromFile(Filename: AnsiString; LanguageID: Cardinal): AnsiString; | |||||
| var | |||||
| fs: TFileStream; | |||||
| begin | |||||
| fs := TFileStream.Create(String(Filename), fmOpenRead or fmShareDenyWrite); | |||||
| try | |||||
| result := GetTTFontFullNameFromStream(fs, LanguageID); | |||||
| finally | |||||
| fs.Free; | |||||
| end; | |||||
| end; | |||||
| end. | |||||
| @@ -0,0 +1,304 @@ | |||||
| unit utsTypes; | |||||
| {$mode objfpc}{$H+} | |||||
| interface | |||||
| uses | |||||
| Classes, SysUtils; | |||||
| type | |||||
| TtsCodePage = ( | |||||
| tsUTF8, | |||||
| tsISO_8859_1, | |||||
| tsISO_8859_2, | |||||
| tsISO_8859_3, | |||||
| tsISO_8859_4, | |||||
| tsISO_8859_5, | |||||
| tsISO_8859_6, | |||||
| tsISO_8859_7, | |||||
| tsISO_8859_8, | |||||
| tsISO_8859_9, | |||||
| tsISO_8859_10, | |||||
| tsISO_8859_11, | |||||
| tsISO_8859_13, | |||||
| tsISO_8859_14, | |||||
| tsISO_8859_15, | |||||
| tsISO_8859_16, | |||||
| tsISO_037, | |||||
| tsISO_437, | |||||
| tsISO_500, | |||||
| tsISO_737, | |||||
| tsISO_775, | |||||
| tsISO_850, | |||||
| tsISO_852, | |||||
| tsISO_855, | |||||
| tsISO_857, | |||||
| tsISO_860, | |||||
| tsISO_861, | |||||
| tsISO_862, | |||||
| tsISO_863, | |||||
| tsISO_864, | |||||
| tsISO_865, | |||||
| tsISO_866, | |||||
| tsISO_869, | |||||
| tsISO_874, | |||||
| tsISO_875, | |||||
| tsISO_1026, | |||||
| tsISO_1250, | |||||
| tsISO_1251, | |||||
| tsISO_1252, | |||||
| tsISO_1253, | |||||
| tsISO_1254, | |||||
| tsISO_1255, | |||||
| tsISO_1256, | |||||
| tsISO_1257, | |||||
| tsISO_1258); | |||||
| TtsFontStyle = ( | |||||
| tsStyleBold, | |||||
| tsStyleItalic, | |||||
| tsStyleUnderline, | |||||
| tsStyleStrikeout); | |||||
| TtsFontStyles = set of TtsFontStyle; | |||||
| TtsVertAlignment = ( | |||||
| tsVertAlignTop, | |||||
| tsVertAlignCenter, | |||||
| tsVertAlignBottom); | |||||
| TtsHorzAlignment = ( | |||||
| tsHorzAlignLeft, | |||||
| tsHorzAlignCenter, | |||||
| tsHorzAlignRight, | |||||
| tsHorzAlignJustify); | |||||
| TtsFormat = ( | |||||
| tsFormatEmpty, | |||||
| tsFormatRGBA8, | |||||
| tsFormatLumAlpha8, | |||||
| tsFormatAlpha8); | |||||
| TtsAntiAliasing = ( | |||||
| tsAANone, | |||||
| tsAANormal); | |||||
| TtsColorChannel = ( | |||||
| tsChannelRed, | |||||
| tsChannelGreen, | |||||
| tsChannelBlue, | |||||
| tsChannelAlpha); | |||||
| TtsColorChannels = set of TtsColorChannel; | |||||
| TtsImageMode = ( | |||||
| tsModeIgnore, | |||||
| tsModeReplace, | |||||
| tsModeModulate); | |||||
| TtsImageModes = array[TtsColorChannel] of TtsImageMode; | |||||
| TtsImageModeFunc = function(const aSource, aDest: Single): Single; | |||||
| TtsFontProperties = packed record | |||||
| Fontname: String; | |||||
| Copyright: String; | |||||
| FaceName: String; | |||||
| StyleName: String; | |||||
| FullName: String; | |||||
| Size: Integer; | |||||
| Style: TtsFontStyles; | |||||
| AntiAliasing: TtsAntiAliasing; | |||||
| DefaultChar: WideChar; | |||||
| Ascent: Integer; | |||||
| Descent: Integer; | |||||
| ExternalLeading: Integer; | |||||
| BaseLineOffset: Integer; | |||||
| UnderlinePos: Integer; | |||||
| UnderlineSize: Integer; | |||||
| StrikeoutPos: Integer; | |||||
| StrikeoutSize: Integer; | |||||
| end; | |||||
| TtsPosition = packed record | |||||
| x, y: Integer; | |||||
| end; | |||||
| PtsPosition = ^TtsPosition; | |||||
| TtsPositionF = packed record | |||||
| x, y: Single; | |||||
| end; | |||||
| PtsPositionF = ^TtsPositionF; | |||||
| TtsRect = packed record | |||||
| case Byte of | |||||
| 0: (TopLeft: TtsPosition; BottomRight: TtsPosition); | |||||
| 1: (Left, Top, Right, Bottom: Integer); | |||||
| end; | |||||
| PtsRect = ^TtsRect; | |||||
| TtsRectF = packed record | |||||
| case Byte of | |||||
| 0: (TopLeft: TtsPositionF; BottomRight: TtsPositionF); | |||||
| 1: (Left, Top, Right, Bottom: Single); | |||||
| end; | |||||
| PtsRectF = ^TtsRectF; | |||||
| TtsColor4f = packed record | |||||
| case Boolean of | |||||
| true: (r, g, b, a: Single); | |||||
| false: (arr: array[0..3] of Single); | |||||
| end; | |||||
| PtsColor4f = ^TtsColor4f; | |||||
| TtsColor4ub = packed record | |||||
| case Boolean of | |||||
| true: (r, g, b, a: Byte); | |||||
| false: (arr: array[0..3] of Byte); | |||||
| end; | |||||
| PtsColor4ub = ^TtsColor4ub; | |||||
| TtsTextMetric = packed record | |||||
| Ascent: Integer; | |||||
| Descent: Integer; | |||||
| ExternalLeading: Integer; | |||||
| BaseLineOffset: Integer; | |||||
| CharSpacing: Integer; | |||||
| LineHeight: Integer; | |||||
| LineSpacing: Integer; | |||||
| end; | |||||
| TtsAnsiToWideCharFunc = procedure(aDst: PWideChar; const aSize: Integer; aSource: PAnsiChar; const aCodePage: TtsCodePage; const aDefaultChar: WideChar); | |||||
| function tsColor4f(r, g, b, a: Single): TtsColor4f; | |||||
| function tsRect(const l, t, r, b: Integer): TtsRect; | |||||
| function tsPosition(const x, y: Integer): TtsPosition; | |||||
| function tsFormatSize(const aFormat: TtsFormat): Integer; | |||||
| procedure tsFormatMap(const aFormat: TtsFormat; var aData: PByte; const aColor: TtsColor4f); | |||||
| procedure tsFormatUnmap(const aFormat: TtsFormat; var aData: PByte; out aColor: TtsColor4f); | |||||
| function tsImageModeFuncIgnore(const aSource, aDest: Single): Single; | |||||
| function tsImageModeFuncReplace(const aSource, aDest: Single): Single; | |||||
| function tsImageModeFuncModulate(const aSource, aDest: Single): Single; | |||||
| implementation | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function tsColor4f(r, g, b, a: Single): TtsColor4f; | |||||
| begin | |||||
| result.r := r; | |||||
| result.g := g; | |||||
| result.b := b; | |||||
| result.a := a; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function tsRect(const l, t, r, b: Integer): TtsRect; | |||||
| begin | |||||
| result.Left := l; | |||||
| result.Top := t; | |||||
| result.Right := r; | |||||
| result.Bottom := b; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function tsPosition(const x, y: Integer): TtsPosition; | |||||
| begin | |||||
| result.x := x; | |||||
| result.y := y; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function tsFormatSize(const aFormat: TtsFormat): Integer; | |||||
| begin | |||||
| case aFormat of | |||||
| tsFormatRGBA8: result := 4; | |||||
| tsFormatLumAlpha8: result := 2; | |||||
| tsFormatAlpha8: result := 1; | |||||
| else | |||||
| result := 0; | |||||
| end; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| procedure tsFormatMap(const aFormat: TtsFormat; var aData: PByte; const aColor: TtsColor4f); | |||||
| var | |||||
| i: Integer; | |||||
| s: Single; | |||||
| begin | |||||
| case aFormat of | |||||
| tsFormatRGBA8: begin | |||||
| for i := 0 to 3 do begin | |||||
| aData^ := Trunc($FF * aColor.arr[i]); | |||||
| inc(aData); | |||||
| end; | |||||
| end; | |||||
| tsFormatLumAlpha8: begin | |||||
| s := 0.30 * aColor.r + 0.59 * aColor.g + 0.11 * aColor.b; | |||||
| aData^ := Trunc($FF * s); inc(aData); | |||||
| aData^ := Trunc($FF * s); inc(aData); | |||||
| aData^ := Trunc($FF * s); inc(aData); | |||||
| aData^ := Trunc($FF * aColor.a); inc(aData); | |||||
| end; | |||||
| tsFormatAlpha8: begin | |||||
| aData^ := Trunc($FF * aColor.a); | |||||
| inc(aData); | |||||
| end; | |||||
| end; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| procedure tsFormatUnmap(const aFormat: TtsFormat; var aData: PByte; out aColor: TtsColor4f); | |||||
| var | |||||
| i: Integer; | |||||
| begin | |||||
| case aFormat of | |||||
| tsFormatRGBA8: begin | |||||
| for i := 0 to 3 do begin | |||||
| aColor.arr[i] := aData^ / $FF; | |||||
| inc(aData); | |||||
| end; | |||||
| end; | |||||
| tsFormatLumAlpha8: begin | |||||
| aColor.r := aData^ / $FF; | |||||
| aColor.g := aData^ / $FF; | |||||
| aColor.b := aData^ / $FF; | |||||
| inc(aData); | |||||
| aColor.a := aData^ / $FF; | |||||
| inc(aData); | |||||
| end; | |||||
| tsFormatAlpha8: begin | |||||
| aColor.r := 1.0; | |||||
| aColor.g := 1.0; | |||||
| aColor.b := 1.0; | |||||
| aColor.a := aData^ / $FF; | |||||
| inc(aData); | |||||
| end; | |||||
| end; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function tsImageModeFuncIgnore(const aSource, aDest: Single): Single; | |||||
| begin | |||||
| result := aDest; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function tsImageModeFuncReplace(const aSource, aDest: Single): Single; | |||||
| begin | |||||
| result := aSource; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function tsImageModeFuncModulate(const aSource, aDest: Single): Single; | |||||
| begin | |||||
| result := aSource * aDest; | |||||
| end; | |||||
| end. | |||||
| @@ -0,0 +1,144 @@ | |||||
| unit utsUtils; | |||||
| {$mode objfpc}{$H+} | |||||
| interface | |||||
| uses | |||||
| Classes, SysUtils; | |||||
| function tsStrAlloc(aSize: Cardinal): PWideChar; | |||||
| function tsStrNew(const aText: PWideChar): PWideChar; | |||||
| procedure tsStrDispose(const aText: PWideChar); | |||||
| function tsStrLength(aText: PWideChar): Cardinal; | |||||
| function tsStrCopy(aDst, aSrc: PWideChar): PWideChar; | |||||
| function tsISO_8859_1ToWide(aDst: PWideChar; const aSize: Integer; aSrc: PAnsiChar): Integer; | |||||
| function tsUTF8ToWide(aDst: PWideChar; const aSize: Integer; const aSrc: PAnsiChar; const aDefaultChar: WideChar): Integer; | |||||
| implementation | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function tsStrAlloc(aSize: Cardinal): PWideChar; | |||||
| begin | |||||
| aSize := (aSize + 1) shl 1; | |||||
| GetMem(result, aSize); | |||||
| FillChar(result^, aSize, 0); | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function tsStrNew(const aText: PWideChar): PWideChar; | |||||
| begin | |||||
| result := tsStrAlloc(tsStrLength(aText)); | |||||
| tsStrCopy(result, aText); | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| procedure tsStrDispose(const aText: PWideChar); | |||||
| begin | |||||
| FreeMem(aText); | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function tsStrLength(aText: PWideChar): Cardinal; | |||||
| begin | |||||
| result := 0; | |||||
| if Assigned(aText) then | |||||
| while (ord(aText^) <> 0) do begin | |||||
| inc(result); | |||||
| inc(aText); | |||||
| end; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function tsStrCopy(aDst, aSrc: PWideChar): PWideChar; | |||||
| begin | |||||
| result := aDst; | |||||
| if Assigned(aDst) and Assigned(aSrc) then | |||||
| while ord(aSrc^) <> 0 do begin | |||||
| aDst^ := aSrc^; | |||||
| inc(aDst); | |||||
| inc(aSrc); | |||||
| end; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function tsISO_8859_1ToWide(aDst: PWideChar; const aSize: Integer; aSrc: PAnsiChar): Integer; | |||||
| begin | |||||
| result := 0; | |||||
| if Assigned(aDst) and Assigned(aSrc) then | |||||
| while (ord(aSrc^) <> 0) do begin | |||||
| aDst^ := WideChar(aSrc^); | |||||
| inc(aDst); | |||||
| inc(aSrc); | |||||
| inc(result); | |||||
| end; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function tsUTF8ToWide(aDst: PWideChar; const aSize: Integer; const aSrc: PAnsiChar; const aDefaultChar: WideChar): Integer; | |||||
| procedure AddToDest(aCharCode: UInt64); | |||||
| begin | |||||
| if (aCharCode > $FFFF) then | |||||
| aCharCode := ord(aDefaultChar); | |||||
| PWord(aDst)^ := aCharCode; | |||||
| inc(aDst); | |||||
| result := result + 1; | |||||
| end; | |||||
| const | |||||
| STATE_STARTBYTE = 0; | |||||
| STATE_FOLLOWBYTE = 1; | |||||
| var | |||||
| cc: QWord; | |||||
| len, state, c: Integer; | |||||
| p: PByte; | |||||
| tmp: Byte; | |||||
| begin | |||||
| result := 0; | |||||
| if not Assigned(aDst) or not Assigned(aSrc) or (aSize <= 0) then | |||||
| exit; | |||||
| p := PByte(aSrc); | |||||
| len := Length(aSrc); | |||||
| state := STATE_STARTBYTE; | |||||
| while (len > 0) do begin | |||||
| case state of | |||||
| STATE_STARTBYTE: begin | |||||
| if (p^ and %10000000 = 0) then begin | |||||
| AddToDest(p^); | |||||
| end else if (p^ and %01000000 > 0) then begin | |||||
| tmp := p^; | |||||
| c := 0; | |||||
| while (tmp and %10000000) > 0 do begin | |||||
| inc(c); | |||||
| tmp := tmp shl 1; | |||||
| end; | |||||
| cc := p^ and ((1 shl (7 - c)) - 1); | |||||
| state := STATE_FOLLOWBYTE; | |||||
| c := c - 1; | |||||
| end; | |||||
| end; | |||||
| STATE_FOLLOWBYTE: begin | |||||
| if ((p^ and %11000000) = %10000000) then begin | |||||
| cc := (cc shl 6) or (p^ and %00111111); | |||||
| c := c - 1; | |||||
| if (c = 0) then begin | |||||
| AddToDest(cc); | |||||
| state := STATE_STARTBYTE; | |||||
| end; | |||||
| end else | |||||
| state := STATE_STARTBYTE; | |||||
| end; | |||||
| end; | |||||
| if (result >= aSize) then | |||||
| exit; | |||||
| inc(p); | |||||
| end; | |||||
| end; | |||||
| end. | |||||
| @@ -3082,7 +3082,7 @@ begin | |||||
| // name | // name | ||||
| fFontname := Fontname; | fFontname := Fontname; | ||||
| for Idx := 1 to Min(Length(Fontname), Length(LogFont.lfFaceName)) do | |||||
| for Idx := 1 to min(Length(Fontname), Length(LogFont.lfFaceName)) do | |||||
| LogFont.lfFaceName[Idx -1] := Fontname[Idx]; | LogFont.lfFaceName[Idx -1] := Fontname[Idx]; | ||||
| // char set | // char set | ||||
| @@ -4,6 +4,7 @@ object MainForm: TMainForm | |||||
| Top = 255 | Top = 255 | ||||
| Width = 682 | Width = 682 | ||||
| OnCreate = FormCreate | OnCreate = FormCreate | ||||
| OnDestroy = FormDestroy | |||||
| OnPaint = FormPaint | OnPaint = FormPaint | ||||
| LCLVersion = '1.3' | LCLVersion = '1.3' | ||||
| object ApplicationProperties: TApplicationProperties | object ApplicationProperties: TApplicationProperties | ||||
| @@ -2,27 +2,36 @@ unit uMainForm; | |||||
| {$mode objfpc}{$H+} | {$mode objfpc}{$H+} | ||||
| {.$DEFINE USE_OLD_TS} | |||||
| interface | interface | ||||
| uses | uses | ||||
| Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, uglcContext, TextSuite, uglcTypes, utsTextSuite; | |||||
| Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, uglcContext, TextSuite, uglcTypes, | |||||
| utsTextSuite, utsTypes, utsFontCreatorGDI, utsRendererOpenGL; | |||||
| type | type | ||||
| TMainForm = class(TForm) | TMainForm = class(TForm) | ||||
| ApplicationProperties: TApplicationProperties; | ApplicationProperties: TApplicationProperties; | ||||
| procedure ApplicationPropertiesIdle(Sender: TObject; var Done: Boolean); | procedure ApplicationPropertiesIdle(Sender: TObject; var Done: Boolean); | ||||
| procedure FormCreate(Sender: TObject); | procedure FormCreate(Sender: TObject); | ||||
| procedure FormDestroy(Sender: TObject); | |||||
| procedure FormPaint(Sender: TObject); | procedure FormPaint(Sender: TObject); | ||||
| private | private | ||||
| fFrameTime: QWord; | |||||
| fFrameCount: Integer; | |||||
| fSecTime: QWord; | |||||
| fContext: TglcContext; | fContext: TglcContext; | ||||
| {$IFDEF USE_OLD_TS} | |||||
| fTextSuiteContext: tsContextID; | fTextSuiteContext: tsContextID; | ||||
| fFontID: tsFontID; | fFontID: tsFontID; | ||||
| ftsContext: TtsContext; | |||||
| ftsRenderer: TtsRenderer; | |||||
| ftsCreator: TtsFontCreator; | |||||
| ftsFont: TtsFont; | |||||
| {$ELSE} | |||||
| ftsContext: TtsContext; | |||||
| ftsRenderer: TtsRendererOpenGL; | |||||
| ftsGenerator: TtsFontGeneratorGDI; | |||||
| ftsFont: TtsFont; | |||||
| {$ENDIF} | |||||
| procedure Render; | procedure Render; | ||||
| public | public | ||||
| { public declarations } | { public declarations } | ||||
| @@ -48,19 +57,31 @@ begin | |||||
| pf := TglcContext.MakePF(); | pf := TglcContext.MakePF(); | ||||
| fContext := TglcContext.GetPlatformClass.Create(self, pf); | fContext := TglcContext.GetPlatformClass.Create(self, pf); | ||||
| fContext.BuildContext; | fContext.BuildContext; | ||||
| {$IFDEF USE_OLD_TS} | |||||
| tsInit(TS_INIT_TEXTSUITE or TS_INIT_OPENGL or TS_INIT_GDI); | tsInit(TS_INIT_TEXTSUITE or TS_INIT_OPENGL or TS_INIT_GDI); | ||||
| tsContextCreate(@fTextSuiteContext); | tsContextCreate(@fTextSuiteContext); | ||||
| tsSetParameteri(TS_RENDERER, TS_RENDERER_OPENGL); | tsSetParameteri(TS_RENDERER, TS_RENDERER_OPENGL); | ||||
| tsSetParameteri(TS_CREATOR, TS_CREATOR_GDI); | |||||
| tsSetParameteri(TS_CREATOR, TS_CREATOR_GDI_FACENAME); | |||||
| tsContextBind(fTextSuiteContext); | tsContextBind(fTextSuiteContext); | ||||
| tsFontCreateCreatorA('ttf/calibri.ttf', 24, 0, TS_ANTIALIASING_NORMAL, TS_DEFAULT, @fFontID); | |||||
| tsFontCreateCreatorA('Calibri', 25, 0, TS_ANTIALIASING_NORMAL, TS_DEFAULT, @fFontID); | |||||
| tsFontBind(fFontID); | tsFontBind(fFontID); | ||||
| {$ELSE} | |||||
| ftsContext := TtsContext.Create; | |||||
| ftsRenderer := TtsRendererOpenGL.Create(ftsContext, tsFormatRGBA8); | |||||
| ftsGenerator := TtsFontGeneratorGDI.Create; | |||||
| ftsFont := ftsGenerator.GetFontByName('Calibri', ftsRenderer, 25, [], tsAANormal); | |||||
| ftsFont.LineSpacing := 0; | |||||
| {$ENDIF} | |||||
| end; | |||||
| ftsContext := TtsContext.Create; | |||||
| ftsRenderer := TtsRenderer.Create(ftsContext, tsFormatRGBA8); | |||||
| ftsCreator := TtsFontCreator.Create; | |||||
| ftsFont := TtsFont.Create(ftsRenderer, ftsCreator, '', '', '', '', 12, 0, 0, [], tsAANormal); | |||||
| procedure TMainForm.FormDestroy(Sender: TObject); | |||||
| begin | |||||
| {$IFNDEF USE_OLD_TS} | |||||
| FreeAndNil(ftsFont); | |||||
| FreeAndNil(ftsGenerator); | |||||
| FreeAndNil(ftsRenderer); | |||||
| FreeAndNil(ftsContext); | |||||
| {$ENDIF} | |||||
| end; | end; | ||||
| procedure TMainForm.FormPaint(Sender: TObject); | procedure TMainForm.FormPaint(Sender: TObject); | ||||
| @@ -71,7 +92,22 @@ end; | |||||
| procedure TMainForm.Render; | procedure TMainForm.Render; | ||||
| var | var | ||||
| block: TtsTextBlock; | block: TtsTextBlock; | ||||
| t: QWord; | |||||
| dif: Integer; | |||||
| begin | begin | ||||
| t := GetTickCount64; | |||||
| if (fFrameTime <> 0) then begin | |||||
| dif := t - fFrameTime; | |||||
| inc(fFrameCount, 1); | |||||
| inc(fSecTime, dif); | |||||
| if (fSecTime > 1000) then begin | |||||
| Caption := IntToStr(fFrameCount) + ' FPS'; | |||||
| fFrameCount := 0; | |||||
| dec(fSecTime, 1000); | |||||
| end; | |||||
| end; | |||||
| fFrameTime := t; | |||||
| glViewport(0, 0, ClientWidth, ClientHeight); | glViewport(0, 0, ClientWidth, ClientHeight); | ||||
| glClearColor(0, 0, 0, 0); | glClearColor(0, 0, 0, 0); | ||||
| glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); | glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); | ||||
| @@ -82,23 +118,22 @@ begin | |||||
| glMatrixMode(GL_MODELVIEW); | glMatrixMode(GL_MODELVIEW); | ||||
| glLoadIdentity; | glLoadIdentity; | ||||
| glDisable(GL_CULL_FACE); | |||||
| glDisable(GL_DEPTH_TEST); | |||||
| glEnable(GL_BLEND); | glEnable(GL_BLEND); | ||||
| glcBlendFunc(TglcBlendMode.bmAdditiveAlphaBlend); | glcBlendFunc(TglcBlendMode.bmAdditiveAlphaBlend); | ||||
| //tsTextBeginBlock(10, 10, ClientWidth-10, ClientHeight-10, TS_ALIGN_BLOCK); | |||||
| //tsTextOutA(TEST_STRING); | |||||
| //tsTextEndBlock; | |||||
| block := ftsRenderer.BeginBlock(10, 10, ClientWidth-10, ClientHeight-10, [tsBlockFlagWordWrap]); | |||||
| {$IFDEF USE_OLD_TS} | |||||
| tsTextBeginBlock(0, 0, ClientWidth, ClientHeight, TS_ALIGN_BLOCK); | |||||
| tsTextOutA(TEST_STRING); | |||||
| tsTextEndBlock; | |||||
| {$ELSE} | |||||
| block := ftsRenderer.BeginBlock(0, 0, ClientWidth, ClientHeight, [tsBlockFlagWordWrap]); | |||||
| try | try | ||||
| block.ChangeFont(ftsFont); | block.ChangeFont(ftsFont); | ||||
| block.TextOutW('test'#13#10#13#10'test'#13#13'test'#10#10'test'#13#10#10'test'#13#13#10); | |||||
| block.TextOutW(TEST_STRING); | |||||
| finally | finally | ||||
| ftsRenderer.EndBlock(block); | ftsRenderer.EndBlock(block); | ||||
| end; | end; | ||||
| {$ENDIF} | |||||
| fContext.SwapBuffers; | fContext.SwapBuffers; | ||||
| end; | end; | ||||