forked from 0ad/0ad
Font builder code
This was SVN commit r527.
This commit is contained in:
parent
fd91c74a23
commit
b65d35ea2e
BIN
source/tools/fontbuilder/FontBuilder.ico
Executable file
BIN
source/tools/fontbuilder/FontBuilder.ico
Executable file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
76
source/tools/fontbuilder/FontBuilder.rc
Executable file
76
source/tools/fontbuilder/FontBuilder.rc
Executable file
@ -0,0 +1,76 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#define APSTUDIO_HIDDEN_SYMBOLS
|
||||
#include "windows.h"
|
||||
#undef APSTUDIO_HIDDEN_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_ICON1 ICON "FontBuilder.ico"
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"#include ""windows.h""\r\n"
|
||||
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
30
source/tools/fontbuilder/FontBuilder.sln
Executable file
30
source/tools/fontbuilder/FontBuilder.sln
Executable file
@ -0,0 +1,30 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||
Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "FontBuilder", "FontBuilder.icproj", "{CFCF18FF-C3A4-4E76-BFA1-C5DB476E4687}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
OldRelease = OldRelease
|
||||
Release = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{CFCF18FF-C3A4-4E76-BFA1-C5DB476E4687}.Debug.ActiveCfg = Debug|Win32
|
||||
{CFCF18FF-C3A4-4E76-BFA1-C5DB476E4687}.Debug.Build.0 = Debug|Win32
|
||||
{CFCF18FF-C3A4-4E76-BFA1-C5DB476E4687}.OldRelease.ActiveCfg = Release|Win32
|
||||
{CFCF18FF-C3A4-4E76-BFA1-C5DB476E4687}.OldRelease.Build.0 = Release|Win32
|
||||
{CFCF18FF-C3A4-4E76-BFA1-C5DB476E4687}.Release.ActiveCfg = Release|Win32
|
||||
{CFCF18FF-C3A4-4E76-BFA1-C5DB476E4687}.Release.Build.0 = Release|Win32
|
||||
{277A0C35-0B44-48FC-81FD-119AD97194EA}.Release.Build.0 = Release|Win32
|
||||
{277A0C35-0B44-48FC-81FD-119AD97194EA}.Release.ActiveCfg = Release|Win32
|
||||
{277A0C35-0B44-48FC-81FD-119AD97194EA}.OldRelease.Build.0 = Release|Win32
|
||||
{277A0C35-0B44-48FC-81FD-119AD97194EA}.OldRelease.ActiveCfg = Release|Win32
|
||||
{277A0C35-0B44-48FC-81FD-119AD97194EA}.Debug.Build.0 = Debug|Win32
|
||||
{277A0C35-0B44-48FC-81FD-119AD97194EA}.Debug.ActiveCfg = Debug|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
262
source/tools/fontbuilder/FontBuilder.vcproj
Executable file
262
source/tools/fontbuilder/FontBuilder.vcproj
Executable file
@ -0,0 +1,262 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="FontBuilder"
|
||||
OwnerKey="{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}"
|
||||
ProjectGUID="{277A0C35-0B44-48FC-81FD-119AD97194EA}"
|
||||
RootNamespace="FontBuilder"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""E:\wx\wxWindows-2.4.2\include";"E:\wx\wxWindows-2.4.2\lib\mswud";"E:\freetype\freetype-2.1.8\include";E:\wx\pretends"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;__WXDEBUG__;_UNICODE;UNICODE;wxUSE_UNICODE=1"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
BufferSecurityCheck="TRUE"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="3"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="wxmswud.lib freetype218MT_D.lib comctl32.lib ws2_32.lib rpcrt4.lib"
|
||||
OutputFile="$(OutDir)/FontBuilder.exe"
|
||||
LinkIncremental="2"
|
||||
SuppressStartupBanner="TRUE"
|
||||
AdditionalLibraryDirectories=""E:\wx\wxWindows-2.4.2\lib";"E:\freetype\freetype-2.1.8\objs""
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/FontBuilder.pdb"
|
||||
SubSystem="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="FALSE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="-Qinline_debug_info "
|
||||
Optimization="1"
|
||||
GlobalOptimizations="FALSE"
|
||||
InlineFunctionExpansion="1"
|
||||
EnableIntrinsicFunctions="FALSE"
|
||||
FavorSizeOrSpeed="2"
|
||||
OmitFramePointers="FALSE"
|
||||
EnableFiberSafeOptimizations="FALSE"
|
||||
OptimizeForProcessor="2"
|
||||
OptimizeForWindowsApplication="FALSE"
|
||||
AdditionalIncludeDirectories="E:\wx\wxWindows-2.4.2\include;E:\wx\wxWindows-2.4.2\lib\mswu;E:\freetype\freetype-2.1.8\include"
|
||||
PreprocessorDefinitions="_STATIC_CPPLIB;WIN32;NDEBUG;_WINDOWS;_UNICODE;UNICODE;wxUSE_UNICODE=1"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="2"
|
||||
StructMemberAlignment="0"
|
||||
BufferSecurityCheck="FALSE"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="3"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="FALSE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="wxmswu.lib freetype218MT.lib comctl32.lib ws2_32.lib rpcrt4.lib"
|
||||
OutputFile="$(OutDir)/FontBuilder.exe"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
AdditionalLibraryDirectories="E:\wx\wxWindows-2.4.2\lib;E:\freetype\freetype-2.1.8\objs;e:\icc80\compiler80\ia32\lib"
|
||||
IgnoreDefaultLibraryNames="libmmd"
|
||||
GenerateDebugInformation="FALSE"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="rem upx --best $(TargetPath)"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath=".\filemanip.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\font.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\imagemanip.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\packer.cpp">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="TRUE"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stdafx.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\wxapp.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\wxconfig.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\wxframe.cpp">
|
||||
</File>
|
||||
<Filter
|
||||
Name="platform"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\platform\msw\fontselect.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
||||
<File
|
||||
RelativePath=".\filemanip.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\font.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\imagemanip.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\packer.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Resource.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stdafx.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\wxconfig.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\wxframe.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\wxspinner.h">
|
||||
</File>
|
||||
<Filter
|
||||
Name="platform"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\platform\fontselect.h">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
|
||||
<File
|
||||
RelativePath=".\FontBuilder.ico">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\FontBuilder.rc">
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\fileformat.txt">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\readme.html">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\todo.txt">
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
41
source/tools/fontbuilder/fileformat.txt
Executable file
41
source/tools/fontbuilder/fileformat.txt
Executable file
@ -0,0 +1,41 @@
|
||||
$Id: fileformat.txt,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
|
||||
Fonts consist of
|
||||
fontname.fnt
|
||||
fontname.tga
|
||||
and you load fonts by just specifying the "path/fontname" part.
|
||||
|
||||
The .tga is an 8-bit greyscale image, used for alpha-blending the text.
|
||||
(DXTC allows 0.5 bytes/pixel at best, which isn't much better than
|
||||
TGA's 1 byte/pixel, and DXTC's lossiness is almost noticeable.)
|
||||
|
||||
The .fnt file is something like:
|
||||
|
||||
100
|
||||
512 256
|
||||
3
|
||||
16
|
||||
32 0 0 10 10 12
|
||||
33 10 0 6 10 7
|
||||
3300 16 0 6 10 7
|
||||
|
||||
First line = version number of file, for slightly better error
|
||||
detection if people leave old ones hanging around.
|
||||
|
||||
Second line = size of texture (width/height).
|
||||
|
||||
Third line = number of glyphs in the font.
|
||||
|
||||
Fourth line = line spacing (pixels between each baseline)
|
||||
|
||||
Each subsequent line is
|
||||
|
||||
<code point> <x> <y> <width> <height> <x offset> <y offset> <advance>
|
||||
|
||||
0 <= Code point < 2^16.
|
||||
x, y, width, height are in pixels on the texture.
|
||||
x/y offset are the position of the texture relative to the glyph's origin.
|
||||
advance is the number of pixels to move along for the next character.
|
||||
|
||||
Currently no support for kerning.
|
126
source/tools/fontbuilder/filemanip.cpp
Executable file
126
source/tools/fontbuilder/filemanip.cpp
Executable file
@ -0,0 +1,126 @@
|
||||
// $Id: filemanip.cpp,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "filemanip.h"
|
||||
|
||||
// Ensure there's no padding added into the struct,
|
||||
// in a very non-portable way
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
// For gcc, use "} TGA_HEADER __attribute__ ((packed));" instead of this
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char identsize; // size of ID field that follows 18 byte header (0 usually)
|
||||
char colourmaptype; // type of colour map 0=none, 1=has palette
|
||||
char imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed
|
||||
|
||||
short colourmapstart; // first colour map entry in palette
|
||||
short colourmaplength; // number of colours in palette
|
||||
char colourmapbits; // number of bits per palette entry 15,16,24,32
|
||||
|
||||
short xstart; // image x origin
|
||||
short ystart; // image y origin
|
||||
short width; // image width in pixels
|
||||
short height; // image height in pixels
|
||||
char bits; // image bits per pixel 8,16,24,32
|
||||
char descriptor; // image descriptor bits (vh flip bits)
|
||||
} TGA_HEADER;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
// Convert the RGB image to 8-bit greyscale and output
|
||||
void RGB_OutputGreyscaleTGA(unsigned char* image_data, int width, int height, int pitch, wxFFile& file)
|
||||
{
|
||||
assert(sizeof(TGA_HEADER) == 18);
|
||||
|
||||
TGA_HEADER header;
|
||||
|
||||
header.identsize = 0;
|
||||
header.colourmaptype = 0;
|
||||
header.imagetype = 3;
|
||||
header.xstart = 0;
|
||||
header.ystart = 0;
|
||||
header.width = (short)width;
|
||||
header.height = (short)height;
|
||||
header.bits = 8;
|
||||
header.descriptor = 0;
|
||||
|
||||
file.Write(&header, sizeof(header));
|
||||
|
||||
// Start from the bottom, so things look the right way up
|
||||
image_data += height*pitch;
|
||||
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
image_data -= pitch;
|
||||
|
||||
for (int x = 0; x < width; ++x)
|
||||
file.Write(&image_data[x*3], 1);
|
||||
}
|
||||
}
|
||||
|
||||
std::set<wchar_t> AnalyseChars(wxString filename)
|
||||
{
|
||||
wxFFile File (filename, "rb");
|
||||
if (! File.IsOpened())
|
||||
throw "Cannot open file";
|
||||
|
||||
enum {
|
||||
UNKNOWN,
|
||||
UTF8,
|
||||
UTF16SE, // same-endian as this machine
|
||||
UTF16DE // different-endian
|
||||
} Format = UNKNOWN;
|
||||
|
||||
unsigned short BOM;
|
||||
File.Read(&BOM, 2);
|
||||
if (BOM == 0xFEFF)
|
||||
Format = UTF16SE;
|
||||
else if (BOM == 0xFFFE)
|
||||
Format = UTF16DE;
|
||||
else {
|
||||
// Make an educated guess based on the first byte
|
||||
// If it's like "_\0" it's probably little-endian,
|
||||
// if it's like "\0_" it's probably big-endian
|
||||
if ((BOM & 0xFF00) == 0)
|
||||
Format = UTF16SE;
|
||||
else if ((BOM & 0x00FF) == 0)
|
||||
Format = UTF16DE;
|
||||
else
|
||||
throw "Can't determine endianness of source file - make sure it's UTF16 and starts with a simple letter";
|
||||
// (Maybe it's UTF8, but I don't want to bother with that)
|
||||
|
||||
File.Seek(0); // Make sure the first character is included in the list
|
||||
}
|
||||
|
||||
std::set<wchar_t> Chars;
|
||||
if (Format == UTF16SE)
|
||||
{
|
||||
wchar_t c;
|
||||
while (! File.Eof())
|
||||
{
|
||||
File.Read(&c, 2);
|
||||
if (c != '\r' && c != '\n')
|
||||
Chars.insert(c);
|
||||
}
|
||||
}
|
||||
else if (Format == UTF16DE)
|
||||
{
|
||||
unsigned short c;
|
||||
while (! File.Eof())
|
||||
{
|
||||
if (File.Read(&c, 2) != 2) break; // abort if failed (i.e. eof)
|
||||
c = (c>>8)|((c&0xff)<<8); // swap bytes
|
||||
if (c != '\r' && c != '\n')
|
||||
Chars.insert(c);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw "Internal error - invalid file format";
|
||||
}
|
||||
|
||||
return Chars;
|
||||
}
|
6
source/tools/fontbuilder/filemanip.h
Executable file
6
source/tools/fontbuilder/filemanip.h
Executable file
@ -0,0 +1,6 @@
|
||||
// $Id: filemanip.h,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
#include <set>
|
||||
|
||||
void RGB_OutputGreyscaleTGA(unsigned char* image_data, int width, int height, int pitch, wxFFile& file);
|
||||
std::set<wchar_t> AnalyseChars(wxString filename);
|
305
source/tools/fontbuilder/font.cpp
Executable file
305
source/tools/fontbuilder/font.cpp
Executable file
@ -0,0 +1,305 @@
|
||||
// $Id: font.cpp,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "font.h"
|
||||
#include <math.h>
|
||||
|
||||
FontRenderer::FontRenderer(const char* filename0, const char* filename1, int ptsize)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = FT_Init_FreeType(&FontLibrary0);
|
||||
if (error)
|
||||
{
|
||||
throw "Error initialising FreeType";
|
||||
}
|
||||
|
||||
error = FT_Init_FreeType(&FontLibrary1);
|
||||
if (error)
|
||||
{
|
||||
FT_Done_FreeType(FontLibrary0);
|
||||
throw "Error initialising FreeType";
|
||||
}
|
||||
|
||||
error = FT_New_Face(
|
||||
FontLibrary0,
|
||||
filename0,
|
||||
0, // index of face inside font file
|
||||
&FontFace0
|
||||
);
|
||||
if (error)
|
||||
{
|
||||
FT_Done_FreeType(FontLibrary0);
|
||||
FT_Done_FreeType(FontLibrary1);
|
||||
throw "Error loading primary font";
|
||||
}
|
||||
|
||||
error = FT_New_Face(
|
||||
FontLibrary1,
|
||||
filename1,
|
||||
0, // index of face inside font file
|
||||
&FontFace1
|
||||
);
|
||||
if (error)
|
||||
{
|
||||
FT_Done_Face(FontFace0);
|
||||
FT_Done_FreeType(FontLibrary0);
|
||||
FT_Done_FreeType(FontLibrary1);
|
||||
throw "Error loading secondary font face";
|
||||
}
|
||||
|
||||
error = FT_Set_Char_Size(
|
||||
FontFace0,
|
||||
0, // char_width in 1/64th of points
|
||||
ptsize*64, // char_height in 1/64th of points
|
||||
72, // horizontal device resolution
|
||||
72 // vertical device resolution
|
||||
);
|
||||
if (error)
|
||||
{
|
||||
FT_Done_Face(FontFace0);
|
||||
FT_Done_Face(FontFace1);
|
||||
FT_Done_FreeType(FontLibrary0);
|
||||
FT_Done_FreeType(FontLibrary1);
|
||||
throw "Error loading scalable character from primary font - is this a TrueType font?";
|
||||
}
|
||||
|
||||
error = FT_Set_Char_Size(
|
||||
FontFace1,
|
||||
0, // char_width in 1/64th of points
|
||||
ptsize*64, // char_height in 1/64th of points
|
||||
72, // horizontal device resolution
|
||||
72 // vertical device resolution
|
||||
);
|
||||
if (error)
|
||||
{
|
||||
FT_Done_Face(FontFace0);
|
||||
FT_Done_Face(FontFace1);
|
||||
FT_Done_FreeType(FontLibrary0);
|
||||
FT_Done_FreeType(FontLibrary1);
|
||||
throw "Error loading scalable character from secondary font - is this a TrueType font?";
|
||||
}
|
||||
|
||||
Boldness = 0;
|
||||
Italicness = 0;
|
||||
Tracking = 0;
|
||||
Leading = 0;
|
||||
}
|
||||
|
||||
FontRenderer::~FontRenderer()
|
||||
{
|
||||
FT_Done_Face(FontFace0);
|
||||
FT_Done_Face(FontFace1);
|
||||
FT_Done_FreeType(FontLibrary0);
|
||||
FT_Done_FreeType(FontLibrary1);
|
||||
}
|
||||
|
||||
#define deg2rad(a) ((double)a * 3.14159265358979323846 / 180.0)
|
||||
|
||||
void FontRenderer::LoadGlyph(const int charcode)
|
||||
{
|
||||
FT_Face FontFace = FontFace0;
|
||||
int glyph_index = FT_Get_Char_Index(FontFace0, charcode);
|
||||
|
||||
Missing = false;
|
||||
if (glyph_index == 0)
|
||||
{
|
||||
// Can't find glyph in primary font - switch to secondary
|
||||
FontFace = FontFace1;
|
||||
glyph_index = FT_Get_Char_Index(FontFace1, charcode);
|
||||
|
||||
// Still can't find it - use the missing glyph symbol
|
||||
if (glyph_index == 0)
|
||||
{
|
||||
glyph_index = FT_Get_Char_Index(FontFace1, 0xFFFD);
|
||||
Missing = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int error;
|
||||
|
||||
if (Italicness)
|
||||
{
|
||||
// Start with identity matrix (rotations could be added in here easily)
|
||||
FT_Matrix mat;
|
||||
mat.xx = mat.yy = (FT_Fixed)(0x10000L);
|
||||
mat.xy = mat.yx = (FT_Fixed)(0x00000L);
|
||||
// Apply shear
|
||||
FT_Fixed f = (FT_Fixed)(tan(deg2rad(Italicness)) * 0x10000L);
|
||||
mat.xy += FT_MulFix(f, mat.xx);
|
||||
mat.yy += FT_MulFix(f, mat.yx);
|
||||
|
||||
FT_Set_Transform(FontFace, &mat, 0);
|
||||
}
|
||||
|
||||
error = FT_Load_Glyph(FontFace, glyph_index, FT_LOAD_DEFAULT);
|
||||
if (error)
|
||||
throw "Error loading glyph";
|
||||
|
||||
|
||||
if (Outline)
|
||||
{
|
||||
wxLogFatalError(wxT("Can't do this yet"));
|
||||
/*
|
||||
// Outline renderer which doesn't actually work:
|
||||
|
||||
assert(FontFace->glyph->format == FT_GLYPH_FORMAT_OUTLINE);
|
||||
|
||||
//FT_Outline *FontOutline = new FT_Outline;
|
||||
//error = FT_Outline_New(FontLibrary, 1024, 1024, FontOutline);
|
||||
//assert(!error);
|
||||
FT_Outline *FontOutline = &FontFace->glyph->outline;
|
||||
|
||||
FT_BBox BBox;
|
||||
|
||||
error = FT_Outline_Get_BBox(FontOutline, &BBox);
|
||||
assert(!error);
|
||||
|
||||
// Translate back to (0,0)
|
||||
FT_Outline_Translate(FontOutline, -BBox.xMin, -BBox.yMin);
|
||||
|
||||
FT_Bitmap *Bmp = new FT_Bitmap;
|
||||
Bmp->pixel_mode = FT_PIXEL_MODE_GRAY;
|
||||
Bmp->num_grays = 256;
|
||||
FontFace->glyph->bitmap_left = (BBox.xMin) >> 6;
|
||||
FontFace->glyph->bitmap_top = (BBox.yMax + 31) >> 6;
|
||||
Bmp->width = (BBox.xMax - BBox.xMin) >> 6;
|
||||
Bmp->pitch = 3*Bmp->width;
|
||||
Bmp->rows = (BBox.yMax - BBox.yMin) >> 6;
|
||||
Bmp->buffer = new unsigned char[Bmp->pitch * Bmp->rows];
|
||||
memset(Bmp->buffer, 0, sizeof(unsigned char) * Bmp->pitch * Bmp->rows);
|
||||
|
||||
error = FT_Outline_Get_Bitmap(FontLibrary, FontOutline, Bmp);
|
||||
assert(!error);
|
||||
|
||||
FontFace->glyph->bitmap = *Bmp;
|
||||
|
||||
error = FT_Outline_Done(FontLibrary, FontOutline);
|
||||
assert(!error);
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
// Simple version:
|
||||
error = FT_Render_Glyph(FontFace->glyph, FT_RENDER_MODE_NORMAL);
|
||||
if (error)
|
||||
throw "Error rendering glyph";
|
||||
}
|
||||
|
||||
LastFontFace = FontFace;
|
||||
}
|
||||
|
||||
|
||||
void FontRenderer::GetBoundingBox(int& width, int& height)
|
||||
{
|
||||
FT_Bitmap* bmp = &LastFontFace->glyph->bitmap;
|
||||
width = bmp->width + Boldness;
|
||||
height = bmp->rows;
|
||||
}
|
||||
|
||||
|
||||
void FontRenderer::RenderGlyph(unsigned char* rgb_buffer, int& pos_left, int& pos_top, int width, int height, int pitch, bool single_glyph)
|
||||
{
|
||||
FT_Face FontFace = LastFontFace;
|
||||
|
||||
// This function only tries to work on 8-bit greyscale glyphs
|
||||
if (FontFace->glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY)
|
||||
throw "Error - invalid bitmap format";
|
||||
|
||||
// Add desired spacing, but not after zero-width combining glyphs
|
||||
if (!single_glyph && FontFace->glyph->advance.x)
|
||||
pos_left += Tracking;
|
||||
|
||||
FT_Bitmap* bmp = &FontFace->glyph->bitmap;
|
||||
|
||||
// Pointers to the appropriate row of pixel data
|
||||
unsigned char* ImageRow = rgb_buffer;
|
||||
unsigned char* GlyphRow = bmp->buffer;
|
||||
|
||||
int Left = pos_left;
|
||||
int Top = pos_top;
|
||||
if (!single_glyph)
|
||||
{
|
||||
Left += FontFace->glyph->bitmap_left;
|
||||
Top -= FontFace->glyph->bitmap_top;
|
||||
}
|
||||
|
||||
// Point to the first line that needs to be drawn
|
||||
if (Top >= 0)
|
||||
ImageRow += Top*pitch;
|
||||
|
||||
for (int GlyphY = 0; GlyphY < bmp->rows; ++GlyphY)
|
||||
{
|
||||
// Clip vertically
|
||||
if (Top+GlyphY < 0 || Top+GlyphY >= height)
|
||||
{
|
||||
GlyphRow += bmp->pitch;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int GlyphX = -Boldness; GlyphX < bmp->width+Boldness; ++GlyphX)
|
||||
{
|
||||
// Clip horizontally
|
||||
if (Left+GlyphX < 0 || Left+GlyphX >= width)
|
||||
continue;
|
||||
|
||||
int value = 0;
|
||||
|
||||
if (! Boldness)
|
||||
{
|
||||
value = GlyphRow[GlyphX];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Pretend to be bold - add lots of adjacent images
|
||||
// Calculate value =~ sum(in[x-n] .. in[x+n])
|
||||
|
||||
// Work out valid limits for summing
|
||||
// (with weird shifts so that it does precisely
|
||||
// Boldness pixels)
|
||||
int min = GlyphX - ( Boldness >> 1);
|
||||
if (min < 0) min = 0;
|
||||
int max = GlyphX + ( (Boldness+1) >> 1) + 1;
|
||||
if (max > bmp->width) max = bmp->width;
|
||||
|
||||
for (int x = min; x < max; ++x)
|
||||
value += GlyphRow[x];
|
||||
|
||||
}
|
||||
|
||||
// Additive composition of pixel onto image buffer
|
||||
value += ImageRow[(Left+GlyphX)*3];
|
||||
ImageRow[(Left+GlyphX)*3 ] =
|
||||
ImageRow[(Left+GlyphX)*3+1] =
|
||||
ImageRow[(Left+GlyphX)*3+2] = (unsigned char)(value > 255 ? 255 : value);
|
||||
|
||||
}
|
||||
|
||||
// Point everything at the next line
|
||||
ImageRow += pitch;
|
||||
GlyphRow += bmp->pitch;
|
||||
}
|
||||
|
||||
if (!single_glyph)
|
||||
{
|
||||
// Advance the drawing-cursor ( >>6 due to 26.6-bit number format)
|
||||
pos_left += FontFace->glyph->advance.x >> 6;
|
||||
pos_top += FontFace->glyph->advance.y >> 6;
|
||||
}
|
||||
}
|
||||
|
||||
int FontRenderer::GetLineSpacing()
|
||||
{
|
||||
return Leading + (FontFace0->size->metrics.height >> 6);
|
||||
}
|
||||
|
||||
void FontRenderer::GetMetrics(int& offset_x, int& offset_y, int& advance)
|
||||
{
|
||||
offset_x = LastFontFace->glyph->bitmap_left;
|
||||
offset_y = LastFontFace->glyph->bitmap_top;
|
||||
advance = LastFontFace->glyph->advance.x >> 6;
|
||||
if (advance)
|
||||
offset_x += Tracking;
|
||||
}
|
90
source/tools/fontbuilder/font.h
Executable file
90
source/tools/fontbuilder/font.h
Executable file
@ -0,0 +1,90 @@
|
||||
// $Id: font.h,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
#ifndef _FONT_H_
|
||||
#define _FONT_H_
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_OUTLINE_H
|
||||
#include FT_BBOX_H
|
||||
|
||||
|
||||
// XXX: Kerning ( = hard? got to store giant table for OpenGL to use)
|
||||
|
||||
// XXX: Right-to-left text
|
||||
|
||||
|
||||
|
||||
// Make my IDE a little happier:
|
||||
#if 0
|
||||
#include "freetype/freetype.h"
|
||||
#include "freetype/freetype_defs.h"
|
||||
#include "freetype/ftimage.h"
|
||||
#include "freetype/fttypes.h"
|
||||
#include "freetype/ftbbox.h"
|
||||
#include "freetype/ftoutln.h"
|
||||
#endif
|
||||
|
||||
class FontRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
// Two fonts are required - a primary (0) font which will be used first,
|
||||
// and a secondary (1) font for filling in missing glyphs.
|
||||
// (The secondary font should usually be Arial Unicode MS).
|
||||
FontRenderer(const char* filename0, const char* filename1, int ptsize);
|
||||
|
||||
~FontRenderer();
|
||||
|
||||
// Generate the glyph for the given Unicode code point
|
||||
void LoadGlyph(const int charcode);
|
||||
|
||||
// Put the appropriate pixel sizes into width and height
|
||||
void GetBoundingBox(int& width, int& height);
|
||||
|
||||
// Copy the glyph onto a 24-bit RGB image buffer
|
||||
// pos_left / pos_top: Position to put the origin (usually bottom left corner) of the glyph.
|
||||
// Altered by the function to point towards the next character.
|
||||
// width / height: of bitmap, to do clipping
|
||||
// pitch: Bytes per row, including any padding
|
||||
// single_glyph: If true, doesn't update the cursor and draws with the bounding box at pos_left/top
|
||||
void RenderGlyph(unsigned char* rgb_buffer, int& pos_left, int& pos_top, int width, int height, int pitch, bool single_glyph);
|
||||
|
||||
// Returns baseline-to-baseline distance, including the desired leading
|
||||
int GetLineSpacing();
|
||||
|
||||
// Supplies some information for positioning glyphs
|
||||
void GetMetrics(int& offset_x, int& offset_y, int& advance);
|
||||
|
||||
// Set by LoadGlyph if it can't find the right glyph
|
||||
bool Missing;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
// Font settings, set by users and used by this class:
|
||||
|
||||
// Shear angle (in degrees) for fake italics
|
||||
int Italicness;
|
||||
|
||||
// 0 for standard; otherwise draws n+1 overlapping copies of the text
|
||||
int Boldness;
|
||||
|
||||
// Additional spacing between each non-zero-width glyph and the next
|
||||
int Tracking;
|
||||
|
||||
// Additional spacing between lines
|
||||
int Leading;
|
||||
|
||||
// Whether to draw an outlined font
|
||||
bool Outline;
|
||||
|
||||
private:
|
||||
FT_Library FontLibrary0;
|
||||
FT_Library FontLibrary1;
|
||||
FT_Face FontFace0;
|
||||
FT_Face FontFace1;
|
||||
|
||||
FT_Face LastFontFace; // = FontFace(0|1), depending on the last LoadGlyph
|
||||
};
|
||||
|
||||
#endif // _FONT_H_
|
224
source/tools/fontbuilder/fontbuilder.icproj
Executable file
224
source/tools/fontbuilder/fontbuilder.icproj
Executable file
@ -0,0 +1,224 @@
|
||||
<?xml version="1.0" encoding="windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Intel C++ Project"
|
||||
Version="7.1"
|
||||
Name="FontBuilder"
|
||||
VCNestedProjectGUID="{277A0C35-0B44-48FC-81FD-119AD97194EA}"
|
||||
VCNestedProjectFileName="FontBuilder.vcproj">
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32">
|
||||
<IntelOptions
|
||||
CompilerName="1"/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool">
|
||||
<IntelOptions
|
||||
Optimization="0"
|
||||
MinimalRebuild="1"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
BufferSecurityCheck="1"
|
||||
EnableFunctionLevelLinking="1"
|
||||
ForceConformanceInForLoopScope="1"/>
|
||||
</Tool>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool">
|
||||
<IntelOptions
|
||||
Optimization="1"
|
||||
InlineFunctionExpansion="1"
|
||||
FavorSizeOrSpeed="2"
|
||||
OptimizeForProcessor="3"
|
||||
LoopUnrolling=""
|
||||
StringPooling="1"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="0"
|
||||
ForceConformanceInForLoopScope="1"
|
||||
OpenMPDirectives="1"/>
|
||||
</Tool>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<Files>
|
||||
<File
|
||||
RelativePath=".\filemanip.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\font.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\imagemanip.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\packer.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool">
|
||||
<IntelOptions
|
||||
Optimization="1000"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="1"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="1"/>
|
||||
</Tool>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stdafx.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\wxapp.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\wxconfig.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\wxframe.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\platform\msw\fontselect.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\filemanip.h">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\font.h">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\imagemanip.h">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\packer.h">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\resource.h">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stdafx.h">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\wxconfig.h">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\wxframe.h">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\wxspinner.h">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\platform\fontselect.h">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\FontBuilder.ico">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\FontBuilder.rc">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\fileformat.txt">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\readme.html">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\todo.txt">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"/>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"/>
|
||||
</File>
|
||||
</Files>
|
||||
</VisualStudioProject>
|
||||
|
24
source/tools/fontbuilder/imagemanip.cpp
Executable file
24
source/tools/fontbuilder/imagemanip.cpp
Executable file
@ -0,0 +1,24 @@
|
||||
// $Id: imagemanip.cpp,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "math.h"
|
||||
|
||||
unsigned char* GenerateImage(int width, int height)
|
||||
{
|
||||
unsigned char* ImageData = new unsigned char[width*height*3];
|
||||
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
// Slightly off black, so you can see the bounding boxes
|
||||
// by playing in some paint program
|
||||
ImageData[(x+y*width)*3+0] = 0;
|
||||
ImageData[(x+y*width)*3+1] = 0;
|
||||
ImageData[(x+y*width)*3+2] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ImageData;
|
||||
}
|
4
source/tools/fontbuilder/imagemanip.h
Executable file
4
source/tools/fontbuilder/imagemanip.h
Executable file
@ -0,0 +1,4 @@
|
||||
// $Id: imagemanip.h,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
unsigned char* GenerateImage(int width, int height);
|
||||
unsigned char* GreyscaleToRGB(int width, int height, unsigned char* grey);
|
415
source/tools/fontbuilder/packer.cpp
Executable file
415
source/tools/fontbuilder/packer.cpp
Executable file
@ -0,0 +1,415 @@
|
||||
// $Id: packer.cpp,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "packer.h"
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
PackedFont::PackedFont(FontRenderer* font, std::set<wchar_t> chars)
|
||||
{
|
||||
TextureData = NULL;
|
||||
TextureWidth = TextureHeight = 0;
|
||||
Font = font;
|
||||
Chars = chars;
|
||||
}
|
||||
|
||||
|
||||
PackedFont::~PackedFont()
|
||||
{
|
||||
delete[] TextureData;
|
||||
}
|
||||
|
||||
|
||||
class GlyphInfo {
|
||||
public:
|
||||
GlyphInfo() { c = 0; w = h = size = -1; }
|
||||
GlyphInfo(wchar_t _c, int _w, int _h) { c=_c; w=_w; h=_h; size=(w*w)+(h*h); }
|
||||
wchar_t c;
|
||||
int w, h;
|
||||
int x, y; // of top-left corner
|
||||
|
||||
bool operator<(GlyphInfo& b) { return size > b.size; } // sort biggest first
|
||||
|
||||
private:
|
||||
int size; // used for sorting
|
||||
};
|
||||
|
||||
typedef std::vector<GlyphInfo> GlyphsInfo;
|
||||
|
||||
struct GlyphCharSort : public std::binary_function<GlyphInfo&, GlyphInfo&, bool> {
|
||||
bool operator()(GlyphInfo& x, GlyphInfo& y) { return x.c < y.c; }
|
||||
};
|
||||
|
||||
int next_power_of_two(int x)
|
||||
{
|
||||
// See something like http://bob.allegronetwork.com/prog/tricks.html for an explanation
|
||||
x |= (x >> 1);
|
||||
x |= (x >> 2);
|
||||
x |= (x >> 4);
|
||||
x |= (x >> 8);
|
||||
x |= (x >> 16);
|
||||
return x+1;
|
||||
}
|
||||
|
||||
// To avoid a few ugly gotos. Returns true on collision.
|
||||
inline bool TryFittingInternal(const int &x, const int &y, GlyphsInfo& glyphs, const GlyphsInfo::iterator& ThisGlyph)
|
||||
{
|
||||
for (GlyphsInfo::iterator OtherGlyph = glyphs.begin(); OtherGlyph != ThisGlyph; ++OtherGlyph)
|
||||
{
|
||||
// Test for collisions - effectively trying to find a line that
|
||||
// can fit between the two rectangles
|
||||
if (x <= OtherGlyph->x+OtherGlyph->w
|
||||
&& x+ThisGlyph->w >= OtherGlyph->x
|
||||
&& y <= OtherGlyph->y+OtherGlyph->h
|
||||
&& y+ThisGlyph->h >= OtherGlyph->y) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool TryFitting(const int packing_precision, const int texture_width, const int texture_height, const bool randomness, GlyphsInfo& glyphs, bool ProgressCallback(float, wxString, void*), void* CallbackData)
|
||||
{
|
||||
// A roughly O(n^3) algorithm, but with lots of attempted
|
||||
// optimisations that do occasionally work.
|
||||
|
||||
int count = 0;
|
||||
|
||||
int ProgressCurrent = 0;
|
||||
int ProgressMax = (int)glyphs.size();
|
||||
|
||||
GlyphInfo* LastGlyph = NULL;
|
||||
for (GlyphsInfo::iterator ThisGlyph = glyphs.begin(); ThisGlyph != glyphs.end(); ++ThisGlyph, ++count)
|
||||
{
|
||||
if (ProgressCallback != NULL)
|
||||
{
|
||||
// Squaring makes the bar increase at a more constant rate
|
||||
float Progress = powf((float)ProgressCurrent++ / (float)ProgressMax, 2.0f);
|
||||
if (ProgressCallback(Progress, wxT("Fitting"), CallbackData))
|
||||
throw "Aborted";
|
||||
}
|
||||
|
||||
// After the first few easy ones, try sticking things in randomly
|
||||
// and see if it turns out adequately.
|
||||
|
||||
if (randomness && count > 32)
|
||||
{
|
||||
/*
|
||||
// except this is quite rubbish, so don't bother
|
||||
|
||||
bool fitted = false;
|
||||
for (int i = 0; i < 16; ++i) // try several times
|
||||
{
|
||||
int x = 1 + rand() % (texture_width-ThisGlyph->w-1);
|
||||
int y = 1 + rand() % (texture_height-ThisGlyph->h-1);
|
||||
for (GlyphsInfo::iterator OtherGlyph = glyphs.begin(); OtherGlyph != ThisGlyph; ++OtherGlyph)
|
||||
if (box_collide(x, y, x+ThisGlyphRef.w, y+ThisGlyphRef.h, OtherGlyph->x, OtherGlyph->y, OtherGlyph->x+OtherGlyph->w, OtherGlyph->y+OtherGlyph->h))
|
||||
goto randomly_collided;
|
||||
|
||||
ThisGlyph->x = x;
|
||||
ThisGlyph->y = y;
|
||||
goto fitted;
|
||||
|
||||
randomly_collided: ;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
bool fitted = false;
|
||||
|
||||
int starty, stepy;
|
||||
|
||||
// Check whether this glyph is no smaller than the previous one
|
||||
if (LastGlyph && LastGlyph->w <= ThisGlyph->w && LastGlyph->h <= ThisGlyph->h)
|
||||
{
|
||||
// If so, carry on the fitting from where the last glyph left off,
|
||||
// because we've already discovered that there's no more
|
||||
// space above.
|
||||
--count;
|
||||
if (count & 1)
|
||||
stepy = -packing_precision;
|
||||
else
|
||||
stepy = packing_precision;
|
||||
starty = LastGlyph->y;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Alternate between fitting glyphs at the top and bottom
|
||||
// to make things go a bit faster by minimising collisions
|
||||
if (count & 1)
|
||||
starty = texture_height-ThisGlyph->h-1, stepy = -packing_precision;
|
||||
else
|
||||
starty = 1, stepy = packing_precision;
|
||||
}
|
||||
|
||||
for (int y = starty; y > 0 && y < texture_height-ThisGlyph->h; y += stepy)
|
||||
{
|
||||
// and alternate between left and right
|
||||
int startx, stepx;
|
||||
if (count & 2)
|
||||
startx = 1, stepx = packing_precision;
|
||||
else
|
||||
startx = texture_width-ThisGlyph->w-1, stepx = -packing_precision;
|
||||
|
||||
int x;
|
||||
|
||||
/* If you have a multiple-processor machine and the Intel C++ compiler,
|
||||
// this parallel version might be a little faster. (It's only a few
|
||||
// tens of percents slower on a hyperthreaded computer)
|
||||
|
||||
// [Assuming it works at all, which it probably doesn't because I haven't
|
||||
// tried compiling it recently]
|
||||
|
||||
if (startx == 1)
|
||||
{
|
||||
int max = texture_width-ThisGlyph->w;
|
||||
#pragma omp parallel shared(startx, texture_width, ThisGlyph, stepx, glyphs)
|
||||
{
|
||||
#pragma omp for schedule(static) nowait
|
||||
for (x = startx; x < max; x += stepx)
|
||||
{
|
||||
if (! TryFittingInternal(x, y, glyphs, ThisGlyph))
|
||||
{
|
||||
ThisGlyph->x = x;
|
||||
stepx = 1e9; // Ugly hack so the threads finish at the same time
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#pragma omp parallel shared(startx, texture_width, ThisGlyph, stepx, glyphs)
|
||||
{
|
||||
#pragma omp for schedule(static) nowait
|
||||
for (x = startx; x > 0; x += stepx)
|
||||
{
|
||||
if (! TryFittingInternal(x, y, glyphs, ThisGlyph))
|
||||
{
|
||||
ThisGlyph->x = x;
|
||||
stepx = -1e9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (stepx == 1e9 || stepx == -1e9)
|
||||
{
|
||||
ThisGlyph->y = y;
|
||||
goto fitted;
|
||||
}
|
||||
*/
|
||||
if (startx == 1)
|
||||
{
|
||||
for (x = startx; x < texture_width-ThisGlyph->w; x += stepx)
|
||||
{
|
||||
if (! TryFittingInternal(x, y, glyphs, ThisGlyph))
|
||||
{
|
||||
ThisGlyph->x = x;
|
||||
fitted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x = startx; x > 0; x += stepx)
|
||||
{
|
||||
if (! TryFittingInternal(x, y, glyphs, ThisGlyph))
|
||||
{
|
||||
ThisGlyph->x = x;
|
||||
fitted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fitted)
|
||||
{
|
||||
ThisGlyph->y = y;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (!fitted)
|
||||
// Couldn't fit glyph anywhere - give up
|
||||
return false;
|
||||
|
||||
//fitted: ; // for lazy people who just want to goto
|
||||
|
||||
LastGlyph = &*ThisGlyph;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TryFittingLots(int& texture_width, int& texture_height, GlyphsInfo& glyphs, bool ProgressCallback(float, wxString, void*), void* CallbackData)
|
||||
{
|
||||
// Try the fairly fast method
|
||||
if (TryFitting(16, texture_width, texture_height, false, glyphs, ProgressCallback, CallbackData))
|
||||
return true;
|
||||
|
||||
// Go a bit more carefully
|
||||
if (TryFitting(8, texture_width, texture_height, false, glyphs, ProgressCallback, CallbackData))
|
||||
return true;
|
||||
|
||||
// Maybe it just needs a little more precision?
|
||||
if (TryFitting(2, texture_width, texture_height, false, glyphs, ProgressCallback, CallbackData))
|
||||
return true;
|
||||
|
||||
// This takes a long time and doesn't usually achieve much, but try it anyway
|
||||
if (TryFitting(1, texture_width, texture_height, false, glyphs, ProgressCallback, CallbackData))
|
||||
return true;
|
||||
|
||||
// Try swapping the dimensions if it's currently rectangular
|
||||
if (texture_width != texture_height)
|
||||
{
|
||||
std::swap(texture_width, texture_height);
|
||||
if (TryFitting(1, texture_width, texture_height, false, glyphs, ProgressCallback, CallbackData))
|
||||
return true;
|
||||
// Didn't work, swap back again
|
||||
std::swap(texture_width, texture_height);
|
||||
}
|
||||
|
||||
// Double the size and try again
|
||||
if (texture_height == texture_width)
|
||||
texture_width *= 2;
|
||||
else
|
||||
texture_height *= 2;
|
||||
|
||||
if (TryFitting(32, texture_width, texture_height, true, glyphs, ProgressCallback, CallbackData))
|
||||
return true;
|
||||
|
||||
// How much space can it need?!
|
||||
if (TryFitting(4, texture_width, texture_height, false, glyphs, ProgressCallback, CallbackData))
|
||||
return true;
|
||||
|
||||
// Give up
|
||||
return false;
|
||||
}
|
||||
|
||||
void PackedFont::Generate(bool ProgressCallback(float, wxString, void*) = NULL, void* CallbackData = NULL)
|
||||
{
|
||||
GlyphsInfo glyphs;
|
||||
|
||||
int total_area = 0;
|
||||
|
||||
std::vector<wchar_t> MissingGlyphs;
|
||||
|
||||
int ProgressCurrent = 0;
|
||||
int ProgressMax = (int)Chars.size();
|
||||
|
||||
std::list<GlyphInfo> SortableGlyphs;
|
||||
|
||||
for (std::set<wchar_t>::iterator c = Chars.begin(); c != Chars.end(); ++c)
|
||||
{
|
||||
if (ProgressCallback != NULL)
|
||||
if (ProgressCallback((float)ProgressCurrent++ / (float)ProgressMax, wxT("Measuring"), CallbackData))
|
||||
throw "Aborted";
|
||||
|
||||
int w, h;
|
||||
Font->LoadGlyph(*c);
|
||||
if (Font->Missing)
|
||||
{
|
||||
// Was the missing glyph missing?
|
||||
if (*c == 0xFFFD)
|
||||
{
|
||||
// Just use a question mark. (Surely *every* font has a question mark...)
|
||||
Font->LoadGlyph('?');
|
||||
if (Font->Missing)
|
||||
throw "Can't find either a missing glyph symbol or a question mark!";
|
||||
Font->GetBoundingBox(w, h);
|
||||
SortableGlyphs.push_back( GlyphInfo('?', w, h) );
|
||||
total_area += w*h;
|
||||
}
|
||||
else
|
||||
{
|
||||
MissingGlyphs.push_back(*c);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Font->GetBoundingBox(w, h);
|
||||
SortableGlyphs.push_back( GlyphInfo(*c, w, h) );
|
||||
total_area += w*h;
|
||||
}
|
||||
}
|
||||
SortableGlyphs.sort();
|
||||
// Convert into a vector for a little more speed
|
||||
for (std::list<GlyphInfo>::iterator i = SortableGlyphs.begin(); i != SortableGlyphs.end(); ++i)
|
||||
{
|
||||
glyphs.push_back(*i);
|
||||
}
|
||||
|
||||
// Calculate minimum size square to hold all glyphs
|
||||
int texture_width, texture_height;
|
||||
texture_width = texture_height = next_power_of_two(int( sqrt((double)total_area) ));
|
||||
|
||||
// See if a smaller rectangle ought to still fit
|
||||
if (texture_width*texture_height > total_area*2)
|
||||
texture_height /= 2;
|
||||
|
||||
if (! TryFittingLots(texture_width, texture_height, glyphs, ProgressCallback, CallbackData))
|
||||
throw "Failed to fit all the glyphs, too many times.";
|
||||
|
||||
TextureData = new unsigned char[texture_width*texture_height*3];
|
||||
memset(TextureData, 0, texture_width*texture_height*3);
|
||||
TextureWidth = texture_width;
|
||||
TextureHeight = texture_height;
|
||||
|
||||
FontDefinition = wxEmptyString;
|
||||
FontDefinition += wxT("100\n"); // version number
|
||||
FontDefinition << TextureWidth << wxT(" ") << TextureHeight << wxT("\n"); // size of texture
|
||||
FontDefinition << (int)glyphs.size() << wxT("\n"); // number of glyphs
|
||||
FontDefinition << Font->GetLineSpacing() << wxT("\n");
|
||||
|
||||
SortableGlyphs.clear();
|
||||
for (GlyphsInfo::iterator i = glyphs.begin(); i != glyphs.end(); ++i)
|
||||
{
|
||||
SortableGlyphs.push_back(*i);
|
||||
}
|
||||
SortableGlyphs.sort(GlyphCharSort());
|
||||
|
||||
ProgressCurrent = 0;
|
||||
ProgressMax = (int)glyphs.size();
|
||||
for (std::list<GlyphInfo>::iterator ThisGlyph = SortableGlyphs.begin(); ThisGlyph != SortableGlyphs.end(); ++ThisGlyph)
|
||||
{
|
||||
if (ProgressCallback != NULL)
|
||||
if (ProgressCallback((float)ProgressCurrent++ / (float)ProgressMax, wxT("Rendering"), CallbackData))
|
||||
throw "Aborted";
|
||||
|
||||
Font->LoadGlyph(ThisGlyph->c);
|
||||
Font->RenderGlyph(TextureData, ThisGlyph->x, ThisGlyph->y, texture_width, texture_height, texture_width*3, true);
|
||||
int offset_x, offset_y, advance;
|
||||
Font->GetMetrics(offset_x, offset_y, advance);
|
||||
FontDefinition << (int)ThisGlyph->c
|
||||
<< wxT(" ") << ThisGlyph->x
|
||||
<< wxT(" ") << (TextureHeight - ThisGlyph->y) // because it's stored upside-down
|
||||
<< wxT(" ") << ThisGlyph->w
|
||||
<< wxT(" ") << ThisGlyph->h
|
||||
<< wxT(" ") << offset_x
|
||||
<< wxT(" ") << offset_y
|
||||
<< wxT(" ") << advance
|
||||
<< wxT("\n");
|
||||
}
|
||||
|
||||
if (MissingGlyphs.size())
|
||||
{
|
||||
wxString Error = wxString::Format(wxT("WARNING: %d glyphs were missing: "), MissingGlyphs.size());
|
||||
for (size_t i = 0; i < MissingGlyphs.size(); ++i)
|
||||
{
|
||||
if (i) Error += wxT(", ");
|
||||
if (i == 20)
|
||||
{
|
||||
Error += wxT("...");
|
||||
break;
|
||||
}
|
||||
Error += wxString::Format(wxT("%d"), MissingGlyphs[i]);
|
||||
}
|
||||
wxLogWarning(Error);
|
||||
}
|
||||
}
|
28
source/tools/fontbuilder/packer.h
Executable file
28
source/tools/fontbuilder/packer.h
Executable file
@ -0,0 +1,28 @@
|
||||
// $Id: packer.h,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
#include "font.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
class PackedFont
|
||||
{
|
||||
public:
|
||||
PackedFont(FontRenderer* font, std::set<wchar_t> chars);
|
||||
~PackedFont();
|
||||
|
||||
void Generate(bool ProgressCallback(float, wxString, void*), void* CallbackData);
|
||||
|
||||
// Sizes are always a power of two
|
||||
int TextureWidth;
|
||||
int TextureHeight;
|
||||
|
||||
// 24-bit (RGB) but greyscale image
|
||||
unsigned char* TextureData;
|
||||
|
||||
// For the text file describing how to read all the glyphs
|
||||
wxString FontDefinition;
|
||||
|
||||
private:
|
||||
FontRenderer* Font;
|
||||
std::set<wchar_t> Chars;
|
||||
};
|
24
source/tools/fontbuilder/platform/fontselect.h
Executable file
24
source/tools/fontbuilder/platform/fontselect.h
Executable file
@ -0,0 +1,24 @@
|
||||
// $Id: fontselect.h,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
class FontSelectorDialog : public wxDialog
|
||||
{
|
||||
public:
|
||||
FontSelectorDialog(wxWindow* parent);
|
||||
~FontSelectorDialog();
|
||||
|
||||
wxString FontName;
|
||||
wxString FontFilename;
|
||||
|
||||
void OnFontSelect(wxCommandEvent& event);
|
||||
void OnOK(wxCommandEvent& event);
|
||||
|
||||
static void DefaultFonts(wxString& Name0, wxString& Filename0, wxString& Name1, wxString& Filename1);
|
||||
|
||||
private:
|
||||
|
||||
wxArrayString FontNames;
|
||||
wxCharBuffer** FontFilenames;
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
136
source/tools/fontbuilder/platform/msw/fontselect.cpp
Executable file
136
source/tools/fontbuilder/platform/msw/fontselect.cpp
Executable file
@ -0,0 +1,136 @@
|
||||
// $Id: fontselect.cpp,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "../fontselect.h"
|
||||
|
||||
#include "wx/msw/registry.h"
|
||||
|
||||
enum
|
||||
{
|
||||
ID_FontList = wxID_HIGHEST+1,
|
||||
ID_FontPreview
|
||||
};
|
||||
|
||||
BEGIN_EVENT_TABLE(FontSelectorDialog, wxDialog)
|
||||
EVT_LISTBOX(ID_FontList, FontSelectorDialog::OnFontSelect)
|
||||
EVT_BUTTON(wxID_OK, FontSelectorDialog::OnOK)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
FontSelectorDialog::FontSelectorDialog(wxWindow* parent)
|
||||
: wxDialog(parent, -1, wxString(wxT("Font selector")), wxDefaultPosition, wxSize(400, 200), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
{
|
||||
wxBoxSizer* MainSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
wxString PreviewString;
|
||||
PreviewString += wxT("Aa");
|
||||
PreviewString += (wchar_t)0x0105; // LATIN SMALL LETTER A WITH OGONEK
|
||||
PreviewString += wxT("\nBb");
|
||||
PreviewString += (wchar_t)0x00DF; // LATIN SMALL LETTER SHARP S
|
||||
PreviewString += wxT("\nCc");
|
||||
PreviewString += (wchar_t)0x00E7; // LATIN SMALL LETTER C WITH CEDILLA
|
||||
PreviewString += (wchar_t)0x033F; // COMBINING DOUBLE OVERLINE
|
||||
PreviewString += wxT("\n");
|
||||
PreviewString += (wchar_t)0xFB4E; // HEBREW LETTER PE WITH RAFE
|
||||
PreviewString += (wchar_t)0xFB6B; // ARABIC LETTER VEH FINAL FORM
|
||||
PreviewString += (wchar_t)0xF915; // CJK COMPATIBILITY IDEOGRAPH-F915
|
||||
PreviewString += (wchar_t)0x3342; // SQUARE HOON
|
||||
|
||||
wxBoxSizer* TopSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxListBox* FontListBox = new wxListBox(this, ID_FontList, wxDefaultPosition, wxSize(200, 100));
|
||||
TopSizer->Add(FontListBox, 0, wxGROW);
|
||||
TopSizer->Add(new wxStaticText(this, ID_FontPreview, PreviewString), 1, wxGROW);
|
||||
MainSizer->Add(TopSizer, 1);
|
||||
|
||||
wxBoxSizer* ButtonSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
ButtonSizer->Add(new wxButton(this, wxID_OK, wxT("OK")), 0, wxALL, 10);
|
||||
ButtonSizer->Add(new wxButton(this, wxID_CANCEL, wxT("Cancel")), 0, wxALL, 10);
|
||||
MainSizer->Add(ButtonSizer, 0, wxALIGN_CENTER);
|
||||
|
||||
SetSizer(MainSizer);
|
||||
|
||||
// Get a list of all the fonts installed on the system
|
||||
|
||||
wxRegKey FontKey (wxT("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"));
|
||||
|
||||
// Get the list of keys (= font names)
|
||||
wxString ValueName;
|
||||
long ValueIndex;
|
||||
FontKey.GetFirstValue(ValueName, ValueIndex);
|
||||
do {
|
||||
if (! ValueName.IsEmpty())
|
||||
FontNames.Add(ValueName);
|
||||
} while (FontKey.GetNextValue(ValueName, ValueIndex));
|
||||
|
||||
FontNames.Sort();
|
||||
|
||||
// Get all the filenames, and store in the listbox's client data
|
||||
|
||||
FontFilenames = new wxCharBuffer*[FontNames.Count()];
|
||||
|
||||
for (size_t i = 0; i < FontNames.Count(); ++i)
|
||||
{
|
||||
wxString t;
|
||||
FontKey.QueryValue(FontNames[i], t);
|
||||
wxCharBuffer* b = new wxCharBuffer(t.mb_str());
|
||||
FontFilenames[i] = b;
|
||||
}
|
||||
|
||||
FontListBox->Set(FontNames, (void**)FontFilenames);
|
||||
}
|
||||
|
||||
FontSelectorDialog::~FontSelectorDialog()
|
||||
{
|
||||
for (size_t i = 0; i < FontNames.Count(); ++i)
|
||||
delete FontFilenames[i];
|
||||
delete[] FontFilenames;
|
||||
}
|
||||
|
||||
|
||||
void FontSelectorDialog::OnOK(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
// Find where the fonts are on the disk
|
||||
wxRegKey FontPathKey (wxT("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"));
|
||||
wxString FontPath;
|
||||
FontPathKey.QueryValue(wxT("Fonts"), FontPath);
|
||||
|
||||
wxListBox* FontList = (wxListBox*)wxWindow::FindWindowById(ID_FontList);
|
||||
|
||||
int Selection = FontList->GetSelection();
|
||||
FontFilename = FontPath + wxT("\\");
|
||||
FontFilename += wxString::FromAscii( ((wxCharBuffer*) FontList->GetClientData(Selection))->data() );
|
||||
|
||||
FontName = FontList->GetStringSelection();
|
||||
|
||||
EndModal(wxID_OK);
|
||||
}
|
||||
|
||||
|
||||
void FontSelectorDialog::OnFontSelect(wxCommandEvent& event)
|
||||
{
|
||||
wxString FontName = event.GetString();
|
||||
|
||||
// Translate "Arial (TrueType)" into "Arial", etc
|
||||
wxRegEx ThingyRemove;
|
||||
ThingyRemove.Compile(wxT(" \\(.+\\)$"));
|
||||
ThingyRemove.Replace(&FontName, wxT(""));
|
||||
|
||||
// Set the preview box to use that font
|
||||
wxFont PreviewFont (18, wxDEFAULT, wxNORMAL, wxNORMAL, false, FontName, wxFONTENCODING_SYSTEM);
|
||||
wxStaticText* PreviewText = (wxStaticText*)wxWindow::FindWindowById(ID_FontPreview);
|
||||
PreviewText->SetFont(PreviewFont);
|
||||
}
|
||||
|
||||
void FontSelectorDialog::DefaultFonts(wxString& Name0, wxString& Filename0, wxString& Name1, wxString& Filename1)
|
||||
{
|
||||
// Find where the fonts are on the disk
|
||||
wxRegKey FontPathKey (wxT("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"));
|
||||
wxString FontPath;
|
||||
FontPathKey.QueryValue(wxT("Fonts"), FontPath);
|
||||
|
||||
Name0 = wxT("Verdana (TrueType)");
|
||||
Filename0 = FontPath + wxT("\\verdana.ttf");
|
||||
Name1 = wxT("Arial Unicode MS (TrueType)");
|
||||
Filename1 = FontPath + wxT("\\arialuni.ttf");
|
||||
}
|
78
source/tools/fontbuilder/readme.html
Executable file
78
source/tools/fontbuilder/readme.html
Executable file
@ -0,0 +1,78 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Font Builder</title>
|
||||
</head>
|
||||
<body bgcolor="#fff4e6" text="black" style="font-family:sans-serif">
|
||||
|
||||
<h2>Font Builder</h2>
|
||||
|
||||
<h3>Usage</h3>
|
||||
|
||||
<ol>
|
||||
<li>Choose a <i>primary font</i>, which will be used for as much as
|
||||
it can be used for.
|
||||
<li>Optionally, choose a different <i>secondary font</i> which is used
|
||||
when the primary font is missing certain characters - for example,
|
||||
Trebuchet doesn't include any Greek/Cyrillic/Hebrew characters, so
|
||||
these will be taken from Arial Unicode MS (by default) instead.
|
||||
<li>Use the <i>Preview font</i> button to see what the font looks like
|
||||
by rendering the contents of the textbox. Adjust the font settings
|
||||
until perfection is attained.
|
||||
<li>Choose a desired <i>character list</i> - a text file containing
|
||||
all the characters that must be in the final font. The standard files
|
||||
are <tt>latin.txt</tt> (containing ASCII plus some accented characters,
|
||||
mainly useful for non-localised text) and <tt>standard.txt</tt>
|
||||
(containing Latin, Greek, Cyrillic and Hebrew characters, for text that
|
||||
could be in any language).
|
||||
<li>Click <i>Generate texture</i>, and select a name for the <tt>.fnt</tt>
|
||||
file. A <tt>.tga</tt> texture will also be generated, in the same directory
|
||||
with the same name. Depending on several random coincidences, the texture
|
||||
generation might be very fast or might take quite a while. When it finishes, the
|
||||
excitingly patterned texture will be displayed.
|
||||
<li>Save your settings through the <i>File</i> menu so that you can
|
||||
easily recreate the font later.
|
||||
</ol>
|
||||
|
||||
<h3>Unicode fonts</h3>
|
||||
|
||||
<p>
|
||||
|
||||
The font builder is intended to be used with Unicode characters.
|
||||
Unfortunately, most fonts aren't. The font builder tries
|
||||
to use <i>Arial Unicode MS</i> by default: this seems to
|
||||
be installed by some versions of Microsoft Office, or can
|
||||
be downloaded from locations such as
|
||||
<a href="http://wildfiregames.com/~code/libraries/fonts/arialuni.exe">this</a> (12MB
|
||||
self-extracting 7-Zip). It's probably worth getting, since it
|
||||
includes almost every Unicode glyph that you could wish for.
|
||||
|
||||
</p><p>
|
||||
|
||||
Another potentially useful Unicode font is Bitstream Cyberbit
|
||||
(available from <a href="ftp://ftp.netscape.com/pub/communicator/extras/fonts/windows/Cyberbit.ZIP">Netscape's FTP server</a>,
|
||||
6MB).
|
||||
|
||||
</p><p>
|
||||
|
||||
All fonts must be installed into Windows before you can use
|
||||
them in the font builder.
|
||||
|
||||
</p>
|
||||
|
||||
<h3>Font settings</h3>
|
||||
|
||||
<ul>
|
||||
<li><b>Size</b> - size of the font in arbitrary units.
|
||||
<li><b>Boldness</b> - if you don't have a proper bold variation of the
|
||||
font, the boldness setting fakes it by drawing
|
||||
the character several times.
|
||||
<li><b>Italicness</b> - if you don't have a proper italic variaton,
|
||||
the italicness setting slants it in 5-degree increments. Negative
|
||||
values slant the other way.
|
||||
<li><b>Tracking</b> - extra spacing in pixels added between every
|
||||
non-zero-width glyph.
|
||||
<li><b>Leading</b> - extra spacing in pixels between lines of text.
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
25
source/tools/fontbuilder/resource.h
Executable file
25
source/tools/fontbuilder/resource.h
Executable file
@ -0,0 +1,25 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by FontBuilder.rc
|
||||
//
|
||||
#define IDC_MYICON 2
|
||||
#define IDD_FONTBUILDER_DIALOG 102
|
||||
#define IDS_APP_TITLE 103
|
||||
#define IDM_ABOUT 104
|
||||
#define IDM_EXIT 105
|
||||
#define IDI_FONTBUILDER 107
|
||||
#define IDC_FONTBUILDER 109
|
||||
#define IDR_MAINFRAME 128
|
||||
#define IDC_STATIC -1
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NO_MFC 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 130
|
||||
#define _APS_NEXT_COMMAND_VALUE 32771
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 110
|
||||
#endif
|
||||
#endif
|
7
source/tools/fontbuilder/stdafx.cpp
Executable file
7
source/tools/fontbuilder/stdafx.cpp
Executable file
@ -0,0 +1,7 @@
|
||||
// $Id: stdafx.cpp,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// FontBuilder.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
54
source/tools/fontbuilder/stdafx.h
Executable file
54
source/tools/fontbuilder/stdafx.h
Executable file
@ -0,0 +1,54 @@
|
||||
// $Id: stdafx.h,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
// Precompiled headers
|
||||
|
||||
// Exclude rarely-used stuff from Windows headers
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
// Disable some complaints in wx headers
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4267 4311 1125)
|
||||
|
||||
#ifdef __INTEL_COMPILER
|
||||
// Disable some of the excessively pedantic icl /W4 warnings (remarks)
|
||||
#pragma warning (disable: 193 373 444 981 383 1418)
|
||||
#endif
|
||||
|
||||
// Include relevant wx headers
|
||||
#include "wx/wxprec.h"
|
||||
#include "wx/image.h"
|
||||
#include "wx/spinctrl.h"
|
||||
#include "wx/regex.h"
|
||||
#include "wx/ffile.h"
|
||||
#include "wx/utils.h"
|
||||
#include "wx/progdlg.h"
|
||||
#include "wx/wxexpr.h"
|
||||
#include "wx/docview.h"
|
||||
#include "wx/config.h"
|
||||
#include "wx/filename.h"
|
||||
#include "wx/config.h"
|
||||
|
||||
#pragma warning (pop)
|
||||
|
||||
#include <set>
|
||||
#include <list>
|
||||
|
||||
|
||||
//// Things other than precompiled headers which
|
||||
// are just useful to include everywhere:
|
||||
|
||||
// For nicer memory-leak detection
|
||||
#ifdef _DEBUG
|
||||
#include <crtdbg.h>
|
||||
#define new new(_NORMAL_BLOCK ,__FILE__, __LINE__)
|
||||
#endif
|
||||
|
||||
const wxString version = wxT("v0.9");
|
||||
|
||||
// Don't care about copy constructors / assignment operators
|
||||
#pragma warning (disable: 4511 4512)
|
||||
|
||||
#ifdef __INTEL_COMPILER
|
||||
// Disable some of the excessively pedantic warnings again
|
||||
#pragma warning (disable: 193 373 444 981 383 1418)
|
||||
#endif
|
16
source/tools/fontbuilder/todo.txt
Executable file
16
source/tools/fontbuilder/todo.txt
Executable file
@ -0,0 +1,16 @@
|
||||
$Id: todo.txt,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
* Optimise storage of duplicated bitmaps (e.g. e and e-with-some-accent,
|
||||
comma and semicolon, anything and fullwidth versions, etc)
|
||||
|
||||
* Optional antialiasing
|
||||
|
||||
* Optional outlining (text with e.g. yellow fill and black outline
|
||||
is made by drawing the black outline font and then the yellow
|
||||
normal font)
|
||||
|
||||
* Are the one-pixel black borders necessary? I don't trust graphics
|
||||
cards not to leak a little bit, especially when they force texture
|
||||
compression and filtering and antialiasing
|
||||
|
||||
* Work out when I should say 'character', when 'code point', and when 'glyph'
|
34
source/tools/fontbuilder/wxapp.cpp
Executable file
34
source/tools/fontbuilder/wxapp.cpp
Executable file
@ -0,0 +1,34 @@
|
||||
// $Id: wxapp.cpp,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "wxframe.h"
|
||||
#include "wxconfig.h"
|
||||
|
||||
class FontBuilderApp : public wxApp
|
||||
{
|
||||
public:
|
||||
virtual bool OnInit();
|
||||
virtual int OnExit();
|
||||
};
|
||||
|
||||
|
||||
IMPLEMENT_APP(FontBuilderApp)
|
||||
|
||||
bool FontBuilderApp::OnInit()
|
||||
{
|
||||
ConfigInit();
|
||||
|
||||
MainFrame *frame = new MainFrame(wxString::Format(wxT("Font Builder %s"), version), wxDefaultPosition, wxSize(640,480));
|
||||
frame->SetIcon(wxIcon(wxT("IDI_ICON1")));
|
||||
frame->Show(true);
|
||||
SetTopWindow(frame);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int FontBuilderApp::OnExit()
|
||||
{
|
||||
ConfigDestroy();
|
||||
return 0;
|
||||
}
|
55
source/tools/fontbuilder/wxconfig.cpp
Executable file
55
source/tools/fontbuilder/wxconfig.cpp
Executable file
@ -0,0 +1,55 @@
|
||||
// $Id: wxconfig.cpp,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "wxconfig.h"
|
||||
|
||||
void ConfigInit()
|
||||
{
|
||||
wxConfig* cfg = new wxConfig(wxT("WFG Font Builder"));
|
||||
wxConfig::Set(cfg);
|
||||
|
||||
// Default paths, for the first time program is run:
|
||||
|
||||
// Get "x:\wherever\etc\binaries\"
|
||||
wxFileName cwd = wxFileName::GetCwd()+wxT("\\");
|
||||
cwd.RemoveDir((int)cwd.GetDirCount()-1);
|
||||
|
||||
if (!ConfigGet(wxT("FSF path")))
|
||||
{
|
||||
wxFileName dir = cwd; dir.AppendDir(wxT("data\\tools\\fontbuilder\\settings"));
|
||||
ConfigSet(wxT("FSF path"), dir.GetPath(wxPATH_GET_VOLUME));
|
||||
}
|
||||
|
||||
if (!ConfigGet(wxT("FNT path")))
|
||||
{
|
||||
wxFileName dir = cwd; dir.AppendDir(wxT("data\\mods\\official\\fonts"));
|
||||
ConfigSet(wxT("FNT path"), dir.GetPath(wxPATH_GET_VOLUME));
|
||||
}
|
||||
|
||||
if (!ConfigGet(wxT("Charset path")))
|
||||
{
|
||||
wxFileName dir = cwd; dir.AppendDir(wxT("data\\tools\\fontbuilder\\charsets"));
|
||||
ConfigSet(wxT("Charset path"), dir.GetPath(wxPATH_GET_VOLUME));
|
||||
}
|
||||
}
|
||||
|
||||
wxString ConfigGet(wxString key)
|
||||
{
|
||||
wxConfig* cfg = (wxConfig*) wxConfig::Get();
|
||||
wxString ret;
|
||||
cfg->Read(key, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ConfigSet(wxString key, wxString value)
|
||||
{
|
||||
wxConfig* cfg = (wxConfig*) wxConfig::Get();
|
||||
cfg->Write(key, value);
|
||||
}
|
||||
|
||||
void ConfigDestroy()
|
||||
{
|
||||
delete wxConfig::Get();
|
||||
}
|
||||
|
6
source/tools/fontbuilder/wxconfig.h
Executable file
6
source/tools/fontbuilder/wxconfig.h
Executable file
@ -0,0 +1,6 @@
|
||||
// $Id: wxconfig.h,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
void ConfigInit();
|
||||
wxString ConfigGet(wxString key);
|
||||
void ConfigSet(wxString key, wxString value);
|
||||
void ConfigDestroy();
|
575
source/tools/fontbuilder/wxframe.cpp
Executable file
575
source/tools/fontbuilder/wxframe.cpp
Executable file
@ -0,0 +1,575 @@
|
||||
// $Id: wxframe.cpp,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "wxframe.h"
|
||||
#include "wxconfig.h"
|
||||
#include "wxspinner.h"
|
||||
|
||||
#include "platform/fontselect.h"
|
||||
|
||||
#include "imagemanip.h"
|
||||
#include "font.h"
|
||||
#include "packer.h"
|
||||
#include "filemanip.h"
|
||||
|
||||
bool Changes = false;
|
||||
|
||||
enum
|
||||
{
|
||||
ID_Quit = wxID_HIGHEST+1,
|
||||
ID_About,
|
||||
ID_New,
|
||||
ID_Save,
|
||||
ID_Open,
|
||||
ID_Recent,
|
||||
|
||||
ID_GeneratePreview,
|
||||
ID_GenerateTexture,
|
||||
|
||||
ID_FontSelect0,
|
||||
ID_FontSelect1,
|
||||
ID_CharSelect,
|
||||
|
||||
// For accessing values:
|
||||
ID_PreviewText,
|
||||
ID_Style_Size,
|
||||
ID_Style_Boldness,
|
||||
ID_Style_Italicness,
|
||||
ID_Style_Tracking,
|
||||
ID_Style_Leading
|
||||
};
|
||||
|
||||
BEGIN_EVENT_TABLE(MainFrame, wxFrame)
|
||||
EVT_MENU(ID_Quit, MainFrame::OnQuit)
|
||||
EVT_MENU(ID_About, MainFrame::OnAbout)
|
||||
EVT_MENU(ID_Save, MainFrame::OnSave)
|
||||
EVT_MENU(ID_Open, MainFrame::OnOpen)
|
||||
EVT_MENU_RANGE(wxID_FILE1, wxID_FILE9, MainFrame::OnMRUFile)
|
||||
|
||||
EVT_BUTTON(ID_FontSelect0, MainFrame::OnFontSelect0)
|
||||
EVT_BUTTON(ID_FontSelect1, MainFrame::OnFontSelect1)
|
||||
EVT_BUTTON(ID_CharSelect, MainFrame::OnCharSelect)
|
||||
|
||||
EVT_BUTTON(ID_GeneratePreview, MainFrame::OnGeneratePreview)
|
||||
EVT_BUTTON(ID_GenerateTexture, MainFrame::OnGenerateTexture)
|
||||
|
||||
EVT_CLOSE(MainFrame::OnClose)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE(BitmapPanel, wxPanel)
|
||||
EVT_PAINT(BitmapPanel::OnPaint)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
MainFrame::MainFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
|
||||
: wxFrame((wxFrame *)NULL, -1, title, pos, size)
|
||||
{
|
||||
RecentFiles = new wxFileHistory(5);
|
||||
|
||||
wxMenu* menuFile = new wxMenu;
|
||||
|
||||
//menuFile->Append(ID_New, wxT("&New"));
|
||||
menuFile->Append(ID_Open, wxT("&Open..."));
|
||||
menuFile->Append(ID_Save, wxT("&Save..."));
|
||||
menuFile->AppendSeparator();
|
||||
wxMenu* menuRecent = new wxMenu;
|
||||
menuFile->Append(ID_Recent, wxT("&Recent files"), menuRecent);
|
||||
menuFile->AppendSeparator();
|
||||
menuFile->Append(ID_About, wxT("&About"));
|
||||
menuFile->AppendSeparator();
|
||||
menuFile->Append(ID_Quit, wxT("E&xit"));
|
||||
|
||||
RecentFiles->UseMenu(menuRecent);
|
||||
|
||||
wxConfig* config = (wxConfig*)wxConfig::Get();
|
||||
RecentFiles->Load(*config);
|
||||
|
||||
wxMenuBar* menuBar = new wxMenuBar;
|
||||
menuBar->Append(menuFile, wxT("&File"));
|
||||
|
||||
SetMenuBar(menuBar);
|
||||
|
||||
CreateStatusBar();
|
||||
|
||||
// For textboxes that need to display Unicode text:
|
||||
wxFont ArialUnicodeFont (12, wxDEFAULT, wxNORMAL, wxNORMAL, false, wxT("Arial Unicode MS"), wxFONTENCODING_SYSTEM);
|
||||
|
||||
// Main panel that fills the whole window
|
||||
wxPanel* Panel = new wxPanel(this);
|
||||
|
||||
// Split the window into three main rows - controls, preview text, graphic
|
||||
wxBoxSizer* OutlineSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
// Split the controls part into three main columns: font, styles, actions
|
||||
wxBoxSizer* ControlSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
// Get some default values
|
||||
FontSelectorDialog::DefaultFonts(FontName0, FontFilename0, FontName1, FontFilename1);
|
||||
CharFilename = wxT("<ascii>");
|
||||
CharName = wxT("Basic ASCII");
|
||||
|
||||
wxFlexGridSizer* FontSizer = new wxFlexGridSizer(2);
|
||||
FontSizer->AddGrowableCol(0);
|
||||
|
||||
FontSizer->Add(new wxStaticText(Panel, -1, wxT("Primary font:")), 0, wxALIGN_RIGHT | wxALL, 2);
|
||||
FontSizer->Add(new wxButton(Panel, ID_FontSelect0, FontName0), 0, wxGROW | wxALL, 2);
|
||||
|
||||
FontSizer->Add(new wxStaticText(Panel, -1, wxT("Secondary font:")), 0, wxALIGN_RIGHT | wxALL, 2);
|
||||
FontSizer->Add(new wxButton(Panel, ID_FontSelect1, FontName1), 0, wxGROW | wxALL, 2);
|
||||
|
||||
FontSizer->Add(new wxStaticText(Panel, -1, wxT("Character list:")), 0, wxALIGN_RIGHT | wxALL, 2);
|
||||
FontSizer->Add(new wxButton(Panel, ID_CharSelect, CharName), 0, wxGROW | wxALL, 2);
|
||||
|
||||
ControlSizer->Add(FontSizer, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_HORIZONTAL | wxALIGN_TOP, 8);
|
||||
|
||||
wxFlexGridSizer* StyleSizer = new wxFlexGridSizer(2);
|
||||
StyleSizer->AddGrowableCol(0);
|
||||
|
||||
StyleSizer->Add(new wxStaticText(Panel, -1, wxT("Size:")), 0, wxALIGN_RIGHT | wxLEFT | wxRIGHT, 2);
|
||||
StyleSizer->Add(new StyleSpinCtrl(Panel, ID_Style_Size, 1, 1024, 18), 0, wxGROW | wxLEFT | wxRIGHT, 2);
|
||||
|
||||
StyleSizer->Add(new wxStaticText(Panel, -1, wxT("Boldness:")), 0, wxALIGN_RIGHT | wxLEFT | wxRIGHT, 2);
|
||||
StyleSizer->Add(new StyleSpinCtrl(Panel, ID_Style_Boldness, 0, 16, 0), 0, wxGROW | wxLEFT | wxRIGHT, 2);
|
||||
|
||||
StyleSizer->Add(new wxStaticText(Panel, -1, wxT("Italicness:")), 0, wxALIGN_RIGHT | wxLEFT | wxRIGHT, 2);
|
||||
StyleSizer->Add(new StyleSpinCtrl(Panel, ID_Style_Italicness, -16, 16, 0), 0, wxGROW | wxLEFT | wxRIGHT, 2);
|
||||
|
||||
StyleSizer->Add(new wxStaticText(Panel, -1, wxT("Tracking:")), 0, wxALIGN_RIGHT | wxLEFT | wxRIGHT, 2);
|
||||
StyleSizer->Add(new StyleSpinCtrl(Panel, ID_Style_Tracking, -256, 256, 0), 0, wxGROW | wxLEFT | wxRIGHT, 2);
|
||||
|
||||
StyleSizer->Add(new wxStaticText(Panel, -1, wxT("Leading:")), 0, wxALIGN_RIGHT | wxLEFT | wxRIGHT, 2);
|
||||
StyleSizer->Add(new StyleSpinCtrl(Panel, ID_Style_Leading, -256, 256, 0), 0, wxGROW | wxLEFT | wxRIGHT, 2);
|
||||
|
||||
ControlSizer->Add(StyleSizer, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER, 8);
|
||||
|
||||
wxBoxSizer* GenerateSizer = new wxBoxSizer(wxVERTICAL);
|
||||
GenerateSizer->Add(new wxButton(Panel, ID_GeneratePreview, wxT("Preview font")), 1, wxGROW | wxALL | wxALIGN_CENTER, 4);
|
||||
GenerateSizer->Add(new wxButton(Panel, ID_GenerateTexture, wxT("Generate texture")), 1, wxGROW | wxALL | wxALIGN_CENTER, 4);
|
||||
ControlSizer->Add(GenerateSizer, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_HORIZONTAL | wxALIGN_TOP, 8);
|
||||
|
||||
OutlineSizer->Add(ControlSizer);
|
||||
|
||||
OutlineSizer->Add(new wxStaticText(Panel, -1, wxT("Text to display in preview:")), 0, wxALL, 2);
|
||||
|
||||
// Create a textbox containing "abcABCfunnysymbols"
|
||||
wxString Font_string = wxT("abcABC"); Font_string += wchar_t(225); Font_string += wchar_t(223); Font_string += wchar_t(231); Font_string += wchar_t(779);Font_string += wchar_t(9812);
|
||||
wxTextCtrl* PreviewTextBox = new wxTextCtrl(Panel, ID_PreviewText, Font_string, wxDefaultPosition, wxSize(300, 80), wxTE_MULTILINE);
|
||||
PreviewTextBox->SetFont(ArialUnicodeFont);
|
||||
|
||||
OutlineSizer->Add(PreviewTextBox, 0, wxGROW | wxLEFT | wxRIGHT, 4);
|
||||
|
||||
PreviewPanel = new BitmapPanel(Panel);
|
||||
OutlineSizer->Add(PreviewPanel, 1, wxGROW);
|
||||
|
||||
Panel->SetSizer(OutlineSizer);
|
||||
|
||||
PreviewImageData = NULL;
|
||||
PreviewImage = NULL;
|
||||
PreviewWidth = 512;
|
||||
PreviewHeight = 256;
|
||||
}
|
||||
|
||||
|
||||
void MainFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
Close(false);
|
||||
}
|
||||
|
||||
void MainFrame::OnClose(wxCloseEvent& event)
|
||||
{
|
||||
if (Changes)
|
||||
{
|
||||
wxMessageDialog dlg (this, wxT("The font settings have been altered.\n\nDo you want to save the changes?"), wxT("Font Builder"), wxYES_NO|wxCANCEL | wxICON_QUESTION);
|
||||
int ret = dlg.ShowModal();
|
||||
if (ret == wxID_CANCEL)
|
||||
{
|
||||
event.Veto();
|
||||
return;
|
||||
}
|
||||
else if (ret == wxID_YES)
|
||||
{
|
||||
if (! SaveDialog())
|
||||
{
|
||||
event.Veto();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wxConfig* config = (wxConfig*)wxConfig::Get();
|
||||
RecentFiles->Save(*config);
|
||||
delete RecentFiles;
|
||||
|
||||
delete PreviewImage;
|
||||
delete[] PreviewImageData;
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void MainFrame::LoadSettings(wxString& filename)
|
||||
{
|
||||
wxExprDatabase db;
|
||||
|
||||
db.Read(filename);
|
||||
|
||||
wxTextCtrl* PreviewTextCtrl = (wxTextCtrl*)wxWindow::FindWindowById(ID_PreviewText);
|
||||
StyleSpinCtrl* BoldnessCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Boldness);
|
||||
StyleSpinCtrl* ItalicnessCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Italicness);
|
||||
StyleSpinCtrl* SizeCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Size);
|
||||
StyleSpinCtrl* TrackingCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Tracking);
|
||||
StyleSpinCtrl* LeadingCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Leading);
|
||||
wxButton* FontSelect0 = (wxButton*)wxWindow::FindWindowById(ID_FontSelect0);
|
||||
wxButton* FontSelect1 = (wxButton*)wxWindow::FindWindowById(ID_FontSelect1);
|
||||
wxButton* CharSelect = (wxButton*)wxWindow::FindWindowById(ID_CharSelect);
|
||||
|
||||
db.BeginFind();
|
||||
|
||||
wxExpr *Settings = db.FindClauseByFunctor(wxT("Settings"));
|
||||
Settings->GetAttributeValue(wxT("FontName0"), FontName0);
|
||||
Settings->GetAttributeValue(wxT("FontName1"), FontName1);
|
||||
Settings->GetAttributeValue(wxT("FontFilename0"), FontFilename0);
|
||||
Settings->GetAttributeValue(wxT("FontFilename1"), FontFilename1);
|
||||
FontSelect0->SetLabel(FontName0);
|
||||
FontSelect1->SetLabel(FontName1);
|
||||
|
||||
Settings->GetAttributeValue(wxT("CharName"), CharName);
|
||||
Settings->GetAttributeValue(wxT("CharFilename"), CharFilename);
|
||||
CharSelect->SetLabel(CharName);
|
||||
|
||||
int t;
|
||||
Settings->GetAttributeValue(wxT("Boldness"), t); BoldnessCtrl->SetValue(t);
|
||||
Settings->GetAttributeValue(wxT("Italicness"), t); ItalicnessCtrl->SetValue(t);
|
||||
Settings->GetAttributeValue(wxT("Size"), t); SizeCtrl->SetValue(t);
|
||||
Settings->GetAttributeValue(wxT("Tracking"), t); TrackingCtrl->SetValue(t);
|
||||
Settings->GetAttributeValue(wxT("Leading"), t); LeadingCtrl->SetValue(t);
|
||||
|
||||
wxString PreviewTextUTF;
|
||||
Settings->GetAttributeValue(wxT("PreviewText"), PreviewTextUTF);
|
||||
|
||||
// Unpleasant conversion from UTF8 (pretending to be UTF16) into UTF16:
|
||||
char* buffer = new char[PreviewTextUTF.length()+1];
|
||||
for (size_t i=0; i<PreviewTextUTF.length(); ++i)
|
||||
buffer[i] = (char)PreviewTextUTF.GetChar(i);
|
||||
buffer[PreviewTextUTF.length()] = 0;
|
||||
wxString PreviewText (buffer, wxConvUTF8);
|
||||
delete[] buffer;
|
||||
|
||||
PreviewTextCtrl->SetValue(PreviewText);
|
||||
|
||||
Changes = false;
|
||||
}
|
||||
|
||||
void MainFrame::SaveSettings(wxString& filename)
|
||||
{
|
||||
wxExprDatabase db;
|
||||
|
||||
wxTextCtrl* PreviewTextCtrl = (wxTextCtrl*)wxWindow::FindWindowById(ID_PreviewText);
|
||||
StyleSpinCtrl* BoldnessCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Boldness);
|
||||
StyleSpinCtrl* ItalicnessCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Italicness);
|
||||
StyleSpinCtrl* SizeCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Size);
|
||||
StyleSpinCtrl* TrackingCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Tracking);
|
||||
StyleSpinCtrl* LeadingCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Leading);
|
||||
|
||||
wxExpr *Settings = new wxExpr(wxT("Settings"));
|
||||
Settings->AddAttributeValueString(wxT("FontName0"), FontName0);
|
||||
Settings->AddAttributeValueString(wxT("FontName1"), FontName1);
|
||||
Settings->AddAttributeValueString(wxT("FontFilename0"), FontFilename0);
|
||||
Settings->AddAttributeValueString(wxT("FontFilename1"), FontFilename1);
|
||||
Settings->AddAttributeValueString(wxT("CharName"), CharName);
|
||||
Settings->AddAttributeValueString(wxT("CharFilename"), CharFilename);
|
||||
Settings->AddAttributeValue(wxT("Boldness"), (long)BoldnessCtrl->GetValidValue());
|
||||
Settings->AddAttributeValue(wxT("Italicness"), (long)ItalicnessCtrl->GetValidValue());
|
||||
Settings->AddAttributeValue(wxT("Size"), (long)SizeCtrl->GetValidValue());
|
||||
Settings->AddAttributeValue(wxT("Tracking"), (long)TrackingCtrl->GetValidValue());
|
||||
Settings->AddAttributeValue(wxT("Leading"), (long)LeadingCtrl->GetValidValue());
|
||||
|
||||
// Convert into UTF8 and pretend it's ASCII, because wxExprDatabase doesn't like Unicode
|
||||
wxCharBuffer PreviewTextUTF = PreviewTextCtrl->GetValue().mb_str(wxConvUTF8);
|
||||
Settings->AddAttributeValueString(wxT("PreviewText"), wxString::FromAscii(PreviewTextUTF));
|
||||
|
||||
db.Append(Settings);
|
||||
|
||||
db.Write(filename);
|
||||
|
||||
Changes = false;
|
||||
}
|
||||
|
||||
|
||||
void MainFrame::OnOpen(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
wxFileDialog Dlg (this, wxT("Open font settings"), ConfigGet(wxT("FSF path")), wxEmptyString, wxT("Font settings (*.fst)|*.fst|All files (*.*)|*.*"), wxOPEN | wxHIDE_READONLY);
|
||||
if (Dlg.ShowModal() == wxID_OK)
|
||||
{
|
||||
RecentFiles->AddFileToHistory(Dlg.GetPath());
|
||||
wxString path = Dlg.GetPath();
|
||||
LoadSettings(path);
|
||||
ConfigSet(wxT("FSF path"), Dlg.GetDirectory());
|
||||
}
|
||||
}
|
||||
|
||||
bool MainFrame::SaveDialog()
|
||||
{
|
||||
wxFileDialog Dlg (this, wxT("Save current settings"), ConfigGet(wxT("FSF path")), wxEmptyString, wxT("Font settings (*.fst)|*.fst|All files (*.*)|*.*"), wxSAVE | wxOVERWRITE_PROMPT);
|
||||
if (Dlg.ShowModal() == wxID_OK)
|
||||
{
|
||||
RecentFiles->AddFileToHistory(Dlg.GetPath());
|
||||
wxString path = Dlg.GetPath();
|
||||
SaveSettings(path);
|
||||
ConfigSet(wxT("FSF path"), Dlg.GetDirectory());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void MainFrame::OnSave(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
SaveDialog();
|
||||
}
|
||||
|
||||
|
||||
void MainFrame::OnMRUFile(wxCommandEvent& event)
|
||||
{
|
||||
wxString filename = RecentFiles->GetHistoryFile(event.GetId() - wxID_FILE1);
|
||||
LoadSettings(filename);
|
||||
RecentFiles->AddFileToHistory(filename);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MainFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
wxMessageBox(wxString::Format(wxT("Unicode Font Builder %s - created by Philip Taylor for WildFire Games"), version), wxT("About"), wxOK | wxICON_INFORMATION );
|
||||
}
|
||||
|
||||
|
||||
void MainFrame::OnGeneratePreview(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
GeneratePreview();
|
||||
}
|
||||
|
||||
void MainFrame::GeneratePreview()
|
||||
{
|
||||
if (FontFilename0.IsEmpty() || FontFilename1.IsEmpty())
|
||||
return;
|
||||
|
||||
PreviewPanel->GetSize(&PreviewWidth, &PreviewHeight);
|
||||
|
||||
delete[] PreviewImageData;
|
||||
PreviewImageData = GenerateImage(PreviewWidth, PreviewHeight);
|
||||
|
||||
// Find all the relevant controls (slightly nicer than storing lots of pointers in the class)
|
||||
wxTextCtrl* PreviewTextCtrl = (wxTextCtrl*)wxWindow::FindWindowById(ID_PreviewText);
|
||||
StyleSpinCtrl* BoldnessCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Boldness);
|
||||
StyleSpinCtrl* ItalicnessCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Italicness);
|
||||
StyleSpinCtrl* SizeCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Size);
|
||||
StyleSpinCtrl* TrackingCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Tracking);
|
||||
StyleSpinCtrl* LeadingCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Leading);
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
FontRenderer Font(
|
||||
FontFilename0.ToAscii(),
|
||||
FontFilename1.ToAscii(),
|
||||
SizeCtrl->GetValidValue() );
|
||||
|
||||
Font.Boldness = BoldnessCtrl->GetValidValue();
|
||||
Font.Italicness = 5 * ItalicnessCtrl->GetValidValue();
|
||||
Font.Tracking = TrackingCtrl->GetValidValue();
|
||||
Font.Leading = LeadingCtrl->GetValidValue();
|
||||
Font.Outline = false;
|
||||
|
||||
int x = 16, y = Font.GetLineSpacing();
|
||||
|
||||
wxString PreviewText = PreviewTextCtrl->GetValue();
|
||||
for (size_t i = 0; i < PreviewText.Length(); ++i)
|
||||
{
|
||||
if (PreviewText[i] == wxT('\n'))
|
||||
{
|
||||
x = 16;
|
||||
y += Font.GetLineSpacing();
|
||||
}
|
||||
else
|
||||
{
|
||||
Font.LoadGlyph(PreviewText[i]);
|
||||
Font.RenderGlyph(PreviewImageData, x, y, PreviewWidth, PreviewHeight, PreviewWidth*3, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const char* m) {
|
||||
wxLogError(wxString::Format(wxT("Failed to generate preview: %s"), wxString::FromAscii(m)));
|
||||
return;
|
||||
}
|
||||
|
||||
delete PreviewImage;
|
||||
PreviewImage = new wxImage(PreviewWidth, PreviewHeight, PreviewImageData, true);
|
||||
PreviewPanel->SetBitmap(new wxBitmap(PreviewImage));
|
||||
|
||||
PreviewPanel->Refresh();
|
||||
|
||||
Changes = true;
|
||||
}
|
||||
|
||||
|
||||
void MainFrame::OnGenerateTexture(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
wxFileDialog Dlg (this, wxT("Save font definition and texture"), ConfigGet(wxT("FNT path")), wxEmptyString, wxT("Font definition files (*.fnt)|*.fnt|All files (*.*)|*.*"), wxSAVE | wxOVERWRITE_PROMPT);
|
||||
if (Dlg.ShowModal() == wxID_OK)
|
||||
{
|
||||
wxFileName FontDefnFilename (Dlg.GetPath());
|
||||
wxFileName TextureFilename = FontDefnFilename;
|
||||
TextureFilename.SetExt(wxT("tga"));
|
||||
GenerateTexture(TextureFilename.GetFullPath(), FontDefnFilename.GetFullPath());
|
||||
ConfigSet(wxT("FNT path"), TextureFilename.GetPath());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ProgressDialogCallback(float Progress, wxString Msg, void* data) {
|
||||
return ! ((wxProgressDialog *)data)->Update((int)(Progress*1024.0), Msg);
|
||||
}
|
||||
|
||||
void MainFrame::GenerateTexture(wxString TextureFilename, wxString FontDefnFilename)
|
||||
{
|
||||
if (FontFilename0.IsEmpty() || FontFilename1.IsEmpty())
|
||||
return;
|
||||
|
||||
// Find all the relevant controls (slightly nicer than storing lots of pointers in the class)
|
||||
StyleSpinCtrl* BoldnessCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Boldness);
|
||||
StyleSpinCtrl* ItalicnessCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Italicness);
|
||||
StyleSpinCtrl* SizeCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Size);
|
||||
StyleSpinCtrl* TrackingCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Tracking);
|
||||
StyleSpinCtrl* LeadingCtrl = (StyleSpinCtrl*)wxWindow::FindWindowById(ID_Style_Leading);
|
||||
|
||||
|
||||
// Work out what characters need to be included in the texture
|
||||
|
||||
std::set<wchar_t> Chars;
|
||||
if (CharFilename == wxT("<ascii>"))
|
||||
{
|
||||
for (wchar_t c = 0x20; c < 0x7f; ++c)
|
||||
Chars.insert(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
Chars = AnalyseChars(CharFilename);
|
||||
}
|
||||
catch (const char* m) {
|
||||
wxLogError(wxString::Format(wxT("Failed to analyse character file: %s"), wxString::FromAscii(m)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Add the 'missing' symbol (if it's not missing, it'll use a ? instead)
|
||||
Chars.insert(0xFFFD);
|
||||
|
||||
// Generate the texture
|
||||
try
|
||||
{
|
||||
FontRenderer Font(
|
||||
FontFilename0.ToAscii(),
|
||||
FontFilename1.ToAscii(),
|
||||
SizeCtrl->GetValidValue() );
|
||||
|
||||
Font.Boldness = BoldnessCtrl->GetValidValue();
|
||||
Font.Italicness = 5 * ItalicnessCtrl->GetValidValue();
|
||||
Font.Tracking = TrackingCtrl->GetValidValue();
|
||||
Font.Leading = LeadingCtrl->GetValidValue();
|
||||
Font.Outline = false;
|
||||
|
||||
PackedFont Packed (&Font, Chars);
|
||||
|
||||
wxProgressDialog ProgressDialog (wxT("Progress"), wxT("Thinking..."), 1024, this, wxPD_APP_MODAL | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME);
|
||||
|
||||
try
|
||||
{
|
||||
Packed.Generate(&ProgressDialogCallback, &ProgressDialog);
|
||||
}
|
||||
catch (const char* m) {
|
||||
wxLogError(wxString::Format(wxT("Failed to generate texture: %s"), wxString::FromAscii(m)));
|
||||
return;
|
||||
}
|
||||
|
||||
ProgressDialog.Destroy();
|
||||
|
||||
PreviewWidth = Packed.TextureWidth;
|
||||
PreviewHeight = Packed.TextureHeight;
|
||||
delete[] PreviewImageData;
|
||||
PreviewImageData = new unsigned char[PreviewWidth*PreviewHeight*3];
|
||||
memcpy(PreviewImageData, Packed.TextureData, PreviewWidth*PreviewHeight*3);
|
||||
|
||||
delete PreviewImage;
|
||||
PreviewImage = new wxImage(PreviewWidth, PreviewHeight, PreviewImageData, true);
|
||||
PreviewPanel->SetBitmap(new wxBitmap(PreviewImage));
|
||||
|
||||
PreviewPanel->Refresh();
|
||||
|
||||
wxFFile TGAFile(TextureFilename, "wb");
|
||||
if (! TGAFile.IsOpened())
|
||||
throw "Error opening texture file for output";
|
||||
RGB_OutputGreyscaleTGA(PreviewImageData, PreviewWidth, PreviewHeight, PreviewWidth*3, TGAFile);
|
||||
TGAFile.Close();
|
||||
|
||||
wxFFile FntFile(FontDefnFilename, "w");
|
||||
if (! FntFile.IsOpened())
|
||||
throw "Error opening font definition file for output";
|
||||
FntFile.Write(Packed.FontDefinition);
|
||||
FntFile.Close();
|
||||
}
|
||||
catch (const char* m) {
|
||||
wxLogError(wxString::Format(wxT("Failed to generate texture: %s"), wxString::FromAscii(m)));
|
||||
return;
|
||||
}
|
||||
|
||||
Changes = true;
|
||||
}
|
||||
|
||||
|
||||
void MainFrame::OnFontSelect0(wxCommandEvent& event)
|
||||
{
|
||||
FontSelectorDialog Dlg(this);
|
||||
if (Dlg.ShowModal() == wxID_OK)
|
||||
{
|
||||
FontFilename0 = Dlg.FontFilename;
|
||||
FontName0 = Dlg.FontName;
|
||||
((wxButton*)event.GetEventObject()) -> SetLabel(FontName0);
|
||||
}
|
||||
}
|
||||
|
||||
void MainFrame::OnFontSelect1(wxCommandEvent& event)
|
||||
{
|
||||
FontSelectorDialog Dlg(this);
|
||||
if (Dlg.ShowModal() == wxID_OK)
|
||||
{
|
||||
FontFilename1 = Dlg.FontFilename;
|
||||
FontName1 = Dlg.FontName;
|
||||
((wxButton*)event.GetEventObject()) -> SetLabel(FontName1);
|
||||
}
|
||||
}
|
||||
|
||||
void MainFrame::OnCharSelect(wxCommandEvent& event)
|
||||
{
|
||||
wxFileDialog Dlg(this, wxT("UTF16 text file containing desired characters"), ConfigGet(wxT("Charset path")), wxEmptyString, wxT("Text files (*.txt)|*.txt|All files (*.*)|*.*"), wxOPEN | wxHIDE_READONLY);
|
||||
if (Dlg.ShowModal() == wxID_OK)
|
||||
{
|
||||
CharFilename = Dlg.GetPath();
|
||||
CharName = Dlg.GetFilename();
|
||||
((wxButton*)event.GetEventObject()) -> SetLabel(CharName);
|
||||
ConfigSet(wxT("Charset path"), Dlg.GetDirectory());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void BitmapPanel::OnPaint(wxPaintEvent& WXUNUSED(event))
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
if (Bitmap)
|
||||
dc.DrawBitmap(*Bitmap, 0, 0, false);
|
||||
}
|
78
source/tools/fontbuilder/wxframe.h
Executable file
78
source/tools/fontbuilder/wxframe.h
Executable file
@ -0,0 +1,78 @@
|
||||
// $Id: wxframe.h,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
class BitmapPanel : public wxPanel
|
||||
{
|
||||
public:
|
||||
BitmapPanel(wxWindow* parent)
|
||||
: wxPanel(parent)
|
||||
{
|
||||
Bitmap = NULL;
|
||||
}
|
||||
|
||||
~BitmapPanel()
|
||||
{
|
||||
delete Bitmap;
|
||||
}
|
||||
|
||||
void OnPaint(wxPaintEvent& event);
|
||||
void SetBitmap(wxBitmap* bmp)
|
||||
{
|
||||
delete Bitmap;
|
||||
Bitmap = bmp;
|
||||
}
|
||||
|
||||
private:
|
||||
wxBitmap* Bitmap;
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
|
||||
|
||||
class MainFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
MainFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
|
||||
|
||||
void OnQuit(wxCommandEvent& event);
|
||||
void OnClose(wxCloseEvent& event);
|
||||
void OnAbout(wxCommandEvent& event);
|
||||
|
||||
bool SaveDialog();
|
||||
void OnSave(wxCommandEvent& event);
|
||||
void OnOpen(wxCommandEvent& event);
|
||||
|
||||
void OnMRUFile(wxCommandEvent& event);
|
||||
|
||||
void OnFontSelect0(wxCommandEvent& event);
|
||||
void OnFontSelect1(wxCommandEvent& event);
|
||||
void OnCharSelect(wxCommandEvent& event);
|
||||
|
||||
void OnGeneratePreview(wxCommandEvent& event);
|
||||
void OnGenerateTexture(wxCommandEvent& event);
|
||||
|
||||
private:
|
||||
BitmapPanel* PreviewPanel;
|
||||
unsigned char* PreviewImageData;
|
||||
wxImage* PreviewImage;
|
||||
|
||||
void GeneratePreview();
|
||||
int PreviewWidth, PreviewHeight;
|
||||
|
||||
void GenerateTexture(wxString TextureFilename, wxString FontDefnFilename);
|
||||
|
||||
void SaveSettings(wxString& filename);
|
||||
void LoadSettings(wxString& filename);
|
||||
|
||||
wxString FontName0;
|
||||
wxString FontName1;
|
||||
wxString FontFilename0;
|
||||
wxString FontFilename1;
|
||||
|
||||
wxString CharName;
|
||||
wxString CharFilename;
|
||||
|
||||
wxFileHistory* RecentFiles;
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
22
source/tools/fontbuilder/wxspinner.h
Executable file
22
source/tools/fontbuilder/wxspinner.h
Executable file
@ -0,0 +1,22 @@
|
||||
// $Id: wxspinner.h,v 1.1 2004/06/17 19:32:04 philip Exp $
|
||||
|
||||
class StyleSpinCtrl : public wxSpinCtrl
|
||||
{
|
||||
public:
|
||||
|
||||
StyleSpinCtrl(wxWindow* parent, wxWindowID win_id, int min_val, int max_val, int initial_val)
|
||||
: wxSpinCtrl(parent, win_id, wxEmptyString, wxDefaultPosition, wxSize(50, 20), wxSP_ARROW_KEYS, min_val, max_val, initial_val)
|
||||
{
|
||||
SetValue(initial_val);
|
||||
}
|
||||
|
||||
// Like GetValue, but guaranteed to be inside the range (Min..Max)
|
||||
// no matter what people type in
|
||||
int GetValidValue()
|
||||
{
|
||||
int Value = GetValue();
|
||||
int Min = GetMin();
|
||||
int Max = GetMax();
|
||||
return Value <= Min ? Min : Value >= Max ? Max : Value;
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user