1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
|
/* Copyright (C) 2004 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/**
* @file myx_gc_model.cpp
* @brief Implementation of the model that manages the visual representation in the generic canvas.
*
*/
#ifdef _WINDOWS
#include <windows.h>
#else
#endif // ifdef _WINDOWS
#include <assert.h>
#include <gl/gl.h>
#include "myx_gc_font_manager.h"
#include "myx_gc_utilities.h"
//----------------------------------------------------------------------------------------------------------------------
CFontManager InternalManager;
// Returns the current font manager (there is always only one).
CFontManager* FontManager(void)
{
return &InternalManager;
}
//----------------------------------------------------------------------------------------------------------------------
CFontManager::~CFontManager(void)
{
Clear();
}
//----------------------------------------------------------------------------------------------------------------------
// Creates a default font entry for all used, but not previously defined fonts.
void CFontManager::CreateDefaultEntry(void)
{
CreateFontEntry(DefaultFontFamily, DefaultFontStyle, 400, DefaultFontDecoration);
FDefaultKey = CreateLookupKey(DefaultFontFamily, DefaultFontStyle, 400, DefaultFontDecoration);
}
//----------------------------------------------------------------------------------------------------------------------
// Creates a range of display lists that match the given font properties and inserts the new font entry in the internal list.
// Note: currently only the first 256 characters of a font are considered. There is a bit more to do for Unicode.
TFontEntry CFontManager::CreateFontEntry(const string& Family, const string& Style, int Weight, const string& Decoration)
{
TFontEntry Entry;
// Check if this font was already defined.
string Key = CreateLookupKey(Family, Style, Weight, Decoration);
CFontListIterator Iterator = FFontList.find(Key);
if (Iterator != FFontList.end())
return Iterator->second;
else
{
Entry.Range = 256;
Entry.Base = glGenLists(Entry.Range);
BOOL isItalic = FALSE;
BOOL isUnderlined = FALSE;
BOOL isStruckOut = FALSE;
// Parse style string. Note this is UTF-8 encoded, however only certain ASCII strings are valid in this context.
// Hence no conversion to UTF-16 is necessary.
char Separators[] = "|";
char* Buffer = new char[Decoration.size() + 1];
strncpy(Buffer, Decoration.c_str(), Decoration.size());
Buffer[Decoration.size()] = '\0';
char* Token = strtok(Buffer, Separators);
while (Token != NULL)
{
if (strcmp("underline", Token) == 0)
isUnderlined = TRUE;
else
if (strcmp("line-through", Token) == 0)
isStruckOut = TRUE;
Token = strtok(NULL, Separators);
};
delete[] Buffer;
if ((Style == "italic") || (Style == "oblique"))
isItalic = TRUE;
// Covert font family name from utf8 to WideChar.
wstring FontName = Utf8ToUtf16(Family);
#ifdef _WINDOWS
// This part is now highly platform specific. We need Unicode support here, which should be enabled for the project.
HDC DC = CreateCompatibleDC(0);
try
{
LOGFONT FontData;
// Note: The font size doesn't really matter here (it shouldn't be too small though), because we can scale the text
// arbitrarily using OpenGL commands.
FontData.lfHeight = -20;
FontData.lfWidth = 0;
FontData.lfEscapement = 0;
FontData.lfOrientation = 0;
FontData.lfWeight = Weight;
FontData.lfItalic = isItalic;
FontData.lfUnderline = isUnderlined;
FontData.lfStrikeOut = isStruckOut;
FontData.lfCharSet = DEFAULT_CHARSET;
FontData.lfOutPrecision = OUT_TT_ONLY_PRECIS;
FontData.lfClipPrecision = CLIP_DEFAULT_PRECIS;
FontData.lfQuality = PROOF_QUALITY;
FontData.lfPitchAndFamily = VARIABLE_PITCH;
wcscpy(FontData.lfFaceName, FontName.c_str());
HFONT Font = CreateFontIndirect(&FontData);
HFONT OldFont = (HFONT) SelectObject(DC, Font);
if (!wglUseFontOutlines(DC, 0, Entry.Range, Entry.Base, 0, 0, WGL_FONT_POLYGONS, NULL))
{
#ifdef _DEBUG
char Buffer[1000];
DWORD ErrorNum = GetLastError();
DWORD Len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ARGUMENT_ARRAY, NULL, ErrorNum, 0, Buffer,
sizeof(Buffer), NULL);
ASSERT(false, Buffer);
#endif // #ifdef _DEBUG
glDeleteLists(Entry.Base, Entry.Range);
Entry.Base = 0;
Entry.Range = 0;
};
SelectObject(DC, OldFont);
DeleteObject(Font);
ReleaseDC(0, DC);
}
catch(...)
{
ReleaseDC(0, DC);
throw;
}
#else
TODO: Create display lists for non-Windows platforms.
#endif // _WINDOWS
// Store the new font entry in the internal list.
FFontList[Key] = Entry;
};
return Entry;
}
//----------------------------------------------------------------------------------------------------------------------
// Creates a string that can be used for lookup in the font list.
// Either parameter can be NULL (or 0 for Weight) causing the manager to use the default values for them each missing
// parameter. See header file for the list of default values.
string CFontManager::CreateLookupKey(const string& Family, const string& Style, int Weight, const string& Decoration)
{
char WeightString[11];
// Construct a lookup string out of the font properties.
string Key = Family + Style + Decoration;
itoa(Weight, WeightString, 10);
Key += WeightString;
return Key;
}
//----------------------------------------------------------------------------------------------------------------------
// Looks up a font display list determined by the given attributes. Either parameter can be NULL (or 0 for Weight)
// causing the manager to use the default values for them each missing parameter.
// See header file for the list of default values.
// If there is no such font entry defined as given by the paramerters then a default list base is returned.
GLuint CFontManager::GetFontBase(const string& Family, const string& Style, int Weight, const string& Decoration)
{
string Key = CreateLookupKey(Family, Style, Weight, Decoration);
CFontListIterator Entry = FFontList.find(Key);
if (Entry == FFontList.end())
{
TFontEntry Default = FFontList[FDefaultKey];
return Default.Base;
}
else
return Entry->second.Base;
}
//----------------------------------------------------------------------------------------------------------------------
// Clears the font list and deletes all display lists.
void CFontManager::Clear(void)
{
for (CFontListIterator Iterator = FFontList.begin(); Iterator != FFontList.end(); Iterator++)
{
glDeleteLists(Iterator->second.Base, Iterator->second.Range);
};
FFontList.clear();
}
//----------------------------------------------------------------------------------------------------------------------
|