bool GlyphPage::fill(UChar* buffer, unsigned bufferLength, const Font* fontData) { // bufferLength will be greater than the requested number of glyphs if the buffer contains surrogate pairs. // We won't support this for now. if (bufferLength > GlyphPage::size) return false; bool haveGlyphs = false; HWndDC dc(0); SaveDC(dc); SelectObject(dc, fontData->platformData().hfont()); WORD localGlyphBuffer[GlyphPage::size * 2]; DWORD result = GetGlyphIndices(dc, buffer, bufferLength, localGlyphBuffer, GGI_MARK_NONEXISTING_GLYPHS); bool success = result != GDI_ERROR && static_cast<unsigned>(result) == bufferLength; if (success) { for (unsigned i = 0; i < GlyphPage::size; i++) { Glyph glyph = localGlyphBuffer[i]; if (glyph == 0xffff) setGlyphForIndex(i, 0); else { setGlyphForIndex(i, glyph); haveGlyphs = true; } } } RestoreDC(dc, -1); return haveGlyphs; }
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData) { // bufferLength will be greater than the requested number of glyphs if the buffer contains surrogate pairs. // We won't support this for now. if (bufferLength > length) return false; bool haveGlyphs = false; HDC dc = GetDC((HWND)0); SaveDC(dc); SelectObject(dc, fontData->platformData().hfont()); TEXTMETRIC tm; GetTextMetrics(dc, &tm); WORD localGlyphBuffer[GlyphPage::size * 2]; DWORD result = GetGlyphIndices(dc, buffer, bufferLength, localGlyphBuffer, 0); bool success = result != GDI_ERROR && static_cast<unsigned>(result) == bufferLength; if (success) { for (unsigned i = 0; i < length; i++) { Glyph glyph = localGlyphBuffer[i]; if (!glyph) setGlyphDataForIndex(offset + i, 0, 0); else { setGlyphDataForIndex(offset + i, glyph, fontData); haveGlyphs = true; } } } RestoreDC(dc, -1); ReleaseDC(0, dc); return haveGlyphs; }
void getGlyphIds(FILE *fp, Options *opts) { LOGFONT fontDetails = {0}; HFONT font; HDC hdc = GetDC(NULL); HGDIOBJ old; WORD result[4]; DWORD ret; wchar_t buffer[BUFSIZ]; fontDetails.lfWeight = opts->bold ? 700 : 0; fontDetails.lfItalic = opts->italic; wcsncpy_s(fontDetails.lfFaceName, 32, opts->font_name, _TRUNCATE); fontDetails.lfCharSet = SHIFTJIS_CHARSET; font = CreateFontIndirect(&fontDetails); old = SelectObject(hdc, font); GetTextFace(hdc, BUFSIZ, buffer); printf("Selected text face: %S\n", buffer); ret = GetGlyphIndices(hdc, L"てst", 3, result, GGI_MARK_NONEXISTING_GLYPHS); SelectObject(hdc, old); DeleteObject(font); ReleaseDC(NULL, hdc); }
// Lazily initializes space glyph static Glyph initSpaceGlyph(HDC dc, Glyph* spaceGlyph) { if (*spaceGlyph) return *spaceGlyph; static wchar_t space = ' '; GetGlyphIndices(dc, &space, 1, spaceGlyph, 0); return *spaceGlyph; }
WORD getSpaceGlyph(HFONT hfont) { HWndDC dc(0); HGDIOBJ oldFont = SelectObject(dc, hfont); WCHAR space = L' '; WORD spaceGlyph = 0; GetGlyphIndices(dc, &space, 1, &spaceGlyph, 0); SelectObject(dc, oldFont); return spaceGlyph; }
static int getGlyphForChar (HDC dc, juce_wchar character) { const WCHAR charToTest[] = { (WCHAR) character, 0 }; WORD index = 0; if (GetGlyphIndices (dc, charToTest, 1, &index, GGI_MARK_NONEXISTING_GLYPHS) == GDI_ERROR || index == 0xffff) return -1; return index; }
sBool sFont2D::LetterExists(sChar letter) { SelectObject(sGDIDCOffscreen,prv->Font); sChar in[2]; WORD out[2]; in[0] = letter; in[1] = 0; if(GetGlyphIndices(sGDIDCOffscreen,&letter,1,out,GGI_MARK_NONEXISTING_GLYPHS)!=1) return 0; return out[0]!=0xffff; }
/* [fault_status][comm_status] */ error_status_t gdipp_rpc_get_glyph_indices( /* [in] */ handle_t h_gdipp_rpc, /* [context_handle_noserialize][in] */ GDIPP_RPC_SESSION_HANDLE h_session, /* [size_is][string][in] */ const wchar_t *str, /* [in] */ int count, /* [size_is][out] */ unsigned short *gi) { 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 GetGlyphIndices(curr_session->font_holder, str, count, gi, GGI_MARK_NONEXISTING_GLYPHS); return RPC_S_OK; }
bool GlyphPage::fill(UChar* buffer, unsigned bufferLength, const FontData* fontData) { HDC dc = GetDC((HWND)0); SaveDC(dc); SelectObject(dc, fontData->m_font.hfont()); TEXTMETRIC tm; GetTextMetrics(dc, &tm); WORD localGlyphBuffer[GlyphPage::size]; GetGlyphIndices(dc, buffer, bufferLength, localGlyphBuffer, 0); for (unsigned i = 0; i < GlyphPage::size; i++) setGlyphDataForIndex(i, localGlyphBuffer[i], fontData); RestoreDC(dc, -1); ReleaseDC(0, dc); return true; }
float getStringWidth (const String& text) { const CharPointer_UTF16 utf16 (text.toUTF16()); const size_t numChars = utf16.length(); HeapBlock<int16> results (numChars + 1); results[numChars] = -1; float x = 0; if (GetGlyphIndices (dc, utf16, (int) numChars, reinterpret_cast <WORD*> (results.getData()), GGI_MARK_NONEXISTING_GLYPHS) != GDI_ERROR) { for (size_t i = 0; i < numChars; ++i) x += getKerning (dc, results[i], results[i + 1]); } return x; }
void getGlyphPositions (const String& text, Array <int>& resultGlyphs, Array <float>& xOffsets) { const CharPointer_UTF16 utf16 (text.toUTF16()); const size_t numChars = utf16.length(); HeapBlock<int16> results (numChars + 1); results[numChars] = -1; float x = 0; if (GetGlyphIndices (dc, utf16, (int) numChars, reinterpret_cast <WORD*> (results.getData()), GGI_MARK_NONEXISTING_GLYPHS) != GDI_ERROR) { resultGlyphs.ensureStorageAllocated ((int) numChars); xOffsets.ensureStorageAllocated ((int) numChars + 1); for (size_t i = 0; i < numChars; ++i) { resultGlyphs.add (results[i]); xOffsets.add (x); x += getKerning (dc, results[i], results[i + 1]); } } xOffsets.add (x); }
bool loadGlyphIfPossible (juce_wchar character) { HDC dc = FontDCHolder::getInstance()->loadFont (name, isBold, isItalic, 0); GLYPHMETRICS gm; // if this is the fallback font, skip checking for the glyph's existence. This is because // with fonts like Tahoma, GetGlyphIndices can say that a glyph doesn't exist, but it still // gets correctly created later on. if (! isFallbackFont) { const WCHAR charToTest[] = { (WCHAR) character, 0 }; WORD index = 0; if (GetGlyphIndices (dc, charToTest, 1, &index, GGI_MARK_NONEXISTING_GLYPHS) != GDI_ERROR && index == 0xffff) { return false; } } Path glyphPath; TEXTMETRIC tm; if (! GetTextMetrics (dc, &tm)) { addGlyph (character, glyphPath, 0); return true; } const float height = (float) tm.tmHeight; static const MAT2 identityMatrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } }; const int bufSize = GetGlyphOutline (dc, character, GGO_NATIVE, &gm, 0, 0, &identityMatrix); if (bufSize > 0) { HeapBlock<char> data (bufSize); GetGlyphOutline (dc, character, GGO_NATIVE, &gm, bufSize, data, &identityMatrix); const TTPOLYGONHEADER* pheader = reinterpret_cast<TTPOLYGONHEADER*> (data.getData()); const float scaleX = 1.0f / height; const float scaleY = -1.0f / height; while ((char*) pheader < data + bufSize) { float x = scaleX * pheader->pfxStart.x.value; float y = scaleY * pheader->pfxStart.y.value; glyphPath.startNewSubPath (x, y); const TTPOLYCURVE* curve = (const TTPOLYCURVE*) ((const char*) pheader + sizeof (TTPOLYGONHEADER)); const char* const curveEnd = ((const char*) pheader) + pheader->cb; while ((const char*) curve < curveEnd) { if (curve->wType == TT_PRIM_LINE) { for (int i = 0; i < curve->cpfx; ++i) { x = scaleX * curve->apfx[i].x.value; y = scaleY * curve->apfx[i].y.value; glyphPath.lineTo (x, y); } } else if (curve->wType == TT_PRIM_QSPLINE) { for (int i = 0; i < curve->cpfx - 1; ++i) { const float x2 = scaleX * curve->apfx[i].x.value; const float y2 = scaleY * curve->apfx[i].y.value; float x3, y3; if (i < curve->cpfx - 2) { x3 = 0.5f * (x2 + scaleX * curve->apfx[i + 1].x.value); y3 = 0.5f * (y2 + scaleY * curve->apfx[i + 1].y.value); } else { x3 = scaleX * curve->apfx[i + 1].x.value; y3 = scaleY * curve->apfx[i + 1].y.value; } glyphPath.quadraticTo (x2, y2, x3, y3); x = x3; y = y3; } } curve = (const TTPOLYCURVE*) &(curve->apfx [curve->cpfx]); } pheader = (const TTPOLYGONHEADER*) curve; glyphPath.closeSubPath(); } } addGlyph (character, glyphPath, gm.gmCellIncX / height); int numKPs; const KERNINGPAIR* const kps = FontDCHolder::getInstance()->getKerningPairs (numKPs); for (int i = 0; i < numKPs; ++i) { if (kps[i].wFirst == character) addKerningPair (kps[i].wFirst, kps[i].wSecond, kps[i].iKernAmount / height); } return true; }
// 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; }