static UINT calc_ppem_for_height(HDC hdc, LONG height) { BYTE os2[78]; /* size of version 0 table */ BYTE hhea[8]; /* just enough to get the ascender and descender */ LONG ascent = 0, descent = 0; UINT emsize; if(height < 0) return -height; if(GetFontData(hdc, MS_MAKE_TAG('O','S','/','2'), 0, os2, sizeof(os2)) == sizeof(os2)) { ascent = GET_BE_WORD(os2 + 74); /* usWinAscent */ descent = GET_BE_WORD(os2 + 76); /* usWinDescent */ } if(ascent + descent == 0) { if(GetFontData(hdc, MS_MAKE_TAG('h','h','e','a'), 0, hhea, sizeof(hhea)) == sizeof(hhea)) { ascent = (signed short)GET_BE_WORD(hhea + 4); /* Ascender */ descent = -(signed short)GET_BE_WORD(hhea + 6); /* Descender */ } } if(ascent + descent == 0) return height; get_bbox(hdc, NULL, &emsize); return MulDiv(emsize, height, ascent + descent); }
bool GDI2FT_OS2_METRICS::init( HDC hdc ) /* -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- */ { DWORD font_data_size; font_data_size = GetFontData( hdc, OS2_TABLE_TAG, offsetof( TT_OS2, xAvgCharWidth ), &_xAvgCharWidth, sizeof( _xAvgCharWidth ) ); if( font_data_size == GDI_ERROR ) return false; font_data_size = GetFontData( hdc, OS2_TABLE_TAG, offsetof( TT_OS2, usWeightClass ), &_usWeightClass, sizeof( _usWeightClass ) ); if( font_data_size == GDI_ERROR ) return false; font_data_size = GetFontData( hdc, OS2_TABLE_TAG, offsetof( TT_OS2, usWidthClass ), &_usWidthClass, sizeof( _usWidthClass ) ); if( font_data_size == GDI_ERROR ) return false; font_data_size = GetFontData( hdc, OS2_TABLE_TAG, offsetof( TT_OS2, fsSelection ), &_fsSelection, sizeof( _fsSelection ) ); if( font_data_size == GDI_ERROR ) return false; _xAvgCharWidth = SWAPWORD( _xAvgCharWidth ); _usWeightClass = SWAPWORD( _usWeightClass ); _usWidthClass = SWAPWORD( _usWidthClass ); _fsSelection = SWAPWORD( _fsSelection ); return true; }
static bool GetDataFromHFONT( HFONT hf, char** outFontBuffer, unsigned int& outFontBufferLen ) { HDC hdc; if ( ( hdc = GetDC(0) ) == NULL ) { DeleteObject(hf); return false; } SelectObject(hdc, hf); outFontBufferLen = GetFontData(hdc, 0, 0, 0, 0); if (outFontBufferLen == GDI_ERROR) { ReleaseDC(0, hdc); DeleteObject(hf); return false; } *outFontBuffer = (char *) malloc( outFontBufferLen ); if ( GetFontData( hdc, 0, 0, *outFontBuffer, (DWORD) outFontBufferLen ) == GDI_ERROR ) { free( *outFontBuffer ); *outFontBuffer = NULL; outFontBufferLen = 0; ReleaseDC(0, hdc); DeleteObject(hf); return false; } ReleaseDC( 0, hdc ); DeleteObject( hf ); return true; }
bool os2_metrics::init(HDC hdc) { // retrieve needed fields from the OS/2 table DWORD font_data_size; font_data_size = GetFontData(hdc, OS2_TABLE_TAG, offsetof(TT_OS2, xAvgCharWidth), &_xAvgCharWidth, sizeof(_xAvgCharWidth)); if (font_data_size == GDI_ERROR) return false; font_data_size = GetFontData(hdc, OS2_TABLE_TAG, offsetof(TT_OS2, usWeightClass), &_usWeightClass, sizeof(_usWeightClass)); if (font_data_size == GDI_ERROR) return false; font_data_size = GetFontData(hdc, OS2_TABLE_TAG, offsetof(TT_OS2, usWidthClass), &_usWidthClass, sizeof(_usWidthClass)); if (font_data_size == GDI_ERROR) return false; font_data_size = GetFontData(hdc, OS2_TABLE_TAG, offsetof(TT_OS2, fsSelection), &_fsSelection, sizeof(_fsSelection)); if (font_data_size == GDI_ERROR) return false; _xAvgCharWidth = SWAPWORD(_xAvgCharWidth); _usWeightClass = SWAPWORD(_usWeightClass); _usWidthClass = SWAPWORD(_usWidthClass); _fsSelection = SWAPWORD(_fsSelection); return true; }
static VOID *load_gsub_table(HDC hdc) { VOID* GSUB_Table = NULL; int length = GetFontData(hdc, GSUB_TAG , 0, NULL, 0); if (length != GDI_ERROR) { GSUB_Table = HeapAlloc(GetProcessHeap(),0,length); GetFontData(hdc, GSUB_TAG , 0, GSUB_Table, length); TRACE("Loaded GSUB table of %i bytes\n",length); } return GSUB_Table; }
static BOOL LoadTable(HDC hdc, OTTable *table) { unsigned int i; if(table->MS_tag == MS_MAKE_TAG('g','d','i','r')) return TRUE; table->len = GetFontData(hdc, table->MS_tag, 0, NULL, 0); table->data = HeapAlloc(GetProcessHeap(), 0, (table->len + 3) & ~3 ); memset(table->data + ((table->len - 1) & ~3), 0, sizeof(DWORD)); GetFontData(hdc, table->MS_tag, 0, table->data, table->len); table->check = 0; for(i = 0; i < (table->len + 3) / 4; i++) table->check += FLIP_ORDER(*((DWORD*)(table->data) + i)); return TRUE; }
static BOOL get_font_metrics(HDC hdc, struct font_metrics *fm) { OUTLINETEXTMETRICW otm; TT_OS2_V2 tt_os2; TT_HHEA tt_hori; LONG size; UINT16 line_gap; otm.otmSize = sizeof(otm); if (!GetOutlineTextMetricsW(hdc, otm.otmSize, &otm)) return FALSE; fm->em_height = otm.otmEMSquare; fm->dpi = GetDeviceCaps(hdc, LOGPIXELSY); memset(&tt_hori, 0, sizeof(tt_hori)); if (GetFontData(hdc, MS_HHEA_TAG, 0, &tt_hori, sizeof(tt_hori)) != GDI_ERROR) { fm->ascent = GET_BE_WORD(tt_hori.Ascender); fm->descent = -GET_BE_WORD(tt_hori.Descender); TRACE("hhea: ascent %d, descent %d\n", fm->ascent, fm->descent); line_gap = GET_BE_WORD(tt_hori.LineGap); fm->line_spacing = fm->ascent + fm->descent + line_gap; TRACE("line_gap %u, line_spacing %u\n", line_gap, fm->line_spacing); if (fm->ascent + fm->descent != 0) return TRUE; } size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0); if (size == GDI_ERROR) return FALSE; if (size > sizeof(tt_os2)) size = sizeof(tt_os2); memset(&tt_os2, 0, sizeof(tt_os2)); if (GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size) != size) return FALSE; fm->ascent = GET_BE_WORD(tt_os2.usWinAscent); fm->descent = GET_BE_WORD(tt_os2.usWinDescent); TRACE("usWinAscent %u, usWinDescent %u\n", fm->ascent, fm->descent); if (fm->ascent + fm->descent == 0) { fm->ascent = GET_BE_WORD(tt_os2.sTypoAscender); fm->descent = GET_BE_WORD(tt_os2.sTypoDescender); TRACE("sTypoAscender %u, sTypoDescender %u\n", fm->ascent, fm->descent); } line_gap = GET_BE_WORD(tt_os2.sTypoLineGap); fm->line_spacing = fm->ascent + fm->descent + line_gap; TRACE("line_gap %u, line_spacing %u\n", line_gap, fm->line_spacing); return TRUE; }
PassRefPtr<SharedBuffer> FontPlatformData::openTypeTable(uint32_t table) const { HWndDC hdc(0); HGDIOBJ oldFont = SelectObject(hdc, hfont()); DWORD size = GetFontData(hdc, table, 0, 0, 0); RefPtr<SharedBuffer> buffer; if (size != GDI_ERROR) { buffer = SharedBuffer::create(size); DWORD result = GetFontData(hdc, table, 0, (PVOID)buffer->data(), size); ASSERT(result == size); } SelectObject(hdc, oldFont); return buffer.release(); }
static QString getEnglishName(const QString &familyName) { QString i18n_name; HDC hdc = GetDC( 0 ); LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT)); memcpy(lf.lfFaceName, familyName.utf16(), qMin(LF_FACESIZE, familyName.length()) * sizeof(wchar_t)); lf.lfCharSet = DEFAULT_CHARSET; HFONT hfont = CreateFontIndirect(&lf); if(!hfont) { ReleaseDC(0, hdc); return QString(); } HGDIOBJ oldobj = SelectObject( hdc, hfont ); const DWORD name_tag = MAKE_TAG( 'n', 'a', 'm', 'e' ); // get the name table unsigned char *table = 0; DWORD bytes = GetFontData( hdc, name_tag, 0, 0, 0 ); if ( bytes == GDI_ERROR ) { // ### Unused variable /* int err = GetLastError(); */ goto error; } table = new unsigned char[bytes]; GetFontData(hdc, name_tag, 0, table, bytes); if ( bytes == GDI_ERROR ) goto error; i18n_name = getEnglishName(table, bytes); error: delete [] table; SelectObject( hdc, oldobj ); DeleteObject( hfont ); ReleaseDC( 0, hdc ); //qDebug("got i18n name of '%s' for font '%s'", i18n_name.latin1(), familyName.toLocal8Bit().data()); return i18n_name; }
String GetFontDataSys(Font font) { String r; HFONT hfont = GetWin32Font(font, 0); if(hfont) { HDC hdc = Win32_IC(); HFONT ohfont = (HFONT) ::SelectObject(hdc, hfont); DWORD size = GetFontData(hdc, 0, 0, NULL, 0); if(size == GDI_ERROR) { LLOG("PdfDraw::Finish: GDI_ERROR on font " << pdffont.GetKey(i)); return Null; } StringBuffer b(size); GetFontData(hdc, 0, 0, b, size); ::SelectObject(hdc, ohfont); r = b; } return r; }
/* [fault_status][comm_status] */ error_status_t gdipp_rpc_get_font_size( /* [in] */ handle_t h_gdipp_rpc, /* [context_handle_noserialize][in] */ GDIPP_RPC_SESSION_HANDLE h_session, /* [in] */ unsigned long table, /* [in] */ unsigned long offset, /* [out] */ unsigned long *font_size) { const gdipp::rpc_session *curr_session = reinterpret_cast<const gdipp::rpc_session *>(h_session); *font_size = GetFontData(curr_session->font_holder, table, offset, NULL, 0); return RPC_S_OK; }
//------------------------------------------------------------------------------ void IGUIFont_ft2::DrawString(IGUIInterfaceRender* pRender, const CGUIStringRender& rString, const CGUIVector2& rPos, real fAlpha, int32 nStartPos, int32 nEndPos) { if( rString.m_strContent.empty()) { //empty string return; } CGUIVector2 aPos = rPos; if( nEndPos<0 || nEndPos>int32(rString.m_strContent.size())) { nEndPos = rString.m_strContent.size(); } const CGUIStringRenderInfo& rInfo = rString.m_aStringInfo; CGUIFontData_ft2* pFontData = GetFontData( rInfo.m_uFontID ); for( int32 i=nStartPos; i<nEndPos; ++i) { SCharData_ft2 * pCharData = pFontData->GetCharData( rString.m_strContent[i] ); if( pCharData->m_pTexture) { CGUIRect aCharRect( CGUIVector2(aPos.x+pCharData->m_fBearingX*rInfo.m_fFontScale, aPos.y-pCharData->m_fBearingY*rInfo.m_fFontScale), CGUISize(pCharData->m_fBitmapWidth*rInfo.m_fFontScale,pCharData->m_fBitmapHeight*rInfo.m_fFontScale)); //dest area size CGUIColor aColor(rInfo.m_aColor); aColor.SetAlpha(aColor.GetAlpha()*fAlpha); pRender->DrawTile( aCharRect, 0, pCharData->m_pTexture, pCharData->m_aUV, eImageOrientation_Normal, aColor, aColor, aColor, aColor); } aPos.x+=pCharData->m_aSize.m_fWidth*rInfo.m_fFontScale; } }
bool os2_metrics::init(void *font_id) { // retrieve needed fields from the OS/2 table DWORD font_data_size; const HDC font_holder = dc_pool_instance.claim(); assert(font_holder != NULL); font_mgr_instance.select_font(font_id, font_holder); font_data_size = GetFontData(font_holder, OS2_TABLE_TAG, offsetof(TT_OS2, xAvgCharWidth), reinterpret_cast<byte *>(&_xAvgCharWidth), sizeof(_xAvgCharWidth)); if (font_data_size == GDI_ERROR) goto failed_init_os2_metrics; font_data_size = GetFontData(font_holder, OS2_TABLE_TAG, offsetof(TT_OS2, usWeightClass), reinterpret_cast<byte *>(&_usWeightClass), sizeof(_usWeightClass)); if (font_data_size == GDI_ERROR) goto failed_init_os2_metrics; font_data_size = GetFontData(font_holder, OS2_TABLE_TAG, offsetof(TT_OS2, usWidthClass), reinterpret_cast<byte *>(&_usWidthClass), sizeof(_usWidthClass)); if (font_data_size == GDI_ERROR) goto failed_init_os2_metrics; font_data_size = GetFontData(font_holder, OS2_TABLE_TAG, offsetof(TT_OS2, fsSelection), reinterpret_cast<byte *>(&_fsSelection), sizeof(_fsSelection)); if (font_data_size == GDI_ERROR) goto failed_init_os2_metrics; _xAvgCharWidth = SWAPWORD(_xAvgCharWidth); _usWeightClass = SWAPWORD(_usWeightClass); _usWidthClass = SWAPWORD(_usWidthClass); _fsSelection = SWAPWORD(_fsSelection); return true; failed_init_os2_metrics: dc_pool_instance.free(font_holder); return false; }
/* [fault_status][comm_status] */ error_status_t gdipp_rpc_get_font_data( /* [in] */ handle_t h_gdipp_rpc, /* [context_handle_noserialize][in] */ GDIPP_RPC_SESSION_HANDLE h_session, /* [in] */ unsigned long table, /* [in] */ unsigned long offset, /* [size_is][out] */ byte *data_buf, /* [in] */ unsigned long buf_size) { const gdipp::rpc_session *curr_session = reinterpret_cast<const gdipp::rpc_session *>(h_session); // TODO: output pointer is not allocated with MIDL_user_allocate // TODO: return value not returned GetFontData(curr_session->font_holder, table, offset, data_buf, buf_size); return RPC_S_OK; }
static BOOL is_fake_italic( HDC hdc ) { TEXTMETRICW tm; BYTE head[54]; /* the head table is 54 bytes long */ WORD mac_style; GetTextMetricsW( hdc, &tm ); if (!tm.tmItalic) return FALSE; if (GetFontData( hdc, MS_MAKE_TAG('h','e','a','d'), 0, head, sizeof(head) ) == GDI_ERROR) return FALSE; mac_style = GET_BE_WORD( head + 44 ); TRACE( "mac style %04x\n", mac_style ); return !(mac_style & 2); }
/**************************************************************************** * get_bbox * * This retrieves the bounding box of the font in font units as well as * the size of the emsquare. To avoid having to worry about mapping mode and * the font size we'll get the data directly from the TrueType HEAD table rather * than using GetOutlineTextMetrics. */ static BOOL get_bbox(PSDRV_PDEVICE *physDev, RECT *rc, UINT *emsize) { BYTE head[54]; /* the head table is 54 bytes long */ if(GetFontData(physDev->hdc, MS_MAKE_TAG('h','e','a','d'), 0, head, sizeof(head)) == GDI_ERROR) { ERR("Can't retrieve head table\n"); return FALSE; } *emsize = GET_BE_WORD(head + 18); /* unitsPerEm */ rc->left = (signed short)GET_BE_WORD(head + 36); /* xMin */ rc->bottom = (signed short)GET_BE_WORD(head + 38); /* yMin */ rc->right = (signed short)GET_BE_WORD(head + 40); /* xMax */ rc->top = (signed short)GET_BE_WORD(head + 42); /* yMax */ return TRUE; }
/**************************************************************************** * get_bbox * * This retrieves the bounding box of the font in font units as well as * the size of the emsquare. To avoid having to worry about mapping mode and * the font size we'll get the data directly from the TrueType HEAD table rather * than using GetOutlineTextMetrics. */ static UINT get_bbox(HDC hdc, RECT *rc) { BYTE head[54]; /* the head table is 54 bytes long */ if(GetFontData(hdc, MS_MAKE_TAG('h','e','a','d'), 0, head, sizeof(head)) == GDI_ERROR) { ERR("Can't retrieve head table\n"); return 0; } if(rc) { rc->left = (signed short)GET_BE_WORD(head + 36); /* xMin */ rc->bottom = (signed short)GET_BE_WORD(head + 38); /* yMin */ rc->right = (signed short)GET_BE_WORD(head + 40); /* xMax */ rc->top = (signed short)GET_BE_WORD(head + 42); /* yMax */ } return GET_BE_WORD(head + 18); /* unitsPerEm */ }
/** * FreeType 用 ストリーム読み込み関数 * @param stream FT_Streamへのポインタ * @param offset ストリーム先頭からのオフセット * @param buffer 格納先バッファ * @param count 読み出すバイト数 * @return 何バイト読み込まれたか */ unsigned long tNativeFreeTypeFace::IoFunc( FT_Stream stream, unsigned long offset, unsigned char* buffer, unsigned long count ) { if(count != 0) { tNativeFreeTypeFace * _this = static_cast<tNativeFreeTypeFace*>(stream->descriptor.pointer); DWORD result = GetFontData(_this->DC, _this->IsTTC ? TVP_TT_TABLE_ttcf : 0, offset, buffer, count); if(result == GDI_ERROR) { // エラー return 0; } return result; } return 0; }
//------------------------------------------------------------------------------ CGUISize IGUIFont_ft2::GetCharacterSize( wchar charCode, const CGUIStringRenderInfo& rInfo ) { CGUIFontData_ft2* pFontData = GetFontData( rInfo.m_uFontID ); SCharData_ft2 * pCharData = pFontData->GetCharData( charCode ); return pCharData->m_aSize * rInfo.m_fFontScale; }
bool FreeTypeSysFontData::Init(LPCTSTR name, int weight, bool italic) { const CGdippSettings* pSettings = CGdippSettings::GetInstance(); void* pNameFromGDI = NULL; // Windows 偐傜庢摼偟偨 name 僞僌偺撪梕 void* pNameFromFreeType = NULL; // FreeType 偐傜庢摼偟偨 name 僞僌偺撪梕 HFONT hf = NULL; DWORD cbNameTable; DWORD cbFontData; int index; DWORD buf; FT_StreamRec& fsr = m_ftStream; m_name.assign(name); m_hdc = CreateCompatibleDC(NULL); if(m_hdc == NULL) { return false; } // 柤慜埲奜揔摉 if (pSettings->FontSubstitutes() < SETTING_FONTSUBSTITUTE_ALL) { hf = CreateFont( 12, 0, 0, 0, weight, italic, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, FONT_MAGIC_NUMBER, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, name); } else hf = CreateFont( 12, 0, 0, 0, weight, italic, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, name); if(hf == NULL){ return false; } m_hOldFont = SelectFont(m_hdc, hf); // 僼僅儞僩僨乕僞偑摼傜傟偦偆偐僠僃僢僋 cbNameTable = ::GetFontData(m_hdc, TVP_TT_TABLE_name, 0, NULL, 0); if(cbNameTable == GDI_ERROR){ goto ERROR_Init; } pNameFromGDI = malloc(cbNameTable); if (!pNameFromGDI) { goto ERROR_Init; } pNameFromFreeType = malloc(cbNameTable); if (!pNameFromFreeType) { goto ERROR_Init; } //- name 僞僌偺撪梕傪儊儌儕偵撉傒崬傓 if(GetFontData(m_hdc, TVP_TT_TABLE_name, 0, pNameFromGDI, cbNameTable) == GDI_ERROR){ goto ERROR_Init; } // 僼僅儞僩僒僀僘庢摼張棟 cbFontData = ::GetFontData(m_hdc, TVP_TT_TABLE_ttcf, 0, &buf, 1); if(cbFontData == 1){ // TTC 僼傽僀儖偩偲巚傢傟傞 cbFontData = ::GetFontData(m_hdc, TVP_TT_TABLE_ttcf, 0, NULL, 0); m_isTTC = true; } else{ cbFontData = ::GetFontData(m_hdc, 0, 0, NULL, 0); } if(cbFontData == GDI_ERROR){ // 僄儔乕; GetFontData 偱偼埖偊側偐偭偨 goto ERROR_Init; } if (pSettings->UseMapping()) { HANDLE hmap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT | SEC_NOCACHE, 0, cbFontData, NULL); if (!hmap) { goto ERROR_Init; } m_pMapping = MapViewOfFile(hmap, FILE_MAP_ALL_ACCESS, 0, 0, cbFontData); m_dwSize = cbFontData; CloseHandle(hmap); if (m_pMapping) { ::GetFontData(m_hdc, m_isTTC ? TVP_TT_TABLE_ttcf : 0, 0, m_pMapping, cbFontData); } } // FT_StreamRec 偺奺僼傿乕儖僪傪杽傔傞 fsr.base = 0; fsr.size = cbFontData; fsr.pos = 0; fsr.descriptor.pointer = this; fsr.pathname.pointer = NULL; fsr.read = IoFunc; fsr.close = CloseFunc; index = 0; m_locked = true; if(!OpenFaceByIndex(index)){ goto ERROR_Init; } for(;;) { // FreeType 偐傜丄name 僞僌偺僒僀僘傪庢摼偡傞 FT_ULong length = 0; FT_Error err = FT_Load_Sfnt_Table(m_ftFace, TTAG_name, 0, NULL, &length); if(err){ goto ERROR_Init; } // FreeType 偐傜摼偨 name 僞僌偺挿偝傪 Windows 偐傜摼偨挿偝偲斾妑 if(length == cbNameTable){ // FreeType 偐傜 name 僞僌傪庢摼 err = FT_Load_Sfnt_Table(m_ftFace, TTAG_name, 0, (unsigned char*)pNameFromFreeType, &length); if(err){ goto ERROR_Init; } // FreeType 偐傜撉傒崬傫偩 name 僞僌偺撪梕偲丄Windows 偐傜撉傒崬傫偩 // name 僞僌偺撪梕傪斾妑偡傞丅 // 堦抳偟偰偄傟偽偦偺 index 偺僼僅儞僩傪巊偆丅 if(!memcmp(pNameFromGDI, pNameFromFreeType, cbNameTable)){ // 堦抳偟偨 // face 偼奐偄偨傑傑 break; // 儖乕僾傪敳偗傞 } } // 堦抳偟側偐偭偨 // 僀儞僨僢僋僗傪堦偮憹傗偟丄偦偺 face 傪奐偔 index ++; if(!OpenFaceByIndex(index)){ // 堦抳偡傞 face 偑側偄傑傑 僀儞僨僢僋僗偑斖埻傪挻偊偨偲尒傜傟傞 // index 傪 0 偵愝掕偟偰偦偺 index 傪奐偒丄儖乕僾傪敳偗傞 index = 0; if(!OpenFaceByIndex(index)){ goto ERROR_Init; } break; } } free(pNameFromGDI); free(pNameFromFreeType); m_locked = false; return true; ERROR_Init: m_locked = false; if (hf) { SelectFont(m_hdc, m_hOldFont); DeleteFont(hf); m_hOldFont = NULL; } free(pNameFromGDI); free(pNameFromFreeType); return false; }
//------------------------------------------------------------------------------ real IGUIFont_ft2::GetFontHeight( const CGUIStringRenderInfo& rInfo ) { CGUIFontData_ft2* pFontData = GetFontData( rInfo.m_uFontID ); return pFontData->GetFontSize() * rInfo.m_fFontScale; }
// Fills |length| glyphs starting at |offset| in a |page| in the Basic // Multilingual Plane (<= U+FFFF). The input buffer size should be the // same as |length|. We can use the standard Windows GDI functions here. // Returns true if any glyphs were found. static bool fillBMPGlyphs(unsigned offset, unsigned length, UChar* buffer, GlyphPage* page, const SimpleFontData* fontData, bool recurse) { HDC dc = GetDC((HWND)0); HGDIOBJ oldFont = SelectObject(dc, fontData->platformData().hfont()); TEXTMETRIC tm = {0}; if (!GetTextMetrics(dc, &tm)) { SelectObject(dc, oldFont); ReleaseDC(0, dc); if (recurse) { if (PlatformBridge::ensureFontLoaded(fontData->platformData().hfont())) return fillBMPGlyphs(offset, length, buffer, page, fontData, false); fillEmptyGlyphs(page); return false; } else { // FIXME: Handle gracefully the error if this call also fails. // See http://crbug.com/6401 LOG_ERROR("Unable to get the text metrics after second attempt"); fillEmptyGlyphs(page); return false; } } // FIXME: GetGlyphIndices() sets each item of localGlyphBuffer[] // with the one of the values listed below. // * With the GGI_MARK_NONEXISTING_GLYPHS flag // + If the font has a glyph available for the character, // localGlyphBuffer[i] > 0x0. // + If the font does not have glyphs available for the character, // localGlyphBuffer[i] = 0x1F (TrueType Collection?) or // 0xFFFF (OpenType?). // * Without the GGI_MARK_NONEXISTING_GLYPHS flag // + If the font has a glyph available for the character, // localGlyphBuffer[i] > 0x0. // + If the font does not have glyphs available for the character, // localGlyphBuffer[i] = 0x80. // (Windows automatically assigns the glyph for a box character to // prevent ExtTextOut() from returning errors.) // To avoid from hurting the rendering performance, this code just // tells WebKit whether or not the all glyph indices for the given // characters are 0x80 (i.e. a possibly-invalid glyph) and let it // use alternative fonts for the characters. // Although this may cause a problem, it seems to work fine as far as I // have tested. (Obviously, I need more tests.) WORD localGlyphBuffer[GlyphPage::size]; // FIXME: I find some Chinese characters can not be correctly displayed // when call GetGlyphIndices without flag GGI_MARK_NONEXISTING_GLYPHS, // because the corresponding glyph index is set as 0x20 when current font // does not have glyphs available for the character. According a blog post // http://blogs.msdn.com/michkap/archive/2006/06/28/649791.aspx // I think we should switch to the way about calling GetGlyphIndices with // flag GGI_MARK_NONEXISTING_GLYPHS, it should be OK according the // description of MSDN. // Also according to Jungshik and Hironori's suggestion and modification // we treat turetype and raster Font as different way when windows version // is less than Vista. GetGlyphIndices(dc, buffer, length, localGlyphBuffer, GGI_MARK_NONEXISTING_GLYPHS); // Copy the output to the GlyphPage bool haveGlyphs = false; int invalidGlyph = 0xFFFF; const DWORD cffTableTag = 0x20464643; // 4-byte identifier for OpenType CFF table ('CFF '). if (!isVistaOrNewer() && !(tm.tmPitchAndFamily & TMPF_TRUETYPE) && (GetFontData(dc, cffTableTag, 0, 0, 0) == GDI_ERROR)) invalidGlyph = 0x1F; Glyph spaceGlyph = 0; // Glyph for a space. Lazily filled. for (unsigned i = 0; i < length; i++) { UChar c = buffer[i]; Glyph glyph = localGlyphBuffer[i]; const SimpleFontData* glyphFontData = fontData; // When this character should be a space, we ignore whatever the font // says and use a space. Otherwise, if fonts don't map one of these // space or zero width glyphs, we will get a box. if (Font::treatAsSpace(c)) { // Hard code the glyph indices for characters that should be // treated like spaces. glyph = initSpaceGlyph(dc, &spaceGlyph); } else if (glyph == invalidGlyph) { // WebKit expects both the glyph index and FontData // pointer to be 0 if the glyph is not present glyph = 0; glyphFontData = 0; } else haveGlyphs = true; page->setGlyphDataForCharacter(offset + i, glyph, glyphFontData); } SelectObject(dc, oldFont); ReleaseDC(0, dc); return haveGlyphs; }
//------------------------------------------------------------------------------ void IGUIFont_ft2::DrawString(IGUIInterfaceRender* pRender, const CGUIStringRender& rString, const CGUIRect& rStringRect, ETextAlignmentHorz uTextAlignmentHorz, ETextAlignmentVert uTextAlignmentVert, real fAlpha, int32 nStartPos, int32 nEndPos) { if( rString.m_strContent.empty()) { //empty string return; } const CGUIStringRenderInfo& rInfo = rString.m_aStringInfo; CGUIFontData_ft2* pFontData = GetFontData( rInfo.m_uFontID ); real fScaledStringWidth = GetStringWidth(rString); real fScaledStringHeight = pFontData->GetFontSize() * rInfo.m_fFontScale; CGUIVector2 aPos; switch( uTextAlignmentHorz ) { case eTextAlignment_Horz_Left: aPos.x = rStringRect.m_fLeft; break; case eTextAlignment_Horz_Right: aPos.x = rStringRect.m_fRight-fScaledStringWidth; break; case eTextAlignment_Horz_Center: default: aPos.x = floor(rStringRect.m_fLeft+(rStringRect.GetWidth()-fScaledStringWidth)/2); break; } switch( uTextAlignmentVert ) { case eTextAlignment_Vert_Up: aPos.y = rStringRect.m_fTop; break; case eTextAlignment_Vert_Down: aPos.y = rStringRect.m_fBottom - fScaledStringHeight; break; case eTextAlignment_Vert_Center: default: aPos.y = ceil(rStringRect.m_fTop + (rStringRect.GetHeight() - fScaledStringHeight) / 2); break; } aPos.y += fScaledStringHeight; if( nEndPos < 0 || nEndPos >int32( rString.m_strContent.size())) { nEndPos = rString.m_strContent.size(); } for( int32 i= nStartPos; i<nEndPos; ++i) { SCharData_ft2 * pCharData = pFontData->GetCharData( rString.m_strContent[i] ); if( pCharData->m_pTexture) { CGUIRect aCharRect( CGUIVector2(aPos.x+pCharData->m_fBearingX*rInfo.m_fFontScale, aPos.y-pCharData->m_fBearingY*rInfo.m_fFontScale), CGUISize(pCharData->m_fBitmapWidth*rInfo.m_fFontScale,pCharData->m_fBitmapHeight*rInfo.m_fFontScale)); //dest area size CGUIColor aColor(rInfo.m_aColor); aColor.SetAlpha(aColor.GetAlpha()*fAlpha); pRender->DrawTile( aCharRect, 0, pCharData->m_pTexture, pCharData->m_aUV, eImageOrientation_Normal, aColor, aColor, aColor, aColor); } aPos.x+=pCharData->m_aSize.m_fWidth*rInfo.m_fFontScale; } }
bool QWindowsFontEngine::hasCMapTable() const { HDC hdc = m_fontEngineData->hdc; SelectObject(hdc, hfont); return GetFontData(hdc, MAKE_LITTLE_ENDIAN_TAG('c', 'm', 'a', 'p'), 0, 0, 0) != GDI_ERROR; }
BOOL bTestGFD ( HDC hdc ) { ULONG row = 0; // screen row coordinate to print at HFONT hfont; HFONT hfontOriginal; LOGFONT lfnt; ULONG cjBuffer; PBYTE pjBuffer; // Clear the screen to black. BitBlt(hdc, 0, 0, CX, CY, (HDC) 0, 0, 0, 0); // Get a font. memset(&lfnt, 0, sizeof(lfnt)); lstrcpy(lfnt.lfFaceName, "Lucida Blackletter"); lfnt.lfHeight = 40; lfnt.lfWeight = 400; if ((hfont = CreateFontIndirect(&lfnt)) == NULL) { DbgPrint("ft!bTestGFD(): Logical font creation failed.\n"); return FALSE; } hfontOriginal = SelectObject(hdc, hfont); // Determine buffer size needed by GetFontData. // 'OS/2' if ( (cjBuffer = (ULONG) GetFontData(hdc, 0x4f532f32, 0, (PVOID) NULL, 0)) == (ULONG) -1 ) { DbgPrint("ft!bTestGFD(): could not get buffer size from API\n"); return FALSE; } // Allocate memory. if ( (pjBuffer = (PBYTE) LocalAlloc(LPTR, cjBuffer)) == (PBYTE) NULL ) { DbgPrint("ft!bTestGFD(): LocalAlloc(LPTR, 0x%lx) failed\n", cjBuffer); return FALSE; } // Get the OS/2 table from TrueType. if ( GetFontData(hdc, 0x4f532f32, 0, (PVOID) pjBuffer, cjBuffer) == (DWORD) -1 ) { LocalFree(pjBuffer); DbgPrint("ft!bTestGFD(): call to GetFontData failed\n"); return FALSE; } // Flush out batched calls. GdiFlush(); // Allow an opportunity to examine the contents. DbgPrint("ft!bTestGFD(): call to GetFontData succeeded\n"); DbgPrint("\tOS/2 TrueType table is at 0x%lx, size is 0x%lx (%ld)\n", pjBuffer, cjBuffer, cjBuffer); DbgBreakPoint(); // Restore the font. SelectObject(hdc, hfontOriginal); DeleteObject(hfont); // Free allocated memory. LocalFree(pjBuffer); return TRUE; }
/** * Fonts can have localised names and when the system locale is the same as * one of those localised names Windows will always return that localised name * instead of allowing to get the non-localised (English US) name of the font. * This will later on give problems as freetype uses the non-localised name of * the font and we need to compare based on that name. * Windows furthermore DOES NOT have an API to get the non-localised name nor * can we override the system locale. This means that we have to actually read * the font itself to gather the font name we want. * Based on: http://blogs.msdn.com/michkap/archive/2006/02/13/530814.aspx * @param logfont the font information to get the english name of. * @return the English name (if it could be found). */ static const char *GetEnglishFontName(const ENUMLOGFONTEX *logfont) { static char font_name[MAX_PATH]; const char *ret_font_name = NULL; uint pos = 0; HDC dc; HGDIOBJ oldfont; byte *buf; DWORD dw; uint16 format, count, stringOffset, platformId, encodingId, languageId, nameId, length, offset; HFONT font = CreateFontIndirect(&logfont->elfLogFont); if (font == NULL) goto err1; dc = GetDC(NULL); oldfont = SelectObject(dc, font); dw = GetFontData(dc, 'eman', 0, NULL, 0); if (dw == GDI_ERROR) goto err2; buf = MallocT<byte>(dw); dw = GetFontData(dc, 'eman', 0, buf, dw); if (dw == GDI_ERROR) goto err3; format = buf[pos++] << 8; format += buf[pos++]; assert(format == 0); count = buf[pos++] << 8; count += buf[pos++]; stringOffset = buf[pos++] << 8; stringOffset += buf[pos++]; for (uint i = 0; i < count; i++) { platformId = buf[pos++] << 8; platformId += buf[pos++]; encodingId = buf[pos++] << 8; encodingId += buf[pos++]; languageId = buf[pos++] << 8; languageId += buf[pos++]; nameId = buf[pos++] << 8; nameId += buf[pos++]; if (nameId != 1) { pos += 4; // skip length and offset continue; } length = buf[pos++] << 8; length += buf[pos++]; offset = buf[pos++] << 8; offset += buf[pos++]; /* Don't buffer overflow */ length = min(length, MAX_PATH - 1); for (uint j = 0; j < length; j++) font_name[j] = buf[stringOffset + offset + j]; font_name[length] = '\0'; if ((platformId == 1 && languageId == 0) || // Macintosh English (platformId == 3 && languageId == 0x0409)) { // Microsoft English (US) ret_font_name = font_name; break; } } err3: free(buf); err2: SelectObject(dc, oldfont); ReleaseDC(NULL, dc); DeleteObject(font); err1: return ret_font_name == NULL ? WIDE_TO_MB((const TCHAR*)logfont->elfFullName) : ret_font_name; }
void GR_Win32CharWidths::_retrieveFontInfo(HDC hdc) { // retrieve CMAP table for this font DWORD iTableSize = GetFontData(hdc, CMAP, 0, NULL, 0); char * buff = NULL, * p; UT_uint16 i, j, k; UT_uint16 iTCount; if(!iTableSize || iTableSize==GDI_ERROR) goto end_processing; buff = new char[iTableSize]; if(!buff) goto end_processing; if(GDI_ERROR == GetFontData(hdc, CMAP, 0, (LPVOID)buff, iTableSize)) goto end_processing; // now process the data in the table ... p = buff; UT_uint32 iOffset; UT_uint16 iFormat; iTCount = *((UT_uint16*)&buff[2]); DO_BE2LE(iTCount); p += 4; for(i = 0; i < iTCount; i++) { UT_uint16 iPlatform = *((UT_uint16*)p); DO_BE2LE(iPlatform); p += 2; UT_uint16 iId = *((UT_uint16*)p); DO_BE2LE(iId); p += 2; if(iPlatform == 3 && iId == 1) { iOffset = *((UT_uint32*)p); DO_BE2LE32(iOffset); p += 4; iFormat = *((UT_uint16*)(&buff[0]+iOffset)); DO_BE2LE(iFormat); if(iFormat != 4) { continue; } p = &buff[0] + iOffset + 2; UT_uint16 iLength = *((UT_uint16*)p); DO_BE2LE(iLength); p += 4; UT_uint16 iSegCount = *((UT_uint16*)p); DO_BE2LE(iSegCount); iSegCount /= 2; p += 8; UT_uint16 * pEnd = (UT_uint16*)p; p += 2*iSegCount + 2; UT_uint16 * pStart = (UT_uint16*)p; p += 2*iSegCount; //UT_uint16 * pDelta = (UT_uint16*)p; p += 2*iSegCount; UT_uint16 * pRangeOffset = (UT_uint16*)p; p += 2*iSegCount; for(j = 0; j < iSegCount; j++) { DO_BE2LE(pRangeOffset[j]); DO_BE2LE(pStart[j]); DO_BE2LE(pEnd[j]); if(pRangeOffset[j] == 0) { m_vRanges.addItem(pStart[j]); m_vRanges.addItem(pEnd[j]); } else { UT_uint16 iStartChar = pStart[j]; for(k = pStart[j]; k <= pEnd[j]; k++) { if(pStart[j] == 0xffff && pEnd[j] == 0xffff) { // pEnd[j] == 0xffff indicates the last // segment; according to the docs this // segment need not, but can, contain any // valid mappings, and the docs do // not. Presumably if the segement // contains more than on character there // are some valid mapings, if not, i.e., // If pStart[j] == 0xffff, we will // assume that the mapping is not valid // Tomas, Oct 25, 2003 break; } if(0 == *(pRangeOffset[j]/2 + (k - pStart[j]) + &pRangeOffset[j])) { // this character is not present, dump // everyting up to here if(k > iStartChar) { m_vRanges.addItem(iStartChar); m_vRanges.addItem(k-1); } iStartChar = k + 1; } } if(iStartChar <= k - 1) { // dump what is left over m_vRanges.addItem(iStartChar); m_vRanges.addItem(k-1); } } } // not interested in any further tables } else if(iPlatform == 3 && iId == 0) { // symbol font m_vRanges.addItem(0x20); m_vRanges.addItem(0x255); } else { // move past the offset long p += 4; } } // g_free the table data delete [] buff; end_processing: // sanity check if(m_vRanges.getItemCount() == 0) { UT_DEBUGMSG(("GR_Win32CharWidths::_retrieveFontInfo: no ranges in font!!!\n")); // just assume everything is present m_vRanges.addItem(0); m_vRanges.addItem(0xffffffff); } #ifdef DEBUG for(UT_sint32 n = 0; n < m_vRanges.getItemCount() - 1; n += 2) { xxx_UT_DEBUGMSG(("GR_Win32CharWidths::_retrieveFontInfo: range 0x%04x - 0x%04x\n", m_vRanges.getNthItem(n), m_vRanges.getNthItem(n+1))); } #endif }
// This function creates a font resource for the given font name with the // embedding type set appropriately for the licensing intent of the font. HRESULT CreateFontResourceForFont( IXpsOMObjectFactory* xpsFactory, LPCWSTR fontName, IXpsOMFontResource **fontResource ) { HRESULT hr = S_OK; HDC hDC = NULL; LOGFONT logFont = {}; HGDIOBJ hFont = NULL; ULONG privStatus = 0; LONG ttStatus; XPS_FONT_EMBEDDING embedding = XPS_FONT_EMBEDDING_NORMAL; DWORD fontDataLen = GDI_ERROR; HGLOBAL hGlobal = NULL; LPVOID ptr = NULL; IStream *fontStream = NULL; GUID fontObfuscationGuid = {}; IOpcPartUri* partUri = NULL; wchar_t fontPartName[60]; hDC = CreateDC(L"DISPLAY", NULL, NULL, NULL); if (!hDC) { fwprintf(stderr, L"ERROR: Could not create device context\n"); hr = E_UNEXPECTED; } if (SUCCEEDED(hr)) { if (wcscpy_s(logFont.lfFaceName, fontName) != 0) { fwprintf(stderr, L"ERROR: Could not copy font name into LOGFONT structure\n"); hr = E_UNEXPECTED; } } if (SUCCEEDED(hr)) { hFont = CreateFontIndirect(&logFont); if (!hFont) { fwprintf(stderr, L"ERROR: Could not create font\n"); hr = E_UNEXPECTED; } } if (SUCCEEDED(hr)) { if (!SelectObject(hDC, hFont)) { fwprintf(stderr, L"ERROR: Could not select object\n"); hr = E_UNEXPECTED; } } if (SUCCEEDED(hr)) { if ((ttStatus = TTGetEmbeddingType(hDC, &privStatus)) != E_NONE) { if (ttStatus == E_NOTATRUETYPEFONT) { fwprintf(stderr, L"ERROR: %s is not a TrueType font\n", fontName); } else { fwprintf(stderr, L"ERROR: Could not get embedding type: %08X\n", ttStatus); } hr = E_UNEXPECTED; } } if (SUCCEEDED(hr)) { switch (privStatus) { case EMBED_PREVIEWPRINT: // Restricted font embedding = XPS_FONT_EMBEDDING_RESTRICTED; break; case EMBED_EDITABLE: // Editable font - MUST obfuscate embedding = XPS_FONT_EMBEDDING_OBFUSCATED; break; case EMBED_INSTALLABLE: // Installable font - SHOULD obfuscate embedding = XPS_FONT_EMBEDDING_OBFUSCATED; break; case EMBED_NOEMBEDDING: fwprintf(stderr, L"ERROR: %s may not be embedded\n", fontName); hr = E_UNEXPECTED; break; default: fwprintf(stderr, L"ERROR: Unrecognized embedding privileges: %08X\n", privStatus); hr = E_UNEXPECTED; break; } } if (SUCCEEDED(hr)) { fontDataLen = GetFontData(hDC, 0, 0, NULL, 0); if (fontDataLen == GDI_ERROR) { fwprintf(stderr, L"ERROR: Could not get length of font data\n"); hr = E_UNEXPECTED; } } if (SUCCEEDED(hr)) { hGlobal = GlobalAlloc(GMEM_MOVEABLE, fontDataLen); if (!hGlobal) { fwprintf(stderr, L"ERROR: Could not allocate memory with GlobalAlloc\n"); hr = E_OUTOFMEMORY; } } if (SUCCEEDED(hr)) { ptr = GlobalLock(hGlobal); if (!ptr) { hr = HRESULT_FROM_WIN32(GetLastError()); fwprintf(stderr, L"ERROR: Could not lock global memory object: %08X\n", hr); } else { if (GetFontData(hDC, 0, 0, ptr, fontDataLen) == GDI_ERROR) { fwprintf(stderr, L"ERROR: Could not get font data\n"); hr = E_UNEXPECTED; } GlobalUnlock(hGlobal); } } // Could perform font subsetting with CreateFontPackage here. if (SUCCEEDED(hr)) { if (FAILED(hr = CreateStreamOnHGlobal(hGlobal, TRUE, &fontStream))) { fwprintf(stderr, L"ERROR: Could not create font stream: %08X\n", hr); } else { // If CreateStreamOnHGlobal succeeded, the stream now controls the lifetime of the // HGLOBAL. hGlobal = NULL; } } if (SUCCEEDED(hr)) { if (FAILED(hr = CoCreateGuid(&fontObfuscationGuid))) { fwprintf(stderr, L"ERROR: Could not create GUID for obfuscation: %08X\n", hr); } } if (SUCCEEDED(hr)) { if (swprintf_s( fontPartName, sizeof(fontPartName)/sizeof(wchar_t), L"/Resources/Fonts/%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X.odttf", fontObfuscationGuid.Data1, fontObfuscationGuid.Data2, fontObfuscationGuid.Data3, fontObfuscationGuid.Data4[0], fontObfuscationGuid.Data4[1], fontObfuscationGuid.Data4[2], fontObfuscationGuid.Data4[3], fontObfuscationGuid.Data4[4], fontObfuscationGuid.Data4[5], fontObfuscationGuid.Data4[6], fontObfuscationGuid.Data4[7] ) == -1) { fwprintf(stderr, L"ERROR: Could not format GUID into part name\n"); hr = E_UNEXPECTED; } } if (SUCCEEDED(hr)) { if (FAILED(hr = xpsFactory->CreatePartUri( fontPartName, &partUri))) { fwprintf(stderr, L"ERROR: Could not create part URI: %08X\n", hr); } } if (SUCCEEDED(hr)) { if (FAILED(hr = xpsFactory->CreateFontResource( fontStream, embedding, partUri, FALSE, fontResource ))) { fwprintf(stderr, L"ERROR: Could not create font resource: %08X\n", hr); } } if (fontStream) { fontStream->Release(); fontStream = NULL; } if (partUri) { partUri->Release(); partUri = NULL; } if (hGlobal) { GlobalFree(hGlobal); } if (hFont) { DeleteObject(hFont); } if (hDC) { DeleteDC(hDC); } return hr; }
static CFStringRef getPostScriptName(CFStringRef faceName, HDC dc) { const DWORD cMaxNameTableSize = 1024 * 1024; static HashMap<String, RetainPtr<CFStringRef> > nameMap; // Check our hash first. String faceString(faceName); RetainPtr<CFStringRef> result = nameMap.get(faceString); if (result) return result.get(); // We need to obtain the PostScript name from the name table and use it instead,. DWORD bufferSize = GetFontData(dc, 'eman', 0, NULL, 0); // "name" backwards if (bufferSize == 0 || bufferSize == GDI_ERROR || bufferSize > cMaxNameTableSize) return NULL; Vector<BYTE> bufferVector(bufferSize); BYTE* buffer = bufferVector.data(); if (GetFontData(dc, 'eman', 0, buffer, bufferSize) == GDI_ERROR) return NULL; if (bufferSize < 6) return NULL; USHORT numberOfRecords = readBigEndianWord(buffer + 2); UINT stringsOffset = readBigEndianWord(buffer + 4); if (bufferSize < stringsOffset) return NULL; BYTE* strings = buffer + stringsOffset; // Now walk each name record looking for a Mac or Windows PostScript name. UINT offset = 6; for (int i = 0; i < numberOfRecords; i++) { if (bufferSize < offset + 12) return NULL; USHORT platformID = readBigEndianWord(buffer + offset); USHORT encodingID = readBigEndianWord(buffer + offset + 2); USHORT languageID = readBigEndianWord(buffer + offset + 4); USHORT nameID = readBigEndianWord(buffer + offset + 6); USHORT length = readBigEndianWord(buffer + offset + 8); USHORT nameOffset = readBigEndianWord(buffer + offset + 10); if (platformID == 3 && encodingID == 1 && languageID == 0x409 && nameID == 6) { // This is a Windows PostScript name and is therefore UTF-16. // Pass Big Endian as the encoding. if (bufferSize < stringsOffset + nameOffset + length) return NULL; result = adoptCF(CFStringCreateWithBytes(NULL, strings + nameOffset, length, kCFStringEncodingUTF16BE, false)); break; } else if (platformID == 1 && encodingID == 0 && languageID == 0 && nameID == 6) { // This is a Mac PostScript name and is therefore ASCII. // See http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html if (bufferSize < stringsOffset + nameOffset + length) return NULL; result = adoptCF(CFStringCreateWithBytes(NULL, strings + nameOffset, length, kCFStringEncodingASCII, false)); break; } offset += 12; } if (result) nameMap.set(faceString, result); return result.get(); }
/**************************************************************************** * get_download_name */ static void get_download_name(PHYSDEV dev, LPOUTLINETEXTMETRICA potm, char **str) { int len; char *p; DWORD size; size = GetFontData(dev->hdc, MS_MAKE_TAG('n','a','m','e'), 0, NULL, 0); if(size != 0 && size != GDI_ERROR) { BYTE *name = HeapAlloc(GetProcessHeap(), 0, size); if(name) { USHORT count, i; BYTE *strings; struct { USHORT platform_id; USHORT encoding_id; USHORT language_id; USHORT name_id; USHORT length; USHORT offset; } *name_record; GetFontData(dev->hdc, MS_MAKE_TAG('n','a','m','e'), 0, name, size); count = GET_BE_WORD(name + 2); strings = name + GET_BE_WORD(name + 4); name_record = (typeof(name_record))(name + 6); for(i = 0; i < count; i++, name_record++) { name_record->platform_id = GET_BE_WORD(&name_record->platform_id); name_record->encoding_id = GET_BE_WORD(&name_record->encoding_id); name_record->language_id = GET_BE_WORD(&name_record->language_id); name_record->name_id = GET_BE_WORD(&name_record->name_id); name_record->length = GET_BE_WORD(&name_record->length); name_record->offset = GET_BE_WORD(&name_record->offset); if(name_record->platform_id == 1 && name_record->encoding_id == 0 && name_record->language_id == 0 && name_record->name_id == 6) { TRACE("Got Mac PS name %s\n", debugstr_an((char*)strings + name_record->offset, name_record->length)); *str = HeapAlloc(GetProcessHeap(), 0, name_record->length + 1); memcpy(*str, strings + name_record->offset, name_record->length); *(*str + name_record->length) = '\0'; HeapFree(GetProcessHeap(), 0, name); return; } if(name_record->platform_id == 3 && name_record->encoding_id == 1 && name_record->language_id == 0x409 && name_record->name_id == 6) { WCHAR *unicode = HeapAlloc(GetProcessHeap(), 0, name_record->length + 2); DWORD len; int c; for(c = 0; c < name_record->length / 2; c++) unicode[c] = GET_BE_WORD(strings + name_record->offset + c * 2); unicode[c] = 0; TRACE("Got Windows PS name %s\n", debugstr_w(unicode)); len = WideCharToMultiByte(1252, 0, unicode, -1, NULL, 0, NULL, NULL); *str = HeapAlloc(GetProcessHeap(), 0, len); WideCharToMultiByte(1252, 0, unicode, -1, *str, len, NULL, NULL); HeapFree(GetProcessHeap(), 0, unicode); HeapFree(GetProcessHeap(), 0, name); return; } } TRACE("Unable to find PostScript name\n"); HeapFree(GetProcessHeap(), 0, name); } } len = strlen((char*)potm + (ptrdiff_t)potm->otmpFullName) + 1; *str = HeapAlloc(GetProcessHeap(),0,len); strcpy(*str, (char*)potm + (ptrdiff_t)potm->otmpFullName); p = *str; while((p = strchr(p, ' '))) *p = '_'; return; }