Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
/* 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;
}
Ejemplo n.º 3
0
/* 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;
}