winFont.cpp
Engine/source/platformWin32/winFont.cpp
Public Defines
define
NUMCHARSETMAP() (sizeof(charsetMap) / sizeof())
Public Variables
Public Functions
CopyCharToBitmap(GBitmap * pDstBMP, HDC hSrcHDC, const RectI & r)
createPlatformFont(const char * name, dsize_t size, U32 charset)
BOOL CALLBACK
EnumFamCallBack(LPLOGFONT logFont, LPNEWTEXTMETRIC textMetric, DWORD fontType, LPARAM lParam)
Detailed Description
Public Defines
NUMCHARSETMAP() (sizeof(charsetMap) / sizeof())
Public Variables
U32 charsetMap []
HBITMAP fontBMP
HDC fontHDC
Public Functions
CopyCharToBitmap(GBitmap * pDstBMP, HDC hSrcHDC, const RectI & r)
createFontInit(void )
createFontShutdown(void )
createPlatformFont(const char * name, dsize_t size, U32 charset)
EnumFamCallBack(LPLOGFONT logFont, LPNEWTEXTMETRIC textMetric, DWORD fontType, LPARAM lParam)
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platformWin32/platformWin32.h" 25#include "platformWin32/winFont.h" 26 27#include "gfx/gFont.h" 28#include "gfx/bitmap/gBitmap.h" 29#include "math/mRect.h" 30#include "console/console.h" 31#include "core/strings/unicode.h" 32#include "core/strings/stringFunctions.h" 33#include "core/stringTable.h" 34 35static HDC fontHDC = NULL; 36static HBITMAP fontBMP = NULL; 37 38static U32 charsetMap[]= 39{ 40 ANSI_CHARSET, 41 SYMBOL_CHARSET, 42 SHIFTJIS_CHARSET, 43 HANGEUL_CHARSET, 44 HANGUL_CHARSET, 45 GB2312_CHARSET, 46 CHINESEBIG5_CHARSET, 47 OEM_CHARSET, 48 JOHAB_CHARSET, 49 HEBREW_CHARSET, 50 ARABIC_CHARSET, 51 GREEK_CHARSET, 52 TURKISH_CHARSET, 53 VIETNAMESE_CHARSET, 54 THAI_CHARSET, 55 EASTEUROPE_CHARSET, 56 RUSSIAN_CHARSET, 57 MAC_CHARSET, 58 BALTIC_CHARSET, 59}; 60#define NUMCHARSETMAP (sizeof(charsetMap) / sizeof(U32)) 61 62void createFontInit(void); 63void createFontShutdown(void); 64void CopyCharToBitmap(GBitmap *pDstBMP, HDC hSrcHDC, const RectI &r); 65 66void createFontInit() 67{ 68 //shared library sets the appInstance here 69 winState.appInstance = GetModuleHandle(NULL); 70 fontHDC = CreateCompatibleDC(NULL); 71 fontBMP = CreateCompatibleBitmap(fontHDC, 256, 256); 72} 73 74void createFontShutdown() 75{ 76 DeleteObject(fontBMP); 77 DeleteObject(fontHDC); 78} 79 80void CopyCharToBitmap(GBitmap *pDstBMP, HDC hSrcHDC, const RectI &r) 81{ 82 for (S32 i = r.point.y; i < r.point.y + r.extent.y; i++) 83 { 84 for (S32 j = r.point.x; j < r.point.x + r.extent.x; j++) 85 { 86 COLORREF color = GetPixel(hSrcHDC, j, i); 87 if (color) 88 *pDstBMP->getAddress(j, i) = 255; 89 else 90 *pDstBMP->getAddress(j, i) = 0; 91 } 92 } 93} 94 95//----------------------------------------------------------------------------- 96// WinFont class 97//----------------------------------------------------------------------------- 98 99BOOL CALLBACK EnumFamCallBack(LPLOGFONT logFont, LPNEWTEXTMETRIC textMetric, DWORD fontType, LPARAM lParam) 100{ 101 if( !( fontType & TRUETYPE_FONTTYPE ) ) 102 return true; 103 104 Vector<StringTableEntry>* fonts = (Vector< StringTableEntry>*)lParam; 105 106 const U32 len = dStrlen( logFont->lfFaceName ) * 3 + 1; 107 FrameTemp<UTF8> buffer( len ); 108 convertUTF16toUTF8N( logFont->lfFaceName, buffer, len ); 109 110 fonts->push_back( StringTable->insert( buffer ) ); 111 112 return true; 113} 114 115void PlatformFont::enumeratePlatformFonts( Vector<StringTableEntry>& fonts, UTF16* fontFamily ) 116{ 117 EnumFontFamilies( fontHDC, fontFamily, (FONTENUMPROC)EnumFamCallBack, (LPARAM)&fonts ); 118} 119 120PlatformFont *createPlatformFont(const char *name, dsize_t size, U32 charset /* = TGE_ANSI_CHARSET */) 121{ 122 PlatformFont *retFont = new WinFont; 123 124 if(retFont->create(name, size, charset)) 125 return retFont; 126 127 delete retFont; 128 return NULL; 129} 130 131WinFont::WinFont() : mFont(NULL) 132{ 133} 134 135WinFont::~WinFont() 136{ 137 if(mFont) 138 { 139 DeleteObject(mFont); 140 } 141} 142 143bool WinFont::create(const char *name, dsize_t size, U32 charset /* = TGE_ANSI_CHARSET */) 144{ 145 if(name == NULL || size < 1) 146 return false; 147 148 if(charset > NUMCHARSETMAP) 149 charset = TGE_ANSI_CHARSET; 150 151 U32 weight = 0; 152 U32 doItalic = 0; 153 154 String nameStr = name; 155 nameStr = nameStr.trim(); 156 157 bool haveModifier; 158 do 159 { 160 haveModifier = false; 161 if( nameStr.compare( "Bold", 4, String::NoCase | String::Right ) == 0 ) 162 { 163 weight = 700; 164 nameStr = nameStr.substr( 0, nameStr.length() - 4 ).trim(); 165 haveModifier = true; 166 } 167 if( nameStr.compare( "Italic", 6, String::NoCase | String::Right ) == 0 ) 168 { 169 doItalic = 1; 170 nameStr = nameStr.substr( 0, nameStr.length() - 6 ).trim(); 171 haveModifier = true; 172 } 173 } 174 while( haveModifier ); 175 176#ifdef UNICODE 177 const UTF16* n = nameStr.utf16(); 178 mFont = CreateFont(size,0,0,0,weight,doItalic,0,0,DEFAULT_CHARSET,OUT_TT_PRECIS,0,PROOF_QUALITY,0,n); 179#else 180 mFont = CreateFont(size,0,0,0,weight,doItalic,0,0,charsetMap[charset],OUT_TT_PRECIS,0,PROOF_QUALITY,0,name); 181#endif 182 if(mFont == NULL) 183 return false; 184 185 SelectObject(fontHDC, fontBMP); 186 SelectObject(fontHDC, mFont); 187 GetTextMetrics(fontHDC, &mTextMetric); 188 189 return true; 190} 191 192bool WinFont::isValidChar(const UTF16 ch) const 193{ 194 return ch != 0 /* && (ch >= mTextMetric.tmFirstChar && ch <= mTextMetric.tmLastChar)*/; 195} 196 197bool WinFont::isValidChar(const UTF8 *str) const 198{ 199 return isValidChar(oneUTF8toUTF32(str)); 200} 201 202 203PlatformFont::CharInfo &WinFont::getCharInfo(const UTF16 ch) const 204{ 205 static PlatformFont::CharInfo c; 206 207 dMemset(&c, 0, sizeof(c)); 208 c.bitmapIndex = -1; 209 210 static U8 scratchPad[65536]; 211 212 COLORREF backgroundColorRef = RGB( 0, 0, 0); 213 COLORREF foregroundColorRef = RGB(255, 255, 255); 214 SelectObject(fontHDC, fontBMP); 215 SelectObject(fontHDC, mFont); 216 SetBkColor(fontHDC, backgroundColorRef); 217 SetTextColor(fontHDC, foregroundColorRef); 218 219 MAT2 matrix; 220 GLYPHMETRICS metrics; 221 RectI clip; 222 223 FIXED zero; 224 zero.fract = 0; 225 zero.value = 0; 226 FIXED one; 227 one.fract = 0; 228 one.value = 1; 229 230 matrix.eM11 = one; 231 matrix.eM12 = zero; 232 matrix.eM21 = zero; 233 matrix.eM22 = one; 234 235 236 if(GetGlyphOutline( 237 fontHDC, // handle of device context 238 ch, // character to query 239 GGO_GRAY8_BITMAP, // format of data to return 240 &metrics, // address of structure for metrics 241 sizeof(scratchPad), // size of buffer for data 242 scratchPad, // address of buffer for data 243 &matrix // address of transformation matrix structure 244 ) != GDI_ERROR) 245 { 246 U32 rowStride = (metrics.gmBlackBoxX + 3) & ~3; // DWORD aligned 247 U32 size = rowStride * metrics.gmBlackBoxY; 248 249 // [neo, 5/7/2007 - #3055] 250 // If we get large font sizes rowStride * metrics.gmBlackBoxY will 251 // be larger than scratch pad size and so overwrite mem, boom! 252 // Added range check < scratchPad for now but we need to review what 253 // to do here - do we want to call GetGlyphOutline() first with null 254 // values and get the real size to alloc buffer? 255 //if( size > sizeof( scratchPad ) ) 256 // DebugBreak(); 257 258 for(U32 j = 0; j < size && j < sizeof(scratchPad); j++) 259 { 260 U32 pad = U32(scratchPad[j]) << 2; 261 if(pad > 255) 262 pad = 255; 263 scratchPad[j] = pad; 264 } 265 S32 inc = metrics.gmCellIncX; 266 if(inc < 0) 267 inc = -inc; 268 269 c.xOffset = 0; 270 c.yOffset = 0; 271 c.width = metrics.gmBlackBoxX; 272 c.height = metrics.gmBlackBoxY; 273 c.xOrigin = metrics.gmptGlyphOrigin.x; 274 c.yOrigin = metrics.gmptGlyphOrigin.y; 275 c.xIncrement = metrics.gmCellIncX; 276 277 c.bitmapData = new U8[c.width * c.height]; 278 AssertFatal( c.bitmapData != NULL, "Could not allocate memory for font bitmap data!"); 279 for(U32 y = 0; S32(y) < c.height; y++) 280 { 281 U32 x; 282 for(x = 0; x < c.width; x++) 283 { 284 // [neo, 5/7/2007 - #3055] 285 // See comments above about scratchPad overrun 286 S32 spi = y * rowStride + x; 287 288 if( spi >= sizeof(scratchPad) ) 289 return c; 290 291 c.bitmapData[y * c.width + x] = scratchPad[spi]; 292 } 293 } 294 } 295 else 296 { 297 SIZE size; 298 GetTextExtentPoint32W(fontHDC, &ch, 1, &size); 299 if(size.cx) 300 { 301 c.xIncrement = size.cx; 302 c.bitmapIndex = 0; 303 } 304 } 305 306 return c; 307} 308 309PlatformFont::CharInfo &WinFont::getCharInfo(const UTF8 *str) const 310{ 311 return getCharInfo(oneUTF8toUTF32(str)); 312} 313
