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;
}
Пример #3
0
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;
}
Пример #6
0
    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;
    }
Пример #7
0
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;
}
Пример #8
0
/* [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;
}
Пример #10
0
    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;
    }
Пример #11
0
    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);
    }
Пример #12
0
    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;
}