// http://www.codeproject.com/KB/GDI-plus/measurestring.aspx RectF MeasureTextAccurate(Graphics* g, Font* f, const WCHAR* s, int len) { if (0 == len) { return RectF(0, 0, 0, 0); // TODO: should set height to font's height } // note: frankly, I don't see a difference between those StringFormat variations StringFormat sf(StringFormat::GenericTypographic()); sf.SetFormatFlags(sf.GetFormatFlags() | StringFormatFlagsMeasureTrailingSpaces); // StringFormat sf(StringFormat::GenericDefault()); // StringFormat sf; RectF layoutRect; CharacterRange cr(0, len); sf.SetMeasurableCharacterRanges(1, &cr); Region r; Status status = g->MeasureCharacterRanges(s, len, f, layoutRect, &sf, 1, &r); if (status != Ok) { // TODO: remove whem we figure out why we crash if (!s) { s = L"<null>"; } auto s2 = str::conv::ToUtf8(s, (size_t)len); dbglog::CrashLogF("MeasureTextAccurate: status: %d, font: %p, len: %d, s: '%s'\n", (int)status, f, len, s2.Get()); CrashIf(status != Ok); } RectF bbox; r.GetBounds(&bbox, g); if (bbox.Width != 0) bbox.Width += PER_STR_DX_ADJUST + (PER_CHAR_DX_ADJUST * (float)len); return bbox; }
// -------------------------------------------------------------- void GFontWin32GDIPlus::GetExtent( const char * str, int inCharCount, float * outWidth, float * outHeight, VGDevice * context ) const { if (!inCharCount) { *outWidth = *outHeight = 0; return; } // convert input string DWORD count = (DWORD)mbstowcs(NULL, str, inCharCount); WCHAR * wstr = (WCHAR*) malloc ((count + 1) * sizeof(WCHAR)); mbstowcs(wstr, str, inCharCount); //std::string s(str); //std::wstring wstr(s.length(),L' '); //std::copy(s.begin(), s.end(), wstr.begin()); Graphics* gdiContext = (Graphics*) GetContext( context ); /* -- known Gdi+ issue: We must use the following way to determine correct font extent because typical Graphics::MeasureString() method doesn't work properly (return values are incorrect due to antialiasing) */ Font* dgiFont = GetNativeFont(); // Layout rectangles used for drawing strings RectF layoutRect_A(0.0f, 0.0f, 1300.0f, 1300.0f); // 1 range of character positions within the string CharacterRange charRange(0, inCharCount); // String format used to apply to string when drawing StringFormat strFormat; // Set three ranges of character positions. strFormat.SetMeasurableCharacterRanges(1, &charRange); Region *pCharRangeRegions = new Region(); // Get the regions that correspond to the ranges within the string when // layout rectangle A is used. gdiContext->MeasureCharacterRanges( wstr, inCharCount, dgiFont, layoutRect_A, &strFormat, 1, pCharRangeRegions); RectF boundRect; pCharRangeRegions->GetBounds( &boundRect, gdiContext); *outWidth = boundRect.Width; *outHeight = boundRect.Height; free (wstr); }
// http://www.codeproject.com/KB/GDI-plus/measurestring.aspx RectF MeasureTextAccurate(Graphics *g, Font *f, const WCHAR *s, int len) { if (0 == len) return RectF(0, 0, 0, 0); // TODO: should set height to font's height // note: frankly, I don't see a difference between those StringFormat variations StringFormat sf(StringFormat::GenericTypographic()); sf.SetFormatFlags(sf.GetFormatFlags() | StringFormatFlagsMeasureTrailingSpaces); //StringFormat sf(StringFormat::GenericDefault()); //StringFormat sf; RectF layoutRect; CharacterRange cr(0, len); sf.SetMeasurableCharacterRanges(1, &cr); Region r; Status status = g->MeasureCharacterRanges(s, len, f, layoutRect, &sf, 1, &r); CrashIf(status != Ok); RectF bbox; r.GetBounds(&bbox, g); if (bbox.Width != 0) bbox.Width += PER_STR_DX_ADJUST + (PER_CHAR_DX_ADJUST * (float)len); return bbox; }
// -------------------------------------------------------------- void GFontWin32GDIPlus::GetExtent( unsigned char c, float * outWidth, float * outHeight, VGDevice * context ) const { WCHAR wstr [] = L"0"; mbstowcs(wstr, (const char*)&c, 1); Graphics* gdiContext = (Graphics*) GetContext( context ); /* -- known Gdi+ issue: We must use the following way to determine correct font extent because typical Graphics::MeasureString() method doesn't work properly (return values are incorrect due to antialiasing) */ Font* dgiFont = GetNativeFont(); // Layout rectangles used for drawing strings RectF layoutRect_A(0.0f, 0.0f, 1300.0f, 1300.0f); // 1 range of character positions within the string CharacterRange charRange(0, 1); // String format used to apply to string when drawing StringFormat strFormat; // Set three ranges of character positions. strFormat.SetMeasurableCharacterRanges(1, &charRange); Region *pCharRangeRegions = new Region(); // Get the regions that correspond to the ranges within the string when // layout rectangle A is used. gdiContext->MeasureCharacterRanges( wstr, 1, dgiFont, layoutRect_A, &strFormat, 1, pCharRangeRegions); RectF boundRect; pCharRangeRegions->GetBounds( &boundRect, gdiContext); *outHeight = boundRect.Height; *outWidth = boundRect.Width; // in some cases (when some symbols must be forced into char map), extent needs to be fixed if (c == 139) *outWidth = 6.0; }