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 dMemset(&mTextMetric, 0, sizeof(mTextMetric)); 134} 135 136WinFont::~WinFont() 137{ 138 if(mFont) 139 { 140 DeleteObject(mFont); 141 } 142} 143 144bool WinFont::create(const char *name, dsize_t size, U32 charset /* = TGE_ANSI_CHARSET */) 145{ 146 if(name == NULL || size < 1) 147 return false; 148 149 if(charset > NUMCHARSETMAP) 150 charset = TGE_ANSI_CHARSET; 151 152 U32 weight = 0; 153 U32 doItalic = 0; 154 155 String nameStr = name; 156 nameStr = nameStr.trim(); 157 158 bool haveModifier; 159 do 160 { 161 haveModifier = false; 162 if( nameStr.compare( "Bold", 4, String::NoCase | String::Right ) == 0 ) 163 { 164 weight = 700; 165 nameStr = nameStr.substr( 0, nameStr.length() - 4 ).trim(); 166 haveModifier = true; 167 } 168 if( nameStr.compare( "Italic", 6, String::NoCase | String::Right ) == 0 ) 169 { 170 doItalic = 1; 171 nameStr = nameStr.substr( 0, nameStr.length() - 6 ).trim(); 172 haveModifier = true; 173 } 174 } 175 while( haveModifier ); 176 177#ifdef UNICODE 178 const UTF16* n = nameStr.utf16(); 179 mFont = CreateFont(size,0,0,0,weight,doItalic,0,0,DEFAULT_CHARSET,OUT_TT_PRECIS,0,PROOF_QUALITY,0,n); 180#else 181 mFont = CreateFont(size,0,0,0,weight,doItalic,0,0,charsetMap[charset],OUT_TT_PRECIS,0,PROOF_QUALITY,0,name); 182#endif 183 if(mFont == NULL) 184 return false; 185 186 SelectObject(fontHDC, fontBMP); 187 SelectObject(fontHDC, mFont); 188 GetTextMetrics(fontHDC, &mTextMetric); 189 190 return true; 191} 192 193bool WinFont::isValidChar(const UTF16 ch) const 194{ 195 return ch != 0 /* && (ch >= mTextMetric.tmFirstChar && ch <= mTextMetric.tmLastChar)*/; 196} 197 198bool WinFont::isValidChar(const UTF8 *str) const 199{ 200 return isValidChar(oneUTF8toUTF32(str)); 201} 202 203 204PlatformFont::CharInfo &WinFont::getCharInfo(const UTF16 ch) const 205{ 206 static PlatformFont::CharInfo c; 207 208 dMemset(&c, 0, sizeof(c)); 209 c.bitmapIndex = -1; 210 211 static U8 scratchPad[65536]; 212 213 COLORREF backgroundColorRef = RGB( 0, 0, 0); 214 COLORREF foregroundColorRef = RGB(255, 255, 255); 215 SelectObject(fontHDC, fontBMP); 216 SelectObject(fontHDC, mFont); 217 SetBkColor(fontHDC, backgroundColorRef); 218 SetTextColor(fontHDC, foregroundColorRef); 219 220 MAT2 matrix; 221 GLYPHMETRICS metrics; 222 RectI clip; 223 224 FIXED zero; 225 zero.fract = 0; 226 zero.value = 0; 227 FIXED one; 228 one.fract = 0; 229 one.value = 1; 230 231 matrix.eM11 = one; 232 matrix.eM12 = zero; 233 matrix.eM21 = zero; 234 matrix.eM22 = one; 235 236 237 if(GetGlyphOutline( 238 fontHDC, // handle of device context 239 ch, // character to query 240 GGO_GRAY8_BITMAP, // format of data to return 241 &metrics, // address of structure for metrics 242 sizeof(scratchPad), // size of buffer for data 243 scratchPad, // address of buffer for data 244 &matrix // address of transformation matrix structure 245 ) != GDI_ERROR) 246 { 247 U32 rowStride = (metrics.gmBlackBoxX + 3) & ~3; // DWORD aligned 248 U32 size = rowStride * metrics.gmBlackBoxY; 249 250 // [neo, 5/7/2007 - #3055] 251 // If we get large font sizes rowStride * metrics.gmBlackBoxY will 252 // be larger than scratch pad size and so overwrite mem, boom! 253 // Added range check < scratchPad for now but we need to review what 254 // to do here - do we want to call GetGlyphOutline() first with null 255 // values and get the real size to alloc buffer? 256 //if( size > sizeof( scratchPad ) ) 257 // DebugBreak(); 258 259 for(U32 j = 0; j < size && j < sizeof(scratchPad); j++) 260 { 261 U32 pad = U32(scratchPad[j]) << 2; 262 if(pad > 255) 263 pad = 255; 264 scratchPad[j] = pad; 265 } 266 S32 inc = metrics.gmCellIncX; 267 if(inc < 0) 268 inc = -inc; 269 270 c.xOffset = 0; 271 c.yOffset = 0; 272 c.width = metrics.gmBlackBoxX; 273 c.height = metrics.gmBlackBoxY; 274 c.xOrigin = metrics.gmptGlyphOrigin.x; 275 c.yOrigin = metrics.gmptGlyphOrigin.y; 276 c.xIncrement = metrics.gmCellIncX; 277 278 c.bitmapData = new U8[c.width * c.height]; 279 AssertFatal( c.bitmapData != NULL, "Could not allocate memory for font bitmap data!"); 280 for(U32 y = 0; S32(y) < c.height; y++) 281 { 282 U32 x; 283 for(x = 0; x < c.width; x++) 284 { 285 // [neo, 5/7/2007 - #3055] 286 // See comments above about scratchPad overrun 287 S32 spi = y * rowStride + x; 288 289 if( spi >= sizeof(scratchPad) ) 290 return c; 291 292 c.bitmapData[y * c.width + x] = scratchPad[spi]; 293 } 294 } 295 } 296 else 297 { 298 SIZE size; 299 GetTextExtentPoint32W(fontHDC, &ch, 1, &size); 300 if(size.cx) 301 { 302 c.xIncrement = size.cx; 303 c.bitmapIndex = 0; 304 } 305 } 306 307 return c; 308} 309 310PlatformFont::CharInfo &WinFont::getCharInfo(const UTF8 *str) const 311{ 312 return getCharInfo(oneUTF8toUTF32(str)); 313} 314