static bool fontContainsCharacter(const FontPlatformData* fontData, const wchar_t* family, UChar32 character) { // FIXME: For non-BMP characters, GetFontUnicodeRanges is of // no use. We have to read directly from the cmap table of a font. // Return true for now. if (character > 0xFFFF) return true; // This cache is just leaked on shutdown. static FontCmapCache* fontCmapCache = 0; if (!fontCmapCache) fontCmapCache = new FontCmapCache; HashMap<const wchar_t*, icu::UnicodeSet*>::iterator it = fontCmapCache->find(family); if (it != fontCmapCache->end()) return it->second->contains(character); HFONT hfont = fontData->hfont(); HDC hdc = GetDC(0); HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(hdc, hfont)); int count = GetFontUnicodeRanges(hdc, 0); if (!count && PlatformSupport::ensureFontLoaded(hfont)) count = GetFontUnicodeRanges(hdc, 0); if (!count) { LOG_ERROR("Unable to get the font unicode range after second attempt"); SelectObject(hdc, oldFont); ReleaseDC(0, hdc); return true; } static Vector<char, 512> glyphsetBuffer; glyphsetBuffer.resize(GetFontUnicodeRanges(hdc, 0)); GLYPHSET* glyphset = reinterpret_cast<GLYPHSET*>(glyphsetBuffer.data()); // In addition, refering to the OS/2 table and converting the codepage list // to the coverage map might be faster. count = GetFontUnicodeRanges(hdc, glyphset); ASSERT(count > 0); SelectObject(hdc, oldFont); ReleaseDC(0, hdc); // FIXME: consider doing either of the following two: // 1) port back ICU 4.0's faster look-up code for UnicodeSet // 2) port Mozilla's CompressedCharMap or gfxSparseBitset unsigned i = 0; icu::UnicodeSet* cmap = new icu::UnicodeSet; while (i < glyphset->cRanges) { WCHAR start = glyphset->ranges[i].wcLow; cmap->add(start, start + glyphset->ranges[i].cGlyphs - 1); i++; } cmap->freeze(); // We don't lowercase |family| because all of them are under our control // and they're already lowercased. fontCmapCache->set(family, cmap); return cmap->contains(character); }
/* Take this code form GolenDict which is a open source software */ static WCHAR * GlyphindexToUnicode(HDC hdc, LPCWSTR lpszString, int cbString) { LPGLYPHSET ranges; WCHAR * allChars, * ptr, * restoredString; WORD * allIndices; unsigned x; // Here we have to decode glyph indices back to chars. We do this // by tedious and ineffective iteration. // ranges = (LPGLYPHSET)malloc( GetFontUnicodeRanges( hdc, 0 ) ); GetFontUnicodeRanges( hdc, ranges ); // Render up all available chars into one ridiculously big string allChars = (WCHAR *)malloc( ( ranges->cGlyphsSupported ) * sizeof( WCHAR ) ); allIndices = (WORD *)malloc( ( ranges->cGlyphsSupported ) * sizeof( WORD ) ); ptr = allChars; for( x = 0; x < ranges->cRanges; ++x ) { WCHAR c = ranges->ranges[x].wcLow; unsigned y = ranges->ranges[ x ].cGlyphs; while( y-- ) *ptr++ = c++; } // Amazing. Now get glyph indices for this one nice string. GetGlyphIndicesW(hdc, allChars, ranges->cGlyphsSupported, allIndices, GGI_MARK_NONEXISTING_GLYPHS ); // Fascinating. Now translate our original input string back into // its readable form. restoredString = (WCHAR *)malloc(cbString * sizeof( WCHAR )); for( x = 0; x < cbString; ++x ) { unsigned y; WORD idx = lpszString[x]; for( y = 0; y < ranges->cGlyphsSupported; ++y ) { if (allIndices[y] == idx ) { restoredString[x] = allChars[ y ]; break; } if ( y == ranges->cGlyphsSupported ) { // Not found restoredString[ x ] = L'?'; } } } // And we're done. free(allIndices); free(allChars); free(ranges); return restoredString; }
/* Constructor of the object : it allocates memory and initializes the member * of the new object. * The user must give the initial GLYPHSET of the font or the master (which * may be NULL) in which case the character map will be empty. */ __GLCcharMap* __glcCharMapCreate(__GLCmaster* inMaster) { __GLCcharMap* This = NULL; This = (__GLCcharMap*)__glcMalloc(sizeof(__GLCcharMap)); if (!This) { __glcRaiseError(GLC_RESOURCE_ERROR); return NULL; } if (inMaster) { HFONT font; DWORD size; HDC dc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); if (FAILED(dc)) { __glcFree(This); __glcRaiseError(GLC_RESOURCE_ERROR); return NULL; } font = CreateFontIndirect(&inMaster->pattern->elfLogFont); if (FAILED(font)) { DeleteDC(dc); __glcFree(This); __glcRaiseError(GLC_RESOURCE_ERROR); return NULL; } if (FAILED(SelectObject(dc, font))) { DeleteDC(dc); DeleteObject(font); __glcFree(This); __glcRaiseError(GLC_RESOURCE_ERROR); return NULL; } size = GetFontUnicodeRanges(dc, NULL); if (!size) { DeleteDC(dc); DeleteObject(font); __glcFree(This); __glcRaiseError(GLC_RESOURCE_ERROR); return NULL; } This->charSet = (LPGLYPHSET)__glcMalloc(size); if (!This->charSet) { DeleteDC(dc); DeleteObject(font); __glcRaiseError(GLC_RESOURCE_ERROR); __glcFree(This); return NULL; } if (!GetFontUnicodeRanges(dc, This->charSet)) { DeleteDC(dc); DeleteObject(font); __glcFree(This->charSet); __glcFree(This); __glcRaiseError(GLC_RESOURCE_ERROR); return NULL; } DeleteDC(dc); DeleteObject(font); } else { This->charSet = (LPGLYPHSET)__glcMalloc(sizeof(GLYPHSET)); if (!This->charSet) { __glcRaiseError(GLC_RESOURCE_ERROR); __glcFree(This); return NULL; } } /* The array 'map' will contain the actual character map */ This->map = __glcArrayCreate(sizeof(__GLCcharMapElement)); if (!This->map) { __glcRaiseError(GLC_RESOURCE_ERROR); __glcFree(This->charSet); __glcFree(This); return NULL; } return This; }