| @@ -33,7 +33,7 @@ | |||
| <PackageName Value="LCL"/> | |||
| </Item1> | |||
| </RequiredPackages> | |||
| <Units Count="13"> | |||
| <Units Count="14"> | |||
| <Unit0> | |||
| <Filename Value="TextSuiteTest.lpr"/> | |||
| <IsPartOfProject Value="True"/> | |||
| @@ -97,6 +97,11 @@ | |||
| <IsPartOfProject Value="True"/> | |||
| <UnitName Value="utsFreeType"/> | |||
| </Unit12> | |||
| <Unit13> | |||
| <Filename Value="..\..\utsOpenGLUtils.pas"/> | |||
| <IsPartOfProject Value="True"/> | |||
| <UnitName Value="utsOpenGLUtils"/> | |||
| </Unit13> | |||
| </Units> | |||
| </ProjectOptions> | |||
| <CompilerOptions> | |||
| @@ -7,7 +7,7 @@ uses | |||
| cthreads, | |||
| {$ENDIF}{$ENDIF} | |||
| Interfaces, sysutils, Forms, uMainForm, utsFontCreatorGDI, utsUtils, utsTypes, utsTtfUtils, utsTextSuite, | |||
| utsRendererOpenGL, utsCodePages, utsPostProcess, utsFontCreatorFreeType, utsGDI, utsFreeType; | |||
| utsRendererOpenGL, utsCodePages, utsPostProcess, utsFontCreatorFreeType, utsGDI, utsFreeType, utsOpenGLUtils; | |||
| {$R *.res} | |||
| @@ -4,13 +4,13 @@ | |||
| <PathDelim Value="\"/> | |||
| <Version Value="9"/> | |||
| <BuildModes Active="Default"/> | |||
| <Units Count="64"> | |||
| <Units Count="65"> | |||
| <Unit0> | |||
| <Filename Value="TextSuiteTest.lpr"/> | |||
| <IsPartOfProject Value="True"/> | |||
| <EditorIndex Value="-1"/> | |||
| <CursorPos X="29" Y="20"/> | |||
| <UsageCount Value="141"/> | |||
| <UsageCount Value="142"/> | |||
| </Unit0> | |||
| <Unit1> | |||
| <Filename Value="uMainForm.pas"/> | |||
| @@ -19,48 +19,45 @@ | |||
| <HasResources Value="True"/> | |||
| <ResourceBaseClass Value="Form"/> | |||
| <UnitName Value="uMainForm"/> | |||
| <IsVisibleTab Value="True"/> | |||
| <EditorIndex Value="-1"/> | |||
| <TopLine Value="140"/> | |||
| <CursorPos X="7" Y="156"/> | |||
| <UsageCount Value="141"/> | |||
| <Loaded Value="True"/> | |||
| <LoadedDesigner Value="True"/> | |||
| <CursorPos X="59" Y="154"/> | |||
| <UsageCount Value="142"/> | |||
| </Unit1> | |||
| <Unit2> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <IsPartOfProject Value="True"/> | |||
| <UnitName Value="utsRendererOpenGL"/> | |||
| <EditorIndex Value="4"/> | |||
| <TopLine Value="448"/> | |||
| <CursorPos X="38" Y="467"/> | |||
| <UsageCount Value="69"/> | |||
| <TopLine Value="48"/> | |||
| <CursorPos X="36" Y="65"/> | |||
| <UsageCount Value="70"/> | |||
| <Loaded Value="True"/> | |||
| </Unit2> | |||
| <Unit3> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <IsPartOfProject Value="True"/> | |||
| <UnitName Value="utsTextSuite"/> | |||
| <EditorIndex Value="3"/> | |||
| <TopLine Value="957"/> | |||
| <CursorPos Y="973"/> | |||
| <UsageCount Value="69"/> | |||
| <IsVisibleTab Value="True"/> | |||
| <EditorIndex Value="1"/> | |||
| <TopLine Value="310"/> | |||
| <CursorPos X="51" Y="324"/> | |||
| <UsageCount Value="70"/> | |||
| <Loaded Value="True"/> | |||
| </Unit3> | |||
| <Unit4> | |||
| <Filename Value="..\..\utsTtfUtils.pas"/> | |||
| <IsPartOfProject Value="True"/> | |||
| <EditorIndex Value="-1"/> | |||
| <UsageCount Value="69"/> | |||
| <UsageCount Value="70"/> | |||
| </Unit4> | |||
| <Unit5> | |||
| <Filename Value="..\..\utsTypes.pas"/> | |||
| <IsPartOfProject Value="True"/> | |||
| <UnitName Value="utsTypes"/> | |||
| <EditorIndex Value="2"/> | |||
| <EditorIndex Value="-1"/> | |||
| <TopLine Value="93"/> | |||
| <CursorPos X="5" Y="109"/> | |||
| <UsageCount Value="69"/> | |||
| <Loaded Value="True"/> | |||
| <UsageCount Value="70"/> | |||
| </Unit5> | |||
| <Unit6> | |||
| <Filename Value="..\..\utsUtils.pas"/> | |||
| @@ -68,18 +65,18 @@ | |||
| <EditorIndex Value="-1"/> | |||
| <TopLine Value="174"/> | |||
| <CursorPos X="26" Y="194"/> | |||
| <UsageCount Value="69"/> | |||
| <UsageCount Value="70"/> | |||
| </Unit6> | |||
| <Unit7> | |||
| <Filename Value="..\..\utsFontCreatorGDI.pas"/> | |||
| <IsPartOfProject Value="True"/> | |||
| <UnitName Value="utsFontCreatorGDI"/> | |||
| <IsVisibleTab Value="True"/> | |||
| <EditorIndex Value="-1"/> | |||
| <WindowIndex Value="1"/> | |||
| <TopLine Value="517"/> | |||
| <CursorPos Y="526"/> | |||
| <UsageCount Value="69"/> | |||
| <Loaded Value="True"/> | |||
| <UsageCount Value="70"/> | |||
| </Unit7> | |||
| <Unit8> | |||
| <Filename Value="..\..\utsCodePages.pas"/> | |||
| @@ -87,7 +84,7 @@ | |||
| <EditorIndex Value="-1"/> | |||
| <TopLine Value="315"/> | |||
| <CursorPos X="21" Y="325"/> | |||
| <UsageCount Value="66"/> | |||
| <UsageCount Value="67"/> | |||
| </Unit8> | |||
| <Unit9> | |||
| <Filename Value="..\..\utsPostProcess.pas"/> | |||
| @@ -95,39 +92,36 @@ | |||
| <EditorIndex Value="-1"/> | |||
| <TopLine Value="216"/> | |||
| <CursorPos X="30" Y="227"/> | |||
| <UsageCount Value="64"/> | |||
| <UsageCount Value="65"/> | |||
| </Unit9> | |||
| <Unit10> | |||
| <Filename Value="..\..\utsFontCreatorFreeType.pas"/> | |||
| <IsPartOfProject Value="True"/> | |||
| <UnitName Value="utsFontCreatorFreeType"/> | |||
| <EditorIndex Value="1"/> | |||
| <EditorIndex Value="-1"/> | |||
| <TopLine Value="237"/> | |||
| <CursorPos X="51" Y="339"/> | |||
| <UsageCount Value="53"/> | |||
| <Loaded Value="True"/> | |||
| <UsageCount Value="54"/> | |||
| </Unit10> | |||
| <Unit11> | |||
| <Filename Value="..\..\utsGDI.pas"/> | |||
| <IsPartOfProject Value="True"/> | |||
| <UnitName Value="utsGDI"/> | |||
| <EditorIndex Value="2"/> | |||
| <EditorIndex Value="-1"/> | |||
| <WindowIndex Value="1"/> | |||
| <TopLine Value="284"/> | |||
| <CursorPos X="12" Y="298"/> | |||
| <UsageCount Value="45"/> | |||
| <Loaded Value="True"/> | |||
| <UsageCount Value="46"/> | |||
| </Unit11> | |||
| <Unit12> | |||
| <Filename Value="..\..\utsFreeType.pas"/> | |||
| <IsPartOfProject Value="True"/> | |||
| <UnitName Value="utsFreeType"/> | |||
| <EditorIndex Value="3"/> | |||
| <EditorIndex Value="-1"/> | |||
| <WindowIndex Value="1"/> | |||
| <TopLine Value="292"/> | |||
| <CursorPos X="31" Y="308"/> | |||
| <UsageCount Value="45"/> | |||
| <Loaded Value="True"/> | |||
| <UsageCount Value="46"/> | |||
| </Unit12> | |||
| <Unit13> | |||
| <Filename Value="new\utsTextSuite.pas"/> | |||
| @@ -255,27 +249,24 @@ | |||
| </Unit28> | |||
| <Unit29> | |||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\ustringh.inc"/> | |||
| <EditorIndex Value="6"/> | |||
| <EditorIndex Value="-1"/> | |||
| <TopLine Value="113"/> | |||
| <CursorPos X="10" Y="129"/> | |||
| <UsageCount Value="38"/> | |||
| <Loaded Value="True"/> | |||
| </Unit29> | |||
| <Unit30> | |||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\ustrings.inc"/> | |||
| <EditorIndex Value="7"/> | |||
| <EditorIndex Value="-1"/> | |||
| <TopLine Value="2091"/> | |||
| <CursorPos X="5" Y="2098"/> | |||
| <UsageCount Value="21"/> | |||
| <Loaded Value="True"/> | |||
| </Unit30> | |||
| <Unit31> | |||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\systemh.inc"/> | |||
| <EditorIndex Value="8"/> | |||
| <EditorIndex Value="-1"/> | |||
| <TopLine Value="502"/> | |||
| <CursorPos X="3" Y="518"/> | |||
| <UsageCount Value="36"/> | |||
| <Loaded Value="True"/> | |||
| </Unit31> | |||
| <Unit32> | |||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\heaph.inc"/> | |||
| @@ -321,19 +312,17 @@ | |||
| <Unit38> | |||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\dynlibs.pas"/> | |||
| <UnitName Value="dynlibs"/> | |||
| <EditorIndex Value="9"/> | |||
| <EditorIndex Value="-1"/> | |||
| <TopLine Value="143"/> | |||
| <CursorPos X="3" Y="149"/> | |||
| <UsageCount Value="30"/> | |||
| <Loaded Value="True"/> | |||
| </Unit38> | |||
| <Unit39> | |||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\win\dynlibs.inc"/> | |||
| <EditorIndex Value="10"/> | |||
| <EditorIndex Value="-1"/> | |||
| <TopLine Value="26"/> | |||
| <CursorPos X="10" Y="42"/> | |||
| <UsageCount Value="28"/> | |||
| <Loaded Value="True"/> | |||
| </Unit39> | |||
| <Unit40> | |||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\win\sysosh.inc"/> | |||
| @@ -374,9 +363,8 @@ | |||
| </Unit44> | |||
| <Unit45> | |||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\objpas.inc"/> | |||
| <EditorIndex Value="5"/> | |||
| <EditorIndex Value="-1"/> | |||
| <UsageCount Value="29"/> | |||
| <Loaded Value="True"/> | |||
| </Unit45> | |||
| <Unit46> | |||
| <Filename Value="C:\Zusatzprogramme\Lazarus\lcl\include\control.inc"/> | |||
| @@ -436,12 +424,11 @@ | |||
| <Unit53> | |||
| <Filename Value="..\..\old\TextSuiteClasses.pas"/> | |||
| <UnitName Value="TextSuiteClasses"/> | |||
| <EditorIndex Value="1"/> | |||
| <EditorIndex Value="-1"/> | |||
| <WindowIndex Value="1"/> | |||
| <TopLine Value="2705"/> | |||
| <CursorPos X="3" Y="2698"/> | |||
| <UsageCount Value="18"/> | |||
| <Loaded Value="True"/> | |||
| </Unit53> | |||
| <Unit54> | |||
| <Filename Value="..\..\old\TextSuite.pas"/> | |||
| @@ -506,133 +493,142 @@ | |||
| </Unit62> | |||
| <Unit63> | |||
| <Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\win\wininc\unifun.inc"/> | |||
| <EditorIndex Value="11"/> | |||
| <EditorIndex Value="-1"/> | |||
| <TopLine Value="53"/> | |||
| <CursorPos X="22" Y="69"/> | |||
| <UsageCount Value="26"/> | |||
| <Loaded Value="True"/> | |||
| </Unit63> | |||
| <Unit64> | |||
| <Filename Value="..\..\utsOpenGLUtils.pas"/> | |||
| <IsPartOfProject Value="True"/> | |||
| <UnitName Value="utsOpenGLUtils"/> | |||
| <EditorIndex Value="2"/> | |||
| <TopLine Value="297"/> | |||
| <CursorPos X="31" Y="382"/> | |||
| <UsageCount Value="21"/> | |||
| <Loaded Value="True"/> | |||
| </Unit64> | |||
| </Units> | |||
| <JumpHistory Count="30" HistoryIndex="29"> | |||
| <Position1> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <Caret Line="1418" Column="11" TopLine="1394"/> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="24" Column="57" TopLine="5"/> | |||
| </Position1> | |||
| <Position2> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <Caret Line="1424" Column="36" TopLine="1400"/> | |||
| <Filename Value="..\..\utsOpenGLUtils.pas"/> | |||
| <Caret Line="327" TopLine="317"/> | |||
| </Position2> | |||
| <Position3> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <Caret Line="1411" TopLine="1400"/> | |||
| <Filename Value="..\..\utsOpenGLUtils.pas"/> | |||
| <Caret Line="335" Column="17" TopLine="317"/> | |||
| </Position3> | |||
| <Position4> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <Caret Line="1414" TopLine="1400"/> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="26" Column="60" TopLine="8"/> | |||
| </Position4> | |||
| <Position5> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <Caret Line="1418" TopLine="1400"/> | |||
| <Filename Value="..\..\utsOpenGLUtils.pas"/> | |||
| <Caret Line="69" Column="15" TopLine="54"/> | |||
| </Position5> | |||
| <Position6> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <Caret Line="1419" TopLine="1400"/> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="27" Column="66" TopLine="10"/> | |||
| </Position6> | |||
| <Position7> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <Caret Line="1420" TopLine="1400"/> | |||
| <Filename Value="..\..\utsOpenGLUtils.pas"/> | |||
| <Caret Line="55" TopLine="55"/> | |||
| </Position7> | |||
| <Position8> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <Caret Line="1421" TopLine="1400"/> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="177" TopLine="171"/> | |||
| </Position8> | |||
| <Position9> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <Caret Line="1422" TopLine="1400"/> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="9" Column="52"/> | |||
| </Position9> | |||
| <Position10> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <Caret Line="1423" TopLine="1400"/> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="17" Column="15"/> | |||
| </Position10> | |||
| <Position11> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <Caret Line="1424" TopLine="1400"/> | |||
| <Filename Value="..\..\utsOpenGLUtils.pas"/> | |||
| <Caret Line="55" Column="48" TopLine="39"/> | |||
| </Position11> | |||
| <Position12> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="277" Column="47" TopLine="258"/> | |||
| <Filename Value="..\..\utsOpenGLUtils.pas"/> | |||
| <Caret Line="58" Column="59" TopLine="39"/> | |||
| </Position12> | |||
| <Position13> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="268" TopLine="258"/> | |||
| <Caret Line="102" Column="18" TopLine="81"/> | |||
| </Position13> | |||
| <Position14> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="269" TopLine="258"/> | |||
| <Filename Value="..\..\utsOpenGLUtils.pas"/> | |||
| <Caret Line="128" Column="30" TopLine="120"/> | |||
| </Position14> | |||
| <Position15> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="270" TopLine="258"/> | |||
| <Caret Line="102" Column="18" TopLine="81"/> | |||
| </Position15> | |||
| <Position16> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="271" TopLine="258"/> | |||
| <Caret Line="19" Column="119" TopLine="3"/> | |||
| </Position16> | |||
| <Position17> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="272" TopLine="258"/> | |||
| <Filename Value="..\..\utsOpenGLUtils.pas"/> | |||
| <Caret Line="63" Column="7" TopLine="46"/> | |||
| </Position17> | |||
| <Position18> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <Caret Line="1413" Column="32" TopLine="1400"/> | |||
| <Filename Value="..\..\utsOpenGLUtils.pas"/> | |||
| <Caret Line="153" Column="29" TopLine="137"/> | |||
| </Position18> | |||
| <Position19> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <Caret Line="2000" Column="3" TopLine="1996"/> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="20" Column="7" TopLine="3"/> | |||
| </Position19> | |||
| <Position20> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <Caret Line="2060" Column="30" TopLine="2037"/> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="122" Column="41" TopLine="106"/> | |||
| </Position20> | |||
| <Position21> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="270" Column="33" TopLine="258"/> | |||
| <Caret Line="22" Column="15" TopLine="6"/> | |||
| </Position21> | |||
| <Position22> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="277" Column="62" TopLine="258"/> | |||
| <Caret Line="137" Column="27" TopLine="121"/> | |||
| </Position22> | |||
| <Position23> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <Caret Line="1429" Column="38" TopLine="1408"/> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="170" Column="15" TopLine="154"/> | |||
| </Position23> | |||
| <Position24> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="277" TopLine="258"/> | |||
| <Caret Line="227" TopLine="199"/> | |||
| </Position24> | |||
| <Position25> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="272" Column="52" TopLine="258"/> | |||
| <Caret Line="30" Column="17" TopLine="15"/> | |||
| </Position25> | |||
| <Position26> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <Caret Line="1424" Column="7" TopLine="1408"/> | |||
| <Filename Value="..\..\utsOpenGLUtils.pas"/> | |||
| <Caret Line="81" Column="34" TopLine="64"/> | |||
| </Position26> | |||
| <Position27> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <Caret Line="110" TopLine="99"/> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="211" Column="14" TopLine="200"/> | |||
| </Position27> | |||
| <Position28> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="272" Column="51" TopLine="258"/> | |||
| <Caret Line="74" Column="40" TopLine="53"/> | |||
| </Position28> | |||
| <Position29> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="444" Column="29" TopLine="429"/> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <Caret Line="973" TopLine="957"/> | |||
| </Position29> | |||
| <Position30> | |||
| <Filename Value="..\..\utsRendererOpenGL.pas"/> | |||
| <Caret Line="448" Column="3" TopLine="441"/> | |||
| <Filename Value="..\..\utsTextSuite.pas"/> | |||
| <Caret Line="1502" Column="61" TopLine="1496"/> | |||
| </Position30> | |||
| </JumpHistory> | |||
| </ProjectSession> | |||
| @@ -610,7 +610,7 @@ const | |||
| {$ELSEIF DEFINED(TS_FT_WIN64)} | |||
| LIB_FREE_TYPE = 'freetype6-x64.dll'; | |||
| {$ELSEIF DEFINED(TS_FT_LINUX)} | |||
| LIB_FREE_TYPE = ??? | |||
| LIB_FREE_TYPE = 'libfreetype.so'; | |||
| {$ELSE} | |||
| {$ERROR 'unknown/unsupported OS'} | |||
| {$IFEND} | |||
| @@ -0,0 +1,387 @@ | |||
| unit utsOpenGLUtils; | |||
| {$mode objfpc}{$H+} | |||
| interface | |||
| uses | |||
| Classes, SysUtils, syncobjs, | |||
| utsTextSuite, utsTypes; | |||
| type | |||
| TtsQuadPosF = array[0..3] of TtsPositionF; | |||
| TtsCharRenderRefOpenGL = class(TtsCharRenderRef) | |||
| public | |||
| TextureID: Integer; // 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 | |||
| 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: Integer; // 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; | |||
| TtsBaseOpenGL = class(TtsRenderer) | |||
| private | |||
| fTextureSize: Integer; | |||
| fColor: TtsColor4f; | |||
| fRenderPos: TtsPosition; | |||
| fFirstTexture: PtsFontTexture; | |||
| fLastTexture: PtsFontTexture; | |||
| procedure FreeTextures(var aTexture: PtsFontTexture); | |||
| procedure FreeTextureTreeItem(var aItem: PtsTextureTreeItem); | |||
| protected | |||
| property Color: TtsColor4f read fColor; | |||
| property RenderPos: TtsPosition read fRenderPos; | |||
| procedure PushTexture(const aTexture: PtsFontTexture); | |||
| function CreateNewTexture: PtsFontTexture; virtual; | |||
| procedure FreeTexture(var aTexture: PtsFontTexture); virtual; | |||
| procedure UploadTexData(const aCharRef: TtsCharRenderRefOpenGL; | |||
| const aCharImage: TtsImage; const X, Y: Integer); virtual; | |||
| protected | |||
| function CreateRenderRef(const aChar: TtsChar; const aCharImage: TtsImage): TtsCharRenderRef; override; | |||
| procedure FreeRenderRef(const aCharRef: TtsCharRenderRef); override; | |||
| procedure BeginRender; 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; | |||
| public | |||
| property TextureSize: Integer read fTextureSize write fTextureSize; | |||
| constructor Create(const aContext: TtsContext; const aFormat: TtsFormat); | |||
| destructor Destroy; override; | |||
| end; | |||
| EtsRendererOpenGL = class(EtsRenderer); | |||
| implementation | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //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; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TtsBaseOpenGL///////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TtsBaseOpenGL.FreeTextures(var aTexture: PtsFontTexture); | |||
| begin | |||
| if not Assigned(aTexture) then | |||
| exit; | |||
| FreeTextures(aTexture^.Next); | |||
| FreeTexture(aTexture); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TtsBaseOpenGL.FreeTextureTreeItem(var aItem: PtsTextureTreeItem); | |||
| begin | |||
| if not Assigned(aItem) then | |||
| exit; | |||
| FreeTextureTreeItem(aItem^.children[0]); | |||
| FreeTextureTreeItem(aItem^.children[1]); | |||
| Dispose(aItem); | |||
| aItem := nil; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TtsBaseOpenGL.PushTexture(const aTexture: PtsFontTexture); | |||
| begin | |||
| aTexture^.Prev := fLastTexture; | |||
| if Assigned(fLastTexture) then | |||
| fLastTexture^.Next := aTexture | |||
| else | |||
| fFirstTexture := aTexture; | |||
| fLastTexture := aTexture; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TtsBaseOpenGL.CreateNewTexture: PtsFontTexture; | |||
| begin | |||
| result := nil; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TtsBaseOpenGL.FreeTexture(var aTexture: PtsFontTexture); | |||
| begin | |||
| if not Assigned(aTexture) then | |||
| exit; | |||
| 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 TtsBaseOpenGL.UploadTexData(const aCharRef: TtsCharRenderRefOpenGL; | |||
| const aCharImage: TtsImage; const X, Y: Integer); | |||
| begin | |||
| // DUMMY | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TtsBaseOpenGL.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; | |||
| UploadTexData(result, aCharImage, x, y); | |||
| 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 TtsBaseOpenGL.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 TtsBaseOpenGL.BeginRender; | |||
| begin | |||
| inherited BeginRender; | |||
| fRenderPos.x := 0; | |||
| fRenderPos.y := 0; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TtsBaseOpenGL.SetDrawPos(const X, Y: Integer); | |||
| begin | |||
| fRenderPos.x := X; | |||
| fRenderPos.y := Y; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TtsBaseOpenGL.GetDrawPos: TtsPosition; | |||
| begin | |||
| result := fRenderPos; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TtsBaseOpenGL.MoveDrawPos(const X, Y: Integer); | |||
| begin | |||
| fRenderPos.x := fRenderPos.x + X; | |||
| fRenderPos.y := fRenderPos.y + Y; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TtsBaseOpenGL.SetColor(const aColor: TtsColor4f); | |||
| begin | |||
| fColor := aColor; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| constructor TtsBaseOpenGL.Create(const aContext: TtsContext; const aFormat: TtsFormat); | |||
| begin | |||
| inherited Create(aContext, aFormat); | |||
| fFirstTexture := nil; | |||
| fLastTexture := nil; | |||
| fTextureSize := 2048; | |||
| fColor := tsColor4f(1, 1, 1, 1); | |||
| fRenderPos := tsPosition(0, 0); | |||
| end; | |||
| destructor TtsBaseOpenGL.Destroy; | |||
| begin | |||
| FreeTextures(fFirstTexture); | |||
| inherited Destroy; | |||
| end; | |||
| end. | |||
| @@ -5,79 +5,32 @@ unit utsRendererOpenGL; | |||
| interface | |||
| uses | |||
| Classes, SysUtils, syncobjs, dglOpenGL, | |||
| utsTextSuite, utsTypes; | |||
| Classes, SysUtils, | |||
| utsTextSuite, utsTypes, utsOpenGLUtils, dglOpenGL; | |||
| 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) | |||
| TtsRendererOpenGL = class(TtsBaseOpenGL) | |||
| 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; | |||
| function CreateNewTexture: PtsFontTexture; override; | |||
| procedure FreeTexture(var aTexture: PtsFontTexture); override; | |||
| procedure UploadTexData(const aCharRef: TtsCharRenderRefOpenGL; | |||
| const aCharImage: TtsImage; const X, Y: Integer); 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 | |||
| @@ -117,23 +70,10 @@ const | |||
| 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)) | |||
| (pos: (1.0, 0.0); tex: (1.0, 0.0)), | |||
| (pos: (1.0, 1.0); tex: (1.0, 1.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///////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -160,12 +100,7 @@ begin | |||
| FORMAT_TYPES[Format].DataFormat, | |||
| nil); | |||
| result^.Prev := fLastTexture; | |||
| if Assigned(fLastTexture) then | |||
| fLastTexture^.Next := result | |||
| else | |||
| fFirstTexture := result; | |||
| fLastTexture := result; | |||
| PushTexture(result); | |||
| except | |||
| if Assigned(result^.Usage) then | |||
| Dispose(result^.Usage); | |||
| @@ -176,216 +111,21 @@ 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); | |||
| glPixelStorei(GL_UNPACK_ALIGNMENT, 4); | |||
| 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) + ')'); | |||
| if Assigned(aTexture) then | |||
| glDeleteTextures(1, @aTexture^.ID); | |||
| inherited FreeTexture(aTexture); | |||
| 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; | |||
| procedure TtsRendererOpenGL.UploadTexData(const aCharRef: TtsCharRenderRefOpenGL; const aCharImage: TtsImage; const X, Y: Integer); | |||
| 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; | |||
| glBindTexture(GL_TEXTURE_2D, aCharRef.TextureID); | |||
| glPixelStorei(GL_UNPACK_ALIGNMENT, 4); | |||
| glTexSubImage2D(GL_TEXTURE_2D, 0, | |||
| x, y, aCharImage.Width, aCharImage.Height, | |||
| FORMAT_TYPES[aCharImage.Format].Format, | |||
| FORMAT_TYPES[aCharImage.Format].DataFormat, | |||
| aCharImage.Data); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -393,10 +133,8 @@ procedure TtsRendererOpenGL.BeginRender; | |||
| begin | |||
| inherited BeginRender; | |||
| fIsRendering := true; | |||
| fRenderPos.x := 0; | |||
| fRenderPos.y := 0; | |||
| glPushMatrix; | |||
| glColor4fv(@fColor.arr[0]); | |||
| glColor4fv(@Color.arr[0]); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -412,32 +150,24 @@ end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TtsRendererOpenGL.SetDrawPos(const X, Y: Integer); | |||
| begin | |||
| fRenderPos.x := X; | |||
| fRenderPos.y := Y; | |||
| inherited SetDrawPos(X, 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; | |||
| inherited MoveDrawPos(X, Y); | |||
| glTranslatef(X, Y, 0); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TtsRendererOpenGL.SetColor(const aColor: TtsColor4f); | |||
| begin | |||
| fColor := aColor; | |||
| glColor4fv(@fColor.arr[0]); | |||
| inherited SetColor(aColor); | |||
| glColor4fv(@Color.arr[0]); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -468,7 +198,7 @@ begin | |||
| glEnableClientState(GL_TEXTURE_COORD_ARRAY); | |||
| glTexCoordPointer(2, GL_FLOAT, SizeOf(TVertex), Pointer(8)); | |||
| glDrawArrays(GL_QUADS, 0, 4); | |||
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | |||
| glDisableClientState(GL_TEXTURE_COORD_ARRAY); | |||
| glDisableClientState(GL_VERTEX_ARRAY); | |||
| @@ -484,13 +214,7 @@ 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); | |||
| fIsRendering := false; | |||
| 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); | |||
| @@ -500,7 +224,6 @@ end; | |||
| destructor TtsRendererOpenGL.Destroy; | |||
| begin | |||
| glDeleteBuffers(1, @fVBO); | |||
| FreeTextures(fFirstTexture); | |||
| inherited Destroy; | |||
| end; | |||
| @@ -321,7 +321,7 @@ type | |||
| function GetRect: TtsRect; | |||
| function PushLineItem(const aItem: PtsLineItem; const aUpdateLineWidth: Boolean = true): Boolean; | |||
| function PushLineItem(const aItem: PtsLineItem): Boolean; | |||
| procedure PushSpacing(const aWidth: Integer); | |||
| procedure FreeLineItem(var aItem: PtsLineItem); | |||
| procedure FreeLineItems(var aItem: PtsLineItem); | |||
| @@ -1499,7 +1499,7 @@ begin | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TtsTextBlock.PushLineItem(const aItem: PtsLineItem; const aUpdateLineWidth: Boolean): Boolean; | |||
| function TtsTextBlock.PushLineItem(const aItem: PtsLineItem): Boolean; | |||
| begin | |||
| result := false; | |||
| if not Assigned(fLastLine) then | |||
| @@ -1733,7 +1733,7 @@ begin | |||
| (fLastLine^.meta.Width + p^.TextWidth > fWidth) then | |||
| begin | |||
| if (fLastLine^.meta.Width = 0) then begin | |||
| if not PushLineItem(p, false) then // if is first word, than add anyway | |||
| if not PushLineItem(p) then // if is first word, than add anyway | |||
| FreeLineItem(p); | |||
| p := nil; | |||
| end; | |||