GLuint drawChar_To_Texture(const char* s) { wchar_t w; HDC hDC = wglGetCurrentDC(); // 选择字体字号、颜色 // 不指定字体名字,操作系统提供默认字体 // 设置颜色为白色 selectFont(FONT_SIZE, DEFAULT_CHARSET, ""); glColor3f(1.0f, 1.0f, 1.0f); // 转化为宽字符 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, s, 2, &w, 1); // 计算绘制的位置 int width, x, y; GetCharWidth32W(hDC, w, w, &width); // 取得字符的宽度 x = (TEXTURE_SIZE - width) / 2; y = FONT_SIZE / 8; //glWindowPos2iARB(x, y); // 一个扩展函数 GLuint list = glGenLists(1); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDisable(GL_FOG); glDisable(GL_TEXTURE_2D); wglUseFontBitmaps(hDC, w, 1, list); glCallList(list); glDeleteLists(list, 1); GLuint texID; glGenTextures(1, &texID); glBindTexture(GL_TEXTURE_2D, texID); glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE4, 0, 0, TEXTURE_SIZE, TEXTURE_SIZE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); return texID; }
static bool FillGlyphDimensions(HDC hDC, const TEXTMETRICW& TextMetric, CTextureStringGlyph* pGlyphs, uint32 nNumGlyphs) { // Setup the transform for the glyph. Just use identity. MAT2 mat; mat.eM11 = FixedFromFloat( 1.0f ); mat.eM12 = FixedFromFloat( 0.0f ); mat.eM21 = FixedFromFloat( 0.0f ); mat.eM22 = FixedFromFloat( 1.0f ); //determine if this is a truetype font or not bool bTrueType = (TextMetric.tmPitchAndFamily & TMPF_TRUETYPE) != 0; // Get the individual widths of all chars in font, indexed by character values. GLYPHMETRICS GlyphMetrics; memset( &GlyphMetrics, 0, sizeof( GlyphMetrics ) ); for( uint32 nCurrGlyph = 0; nCurrGlyph < nNumGlyphs; nCurrGlyph++ ) { // Get the character for this glyph. CTextureStringGlyph& Glyph = pGlyphs[nCurrGlyph]; if(bTrueType) { // Get the glyph metrics for this glyph. if( GDI_ERROR == GetGlyphOutlineW( hDC, Glyph.m_cGlyph, GGO_METRICS, &GlyphMetrics, 0, NULL, &mat )) { // Use the default character on anything that has issues. if( GDI_ERROR == GetGlyphOutlineW( hDC, TextMetric.tmDefaultChar, GGO_METRICS, &GlyphMetrics, 0, NULL, &mat )) { return false; } } //we have the glyph outline, so we now need to convert the data from that over to the glyph data //format Glyph.m_nTotalWidth = GlyphMetrics.gmCellIncX; Glyph.m_rBlackBox.Left() = GlyphMetrics.gmptGlyphOrigin.x; Glyph.m_rBlackBox.Top() = TextMetric.tmAscent - GlyphMetrics.gmptGlyphOrigin.y; Glyph.m_rBlackBox.Right() = Glyph.m_rBlackBox.Left() + GlyphMetrics.gmBlackBoxX + 1; Glyph.m_rBlackBox.Bottom() = Glyph.m_rBlackBox.Top() + GlyphMetrics.gmBlackBoxY + 1; } else { //this is not a truetype font, so we have to use a different approach for getting the glyph //sizes INT nWidth = 0; if(!GetCharWidth32W(hDC, Glyph.m_cGlyph, Glyph.m_cGlyph, &nWidth)) { if(!GetCharWidth32W(hDC, TextMetric.tmDefaultChar, TextMetric.tmDefaultChar, &nWidth)) { return false; } } //setup our character from that information Glyph.m_nTotalWidth = nWidth; Glyph.m_rBlackBox.Left() = 0; Glyph.m_rBlackBox.Top() = 0; Glyph.m_rBlackBox.Right() = nWidth; Glyph.m_rBlackBox.Bottom() = TextMetric.tmHeight; } } //success return true; }
void GR_Win32CharWidths::setCharWidthsOfRange(HDC hdc, UT_UCSChar c0, UT_UCSChar c1) { if(m_vRanges.getItemCount() == 0) { _retrieveFontInfo(hdc); } UINT k; int w; #ifdef DEBUG DWORD iErrorCode = 0; #endif // Windows NT and Windows 95 support the Unicode Font file. // All of the Unicode glyphs can be rendered if the glyph is found in // the font file. However, Windows 95 does not support the Unicode // characters other than the characters for which the particular codepage // of the font file is defined. // Reference Microsoft knowledge base: // Q145754 - PRB ExtTextOutW or TextOutW Unicode Text Output Is Blank if (UT_IsWinNT()) { for (k=c0; k<=c1; k++) { if(k == 0x200B || k == 0xFEFF || k == UCS_LIGATURE_PLACEHOLDER) setWidth(k,0); else if(!_doesGlyphExist(k)) { setWidth(k,GR_CW_ABSENT); } else { GetCharWidth32W(hdc,k,k,&w); #ifdef DEBUG ABC abc; int iRes = GetCharABCWidthsW(hdc,k,k,&abc); #endif // handle overstriking chars here UT_uint32 iOver = UT_isOverstrikingChar(k); if(!w || iOver != UT_NOT_OVERSTRIKING) { iOver &= UT_OVERSTRIKING_TYPE; if(iOver == UT_OVERSTRIKING_RIGHT) { w = 0; } else { ABC abc; UT_DebugOnly<int> iRes = GetCharABCWidthsW(hdc,k,k,&abc); UT_ASSERT( iRes ); if(iOver == UT_OVERSTRIKING_LEFT) { UT_ASSERT( abc.abcB < GR_OC_MAX_WIDTH); w = abc.abcB | GR_OC_LEFT_FLUSHED; } else { w = abc.abcB /*+ abc.abcA + abc.abcC*/; w = -w; } } } setWidth(k,w); } } } else { HFONT hFont = (HFONT) GetCurrentObject(hdc, OBJ_FONT); LOGFONTW aLogFont; UT_DebugOnly<int> iRes = GetObjectW(hFont, sizeof(LOGFONTW), &aLogFont); UT_ASSERT(iRes); xxx_UT_DEBUGMSG(("gr_Win32Graphics::getCharWidth: extra interchar. spacing %d\n", GetTextCharacterExtra(hdc))); if(aLogFont.lfCharSet == SYMBOL_CHARSET) { // Symbol character handling for (k=c0; k<=c1; k++) { if(!_doesGlyphExist(k)) { setWidth(k,GR_CW_ABSENT); } else { SIZE Size; char str[sizeof(UT_UCSChar)]; int iConverted = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) &k, 1, str, sizeof(str), NULL, NULL); GetTextExtentPoint32A(hdc, str, iConverted, &Size); setWidth(k, Size.cx); } } } else { // Unicode font and default character sets for (k=c0; k<=c1; k++) { if(k == 0x200B || k == 0xFEFF || k == UCS_LIGATURE_PLACEHOLDER) setWidth(k,0); else if(!_doesGlyphExist(k)) { setWidth(k,GR_CW_ABSENT); } else { SIZE Size; wchar_t sz1[2]; sz1[0] = k; GetTextExtentPoint32W(hdc, sz1, 1, &Size); // handle overstriking chars here UT_uint32 iOver = UT_isOverstrikingChar(k); if(!Size.cx || iOver != UT_NOT_OVERSTRIKING) { iOver &= UT_OVERSTRIKING_TYPE; if(iOver == UT_OVERSTRIKING_RIGHT) { Size.cx = 0; } else { ABC abc; iRes = GetCharABCWidthsW(hdc,k,k,&abc); // I have commented out the assert below, // because when the function above is called for // the first time, it seems to always // return 0, even though it fills the abc // structure with reasonable values, // Tomas, June 22, 2003 // UT_ASSERT( iRes ); #ifdef DEBUG if(!iRes) { iErrorCode = GetLastError(); } #endif if(iOver == UT_OVERSTRIKING_LEFT) { UT_ASSERT( abc.abcB < GR_OC_MAX_WIDTH); Size.cx = abc.abcB | GR_OC_LEFT_FLUSHED; } else { Size.cx = abc.abcB; Size.cx = -Size.cx; } } } #ifdef DEBUG if(iErrorCode) { LPVOID lpMsgBuf; FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, iErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPWSTR) &lpMsgBuf, 0, NULL ); // Process any inserts in lpMsgBuf. // ... // Display the string. //MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION ); UT_DEBUGMSG(("char width error: %s\n", lpMsgBuf)); // Free the buffer. LocalFree( lpMsgBuf ); } #endif setWidth(k,Size.cx); xxx_UT_DEBUGMSG(("gr_Win32Graphics::getCharWidths: 0x%x: Size.cx %d\n", k, Size.cx)); } } } } }
/* * @implemented */ DWORD WINAPI LpkGetCharacterPlacement( HDC hdc, LPCWSTR lpString, INT uCount, INT nMaxExtent, LPGCP_RESULTSW lpResults, DWORD dwFlags, DWORD dwUnused) { LPWORD lpGlyphs = NULL; SIZE size; DWORD ret = 0; UINT nSet, i; INT cGlyphs; UNREFERENCED_PARAMETER(dwUnused); /* Sanity check (most likely a direct call) */ if (!(dwFlags & GCP_REORDER)) return GetCharacterPlacementW(hdc, lpString, uCount, nMaxExtent, lpResults, dwFlags); nSet = (UINT)uCount; if (nSet > lpResults->nGlyphs) nSet = lpResults->nGlyphs; BIDI_Reorder(hdc, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString, nSet, lpResults->lpOrder, &lpGlyphs, &cGlyphs); lpResults->nGlyphs = (UINT)cGlyphs; if (lpResults->lpGlyphs) wcscpy(lpResults->lpGlyphs, lpGlyphs); if (lpResults->lpDx && !(dwFlags & GCP_GLYPHSHAPE)) { int c; for (i = 0; i < nSet; i++) { if (GetCharWidth32W(hdc, lpResults->lpOutString[i], lpResults->lpOutString[i], &c)) lpResults->lpDx[i] = c; } } /* If glyph shaping was requested */ else if (lpResults->lpDx && (dwFlags & GCP_GLYPHSHAPE)) { int c; if (lpResults->lpGlyphs) { for (i = 0; i < lpResults->nGlyphs; i++) { if (GetCharWidth32W(hdc, lpGlyphs[i], lpGlyphs[i], &c)) lpResults->lpDx[i] = c; } } } /* FIXME: Currently not bidi compliant! */ if (lpResults->lpCaretPos) { int pos = 0; lpResults->lpCaretPos[0] = 0; for (i = 1; i < nSet; i++) { if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size)) lpResults->lpCaretPos[i] = (pos += size.cx); } } if (GetTextExtentPoint32W(hdc, lpString, uCount, &size)) ret = MAKELONG(size.cx, size.cy); HeapFree(GetProcessHeap(), 0, lpGlyphs); return ret; }