Browse Source

* implemented FreeType font generator

master
Bergmann89 11 years ago
parent
commit
03f66b835c
11 changed files with 1719 additions and 672 deletions
  1. +16
    -1
      examples/simple/TextSuiteTest.lpi
  2. +2
    -2
      examples/simple/TextSuiteTest.lpr
  3. +315
    -307
      examples/simple/TextSuiteTest.lps
  4. +22
    -29
      examples/simple/uMainForm.pas
  5. +359
    -0
      utsFontCreatorFreeType.pas
  6. +14
    -326
      utsFontCreatorGDI.pas
  7. +607
    -0
      utsFreeType.pas
  8. +342
    -0
      utsGDI.pas
  9. +4
    -0
      utsPostProcess.pas
  10. +10
    -7
      utsTextSuite.pas
  11. +28
    -0
      utsUtils.pas

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

@@ -33,7 +33,7 @@
<PackageName Value="LCL"/>
</Item1>
</RequiredPackages>
<Units Count="10">
<Units Count="13">
<Unit0>
<Filename Value="TextSuiteTest.lpr"/>
<IsPartOfProject Value="True"/>
@@ -85,6 +85,21 @@
<IsPartOfProject Value="True"/>
<UnitName Value="utsPostProcess"/>
</Unit9>
<Unit10>
<Filename Value="..\..\utsFontCreatorFreeType.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="utsFontCreatorFreeType"/>
</Unit10>
<Unit11>
<Filename Value="..\..\utsGDI.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="utsGDI"/>
</Unit11>
<Unit12>
<Filename Value="..\..\utsFreeType.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="utsFreeType"/>
</Unit12>
</Units>
</ProjectOptions>
<CompilerOptions>


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

@@ -6,8 +6,8 @@ uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, sysutils, Forms, uMainForm,
utsFontCreatorGDI, utsUtils, utsTypes, utsTtfUtils, utsTextSuite, utsRendererOpenGL, utsCodePages, utsPostProcess;
Interfaces, sysutils, Forms, uMainForm, utsFontCreatorGDI, utsUtils, utsTypes, utsTtfUtils, utsTextSuite,
utsRendererOpenGL, utsCodePages, utsPostProcess, utsFontCreatorFreeType, utsGDI, utsFreeType;

{$R *.res}



+ 315
- 307
examples/simple/TextSuiteTest.lps View File

@@ -4,13 +4,13 @@
<PathDelim Value="\"/>
<Version Value="9"/>
<BuildModes Active="Default"/>
<Units Count="60">
<Units Count="64">
<Unit0>
<Filename Value="TextSuiteTest.lpr"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="-1"/>
<CursorPos X="29" Y="20"/>
<UsageCount Value="106"/>
<UsageCount Value="134"/>
</Unit0>
<Unit1>
<Filename Value="uMainForm.pas"/>
@@ -20,95 +20,125 @@
<ResourceBaseClass Value="Form"/>
<UnitName Value="uMainForm"/>
<IsVisibleTab Value="True"/>
<TopLine Value="73"/>
<CursorPos X="78" Y="89"/>
<UsageCount Value="106"/>
<TopLine Value="74"/>
<CursorPos X="31" Y="90"/>
<UsageCount Value="134"/>
<Loaded Value="True"/>
<LoadedDesigner Value="True"/>
</Unit1>
<Unit2>
<Filename Value="..\..\utsRendererOpenGL.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="utsRendererOpenGL"/>
<EditorIndex Value="7"/>
<TopLine Value="37"/>
<CursorPos X="35" Y="114"/>
<UsageCount Value="34"/>
<Loaded Value="True"/>
<EditorIndex Value="-1"/>
<TopLine Value="494"/>
<CursorPos Y="522"/>
<UsageCount Value="62"/>
</Unit2>
<Unit3>
<Filename Value="..\..\utsTextSuite.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="utsTextSuite"/>
<EditorIndex Value="1"/>
<TopLine Value="10"/>
<CursorPos X="5" Y="26"/>
<UsageCount Value="34"/>
<EditorIndex Value="3"/>
<TopLine Value="1335"/>
<CursorPos X="3" Y="1405"/>
<UsageCount Value="62"/>
<Loaded Value="True"/>
</Unit3>
<Unit4>
<Filename Value="..\..\utsTtfUtils.pas"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="-1"/>
<UsageCount Value="34"/>
<UsageCount Value="62"/>
</Unit4>
<Unit5>
<Filename Value="..\..\utsTypes.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="utsTypes"/>
<EditorIndex Value="5"/>
<TopLine Value="282"/>
<CursorPos Y="298"/>
<UsageCount Value="34"/>
<EditorIndex Value="2"/>
<TopLine Value="93"/>
<CursorPos X="5" Y="109"/>
<UsageCount Value="62"/>
<Loaded Value="True"/>
</Unit5>
<Unit6>
<Filename Value="..\..\utsUtils.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="utsUtils"/>
<EditorIndex Value="3"/>
<TopLine Value="161"/>
<CursorPos X="23" Y="180"/>
<UsageCount Value="34"/>
<Loaded Value="True"/>
<EditorIndex Value="-1"/>
<TopLine Value="174"/>
<CursorPos X="26" Y="194"/>
<UsageCount Value="62"/>
</Unit6>
<Unit7>
<Filename Value="..\..\utsFontCreatorGDI.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="utsFontCreatorGDI"/>
<EditorIndex Value="6"/>
<TopLine Value="643"/>
<CursorPos X="33" Y="659"/>
<UsageCount Value="34"/>
<IsVisibleTab Value="True"/>
<WindowIndex Value="1"/>
<TopLine Value="554"/>
<CursorPos X="11" Y="571"/>
<UsageCount Value="62"/>
<Loaded Value="True"/>
</Unit7>
<Unit8>
<Filename Value="..\..\utsCodePages.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="utsCodePages"/>
<EditorIndex Value="4"/>
<TopLine Value="196"/>
<CursorPos X="30" Y="8"/>
<UsageCount Value="31"/>
<Loaded Value="True"/>
<EditorIndex Value="-1"/>
<TopLine Value="315"/>
<CursorPos X="21" Y="325"/>
<UsageCount Value="59"/>
</Unit8>
<Unit9>
<Filename Value="..\..\utsPostProcess.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="utsPostProcess"/>
<EditorIndex Value="2"/>
<TopLine Value="229"/>
<CursorPos X="13" Y="250"/>
<UsageCount Value="29"/>
<Loaded Value="True"/>
<EditorIndex Value="-1"/>
<TopLine Value="216"/>
<CursorPos X="30" Y="227"/>
<UsageCount Value="57"/>
</Unit9>
<Unit10>
<Filename Value="..\..\utsFontCreatorFreeType.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="utsFontCreatorFreeType"/>
<EditorIndex Value="1"/>
<TopLine Value="312"/>
<CursorPos X="21" Y="258"/>
<UsageCount Value="46"/>
<Loaded Value="True"/>
</Unit10>
<Unit11>
<Filename Value="..\..\utsGDI.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="utsGDI"/>
<EditorIndex Value="2"/>
<WindowIndex Value="1"/>
<TopLine Value="284"/>
<CursorPos X="12" Y="298"/>
<UsageCount Value="38"/>
<Loaded Value="True"/>
</Unit11>
<Unit12>
<Filename Value="..\..\utsFreeType.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="utsFreeType"/>
<EditorIndex Value="3"/>
<WindowIndex Value="1"/>
<TopLine Value="340"/>
<CursorPos X="26" Y="363"/>
<UsageCount Value="38"/>
<Loaded Value="True"/>
</Unit12>
<Unit13>
<Filename Value="new\utsTextSuite.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="1886"/>
<CursorPos X="33" Y="1904"/>
<UsageCount Value="91"/>
</Unit10>
<Unit11>
<UsageCount Value="89"/>
</Unit13>
<Unit14>
<Filename Value="old\TextSuite.pas"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
@@ -120,508 +150,486 @@
<TopLine Value="232"/>
<CursorPos X="3" Y="302"/>
</ExtraEditor1>
<UsageCount Value="86"/>
</Unit11>
<Unit12>
<UsageCount Value="84"/>
</Unit14>
<Unit15>
<Filename Value="old\TextSuiteImports.pas"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<TopLine Value="656"/>
<CursorPos X="20" Y="635"/>
<UsageCount Value="86"/>
</Unit12>
<Unit13>
<UsageCount Value="84"/>
</Unit15>
<Unit16>
<Filename Value="old\TextSuiteWideUtils.pas"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<TopLine Value="1243"/>
<CursorPos X="18" Y="1257"/>
<UsageCount Value="86"/>
</Unit13>
<Unit14>
<UsageCount Value="84"/>
</Unit16>
<Unit17>
<Filename Value="old\TextSuiteClasses.pas"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<TopLine Value="654"/>
<CursorPos X="25" Y="673"/>
<UsageCount Value="86"/>
</Unit14>
<Unit15>
<UsageCount Value="84"/>
</Unit17>
<Unit18>
<Filename Value="old\TextSuitePostProcess.pas"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<TopLine Value="163"/>
<CursorPos X="61" Y="141"/>
<UsageCount Value="86"/>
</Unit15>
<Unit16>
<UsageCount Value="84"/>
</Unit18>
<Unit19>
<Filename Value="old\TextSuiteTTFUtils.pas"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<TopLine Value="83"/>
<CursorPos X="3" Y="91"/>
<UsageCount Value="86"/>
</Unit16>
<Unit17>
<UsageCount Value="84"/>
</Unit19>
<Unit20>
<Filename Value="old\TextSuiteVersion.pas"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="-1"/>
<TopLine Value="-1"/>
<CursorPos X="-1" Y="-1"/>
<UsageCount Value="86"/>
</Unit17>
<Unit18>
<UsageCount Value="84"/>
</Unit20>
<Unit21>
<Filename Value="new\utsFontCreatorGDI.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="655"/>
<CursorPos X="53" Y="662"/>
<UsageCount Value="50"/>
</Unit18>
<Unit19>
<UsageCount Value="48"/>
</Unit21>
<Unit22>
<Filename Value="new\utsTtfUtils.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="128"/>
<CursorPos X="17" Y="144"/>
<UsageCount Value="42"/>
</Unit19>
<Unit20>
<UsageCount Value="40"/>
</Unit22>
<Unit23>
<Filename Value="new\utsTypes.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="152"/>
<CursorPos X="5" Y="168"/>
<UsageCount Value="42"/>
</Unit20>
<Unit21>
<UsageCount Value="40"/>
</Unit23>
<Unit24>
<Filename Value="new\utsUtils.pas"/>
<EditorIndex Value="-1"/>
<CursorPos Y="20"/>
<UsageCount Value="42"/>
</Unit21>
<Unit22>
<UsageCount Value="40"/>
</Unit24>
<Unit25>
<Filename Value="new\utsRendererOpenGL.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="356"/>
<CursorPos X="20" Y="376"/>
<UsageCount Value="39"/>
</Unit22>
<Unit23>
<UsageCount Value="37"/>
</Unit25>
<Unit26>
<Filename Value="..\bitSpace\_projects\MassiveUniverseOnline\bitSpaceEngine\src\OpenGLCore\uglcTypes.pas"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<TopLine Value="261"/>
<CursorPos X="3" Y="277"/>
<UsageCount Value="37"/>
</Unit23>
<Unit24>
<UsageCount Value="35"/>
</Unit26>
<Unit27>
<Filename Value="..\bitSpace\_projects\MassiveUniverseOnline\bitSpaceEngine\src\OpenGLCore\dglOpenGL.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="1066"/>
<CursorPos X="27" Y="1082"/>
<UsageCount Value="32"/>
</Unit24>
<Unit25>
<UsageCount Value="30"/>
</Unit27>
<Unit28>
<Filename Value="new\uglctextsuite.pas"/>
<EditorIndex Value="-1"/>
<CursorPos X="3" Y="13"/>
<UsageCount Value="13"/>
</Unit25>
<Unit26>
<UsageCount Value="11"/>
</Unit28>
<Unit29>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\ustringh.inc"/>
<EditorIndex Value="-1"/>
<TopLine Value="110"/>
<CursorPos X="10" Y="126"/>
<UsageCount Value="27"/>
</Unit26>
<Unit27>
<EditorIndex Value="5"/>
<TopLine Value="113"/>
<CursorPos X="10" Y="129"/>
<UsageCount Value="35"/>
<Loaded Value="True"/>
</Unit29>
<Unit30>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\ustrings.inc"/>
<EditorIndex Value="-1"/>
<TopLine Value="1819"/>
<CursorPos X="37" Y="2066"/>
<UsageCount Value="4"/>
</Unit27>
<Unit28>
<EditorIndex Value="6"/>
<TopLine Value="2091"/>
<CursorPos X="5" Y="2098"/>
<UsageCount Value="18"/>
<Loaded Value="True"/>
</Unit30>
<Unit31>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\systemh.inc"/>
<EditorIndex Value="-1"/>
<TopLine Value="756"/>
<CursorPos X="32" Y="774"/>
<UsageCount Value="25"/>
</Unit28>
<Unit29>
<EditorIndex Value="7"/>
<TopLine Value="502"/>
<CursorPos X="3" Y="518"/>
<UsageCount Value="33"/>
<Loaded Value="True"/>
</Unit31>
<Unit32>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\heaph.inc"/>
<EditorIndex Value="-1"/>
<TopLine Value="71"/>
<CursorPos X="10" Y="95"/>
<UsageCount Value="26"/>
</Unit29>
<Unit30>
<UsageCount Value="24"/>
</Unit32>
<Unit33>
<Filename Value="old\TextSuiteCPUUtils.pas"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<CursorPos X="23" Y="20"/>
<UsageCount Value="16"/>
</Unit30>
<Unit31>
<UsageCount Value="14"/>
</Unit33>
<Unit34>
<Filename Value="..\glBitmap\glBitmap\glBitmap.pas"/>
<EditorIndex Value="-1"/>
<CursorPos X="14" Y="14"/>
<UsageCount Value="4"/>
</Unit31>
<Unit32>
<UsageCount Value="2"/>
</Unit34>
<Unit35>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\objpas\math.pp"/>
<EditorIndex Value="-1"/>
<TopLine Value="1011"/>
<CursorPos X="47" Y="1015"/>
<UsageCount Value="8"/>
</Unit32>
<Unit33>
<UsageCount Value="6"/>
</Unit35>
<Unit36>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\mathh.inc"/>
<EditorIndex Value="-1"/>
<TopLine Value="84"/>
<CursorPos X="14" Y="101"/>
<UsageCount Value="8"/>
</Unit33>
<Unit34>
<UsageCount Value="6"/>
</Unit36>
<Unit37>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\genmath.inc"/>
<EditorIndex Value="-1"/>
<TopLine Value="152"/>
<CursorPos X="10" Y="155"/>
<UsageCount Value="8"/>
</Unit34>
<Unit35>
<UsageCount Value="6"/>
</Unit37>
<Unit38>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\dynlibs.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="41"/>
<CursorPos X="10" Y="58"/>
<UsageCount Value="13"/>
</Unit35>
<Unit36>
<UnitName Value="dynlibs"/>
<EditorIndex Value="8"/>
<TopLine Value="143"/>
<CursorPos X="3" Y="149"/>
<UsageCount Value="27"/>
<Loaded Value="True"/>
</Unit38>
<Unit39>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\win\dynlibs.inc"/>
<EditorIndex Value="-1"/>
<TopLine Value="9"/>
<CursorPos X="3" Y="26"/>
<UsageCount Value="13"/>
</Unit36>
<Unit37>
<EditorIndex Value="9"/>
<TopLine Value="26"/>
<CursorPos X="10" Y="42"/>
<UsageCount Value="25"/>
<Loaded Value="True"/>
</Unit39>
<Unit40>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\win\sysosh.inc"/>
<EditorIndex Value="-1"/>
<TopLine Value="11"/>
<CursorPos X="3" Y="19"/>
<UsageCount Value="13"/>
</Unit37>
<Unit38>
<UsageCount Value="11"/>
</Unit40>
<Unit41>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\objpash.inc"/>
<EditorIndex Value="-1"/>
<TopLine Value="177"/>
<CursorPos X="22" Y="195"/>
<UsageCount Value="17"/>
</Unit38>
<Unit39>
<UsageCount Value="15"/>
</Unit41>
<Unit42>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\objpas\sysutils\sysunih.inc"/>
<EditorIndex Value="12"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<TopLine Value="25"/>
<CursorPos X="34" Y="43"/>
<UsageCount Value="28"/>
<Loaded Value="True"/>
</Unit39>
<Unit40>
<UsageCount Value="26"/>
</Unit42>
<Unit43>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\packages\fcl-base\src\syncobjs.pp"/>
<EditorIndex Value="-1"/>
<TopLine Value="113"/>
<CursorPos X="25" Y="115"/>
<UsageCount Value="18"/>
</Unit40>
<Unit41>
<UsageCount Value="16"/>
</Unit43>
<Unit44>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\objpas\classes\classesh.inc"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<TopLine Value="311"/>
<CursorPos X="14" Y="327"/>
<UsageCount Value="25"/>
<Loaded Value="True"/>
</Unit41>
<Unit42>
<UsageCount Value="23"/>
</Unit44>
<Unit45>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\objpas.inc"/>
<EditorIndex Value="11"/>
<WindowIndex Value="1"/>
<CursorPos X="35" Y="24"/>
<UsageCount Value="22"/>
<EditorIndex Value="4"/>
<UsageCount Value="26"/>
<Loaded Value="True"/>
</Unit42>
<Unit43>
</Unit45>
<Unit46>
<Filename Value="C:\Zusatzprogramme\Lazarus\lcl\include\control.inc"/>
<EditorIndex Value="-1"/>
<TopLine Value="2843"/>
<CursorPos Y="2858"/>
<UsageCount Value="15"/>
</Unit43>
<Unit44>
<UsageCount Value="13"/>
</Unit46>
<Unit47>
<Filename Value="C:\Users\Erik\Desktop\RectPacking\unit1.pas"/>
<ComponentName Value="Form1"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="Unit1"/>
<EditorIndex Value="1"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<TopLine Value="376"/>
<CursorPos X="74" Y="397"/>
<UsageCount Value="23"/>
<Loaded Value="True"/>
</Unit44>
<Unit45>
<UsageCount Value="21"/>
</Unit47>
<Unit48>
<Filename Value="..\bitSpace\_projects\MassiveUniverseOnline\bitSpaceEngine\src\OpenGLCore\uglcArrayBuffer.pas"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<TopLine Value="102"/>
<CursorPos X="37" Y="112"/>
<UsageCount Value="12"/>
</Unit45>
<Unit46>
<UsageCount Value="10"/>
</Unit48>
<Unit49>
<Filename Value="..\bitSpace\_projects\MassiveUniverseOnline\bitSpaceEngine\src\OpenGLCore\uglcBitmap.pas"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<TopLine Value="1047"/>
<CursorPos X="15" Y="1043"/>
<UsageCount Value="10"/>
</Unit46>
<Unit47>
<UsageCount Value="8"/>
</Unit49>
<Unit50>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\objpas\objpas.pp"/>
<EditorIndex Value="-1"/>
<TopLine Value="19"/>
<CursorPos X="8" Y="35"/>
<UsageCount Value="10"/>
</Unit47>
<Unit48>
<UsageCount Value="8"/>
</Unit50>
<Unit51>
<Filename Value="C:\Zusatzprogramme\Lazarus\lcl\include\application.inc"/>
<EditorIndex Value="-1"/>
<TopLine Value="966"/>
<CursorPos Y="981"/>
<UsageCount Value="10"/>
</Unit48>
<Unit49>
<UsageCount Value="8"/>
</Unit51>
<Unit52>
<Filename Value="..\bitSpace\_projects\MassiveUniverseOnline\bitSpaceEngine\src\SpaceEngine\uengFrameLimiter.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="14"/>
<CursorPos X="13" Y="14"/>
<UsageCount Value="10"/>
</Unit49>
<Unit50>
<UsageCount Value="8"/>
</Unit52>
<Unit53>
<Filename Value="..\..\old\TextSuiteClasses.pas"/>
<UnitName Value="TextSuiteClasses"/>
<EditorIndex Value="2"/>
<EditorIndex Value="1"/>
<WindowIndex Value="1"/>
<TopLine Value="1811"/>
<CursorPos X="18" Y="1754"/>
<UsageCount Value="17"/>
<TopLine Value="2705"/>
<CursorPos X="3" Y="2698"/>
<UsageCount Value="15"/>
<Loaded Value="True"/>
</Unit50>
<Unit51>
</Unit53>
<Unit54>
<Filename Value="..\..\old\TextSuite.pas"/>
<UnitName Value="TextSuite"/>
<EditorIndex Value="9"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<TopLine Value="29"/>
<CursorPos X="3" Y="45"/>
<UsageCount Value="16"/>
<Loaded Value="True"/>
</Unit51>
<Unit52>
<UsageCount Value="14"/>
</Unit54>
<Unit55>
<Filename Value="..\..\old\TextSuiteWideUtils.pas"/>
<UnitName Value="TextSuiteWideUtils"/>
<EditorIndex Value="10"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<TopLine Value="1362"/>
<CursorPos X="3" Y="1390"/>
<UsageCount Value="16"/>
<Loaded Value="True"/>
</Unit52>
<Unit53>
<UsageCount Value="14"/>
</Unit55>
<Unit56>
<Filename Value="..\..\utsWideStringUtils.pas"/>
<EditorIndex Value="-1"/>
<CursorPos Y="9"/>
<UsageCount Value="20"/>
</Unit53>
<Unit54>
<UsageCount Value="18"/>
</Unit56>
<Unit57>
<Filename Value="..\..\old\TextSuiteCPUUtils.pas"/>
<UnitName Value="TextSuiteCPUUtils"/>
<EditorIndex Value="3"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<UsageCount Value="15"/>
<Loaded Value="True"/>
</Unit54>
<Unit55>
<UsageCount Value="13"/>
</Unit57>
<Unit58>
<Filename Value="..\..\old\TextSuiteImports.pas"/>
<UnitName Value="TextSuiteImports"/>
<EditorIndex Value="4"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<CursorPos X="41" Y="12"/>
<UsageCount Value="15"/>
<Loaded Value="True"/>
</Unit55>
<Unit56>
<UsageCount Value="13"/>
</Unit58>
<Unit59>
<Filename Value="..\..\old\TextSuiteOptions.inc"/>
<EditorIndex Value="5"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<UsageCount Value="15"/>
<Loaded Value="True"/>
</Unit56>
<Unit57>
<UsageCount Value="13"/>
</Unit59>
<Unit60>
<Filename Value="..\..\old\TextSuitePostProcess.pas"/>
<UnitName Value="TextSuitePostProcess"/>
<IsVisibleTab Value="True"/>
<EditorIndex Value="6"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<TopLine Value="261"/>
<CursorPos X="23" Y="345"/>
<UsageCount Value="15"/>
<Loaded Value="True"/>
</Unit57>
<Unit58>
<UsageCount Value="13"/>
</Unit60>
<Unit61>
<Filename Value="..\..\old\TextSuiteTTFUtils.pas"/>
<UnitName Value="TextSuiteTTFUtils"/>
<EditorIndex Value="7"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<UsageCount Value="15"/>
<Loaded Value="True"/>
</Unit58>
<Unit59>
<UsageCount Value="13"/>
</Unit61>
<Unit62>
<Filename Value="..\..\old\TextSuiteVersion.pas"/>
<UnitName Value="TextSuiteVersion"/>
<EditorIndex Value="8"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="1"/>
<UsageCount Value="15"/>
<UsageCount Value="13"/>
</Unit62>
<Unit63>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\win\wininc\unifun.inc"/>
<EditorIndex Value="10"/>
<TopLine Value="53"/>
<CursorPos X="22" Y="69"/>
<UsageCount Value="23"/>
<Loaded Value="True"/>
</Unit59>
</Unit63>
</Units>
<JumpHistory Count="29" HistoryIndex="28">
<JumpHistory Count="26" HistoryIndex="25">
<Position1>
<Filename Value="..\..\utsTextSuite.pas"/>
<Caret Line="878" TopLine="866"/>
<Caret Line="1423" TopLine="1407"/>
</Position1>
<Position2>
<Filename Value="..\..\utsTextSuite.pas"/>
<Caret Line="879" TopLine="866"/>
<Caret Line="1425" TopLine="1407"/>
</Position2>
<Position3>
<Filename Value="..\..\utsTextSuite.pas"/>
<Caret Line="880" TopLine="866"/>
<Caret Line="1429" TopLine="1414"/>
</Position3>
<Position4>
<Filename Value="..\..\old\TextSuiteClasses.pas"/>
<Caret Line="371" Column="23" TopLine="358"/>
<Filename Value="..\..\utsTextSuite.pas"/>
<Caret Line="1430" TopLine="1414"/>
</Position4>
<Position5>
<Filename Value="..\..\old\TextSuiteClasses.pas"/>
<Caret Line="394" Column="68" TopLine="367"/>
<Filename Value="..\..\utsTextSuite.pas"/>
<Caret Line="1433" TopLine="1414"/>
</Position5>
<Position6>
<Filename Value="..\..\utsTextSuite.pas"/>
<Caret Line="882" Column="44" TopLine="866"/>
<Filename Value="..\..\old\TextSuiteClasses.pas"/>
<Caret Line="1825" Column="21" TopLine="1811"/>
</Position6>
<Position7>
<Filename Value="uMainForm.pas"/>
<Caret Line="87" Column="69" TopLine="71"/>
<Filename Value="..\..\old\TextSuiteClasses.pas"/>
</Position7>
<Position8>
<Filename Value="..\..\utsPostProcess.pas"/>
<Caret Line="65" Column="65" TopLine="38"/>
<Filename Value="..\..\utsTextSuite.pas"/>
<Caret Line="1433" Column="33" TopLine="1423"/>
</Position8>
<Position9>
<Filename Value="..\..\utsPostProcess.pas"/>
<Caret Line="243" Column="46" TopLine="223"/>
<Filename Value="..\..\utsTextSuite.pas"/>
<Caret Line="1515" TopLine="1499"/>
</Position9>
<Position10>
<Filename Value="..\..\utsPostProcess.pas"/>
<Caret Line="240" Column="34" TopLine="224"/>
<Filename Value="uMainForm.pas"/>
<Caret Line="87" Column="104" TopLine="73"/>
</Position10>
<Position11>
<Filename Value="uMainForm.pas"/>
<Caret Line="35" Column="15" TopLine="25"/>
<Filename Value="..\..\utsTextSuite.pas"/>
<Caret Line="1517" TopLine="1501"/>
</Position11>
<Position12>
<Filename Value="uMainForm.pas"/>
<Caret Line="91" Column="73" TopLine="71"/>
<Caret Line="89" Column="57" TopLine="73"/>
</Position12>
<Position13>
<Filename Value="..\..\utsPostProcess.pas"/>
<Caret Line="234" Column="19" TopLine="219"/>
<Filename Value="uMainForm.pas"/>
<Caret Line="87" Column="32" TopLine="73"/>
</Position13>
<Position14>
<Filename Value="..\..\utsPostProcess.pas"/>
<Caret Line="241" TopLine="222"/>
<Filename Value="..\..\utsFontCreatorGDI.pas"/>
<Caret Line="571" Column="11" TopLine="554"/>
</Position14>
<Position15>
<Filename Value="..\..\utsPostProcess.pas"/>
<Caret Line="246" TopLine="222"/>
<Filename Value="uMainForm.pas"/>
<Caret Line="104" Column="3" TopLine="75"/>
</Position15>
<Position16>
<Filename Value="..\..\utsPostProcess.pas"/>
<Caret Line="242" TopLine="222"/>
<Filename Value="uMainForm.pas"/>
<Caret Line="99" TopLine="75"/>
</Position16>
<Position17>
<Filename Value="..\..\utsPostProcess.pas"/>
<Caret Line="245" TopLine="222"/>
<Filename Value="uMainForm.pas"/>
<Caret Line="100" TopLine="75"/>
</Position17>
<Position18>
<Filename Value="..\..\utsPostProcess.pas"/>
<Caret Line="244" TopLine="222"/>
<Filename Value="uMainForm.pas"/>
<Caret Line="101" TopLine="75"/>
</Position18>
<Position19>
<Filename Value="..\..\utsPostProcess.pas"/>
<Caret Line="243" TopLine="222"/>
<Filename Value="uMainForm.pas"/>
<Caret Line="102" TopLine="75"/>
</Position19>
<Position20>
<Filename Value="..\..\utsPostProcess.pas"/>
<Caret Line="242" TopLine="222"/>
<Filename Value="uMainForm.pas"/>
<Caret Line="103" TopLine="76"/>
</Position20>
<Position21>
<Filename Value="..\..\utsPostProcess.pas"/>
<Caret Line="241" Column="36" TopLine="225"/>
<Filename Value="uMainForm.pas"/>
<Caret Line="99" TopLine="76"/>
</Position21>
<Position22>
<Filename Value="..\..\utsPostProcess.pas"/>
<Caret Line="243" Column="56" TopLine="229"/>
<Filename Value="uMainForm.pas"/>
<Caret Line="100" TopLine="76"/>
</Position22>
<Position23>
<Filename Value="..\..\utsPostProcess.pas"/>
<Caret Line="248" TopLine="227"/>
<Filename Value="uMainForm.pas"/>
<Caret Line="101" TopLine="76"/>
</Position23>
<Position24>
<Filename Value="..\..\utsPostProcess.pas"/>
<Caret Line="250" Column="80" TopLine="228"/>
<Filename Value="uMainForm.pas"/>
<Caret Line="102" TopLine="76"/>
</Position24>
<Position25>
<Filename Value="..\..\utsPostProcess.pas"/>
<Caret Line="248" Column="28" TopLine="233"/>
<Filename Value="uMainForm.pas"/>
<Caret Line="103" TopLine="76"/>
</Position25>
<Position26>
<Filename Value="..\..\utsPostProcess.pas"/>
<Caret Line="250" Column="48" TopLine="233"/>
</Position26>
<Position27>
<Filename Value="..\..\utsPostProcess.pas"/>
<Caret Line="225" Column="3" TopLine="217"/>
</Position27>
<Position28>
<Filename Value="..\..\utsPostProcess.pas"/>
<Caret Line="246" Column="34" TopLine="228"/>
</Position28>
<Position29>
<Filename Value="uMainForm.pas"/>
<Caret Line="91" Column="73" TopLine="71"/>
</Position29>
<Caret Line="30" Column="5" TopLine="14"/>
</Position26>
</JumpHistory>
</ProjectSession>
<Debugging>
<Watches Count="3">
<BreakPoints Count="1">
<Item1>
<Expression Value="aItem"/>
<Kind Value="bpkSource"/>
<WatchScope Value="wpsLocal"/>
<WatchKind Value="wpkWrite"/>
<Source Value="..\..\utsFontCreatorGDI.pas"/>
<Line Value="570"/>
</Item1>
<Item2>
<Expression Value="aItem^.children[0]"/>
</Item2>
<Item3>
<Expression Value="aItem^.children[1]"/>
</Item3>
</Watches>
</BreakPoints>
</Debugging>
</CONFIG>

+ 22
- 29
examples/simple/uMainForm.pas View File

@@ -7,8 +7,8 @@ unit uMainForm;
interface

uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, uglcContext, TextSuite, uglcTypes,
utsTextSuite, utsTypes, utsFontCreatorGDI, utsRendererOpenGL, utsPostProcess;
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, uglcContext, uglcTypes,
utsTextSuite, utsTypes, utsFontCreatorGDI, utsRendererOpenGL, utsPostProcess, utsFontCreatorFreeType;

type
TMainForm = class(TForm)
@@ -29,8 +29,10 @@ type
ftsContext: TtsContext;
ftsRenderer: TtsRendererOpenGL;
ftsGenerator: TtsFontGeneratorGDI;
ftsFreeType: TtsFontGeneratorFreeType;
ftsFont1: TtsFont;
ftsFont2: TtsFont;
ftsFont3: TtsFont;
{$ENDIF}
procedure Render;
public
@@ -48,23 +50,13 @@ uses
dglOpenGL;

const
TEST_STRING = 'orem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.';
//TEST_STRING = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.';
TEST_STRING = 'Lorem';

procedure TMainForm.FormCreate(Sender: TObject);
var
pf: TglcContextPixelFormatSettings;
pp: TtsPostProcessStep;
pa: TtsImage;
const
data: array[0..63] of Byte = (
$FF, $AA, $88, $44, $44, $88, $AA, $FF,
$AA, $88, $44, $22, $22, $44, $88, $AA,
$88, $44, $22, $11, $11, $22, $44, $88,
$44, $22, $11, $00, $00, $11, $22, $44,
$44, $22, $11, $00, $00, $11, $22, $44,
$88, $44, $22, $11, $11, $22, $44, $88,
$AA, $88, $44, $22, $22, $44, $88, $AA,
$FF, $AA, $88, $44, $44, $88, $AA, $FF);
begin
pf := TglcContext.MakePF();
fContext := TglcContext.GetPlatformClass.Create(self, pf);
@@ -82,6 +74,8 @@ begin
ftsRenderer := TtsRendererOpenGL.Create(ftsContext, tsFormatRGBA8);
ftsGenerator := TtsFontGeneratorGDI.Create(ftsContext);

ftsFreeType := TtsFontGeneratorFreeType.Create(ftsContext);
{
pp := TtsPostProcessFillColor.Create(tsColor4f(0.0, 0.0, 0.0, 1.0), TS_MODES_MODULATE_ALPHA, TS_CHANNELS_RGBA);
pp.AddUsageRange(tsUsageInclude, #$0000, #$FFFF);
ftsGenerator.AddPostProcessStep(pp);
@@ -89,9 +83,15 @@ begin
pp := TtsPostProcessShadow.Create(3, 0, 2, 2, tsColor4f(1.0, 0.0, 1.0, 0.05));
pp.AddUsageRange(tsUsageInclude, #$0000, #$FFFF);
ftsGenerator.AddPostProcessStep(pp);

ftsFont1 := ftsGenerator.GetFontByName('Calibri', ftsRenderer, 100, [tsStyleBold, tsStyleItalic], tsAANormal);
ftsFont2 := ftsGenerator.GetFontByName('Calibri', ftsRenderer, 20, [], tsAANormal);
}
try
ftsFont1 := ftsGenerator.GetFontByFile('Calibri', ftsRenderer, 25, [tsStyleBold], tsAANormal);
ftsFont2 := ftsGenerator.GetFontByName('Calibri', ftsRenderer, 20, [], tsAANormal);
ftsFont3 := ftsFreeType.GetFontByFile('calibrib.ttf', ftsRenderer, 25, tsAANone);
except
on e: EtsException do
MessageDlg('Error', e.Message, mtError, [mbOK], 0);
end;
{$ENDIF}
end;

@@ -104,6 +104,7 @@ begin
FreeAndNil(ftsFont1);
FreeAndNil(ftsFont2);
FreeAndNil(ftsGenerator);
FreeAndNil(ftsFreeType);
FreeAndNil(ftsRenderer);
FreeAndNil(ftsContext);
{$ENDIF}
@@ -134,7 +135,7 @@ begin
fFrameTime := t;

glViewport(0, 0, ClientWidth, ClientHeight);
glClearColor(1, 1, 1, 0);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_PROJECTION);
@@ -151,25 +152,17 @@ begin
tsTextOutA(TEST_STRING);
tsTextEndBlock;
{$ELSE}
block := ftsRenderer.BeginBlock(10, 10, ClientWidth-20, ClientHeight-20, [tsBlockFlagWordWrap]);
block := ftsRenderer.BeginBlock(0, 0, ClientWidth, ClientHeight, [tsBlockFlagWordWrap]);
try
block.HorzAlign := tsHorzAlignJustify;

block.ChangeFont(ftsFont1);
block.ChangeColor(tsColor4f(1.0, 1.0, 1.0, 1.0));
block.TextOutW('L');

block.ChangeFont(ftsFont2);
block.ChangeColor(tsColor4f(1.0, 1.0, 1.0, 1.0));
block.TextOutW(TEST_STRING + sLineBreak);

block.ChangeFont(ftsFont1);
block.ChangeColor(tsColor4f(1.0, 1.0, 1.0, 1.0));
block.TextOutW('L');

block.ChangeFont(ftsFont2);
block.ChangeFont(ftsFont3);
block.ChangeColor(tsColor4f(1.0, 1.0, 1.0, 1.0));
block.TextOutW(TEST_STRING);
block.TextOutA(TEST_STRING);
finally
ftsRenderer.EndBlock(block);
end;


+ 359
- 0
utsFontCreatorFreeType.pas View File

@@ -0,0 +1,359 @@
unit utsFontCreatorFreeType;

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils, syncobjs, dynlibs,
utsTextSuite, utsTypes, utsFreeType;

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TtsFreeTypeFaceHandle = class
private
fFace: FT_Face;
public
constructor Create(const aFace: FT_Face);
destructor Destroy; override;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TtsFontFreeType = class(TtsFont)
private
fHandle: TtsFreeTypeFaceHandle;
public
constructor Create(const aHandle: TtsFreeTypeFaceHandle; const aRenderer: TtsRenderer;
const aGenerator: TtsFontGenerator; const aProperties: TtsFontProperties);
destructor Destroy; override;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TtsFontGeneratorFreeType = class(TtsFontGenerator)
private
fHandle: FT_Library;

function ConvertFont(const aFont: TtsFont): TtsFontFreeType;
procedure LoadNames(const aFace: FT_Face; var aProperties: TtsFontProperties);
protected
function GetGlyphMetrics(const aFont: TtsFont; const aCharCode: WideChar;
out aGlyphOrigin, aGlyphSize: TtsPosition; out aAdvance: Integer): Boolean; override;
procedure GetCharImage(const aFont: TtsFont; const aCharCode: WideChar;
const aCharImage: TtsImage); override;
public
function GetFontByFile(const aFilename: String; const aRenderer: TtsRenderer;
const aSize: Integer; const aAntiAliasing: TtsAntiAliasing): TtsFont; overload;

constructor Create(const aContext: TtsContext);
destructor Destroy; override;
end;

implementation

uses
utsUtils, math;

const
FT_SIZE_FACTOR = 64;
FT_SIZE_RES = 72; //dpi

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TtsFreeTypeFaceHandle/////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TtsFreeTypeFaceHandle.Create(const aFace: FT_Face);
begin
inherited Create;
fFace := aFace;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TtsFreeTypeFaceHandle.Destroy;
begin
FT_Done_Face(fFace);
inherited Destroy;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TtsFontFreeType///////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TtsFontFreeType.Create(const aHandle: TtsFreeTypeFaceHandle; const aRenderer: TtsRenderer;
const aGenerator: TtsFontGenerator; const aProperties: TtsFontProperties);
begin
inherited Create(aRenderer, aGenerator, aProperties);
fHandle := aHandle;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TtsFontFreeType.Destroy;
begin
FreeAndNil(fHandle);
inherited Destroy;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TtsFontGeneratorFreeType//////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TtsFontGeneratorFreeType.ConvertFont(const aFont: TtsFont): TtsFontFreeType;
begin
if not (aFont is TtsFontFreeType) then
raise EtsException.Create('aFont need to be a TtsFontGDI object');
result := (aFont as TtsFontFreeType);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TtsFontGeneratorFreeType.LoadNames(const aFace: FT_Face; var aProperties: TtsFontProperties);
var
i, cnt: FT_Int;
err: FT_Error;
name: FT_SfntName;

function DecodeAnsi(const aCodePage: TtsCodePage): String;
var
tmp: WideString;
len: Integer;
begin
SetLength(tmp, name.string_len);
len := tsAnsiSBCDToWide(@tmp[1], name.string_len, PAnsiChar(name.string_), aCodePage, '?');
SetLength(tmp, len);
result := UTF8Encode(tmp);
end;

function Decode: String;
var
tmp: WideString;
len: Integer;
begin
result := '';
case name.platform_id of
TT_PLATFORM_APPLE_UNICODE: begin
case name.encoding_id of
TT_APPLE_ID_DEFAULT,
TT_APPLE_ID_UNICODE_1_1,
TT_APPLE_ID_UNICODE_2_0: begin
SetLength(tmp, name.string_len);
len := tsUTFBE16ToWide(@tmp[1], name.string_len, name.string_, name.string_len, '?');
SetLength(tmp, len);
result := UTF8Encode(tmp);
end;
end;
end;

TT_PLATFORM_ISO: begin
case name.encoding_id of
TT_ISO_ID_8859_1:
result := DecodeAnsi(tsISO_8859_1);
end;
end;
end;
end;

begin
cnt := FT_Get_Sfnt_Name_Count(aFace);
for i := 0 to cnt-1 do begin
err := FT_Get_Sfnt_Name(aFace, i, @name);
if (err <> 0) then
continue;

case name.name_id of
TT_NAME_ID_COPYRIGHT:
if (aProperties.Copyright = '') then
aProperties.Copyright := Decode;

TT_NAME_ID_FONT_FAMILY:
if (aProperties.Fontname = '') then
aProperties.Fontname := Decode;

TT_NAME_ID_FULL_NAME:
if (aProperties.FullName = '') then
aProperties.FullName := Decode;
end;
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TtsFontGeneratorFreeType.GetGlyphMetrics(const aFont: TtsFont; const aCharCode: WideChar; out aGlyphOrigin, aGlyphSize: TtsPosition; out aAdvance: Integer): Boolean;
var
font: TtsFontFreeType;
err: FT_Error;
begin
result := false;

aGlyphOrigin.x := 0;
aGlyphOrigin.x := 0;
aGlyphSize.x := 0;
aGlyphSize.y := 0;
aAdvance := 0;

font := ConvertFont(aFont);
case font.Properties.AntiAliasing of
tsAANormal:
err := FT_Load_Char(font.fHandle.fFace, Ord(aCharCode), FT_LOAD_DEFAULT);
tsAANone:
err := FT_Load_Char(font.fHandle.fFace, Ord(aCharCode), FT_LOAD_MONOCHROME);
else
raise EtsException.Create('unknown anti aliasing');
end;
case err of
FT_ERR_None:
{ nop };
FT_ERR_Invalid_Character_Code:
exit;
else
raise EtsException.Create('unable to set glyph metrix: error=' + IntToStr(err));
end;

result := true;
with font.fHandle.fFace^.glyph^.metrics do begin
aAdvance := horiAdvance div FT_SIZE_FACTOR;
aGlyphOrigin.x := horiBearingX div FT_SIZE_FACTOR;
aGlyphOrigin.y := horiBearingY div FT_SIZE_FACTOR;
aGlyphSize.x := width div FT_SIZE_FACTOR;
aGlyphSize.y := height div FT_SIZE_FACTOR;
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TtsFontGeneratorFreeType.GetCharImage(const aFont: TtsFont; const aCharCode: WideChar; const aCharImage: TtsImage);
var
font: TtsFontFreeType;
err: FT_Error;
g: FT_GlyphSlot;
b: PFT_Bitmap;

procedure CopyGray;
var
x, y: Integer;
src, dst: PByte;
c: TtsColor4f;
begin
aCharImage.CreateEmpty(font.Renderer.Format, b^.width, b^.rows);
c := tsColor4f(1, 1, 1, 1);
for y := 0 to b^.rows-1 do begin
src := b^.buffer + y * b^.pitch;
dst := aCharImage.Scanline[y];
for x := 0 to b^.width-1 do begin
c.a := src^ / $FF;
inc(src, 1);
tsFormatMap(aCharImage.Format, dst, c);
end;
end;
end;

procedure CopyMono;
var
x, y, i, cnt: Integer;
src, dst: PByte;
tmp: Byte;
c: TtsColor4f;
begin
aCharImage.CreateEmpty(font.Renderer.Format, b^.width, b^.rows);
c := tsColor4f(1, 1, 1, 1);
for y := 0 to b^.rows-1 do begin
src := b^.buffer + y * b^.pitch;
dst := aCharImage.Scanline[y];
x := b^.width;
while (x > 0) do begin
cnt := min(8, x);
tmp := src^;
inc(src, 1);
for i := 1 to cnt do begin
if ((tmp and $80) > 0) then
c.a := 1.0
else
c.a := 0.0;
tmp := (tmp and not $80) shl 1;
tsFormatMap(aCharImage.Format, dst, c);
end;
dec(x, cnt);
end;
end;
end;

begin
font := ConvertFont(aFont);
g := font.fHandle.fFace^.glyph;

if not (font.Properties.AntiAliasing in [tsAANormal, tsAANone]) then
raise Exception.Create('unknown anti aliasing');
case font.Properties.AntiAliasing of
tsAANormal:
err := FT_Load_Char(font.fHandle.fFace, Ord(aCharCode), FT_LOAD_DEFAULT or FT_LOAD_RENDER);
tsAANone:
err := FT_Load_Char(font.fHandle.fFace, Ord(aCharCode), FT_LOAD_MONOCHROME or FT_LOAD_TARGET_MONO or FT_LOAD_RENDER);
end;
if (err <> 0) then
raise EtsException.Create('unable to set glyph metrix: error=' + IntToStr(err));
if (g^.format <> FT_GLYPH_FORMAT_BITMAP) then
raise EtsException.Create('invalid glyph format');

b := @g^.bitmap;
case b^.pixel_mode of
FT_PIXEL_MODE_MONO:
CopyMono;
FT_PIXEL_MODE_GRAY:
CopyGray;
else
raise EtsException.Create('unknown glyph bitmap format');
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TtsFontGeneratorFreeType.GetFontByFile(const aFilename: String; const aRenderer: TtsRenderer;
const aSize: Integer; const aAntiAliasing: TtsAntiAliasing): TtsFont;
var
face: FT_Face;
err: FT_Error;
prop: TtsFontProperties;
begin
err := FT_New_Face(fHandle, PAnsiChar(aFilename), 0, @face);
if (err <> 0) then
raise EtsException.Create('unable to create free type face from file: ' + aFilename + ' error=' + IntToStr(err));

err := FT_Set_Char_Size(face, 0, aSize * FT_SIZE_FACTOR, FT_SIZE_RES, FT_SIZE_RES);
if (err <> 0) then
raise EtsException.Create('unable to set char size: error=' + IntToStr(err));

FillByte(prop, SizeOf(prop), 0);
prop.AntiAliasing := tsAANormal;
prop.FaceName := face^.family_name;
prop.StyleName := face^.style_name;
LoadNames(face, prop);

prop.Size := aSize;
prop.AntiAliasing := aAntiAliasing;
prop.DefaultChar := '?';
prop.Style := [];
if ((face^.style_flags and FT_STYLE_FLAG_BOLD) <> 0) then
Include(prop.Style, tsStyleBold);
if ((face^.style_flags and FT_STYLE_FLAG_ITALIC) <> 0) then
Include(prop.Style, tsStyleItalic);

prop.Ascent := face^.size^.metrics.ascender div FT_SIZE_FACTOR;
prop.Descent := -face^.size^.metrics.descender div FT_SIZE_FACTOR;
prop.ExternalLeading := 0;
prop.BaseLineOffset := 0;

prop.UnderlinePos := face^.underline_position div FT_SIZE_FACTOR;
prop.UnderlineSize := face^.underline_thickness div FT_SIZE_FACTOR;
prop.StrikeoutPos := 0;
prop.StrikeoutSize := 0;

result := TtsFontFreeType.Create(TtsFreeTypeFaceHandle.Create(face), aRenderer, self, prop);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TtsFontGeneratorFreeType.Create(const aContext: TtsContext);
begin
inherited Create(aContext);
fHandle := InitFreeType;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TtsFontGeneratorFreeType.Destroy;
begin
inherited Destroy; // first call interited
QuitFreeType; // QuitFreeType will free callpacks
end;

end.


+ 14
- 326
utsFontCreatorGDI.pas View File

@@ -5,25 +5,10 @@ unit utsFontCreatorGDI;
interface

uses
Classes, SysUtils, syncobjs, dynlibs,
utsTextSuite, utsTypes;
Classes, SysUtils,
utsTextSuite, utsTypes, utsGDI;

type
HDC = Cardinal;

TFixed = packed record
fract: Word;
value: Smallint;
end;

TMat2 = packed record
eM11: TFixed;
eM12: TFixed;
eM21: TFixed;
eM22: TFixed;
end;
PMat2 = ^TMat2;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TtsFontGDI = class(TtsFont)
private
@@ -101,284 +86,6 @@ implementation
uses
math, utsTtfUtils;

const
LIB_GDI32 = 'gdi32.dll';
LIB_KERNEL32 = 'kernel32.dll';

GDI_ERROR = DWORD($FFFFFFFF);

FW_NORMAL = 400;
FW_BOLD = 700;

DEFAULT_CHARSET = 1;

NONANTIALIASED_QUALITY = 3;
ANTIALIASED_QUALITY = 4;

GGO_METRICS = 0;
GGO_BITMAP = 1;
GGO_GRAY8_BITMAP = 6;
GGO_GLYPH_INDEX = $80;

FR_PRIVATE = $10;
FR_NOT_ENUM = $20;

LOCALE_USER_DEFAULT = $0400;
LOCALE_ILANGUAGE = $1;

GCP_MAXEXTENT = $100000;

TMPF_FIXED_PITCH = 1;

type
HFONT = Cardinal;
HGDIOBJ = Cardinal;

TLogFontA = record
lfHeight: Longint;
lfWidth: Longint;
lfEscapement: Longint;
lfOrientation: Longint;
lfWeight: Longint;
lfItalic: Byte;
lfUnderline: Byte;
lfStrikeOut: Byte;
lfCharSet: Byte;
lfOutPrecision: Byte;
lfClipPrecision: Byte;
lfQuality: Byte;
lfPitchAndFamily: Byte;
lfFaceName: array[0..31] of AnsiChar;
end;
PLogFontA = ^TLogFontA;

TTextMetricW = record
tmHeight: Longint;
tmAscent: Longint;
tmDescent: Longint;
tmInternalLeading: Longint;
tmExternalLeading: Longint;
tmAveCharWidth: Longint;
tmMaxCharWidth: Longint;
tmWeight: Longint;
tmOverhang: Longint;
tmDigitizedAspectX: Longint;
tmDigitizedAspectY: Longint;
tmFirstChar: WideChar;
tmLastChar: WideChar;
tmDefaultChar: WideChar;
tmBreakChar: WideChar;
tmItalic: Byte;
tmUnderlined: Byte;
tmStruckOut: Byte;
tmPitchAndFamily: Byte;
tmCharSet: Byte;
end;
PTextMetricW = ^TTextMetricW;

TGlyphMetrics = record
gmBlackBoxX: Cardinal;
gmBlackBoxY: Cardinal;
gmptGlyphOrigin: TtsPosition;
gmCellIncX: Smallint;
gmCellIncY: Smallint;
end;
PGlyphMetrics = ^TGlyphMetrics;

TGCPResultsW = record
lStructSize: DWORD;
lpOutString: PWideChar;
lpOrder: PDWORD;
lpDx: PInteger;
lpCaretPos: PInteger;
lpClass: PChar;
lpGlyphs: PCardinal;
nGlyphs: Cardinal;
nMaxFit: Cardinal;
end;
PGCPResultsW = ^TGCPResultsW;

TPanose = record
bFamilyType: Byte;
bSerifStyle: Byte;
bWeight: Byte;
bProportion: Byte;
bContrast: Byte;
bStrokeVariation: Byte;
bArmStyle: Byte;
bLetterform: Byte;
bMidline: Byte;
bXHeight: Byte;
end;
PPanose = ^TPanose;

TOutlineTextmetricW = record
otmSize: LongWord;
otmTextMetrics: TTextMetricW;
otmFiller: Byte;
otmPanoseNumber: TPanose;
otmfsSelection: LongWord;
otmfsType: LongWord;
otmsCharSlopeRise: Integer;
otmsCharSlopeRun: Integer;
otmItalicAngle: Integer;
otmEMSquare: LongWord;
otmAscent: Integer;
otmDescent: Integer;
otmLineGap: LongWord;
otmsCapEmHeight: LongWord;
otmsXHeight: LongWord;
otmrcFontBox: TtsRect;
otmMacAscent: Integer;
otmMacDescent: Integer;
otmMacLineGap: LongWord;
otmusMinimumPPEM: LongWord;
otmptSubscriptSize: TtsPosition;
otmptSubscriptOffset: TtsPosition;
otmptSuperscriptSize: TtsPosition;
otmptSuperscriptOffset: TtsPosition;
otmsStrikeoutSize: LongWord;
otmsStrikeoutPosition: Integer;
otmsUnderscoreSize: Integer;
otmsUnderscorePosition: Integer;
otmpFamilyName: PWideChar;
otmpFaceName: PWideChar;
otmpStyleName: PWideChar;
otmpFullName: PWideChar;
end;
POutlineTextmetricW = ^TOutlineTextmetricW;

TCreateFontIndirectA = function (const p1: TLogFontA): HFONT; stdcall;

TAddFontResourceA = function(Filename: PAnsiChar): Integer; stdcall;
TAddFontResourceExA = function(Filename: PAnsiChar; Flag: DWORD; pdv: Pointer): Integer; stdcall;
TAddFontMemResourceEx = function(pbFont: Pointer; cbFont: DWORD; pdv: Pointer; pcFonts: PDWORD): THandle; stdcall;
TRemoveFontResourceA = function(Filename: PAnsiChar): Boolean; stdcall;
TRemoveFontResourceExA = function(filename: PAnsiChar; Flag: DWORD; pdv: Pointer): Boolean; stdcall;
TRemoveFontMemResourceEx = function(fh: THandle): Boolean; stdcall;

TGetTextMetricsW = function(DC: HDC; var TM: TTextMetricW): Boolean; stdcall;
TGetGlyphOutlineA = function(DC: HDC; uChar, uFormat: Cardinal; lpgm: PGlyphMetrics; cbBuffer: DWORD; lpvBuffer: Pointer; lpmat2: PMat2): DWORD; stdcall;

TGetCharacterPlacementW = function(DC: HDC; Str: PWideChar; Count, MaxExtent: Integer; Result: PGCPResultsW; Flags: DWORD): DWORD; stdcall;
TGetFontData = function(DC: HDC; TableName, Offset: DWORD; Buffer: Pointer; Data: DWORD): DWORD; stdcall;

TCreateCompatibleDC = function(DC: HDC): HDC; stdcall;
TDeleteDC = function(DC: HDC): Boolean; stdcall;
TSelectObject = function(DC: HDC; p2: HGDIOBJ): HGDIOBJ; stdcall;
TDeleteObject = function(p1: HGDIOBJ): Boolean; stdcall;

TGetOutlineTextMetricsW = function(DC: HDC; p2: LongWord; var OTMetricStructs: TOutlineTextmetricW): LongWord; stdcall;

TGetLocaleInfoA = function(Locale: DWORD; LCType: DWORD; lpLCData: pAnsiChar; cchData: Integer): Integer; stdcall;

var
gdiRefCount: Integer;
gdiCritSec: TCriticalSection;
gdiInitialized: Boolean;
gdiLibHandle: TLibHandle = 0;
kernel32LibHandle: TLibHandle = 0;

CreateFontIndirectA: TCreateFontIndirectA;
AddFontResourceA: TAddFontResourceA;
AddFontResourceExA: TAddFontResourceExA;
AddFontMemResourceEx: TAddFontMemResourceEx;
RemoveFontResourceA: TRemoveFontResourceA;
RemoveFontResourceExA: TRemoveFontResourceExA;
RemoveFontMemResourceEx: TRemoveFontMemResourceEx;
GetTextMetricsW: TGetTextMetricsW;
GetGlyphOutlineA: TGetGlyphOutlineA;
GetCharacterPlacementW: TGetCharacterPlacementW;
GetFontData: TGetFontData;
CreateCompatibleDC: TCreateCompatibleDC;
DeleteDC: TDeleteDC;
SelectObject: TSelectObject;
DeleteObject: TDeleteObject;
GetOutlineTextMetricsW: TGetOutlineTextMetricsW;

GetLocaleInfoA: TGetLocaleInfoA;

procedure InitGDI;

function GetProcAddr(const aLibHandle: TLibHandle; const aName: String): Pointer;
begin
result := GetProcAddress(aLibHandle, aName);
if not Assigned(result) then
raise EtsException.Create('unable to load procedure from library: ' + aName);
end;

begin
try
if (gdiLibHandle = 0) then begin
gdiLibHandle := LoadLibrary(LIB_GDI32);
if (gdiLibHandle = 0) then
raise EtsException.Create('unable to load gdi lib: ' + LIB_GDI32);
end;

if (kernel32LibHandle = 0) then begin
kernel32LibHandle := LoadLibrary(LIB_KERNEL32);
if (kernel32LibHandle = 0) then
raise EtsException.Create('unable to load kernel lib: ' + LIB_KERNEL32);
end;

CreateFontIndirectA := TCreateFontIndirectA( GetProcAddr(gdiLibHandle, 'CreateFontIndirectA'));
AddFontResourceA := TAddFontResourceA( GetProcAddr(gdiLibHandle, 'AddFontResourceA'));
AddFontResourceExA := TAddFontResourceExA( GetProcAddr(gdiLibHandle, 'AddFontResourceExA'));
AddFontMemResourceEx := TAddFontMemResourceEx( GetProcAddr(gdiLibHandle, 'AddFontMemResourceEx'));
RemoveFontResourceA := TRemoveFontResourceA( GetProcAddr(gdiLibHandle, 'RemoveFontResourceA'));
RemoveFontResourceExA := TRemoveFontResourceExA( GetProcAddr(gdiLibHandle, 'RemoveFontResourceExA'));
RemoveFontMemResourceEx := TRemoveFontMemResourceEx(GetProcAddr(gdiLibHandle, 'RemoveFontMemResourceEx'));
GetTextMetricsW := TGetTextMetricsW( GetProcAddr(gdiLibHandle, 'GetTextMetricsW'));
GetGlyphOutlineA := TGetGlyphOutlineA( GetProcAddr(gdiLibHandle, 'GetGlyphOutlineA'));
GetCharacterPlacementW := TGetCharacterPlacementW( GetProcAddr(gdiLibHandle, 'GetCharacterPlacementW'));
GetFontData := TGetFontData( GetProcAddr(gdiLibHandle, 'GetFontData'));
CreateCompatibleDC := TCreateCompatibleDC( GetProcAddr(gdiLibHandle, 'CreateCompatibleDC'));
DeleteDC := TDeleteDC( GetProcAddr(gdiLibHandle, 'DeleteDC'));
SelectObject := TSelectObject( GetProcAddr(gdiLibHandle, 'SelectObject'));
DeleteObject := TDeleteObject( GetProcAddr(gdiLibHandle, 'DeleteObject'));
GetOutlineTextMetricsW := TGetOutlineTextMetricsW( GetProcAddr(gdiLibHandle, 'GetOutlineTextMetricsW'));

GetLocaleInfoA := TGetLocaleInfoA(GetProcAddr(kernel32LibHandle, 'GetLocaleInfoA'));

gdiInitialized := true;
except
gdiInitialized := false;
FreeLibrary(gdiLibHandle);
FreeLibrary(kernel32LibHandle);
end;
end;

procedure QuitGDI;
begin
CreateFontIndirectA := nil;
AddFontResourceA := nil;
AddFontResourceExA := nil;
RemoveFontResourceA := nil;
RemoveFontResourceExA := nil;
GetTextMetricsW := nil;
GetGlyphOutlineA := nil;
GetCharacterPlacementW := nil;
GetFontData := nil;
CreateCompatibleDC := nil;
DeleteDC := nil;
SelectObject := nil;
DeleteObject := nil;

GetLocaleInfoA := nil;

if (gdiLibHandle <> 0) then begin
FreeLibrary(gdiLibHandle);
gdiLibHandle := 0;
end;

if (kernel32LibHandle <> 0) then begin
FreeLibrary(kernel32LibHandle);
kernel32LibHandle := 0;
end;

gdiInitialized := false;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TtsFontGDI////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -853,11 +560,16 @@ var
prop: TtsFontProperties;
begin
reg := TtsFontRegistrationFile.Create(aFilename);
if not reg.IsRegistered then
raise EtsException.Create('unable to register font file: ' + aFilename);
handle := CreateFont(reg.Fontname, aSize, aStyle, aAntiAliasing, prop);
if (handle = 0) then
raise EtsException.Create('unable to create font from file: ' + aFilename);
try
if not reg.IsRegistered then
raise EtsException.Create('unable to register font file: ' + aFilename);
handle := CreateFont(reg.Fontname, aSize, aStyle, aAntiAliasing, prop);
if (handle = 0) then
raise EtsException.Create('unable to create font from file: ' + aFilename);
except
FreeAndNil(reg);
raise;
end;
result := TtsRegistredFontGDI.Create(aRenderer, self, reg, prop, handle);
end;

@@ -882,38 +594,14 @@ end;
constructor TtsFontGeneratorGDI.Create(const aContext: TtsContext);
begin
inherited Create(aContext);
gdiCritSec.Enter;
try
inc(gdiRefCount, 1);
if not gdiInitialized then
InitGDI;
finally
gdiCritSec.Leave;
end;
InitGDI;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TtsFontGeneratorGDI.Destroy;
begin
inherited Destroy; // first free all fonts (managed by parent class)
gdiCritSec.Enter;
try
dec(gdiRefCount, 1);
if (gdiRefCount <= 0) then
QuitGDI;
finally
gdiCritSec.Leave;
end;
QuitGDI;
end;

initialization
gdiRefCount := 0;
gdiInitialized := false;
gdiCritSec := TCriticalSection.Create;

finalization
if gdiInitialized then
QuitGDI;
FreeAndNil(gdiCritSec);

end.

+ 607
- 0
utsFreeType.pas View File

@@ -0,0 +1,607 @@
unit utsFreeType;

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils, syncobjs, dynlibs, utsTextSuite;

type
// Simple Types
FT_Error = Integer;
FT_Library = Pointer;
FT_Short = ShortInt;
FT_UShort = Word;
FT_Int = Integer;
FT_Int32 = Integer;
FT_UInt = Cardinal;
FT_Long = LongInt;
FT_ULong = Cardinal;
FT_Fixed = LongInt;
FT_Pos = LongInt;
FT_F26Dot6 = LongInt;
FT_String = AnsiChar;

// Enums
FT_Encoding = Integer;
FT_Glyph_Format = Integer;

// Pointer
FT_Face = ^FT_FaceRec;
FT_GlyphSlot = ^FT_GlyphSlotRec;
FT_Size = ^FT_SizeRec;
FT_CharMap = ^FT_CharMapRec;

PFT_Library = ^FT_Library;
PFT_Face = ^FT_Face;
PFT_String = ^FT_String;
PFT_SfntName = ^FT_SfntName;
PFT_Bitmap = ^FT_Bitmap;

// unneeded
FT_Driver = Pointer;
FT_Memory = Pointer;
FT_Stream = Pointer;
FT_ListNode = Pointer;
FT_Face_Internal = Pointer;
FT_SubGlyph = Pointer;
FT_Slot_Internal = Pointer;
FT_Size_Internal = Pointer;

FT_Generic_Finalizer = procedure(aObject: Pointer);

FT_Generic = record
data: Pointer;
finalizer: FT_Generic_Finalizer;
end;

FT_BBox = record
xMin, yMin, xMax, yMax: FT_Pos;
end;

FT_Vector = record
x, y: FT_Pos;
end;

FT_ListRec = record
head: FT_ListNode;
tail: FT_ListNode;
end;

FT_CharMapRec = record
face: FT_Face;
encoding: FT_Encoding;
platform_id: FT_UShort;
encoding_id: FT_UShort;
end;

FT_Size_Metrics = record
x_ppem: FT_UShort;
y_ppem: FT_UShort;

x_scale: FT_Fixed;
y_scale: FT_Fixed;

ascender: FT_Pos;
descender: FT_Pos;
height: FT_Pos;
max_advance: FT_Pos;
end;

FT_SizeRec = record
face: FT_Face;
generic_: FT_Generic;
metrics: FT_Size_Metrics;
internal: FT_Size_Internal;
end;

FT_Glyph_Metrics = record
width: FT_Pos;
height: FT_Pos;

horiBearingX: FT_Pos;
horiBearingY: FT_Pos;
horiAdvance: FT_Pos;

vertBearingX: FT_Pos;
vertBearingY: FT_Pos;
vertAdvance: FT_Pos;
end;

FT_Bitmap_Size = record
height: FT_Short;
width: FT_Short;

size: FT_Pos;

x_ppem: FT_Pos;
y_ppem: FT_Pos;
end;

FT_Bitmap = record
rows: Integer;
width: Integer;
pitch: Integer;
buffer: PByte;
num_grays: ShortInt;
pixel_mode: Byte;
palette_mode: Byte;
palette: Pointer;
end;

FT_Outline = record
n_contours: ShortInt;
n_points: ShortInt;

points: ^FT_Vector;
tags: PByte;
contours: PShortInt;

flags: Integer;
end;

FT_GlyphSlotRec = record
library_: FT_Library;
face: FT_Face;
next: FT_GlyphSlot;
reserved: FT_UInt;
generic_: FT_Generic;

metrics: FT_Glyph_Metrics;
linearHoriAdvance: FT_Fixed;
linearVertAdvance: FT_Fixed;
advance: FT_Vector;

format: FT_Glyph_Format;

bitmap: FT_Bitmap;
bitmap_left: FT_Int;
bitmap_top: FT_Int;

outline: FT_Outline;

num_subglyphs: FT_UInt;
subglyphs: FT_SubGlyph;

control_data: Pointer;
control_len: LongInt;

lsb_delta: FT_Pos;
rsb_delta: FT_Pos;

other: Pointer;

internal: FT_Slot_Internal;
end;

FT_FaceRec = record
num_faces: FT_Long;
face_index: FT_Long;

face_flags: FT_Long;
style_flags: FT_Long;

num_glyphs: FT_Long;

family_name: PFT_String;
style_name: PFT_String;

num_fixed_sizes: FT_Int;
available_sizes: ^FT_Bitmap_Size;

num_charmaps: FT_Int;
charmaps: ^FT_CharMap;

generic_: FT_Generic;

bbox: FT_BBox;

units_per_EM: FT_UShort;
ascender: FT_Short;
descender: FT_Short;
height: FT_Short;

max_advance_width: FT_Short;
max_advance_height: FT_Short;

underline_position: FT_Short;
underline_thickness: FT_Short;

glyph: FT_GlyphSlot;
size: FT_Size;
charmap: FT_CharMap;

{ private }
driver: FT_Driver;
memory: FT_Memory;
stream: FT_Stream;
sizes_list: FT_ListRec;
autohint: FT_Generic;
extensions: Pointer;
internal: FT_Face_Internal;
{ private end }
end;

FT_SfntName = record
platform_id: FT_UShort;
encoding_id: FT_UShort;
language_id: FT_UShort;
name_id: FT_UShort;

string_: PByte;
string_len: FT_UInt;
end;

TFT_Init_FreeType = function(aLibrary: PFT_Library): FT_Error;
TFT_Done_FreeType = function(aLibrary: FT_Library): FT_Error;
TFT_New_Face = function(aLibrary: FT_Library; const aFilename: PAnsiChar; aFaceIndex: FT_Long; aFace: PFT_Face): FT_Error;
TFT_Done_Face = function(aFace: FT_Face): FT_Error;

TFT_Get_Sfnt_Name_Count = function(aFace: FT_Face): FT_UInt;
TFT_Get_Sfnt_Name = function(aFace: FT_Face; aIndex: FT_UInt; aName: PFT_SfntName): FT_Error;

TFT_Set_Char_Size = function(aFace: FT_Face; aCharWidth: FT_F26Dot6; aCharHeight: FT_F26Dot6; aHorzDPI: FT_UInt; aVertDPI: FT_UInt): FT_Error;
TFT_Load_Char = function(aFace: FT_Face; aCharCode: FT_ULong; aLoadFlags: FT_Int32): FT_Error;

var
FT_Init_FreeType: TFT_Init_FreeType;
FT_Done_FreeType: TFT_Done_FreeType;
FT_New_Face: TFT_New_Face;
FT_Done_Face: TFT_Done_Face;

FT_Get_Sfnt_Name_Count: TFT_Get_Sfnt_Name_Count;
FT_Get_Sfnt_Name: TFT_Get_Sfnt_Name;

FT_Set_Char_Size: TFT_Set_Char_Size;
FT_Load_Char: TFT_Load_Char;

const
TT_NAME_ID_COPYRIGHT = 0;
TT_NAME_ID_FONT_FAMILY = 1;
TT_NAME_ID_FONT_SUBFAMILY = 2;
TT_NAME_ID_UNIQUE_ID = 3;
TT_NAME_ID_FULL_NAME = 4;
TT_NAME_ID_VERSION_STRING = 5;
TT_NAME_ID_PS_NAME = 6;
TT_NAME_ID_TRADEMARK = 7;

TT_PLATFORM_APPLE_UNICODE = 0;
TT_PLATFORM_MACINTOSH = 1;
TT_PLATFORM_ISO = 2; // deprecated
TT_PLATFORM_MICROSOFT = 3;
TT_PLATFORM_CUSTOM = 4;
TT_PLATFORM_ADOBE = 7; // artificial

TT_ISO_ID_7BIT_ASCII = 0;
TT_ISO_ID_10646 = 1;
TT_ISO_ID_8859_1 = 2;

TT_APPLE_ID_DEFAULT = 0; // Unicode 1.0
TT_APPLE_ID_UNICODE_1_1 = 1; // specify Hangul at U+34xx
TT_APPLE_ID_ISO_10646 = 2; // deprecated
TT_APPLE_ID_UNICODE_2_0 = 3; // or later
TT_APPLE_ID_UNICODE_32 = 4; // 2.0 or later, full repertoire

TT_MAC_ID_ROMAN = 0;
TT_MAC_ID_JAPANESE = 1;
TT_MAC_ID_TRADITIONAL_CHINESE = 2;
TT_MAC_ID_KOREAN = 3;
TT_MAC_ID_ARABIC = 4;
TT_MAC_ID_HEBREW = 5;
TT_MAC_ID_GREEK = 6;
TT_MAC_ID_RUSSIAN = 7;
TT_MAC_ID_RSYMBOL = 8;
TT_MAC_ID_DEVANAGARI = 9;
TT_MAC_ID_GURMUKHI = 10;
TT_MAC_ID_GUJARATI = 11;
TT_MAC_ID_ORIYA = 12;
TT_MAC_ID_BENGALI = 13;
TT_MAC_ID_TAMIL = 14;
TT_MAC_ID_TELUGU = 15;
TT_MAC_ID_KANNADA = 16;
TT_MAC_ID_MALAYALAM = 17;
TT_MAC_ID_SINHALESE = 18;
TT_MAC_ID_BURMESE = 19;
TT_MAC_ID_KHMER = 20;
TT_MAC_ID_THAI = 21;
TT_MAC_ID_LAOTIAN = 22;
TT_MAC_ID_GEORGIAN = 23;
TT_MAC_ID_ARMENIAN = 24;
TT_MAC_ID_MALDIVIAN = 25;
TT_MAC_ID_SIMPLIFIED_CHINESE = 25;
TT_MAC_ID_TIBETAN = 26;
TT_MAC_ID_MONGOLIAN = 27;
TT_MAC_ID_GEEZ = 28;
TT_MAC_ID_SLAVIC = 29;
TT_MAC_ID_VIETNAMESE = 30;
TT_MAC_ID_SINDHI = 31;
TT_MAC_ID_UNINTERP = 32;

FT_LOAD_DEFAULT = 0;
FT_LOAD_NO_SCALE = ( 1 shl 0 );
FT_LOAD_NO_HINTING = ( 1 shl 1 );
FT_LOAD_RENDER = ( 1 shl 2 );
FT_LOAD_NO_BITMAP = ( 1 shl 3 );
FT_LOAD_VERTICAL_LAYOUT = ( 1 shl 4 );
FT_LOAD_FORCE_AUTOHINT = ( 1 shl 5 );
FT_LOAD_CROP_BITMAP = ( 1 shl 6 );
FT_LOAD_PEDANTIC = ( 1 shl 7 );
FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH = ( 1 shl 9 );
FT_LOAD_NO_RECURSE = ( 1 shl 10 );
FT_LOAD_IGNORE_TRANSFORM = ( 1 shl 11 );
FT_LOAD_MONOCHROME = ( 1 shl 12 );
FT_LOAD_LINEAR_DESIGN = ( 1 shl 13 );
FT_LOAD_NO_AUTOHINT = ( 1 shl 15 );
FT_LOAD_COLOR = ( 1 shl 20 );

FT_GLYPH_FORMAT_NONE = 0;
FT_GLYPH_FORMAT_COMPOSITE = (Ord('c') shl 24) or
(Ord('o') shl 16) or
(Ord('m') shl 8) or
(Ord('p'));
FT_GLYPH_FORMAT_BITMAP = (Ord('b') shl 24) or
(Ord('i') shl 16) or
(Ord('t') shl 8) or
(Ord('s'));
FT_GLYPH_FORMAT_OUTLINE = (Ord('o') shl 24) or
(Ord('u') shl 16) or
(Ord('t') shl 8) or
(Ord('l'));
FT_GLYPH_FORMAT_PLOTTER = (Ord('p') shl 24) or
(Ord('l') shl 16) or
(Ord('o') shl 8) or
(Ord('t'));

//FT_PIXEL_MODE_NONE = 0;
FT_PIXEL_MODE_MONO = 0;
FT_PIXEL_MODE_GRAY = 1;
FT_PIXEL_MODE_GRAY2 = 2;
FT_PIXEL_MODE_GRAY4 = 3;
FT_PIXEL_MODE_LCD = 4;
FT_PIXEL_MODE_LCD_V = 5;
FT_PIXEL_MODE_BGRA = 6;

FT_ERR_Ok = $00;
FT_ERR_None = $00;

FT_ERR_Cannot_Open_Resource = $01;
FT_ERR_Unknown_File_Format = $02;
FT_ERR_Invalid_File_Format = $03;
FT_ERR_Invalid_Version = $04;
FT_ERR_Lower_Module_Version = $05;
FT_ERR_Invalid_Argument = $06;
FT_ERR_Unimplemented_Feature = $07;
FT_ERR_Invalid_Table = $08;
FT_ERR_Invalid_Offset = $09;
FT_ERR_Array_Too_Large = $0A;

{ glyph/character errors }
FT_ERR_Invalid_Glyph_Index = $10;
FT_ERR_Invalid_Character_Code = $11;
FT_ERR_Invalid_Glyph_Format = $12;
FT_ERR_Cannot_Render_Glyph = $13;
FT_ERR_Invalid_Outline = $14;
FT_ERR_Invalid_Composite = $15;
FT_ERR_Too_Many_Hints = $16;
FT_ERR_Invalid_Pixel_Size = $17;

{ handle errors }
FT_ERR_Invalid_Handle = $20;
FT_ERR_Invalid_Library_Handle = $21;
FT_ERR_Invalid_Driver_Handle = $22;
FT_ERR_Invalid_Face_Handle = $23;
FT_ERR_Invalid_Size_Handle = $24;
FT_ERR_Invalid_Slot_Handle = $25;
FT_ERR_Invalid_CharMap_Handle = $26;
FT_ERR_Invalid_Cache_Handle = $27;
FT_ERR_Invalid_Stream_Handle = $28;

{ driver errors }
FT_ERR_Too_Many_Drivers = $30;
FT_ERR_Too_Many_Extensions = $31;

{ memory errors }
FT_ERR_Out_Of_Memory = $40;
FT_ERR_Unlisted_Object = $41;

{ stream errors }
FT_ERR_Cannot_Open_Stream = $51;
FT_ERR_Invalid_Stream_Seek = $52;
FT_ERR_Invalid_Stream_Skip = $53;
FT_ERR_Invalid_Stream_Read = $54;
FT_ERR_Invalid_Stream_Operation = $55;
FT_ERR_Invalid_Frame_Operation = $56;
FT_ERR_Nested_Frame_Access = $57;
FT_ERR_Invalid_Frame_Read = $58;

{ raster errors }
FT_ERR_Raster_Uninitialized = $60;
FT_ERR_Raster_Corrupted = $61;
FT_ERR_Raster_Overflow = $62;
FT_ERR_Raster_Negative_Height = $63;

{ cache errors }
FT_ERR_Too_Many_Caches = $70;

{ TrueType and SFNT errors }
FT_ERR_Invalid_Opcode = $80;
FT_ERR_Too_Few_Arguments = $81;
FT_ERR_Stack_Overflow = $82;
FT_ERR_Code_Overflow = $83;
FT_ERR_Bad_Argument = $84;
FT_ERR_Divide_By_Zero = $85;
FT_ERR_Invalid_Reference = $86;
FT_ERR_Debug_OpCode = $87;
FT_ERR_ENDF_In_Exec_Stream = $88;
FT_ERR_Nested_DEFS = $89;
FT_ERR_Invalid_CodeRange = $8A;
FT_ERR_Execution_Too_Long = $8B;
FT_ERR_Too_Many_Function_Defs = $8C;
FT_ERR_Too_Many_Instruction_Defs = $8D;
FT_ERR_Table_Missing = $8E;
FT_ERR_Horiz_Header_Missing = $8F;
FT_ERR_Locations_Missing = $90;
FT_ERR_Name_Table_Missing = $91;
FT_ERR_CMap_Table_Missing = $92;
FT_ERR_Hmtx_Table_Missing = $93;
FT_ERR_Post_Table_Missing = $94;
FT_ERR_Invalid_Horiz_Metrics = $95;
FT_ERR_Invalid_CharMap_Format = $96;
FT_ERR_Invalid_PPem = $97;
FT_ERR_Invalid_Vert_Metrics = $98;
FT_ERR_Could_Not_Find_Context = $99;
FT_ERR_Invalid_Post_Table_Format = $9A;
FT_ERR_Invalid_Post_Table = $9B;

{ CFF CID and Type 1 errors }
FT_ERR_Syntax_Error = $A0;
FT_ERR_Stack_Underflow = $A1;
FT_ERR_Ignore = $A2;

{ BDF errors }
FT_ERR_Missing_Startfont_Field = $B0;
FT_ERR_Missing_Font_Field = $B1;
FT_ERR_Missing_Size_Field = $B2;
FT_ERR_Missing_Chars_Field = $B3;
FT_ERR_Missing_Startchar_Field = $B4;
FT_ERR_Missing_Encoding_Field = $B5;
FT_ERR_Missing_Bbx_Field = $B6;
FT_ERR_Bbx_Too_Big = $B7;
FT_ERR_Corrupted_Font_Header = $B8;
FT_ERR_Corrupted_Font_Glyphs = $B9;

FT_STYLE_FLAG_ITALIC = (1 shl 0);
FT_STYLE_FLAG_BOLD = (1 shl 1);

FT_RENDER_MODE_NORMAL = 0;
FT_RENDER_MODE_LIGHT = 1;
FT_RENDER_MODE_MONO = 2;
FT_RENDER_MODE_LCD = 3;
FT_RENDER_MODE_LCD_V = 4;

FT_LOAD_TARGET_NORMAL = FT_RENDER_MODE_NORMAL shl 16;
FT_LOAD_TARGET_LIGHT = FT_RENDER_MODE_LIGHT shl 16;
FT_LOAD_TARGET_MONO = FT_RENDER_MODE_MONO shl 16;
FT_LOAD_TARGET_LCD = FT_RENDER_MODE_LCD shl 16;
FT_LOAD_TARGET_LCD_V = FT_RENDER_MODE_LCD_V shl 16;

function InitFreeType: FT_Library;
procedure QuitFreeType;

implementation

{$IFDEF WINDOWS}
{$IFDEF WIN32}
{$DEFINE TS_FT_WIN32}
{$ELSE}
{$DEFINE TS_FT_WIN64}
{$ENDIF}
{$ELSE}
{$DEFINE TS_FT_LINUX}
{$ENDIF}

const
{$IF DEFINED(TS_FT_WIN32)}
LIB_FREE_TYPE = 'freetype6-x86.dll';
{$ELSEIF DEFINED(TS_FT_WIN64)}
LIB_FREE_TYPE = 'freetype6-x64.dll';
{$ELSEIF DEFINED(TS_FT_LINUX)}
LIB_FREE_TYPE = ???
{$ELSE}
{$ERROR 'unknown/unsupported OS'}
{$IFEND}

var
FreeTypeInitialized: Boolean;
FreeTypeRefCount: Integer;
FreeTypeCritSec: TCriticalSection;
FreeTypeLibHandle: TLibHandle = 0;

ftLibrary: FT_Library;

function InitFreeType: FT_Library;

function GetProcAddr(const aName: String): Pointer;
begin
result := GetProcAddress(FreeTypeLibHandle, aName);
if not Assigned(result) then
raise EtsException.Create('unable to load procedure from library: ' + aName);
end;

var
err: FT_Error;
begin
result := nil;
FreeTypeCritSec.Enter;
try try
inc(FreeTypeRefCount, 1);
if FreeTypeInitialized then
exit;

if (FreeTypeLibHandle = 0) then begin
FreeTypeLibHandle := LoadLibrary(LIB_FREE_TYPE);
if (FreeTypeLibHandle = 0) then
raise EtsException.Create('unable to load free type lib: ' + LIB_FREE_TYPE + ' error=' + IntToStr(GetLastOSError));
end;

FT_Init_FreeType := TFT_Init_FreeType(GetProcAddr('FT_Init_FreeType'));
FT_Done_FreeType := TFT_Done_FreeType(GetProcAddr('FT_Done_FreeType'));
FT_New_Face := TFT_New_Face( GetProcAddr('FT_New_Face'));
FT_Done_Face := TFT_Done_Face( GetProcAddr('FT_Done_Face'));

FT_Get_Sfnt_Name_Count := TFT_Get_Sfnt_Name_Count(GetProcAddr('FT_Get_Sfnt_Name_Count'));
FT_Get_Sfnt_Name := TFT_Get_Sfnt_Name( GetProcAddr('FT_Get_Sfnt_Name'));

FT_Set_Char_Size := TFT_Set_Char_Size(GetProcAddr('FT_Set_Char_Size'));
FT_Load_Char := TFT_Load_Char( GetProcAddr('FT_Load_Char'));

err := FT_Init_FreeType(@ftLibrary);
if (err <> 0) then
raise EtsException.Create('unable to create free type library handle: ' + IntToStr(err));

FreeTypeInitialized := true;
result := ftLibrary;
except
FreeTypeInitialized := false;
end;
finally
FreeTypeCritSec.Leave;
end;
end;

procedure QuitFreeType;
begin
FreeTypeCritSec.Enter;
try
dec(FreeTypeRefCount, 1);
if (FreeTypeRefCount > 0) then
exit;

FT_Done_FreeType(ftLibrary);

FT_Init_FreeType := nil;
FT_Done_FreeType := nil;

if (FreeTypeLibHandle <> 0) then begin
FreeLibrary(FreeTypeLibHandle);
FreeTypeLibHandle := 0;
end;
FreeTypeInitialized := false;
finally
FreeTypeCritSec.Leave;
end;
end;

initialization
FreeTypeRefCount := 0;
FreeTypeInitialized := false;
FreeTypeCritSec := TCriticalSection.Create;

finalization
if FreeTypeInitialized then
QuitFreeType;
FreeAndNil(FreeTypeCritSec);

end.


+ 342
- 0
utsGDI.pas View File

@@ -0,0 +1,342 @@
unit utsGDI;

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils, utsTypes, syncobjs, dynlibs;

type
HDC = Cardinal;

TFixed = packed record
fract: Word;
value: Smallint;
end;

TMat2 = packed record
eM11: TFixed;
eM12: TFixed;
eM21: TFixed;
eM22: TFixed;
end;
PMat2 = ^TMat2;


const
GDI_ERROR = DWORD($FFFFFFFF);

FW_NORMAL = 400;
FW_BOLD = 700;

DEFAULT_CHARSET = 1;

NONANTIALIASED_QUALITY = 3;
ANTIALIASED_QUALITY = 4;

GGO_METRICS = 0;
GGO_BITMAP = 1;
GGO_GRAY8_BITMAP = 6;
GGO_GLYPH_INDEX = $80;

FR_PRIVATE = $10;
FR_NOT_ENUM = $20;

LOCALE_USER_DEFAULT = $0400;
LOCALE_ILANGUAGE = $1;

GCP_MAXEXTENT = $100000;

TMPF_FIXED_PITCH = 1;

type
HFONT = Cardinal;
HGDIOBJ = Cardinal;

TLogFontA = record
lfHeight: Longint;
lfWidth: Longint;
lfEscapement: Longint;
lfOrientation: Longint;
lfWeight: Longint;
lfItalic: Byte;
lfUnderline: Byte;
lfStrikeOut: Byte;
lfCharSet: Byte;
lfOutPrecision: Byte;
lfClipPrecision: Byte;
lfQuality: Byte;
lfPitchAndFamily: Byte;
lfFaceName: array[0..31] of AnsiChar;
end;
PLogFontA = ^TLogFontA;

TTextMetricW = record
tmHeight: Longint;
tmAscent: Longint;
tmDescent: Longint;
tmInternalLeading: Longint;
tmExternalLeading: Longint;
tmAveCharWidth: Longint;
tmMaxCharWidth: Longint;
tmWeight: Longint;
tmOverhang: Longint;
tmDigitizedAspectX: Longint;
tmDigitizedAspectY: Longint;
tmFirstChar: WideChar;
tmLastChar: WideChar;
tmDefaultChar: WideChar;
tmBreakChar: WideChar;
tmItalic: Byte;
tmUnderlined: Byte;
tmStruckOut: Byte;
tmPitchAndFamily: Byte;
tmCharSet: Byte;
end;
PTextMetricW = ^TTextMetricW;

TGlyphMetrics = record
gmBlackBoxX: Cardinal;
gmBlackBoxY: Cardinal;
gmptGlyphOrigin: TtsPosition;
gmCellIncX: Smallint;
gmCellIncY: Smallint;
end;
PGlyphMetrics = ^TGlyphMetrics;

TGCPResultsW = record
lStructSize: DWORD;
lpOutString: PWideChar;
lpOrder: PDWORD;
lpDx: PInteger;
lpCaretPos: PInteger;
lpClass: PChar;
lpGlyphs: PCardinal;
nGlyphs: Cardinal;
nMaxFit: Cardinal;
end;
PGCPResultsW = ^TGCPResultsW;

TPanose = record
bFamilyType: Byte;
bSerifStyle: Byte;
bWeight: Byte;
bProportion: Byte;
bContrast: Byte;
bStrokeVariation: Byte;
bArmStyle: Byte;
bLetterform: Byte;
bMidline: Byte;
bXHeight: Byte;
end;
PPanose = ^TPanose;

TOutlineTextmetricW = record
otmSize: LongWord;
otmTextMetrics: TTextMetricW;
otmFiller: Byte;
otmPanoseNumber: TPanose;
otmfsSelection: LongWord;
otmfsType: LongWord;
otmsCharSlopeRise: Integer;
otmsCharSlopeRun: Integer;
otmItalicAngle: Integer;
otmEMSquare: LongWord;
otmAscent: Integer;
otmDescent: Integer;
otmLineGap: LongWord;
otmsCapEmHeight: LongWord;
otmsXHeight: LongWord;
otmrcFontBox: TtsRect;
otmMacAscent: Integer;
otmMacDescent: Integer;
otmMacLineGap: LongWord;
otmusMinimumPPEM: LongWord;
otmptSubscriptSize: TtsPosition;
otmptSubscriptOffset: TtsPosition;
otmptSuperscriptSize: TtsPosition;
otmptSuperscriptOffset: TtsPosition;
otmsStrikeoutSize: LongWord;
otmsStrikeoutPosition: Integer;
otmsUnderscoreSize: Integer;
otmsUnderscorePosition: Integer;
otmpFamilyName: PWideChar;
otmpFaceName: PWideChar;
otmpStyleName: PWideChar;
otmpFullName: PWideChar;
end;
POutlineTextmetricW = ^TOutlineTextmetricW;

TCreateFontIndirectA = function (const p1: TLogFontA): HFONT; stdcall;

TAddFontResourceA = function(Filename: PAnsiChar): Integer; stdcall;
TAddFontResourceExA = function(Filename: PAnsiChar; Flag: DWORD; pdv: Pointer): Integer; stdcall;
TAddFontMemResourceEx = function(pbFont: Pointer; cbFont: DWORD; pdv: Pointer; pcFonts: PDWORD): THandle; stdcall;
TRemoveFontResourceA = function(Filename: PAnsiChar): Boolean; stdcall;
TRemoveFontResourceExA = function(filename: PAnsiChar; Flag: DWORD; pdv: Pointer): Boolean; stdcall;
TRemoveFontMemResourceEx = function(fh: THandle): Boolean; stdcall;

TGetTextMetricsW = function(DC: HDC; var TM: TTextMetricW): Boolean; stdcall;
TGetGlyphOutlineA = function(DC: HDC; uChar, uFormat: Cardinal; lpgm: PGlyphMetrics; cbBuffer: DWORD; lpvBuffer: Pointer; lpmat2: PMat2): DWORD; stdcall;

TGetCharacterPlacementW = function(DC: HDC; Str: PWideChar; Count, MaxExtent: Integer; Result: PGCPResultsW; Flags: DWORD): DWORD; stdcall;
TGetFontData = function(DC: HDC; TableName, Offset: DWORD; Buffer: Pointer; Data: DWORD): DWORD; stdcall;

TCreateCompatibleDC = function(DC: HDC): HDC; stdcall;
TDeleteDC = function(DC: HDC): Boolean; stdcall;
TSelectObject = function(DC: HDC; p2: HGDIOBJ): HGDIOBJ; stdcall;
TDeleteObject = function(p1: HGDIOBJ): Boolean; stdcall;

TGetOutlineTextMetricsW = function(DC: HDC; p2: LongWord; var OTMetricStructs: TOutlineTextmetricW): LongWord; stdcall;

TGetLocaleInfoA = function(Locale: DWORD; LCType: DWORD; lpLCData: pAnsiChar; cchData: Integer): Integer; stdcall;

var
CreateFontIndirectA: TCreateFontIndirectA;
AddFontResourceA: TAddFontResourceA;
AddFontResourceExA: TAddFontResourceExA;
AddFontMemResourceEx: TAddFontMemResourceEx;
RemoveFontResourceA: TRemoveFontResourceA;
RemoveFontResourceExA: TRemoveFontResourceExA;
RemoveFontMemResourceEx: TRemoveFontMemResourceEx;
GetTextMetricsW: TGetTextMetricsW;
GetGlyphOutlineA: TGetGlyphOutlineA;
GetCharacterPlacementW: TGetCharacterPlacementW;
GetFontData: TGetFontData;
CreateCompatibleDC: TCreateCompatibleDC;
DeleteDC: TDeleteDC;
SelectObject: TSelectObject;
DeleteObject: TDeleteObject;
GetOutlineTextMetricsW: TGetOutlineTextMetricsW;

GetLocaleInfoA: TGetLocaleInfoA;

procedure InitGDI;
procedure QuitGDI;

implementation

uses
utsTextSuite;

const
LIB_GDI32 = 'gdi32.dll';
LIB_KERNEL32 = 'kernel32.dll';

var
gdiRefCount: Integer;
gdiCritSec: TCriticalSection;
gdiInitialized: Boolean;
gdiLibHandle: TLibHandle = 0;
kernel32LibHandle: TLibHandle = 0;

procedure InitGDI;

function GetProcAddr(const aLibHandle: TLibHandle; const aName: String): Pointer;
begin
result := GetProcAddress(aLibHandle, aName);
if not Assigned(result) then
raise EtsException.Create('unable to load procedure from library: ' + aName);
end;

begin
gdiCritSec.Enter;
try try
inc(gdiRefCount, 1);
if gdiInitialized then
exit;

if (gdiLibHandle = 0) then begin
gdiLibHandle := LoadLibrary(LIB_GDI32);
if (gdiLibHandle = 0) then
raise EtsException.Create('unable to load gdi lib: ' + LIB_GDI32);
end;

if (kernel32LibHandle = 0) then begin
kernel32LibHandle := LoadLibrary(LIB_KERNEL32);
if (kernel32LibHandle = 0) then
raise EtsException.Create('unable to load kernel lib: ' + LIB_KERNEL32);
end;

CreateFontIndirectA := TCreateFontIndirectA( GetProcAddr(gdiLibHandle, 'CreateFontIndirectA'));
AddFontResourceA := TAddFontResourceA( GetProcAddr(gdiLibHandle, 'AddFontResourceA'));
AddFontResourceExA := TAddFontResourceExA( GetProcAddr(gdiLibHandle, 'AddFontResourceExA'));
AddFontMemResourceEx := TAddFontMemResourceEx( GetProcAddr(gdiLibHandle, 'AddFontMemResourceEx'));
RemoveFontResourceA := TRemoveFontResourceA( GetProcAddr(gdiLibHandle, 'RemoveFontResourceA'));
RemoveFontResourceExA := TRemoveFontResourceExA( GetProcAddr(gdiLibHandle, 'RemoveFontResourceExA'));
RemoveFontMemResourceEx := TRemoveFontMemResourceEx(GetProcAddr(gdiLibHandle, 'RemoveFontMemResourceEx'));
GetTextMetricsW := TGetTextMetricsW( GetProcAddr(gdiLibHandle, 'GetTextMetricsW'));
GetGlyphOutlineA := TGetGlyphOutlineA( GetProcAddr(gdiLibHandle, 'GetGlyphOutlineA'));
GetCharacterPlacementW := TGetCharacterPlacementW( GetProcAddr(gdiLibHandle, 'GetCharacterPlacementW'));
GetFontData := TGetFontData( GetProcAddr(gdiLibHandle, 'GetFontData'));
CreateCompatibleDC := TCreateCompatibleDC( GetProcAddr(gdiLibHandle, 'CreateCompatibleDC'));
DeleteDC := TDeleteDC( GetProcAddr(gdiLibHandle, 'DeleteDC'));
SelectObject := TSelectObject( GetProcAddr(gdiLibHandle, 'SelectObject'));
DeleteObject := TDeleteObject( GetProcAddr(gdiLibHandle, 'DeleteObject'));
GetOutlineTextMetricsW := TGetOutlineTextMetricsW( GetProcAddr(gdiLibHandle, 'GetOutlineTextMetricsW'));

GetLocaleInfoA := TGetLocaleInfoA(GetProcAddr(kernel32LibHandle, 'GetLocaleInfoA'));

gdiInitialized := true;
except
gdiInitialized := false;
FreeLibrary(gdiLibHandle);
FreeLibrary(kernel32LibHandle);
end;
finally
gdiCritSec.Leave;
end;
end;

procedure QuitGDI;
begin
gdiCritSec.Enter;
try
dec(gdiRefCount, 1);
if (gdiRefCount > 0) then
exit;

CreateFontIndirectA := nil;
AddFontResourceA := nil;
AddFontResourceExA := nil;
RemoveFontResourceA := nil;
RemoveFontResourceExA := nil;
GetTextMetricsW := nil;
GetGlyphOutlineA := nil;
GetCharacterPlacementW := nil;
GetFontData := nil;
CreateCompatibleDC := nil;
DeleteDC := nil;
SelectObject := nil;
DeleteObject := nil;

GetLocaleInfoA := nil;

if (gdiLibHandle <> 0) then begin
FreeLibrary(gdiLibHandle);
gdiLibHandle := 0;
end;

if (kernel32LibHandle <> 0) then begin
FreeLibrary(kernel32LibHandle);
kernel32LibHandle := 0;
end;

gdiInitialized := false;
finally
gdiCritSec.Leave;
end;
end;

initialization
gdiRefCount := 0;
gdiInitialized := false;
gdiCritSec := TCriticalSection.Create;

finalization
if gdiInitialized then
QuitGDI;
FreeAndNil(gdiCritSec);

end.

+ 4
- 0
utsPostProcess.pas View File

@@ -235,6 +235,10 @@ begin
tmpX := fKernel.Size - fX;
tmpY := fKernel.Size - fY;
aCharImage.Blend(orig, tmpX, tmpY, @tsBlendFundAlpha);

aChar.GlyphOrigin := tsPosition(
aChar.GlyphOrigin.x - tmpX,
aChar.GlyphOrigin.y - tmpX);
finally
FreeAndNil(orig);
end;


+ 10
- 7
utsTextSuite.pas View File

@@ -1513,7 +1513,7 @@ begin
try
if (tsStyleUnderline in aFont.Properties.Style) then
DrawLine(result, CharImage, aFont.Properties.UnderlinePos, aFont.Properties.UnderlineSize);
if (tsStyleUnderline in aFont.Properties.Style) then
if (tsStyleStrikeout in aFont.Properties.Style) then
DrawLine(result, CharImage, aFont.Properties.StrikeoutPos, aFont.Properties.StrikeoutSize);
except
CharImage.FillColor(tsColor4f(1, 0, 0, 0), COLOR_CHANNELS_RGB, IMAGE_MODES_NORMAL);
@@ -2099,7 +2099,7 @@ var
font: TtsFont;
char: TtsChar;
metric: TtsTextMetric;
DrawText: Boolean;
draw: Boolean;

function GetChar(const aCharCode: WideChar): TtsChar;
begin
@@ -2121,7 +2121,7 @@ var
end;

tsItemTypeText: begin
if DrawText and Assigned(font) then begin
if draw and Assigned(font) then begin
c := item^.Text;
while (c^ <> #0) do begin
char := GetChar(c^);
@@ -2136,7 +2136,7 @@ var
end;

tsItemTypeSpace: begin
if DrawText and Assigned(font) then begin
if draw and Assigned(font) then begin
ExtraSpaceActual := ExtraSpaceActual + ExtraSpaceTotal;
c := item^.Text;
while (c^ <> #0) do begin
@@ -2185,9 +2185,11 @@ var
// check vertical clipping
case aBlock.Clipping of
tsClipCharBorder, tsClipWordBorder:
DrawText := (y + line^.meta.Height > rect.Top) and (y < rect.Bottom);
draw := (y + line^.meta.Height > rect.Top) and (y < rect.Bottom);
tsClipCharComplete, tsClipWordComplete:
DrawText := (y > rect.Top) and (y + line^.meta.Height < rect.Bottom);
draw := (y > rect.Top) and (y + line^.meta.Height < rect.Bottom);
else
draw := true;
end;

// check horizontal alignment
@@ -2204,7 +2206,7 @@ var
ExtraSpaceTotal := (aBlock.Width - line^.meta.Width) / line^.meta.SpaceCount;
end;

if DrawText then
if draw then
SetDrawPos(x, y + line^.meta.Ascent);
inc(y, line^.meta.Height + line^.meta.Spacing);
item := line^.First;
@@ -2303,6 +2305,7 @@ begin
if not Assigned(aText) then
exit;
len := Length(aText);
result := tsStrAlloc(len);
tsAnsiToWide(result, len, aText, fCodePage, fCodePageDefault);
end;



+ 28
- 0
utsUtils.pas View File

@@ -16,6 +16,7 @@ function tsStrCopy(aDst, aSrc: PWideChar): PWideChar;
function tsAnsiToWide(aDst: PWideChar; const aSize: Integer; aSrc: PAnsiChar; const aCodePage: TtsCodePage; const aDefaultChar: WideChar): Integer;
function tsISO_8859_1ToWide(aDst: PWideChar; const aSize: Integer; aSrc: PAnsiChar): Integer;
function tsUTF8ToWide(aDst: PWideChar; const aSize: Integer; const aSrc: PAnsiChar; const aDefaultChar: WideChar): Integer;
function tsUTFBE16ToWide(aDst: PWideChar; const aDstSize: Integer; aSrc: PByte; aSrcSize: Integer; const aDefaultChar: WideChar): Integer;
function tsAnsiSBCDToWide(aDst: PWideChar; const aSize: Integer; aSrc: PAnsiChar; const aCodePage: TtsCodePage; const aDefaultChar: WideChar): Integer;

implementation
@@ -162,6 +163,33 @@ begin
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function tsUTFBE16ToWide(aDst: PWideChar; const aDstSize: Integer; aSrc: PByte; aSrcSize: Integer;
const aDefaultChar: WideChar): Integer;
var
tmp: Word;

procedure AddToDest(aCharCode: Word);
begin
if ((aCharCode and $D800) = $D800) or
((aCharCode and $DC00) = $DC00) then
aCharCode := Ord(aDefaultChar);

aDst^ := WideChar(aCharCode);
inc(aDst, 1);
result := result + 1;
end;

begin
result := 0;
while (aSrcSize > 1) and (aDstSize > 0) do begin
tmp := (aSrc^ shl 8) or (aSrc + 1)^;
inc(aSrc, 2);
dec(aSrcSize, 2);
AddToDest(tmp);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function tsAnsiSBCDToWide(aDst: PWideChar; const aSize: Integer; aSrc: PAnsiChar;
const aCodePage: TtsCodePage; const aDefaultChar: WideChar): Integer;


Loading…
Cancel
Save