Browse Source

* moved texture management of OpenGL Renderer to new class

master
Bergmann89 11 years ago
parent
commit
3c6da5e87c
7 changed files with 523 additions and 412 deletions
  1. +6
    -1
      examples/simple/TextSuiteTest.lpi
  2. +1
    -1
      examples/simple/TextSuiteTest.lpr
  3. +97
    -101
      examples/simple/TextSuiteTest.lps
  4. +1
    -1
      utsFreeType.pas
  5. +387
    -0
      utsOpenGLUtils.pas
  6. +28
    -305
      utsRendererOpenGL.pas
  7. +3
    -3
      utsTextSuite.pas

+ 6
- 1
examples/simple/TextSuiteTest.lpi View File

@@ -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>


+ 1
- 1
examples/simple/TextSuiteTest.lpr View File

@@ -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}



+ 97
- 101
examples/simple/TextSuiteTest.lps View File

@@ -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>


+ 1
- 1
utsFreeType.pas View File

@@ -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}


+ 387
- 0
utsOpenGLUtils.pas View File

@@ -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.


+ 28
- 305
utsRendererOpenGL.pas View File

@@ -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;



+ 3
- 3
utsTextSuite.pas View File

@@ -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;


Loading…
Cancel
Save