File: myx_gc_font_manager.cpp

package info (click to toggle)
mysql-query-browser 1.1.6-1sarge0
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 36,320 kB
  • ctags: 24,680
  • sloc: pascal: 203,479; xml: 136,561; ansic: 47,502; cpp: 28,926; sh: 12,433; objc: 4,823; java: 1,849; php: 1,485; python: 1,225; sql: 1,128; makefile: 872
file content (218 lines) | stat: -rw-r--r-- 7,712 bytes parent folder | download
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();
}

//----------------------------------------------------------------------------------------------------------------------