⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uniscribehelper.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
            // Generate a last fallback font based on the script of            // a character to draw while inheriting size and styles            // from the primary font            if (!m_logfont.lfFaceName[0])                setLogFontAndStyle(m_hfont, &m_logfont, &m_style);            // TODO(jungshik): generic type should come from webkit for            // UniscribeHelperTextRun (a derived class used in webkit).            const UChar *family = getFallbackFamily(input, itemLength,                FontDescription::StandardFamily, 0, 0);            bool fontOk = getDerivedFontData(family, m_style, &m_logfont,                                              &ascent, &hfont, &scriptCache);            if (!fontOk) {                // If this GetDerivedFontData is called from the renderer it                // might fail because the sandbox is preventing it from opening                // the font files.  If we are running in the renderer,                // TryToPreloadFont is overridden to ask the browser to preload                // the font for us so we can access it.                tryToPreloadFont(hfont);                // Try again.                fontOk = getDerivedFontData(family, m_style, &m_logfont,                                             &ascent, &hfont, &scriptCache);                ASSERT(fontOk);            }            // TODO(jungshik) : Currently GetDerivedHFont always returns a            // a valid HFONT, but in the future, I may change it to return 0.            ASSERT(hfont);            // We don't need a font_properties for the last resort fallback font            // because we don't have anything more to try and are forced to            // accept empty glyph boxes. If we tried a series of fonts as            // 'last-resort fallback', we'd need it, but currently, we don't.            continue;        } else if (hr == USP_E_SCRIPT_NOT_IN_FONT) {            run.a.eScript = SCRIPT_UNDEFINED;            continue;        } else if (FAILED(hr)) {            // Error shaping.            generatedGlyphs = 0;            result = false;            goto cleanup;        }    }    // Sets Windows font data for this run to those corresponding to    // a font supporting this run. we don't need to store font_properties    // because it's not used elsewhere.    shaping.m_hfont = hfont;    shaping.m_scriptCache = scriptCache;    // The ascent of a font for this run can be different from    // that of the primary font so that we need to keep track of    // the difference per run and take that into account when calling    // ScriptTextOut in |draw|. Otherwise, different runs rendered by    // different fonts would not be aligned vertically.    shaping.m_ascentOffset = m_ascent ? ascent - m_ascent : 0;    result = true;  cleanup:    shaping.m_glyphs.resize(generatedGlyphs);    shaping.m_visualAttributes.resize(generatedGlyphs);    shaping.m_advance.resize(generatedGlyphs);    shaping.m_offsets.resize(generatedGlyphs);    if (tempDC) {        SelectObject(tempDC, oldFont);        ReleaseDC(0, tempDC);    }    // On failure, our logs don't mean anything, so zero those out.    if (!result)        shaping.m_logs.clear();    return result;}void UniscribeHelper::fillShapes(){    m_shapes.resize(m_runs.size());    for (size_t i = 0; i < m_runs.size(); i++) {        int startItem = m_runs[i].iCharPos;        int itemLength = m_inputLength - startItem;        if (i < m_runs.size() - 1)            itemLength = m_runs[i + 1].iCharPos - startItem;        int numGlyphs;        if (itemLength < UNISCRIBE_HELPER_STACK_CHARS) {            // We'll start our buffer sizes with the current stack space            // available in our buffers if the current input fits. As long as            // it doesn't expand past that we'll save a lot of time mallocing.            numGlyphs = UNISCRIBE_HELPER_STACK_CHARS;        } else {            // When the input doesn't fit, give up with the stack since it will            // almost surely not be enough room (unless the input actually            // shrinks, which is unlikely) and just start with the length            // recommended by the Uniscribe documentation as a "usually fits"            // size.            numGlyphs = itemLength * 3 / 2 + 16;        }        // Convert a string to a glyph string trying the primary font, fonts in        // the fallback list and then script-specific last resort font.        Shaping& shaping = m_shapes[i];        if (!shape(&m_input[startItem], itemLength, numGlyphs, m_runs[i], shaping))            continue;        // At the moment, the only time m_disableFontFallback is set is        // when we look up glyph indices for non-BMP code ranges. So,        // we can skip the glyph placement. When that becomes not the case        // any more, we have to add a new flag to control glyph placement.        if (m_disableFontFallback)          continue;        // Compute placements. Note that offsets is documented incorrectly        // and is actually an array.        // DC that we lazily create if Uniscribe commands us to.        // (this does not happen often because scriptCache is already        //  updated when calling ScriptShape).        HDC tempDC = 0;        HGDIOBJ oldFont = 0;        HRESULT hr;        while (true) {            shaping.m_prePadding = 0;            hr = ScriptPlace(tempDC, shaping.m_scriptCache,                             &shaping.m_glyphs[0],                             static_cast<int>(shaping.m_glyphs.size()),                             &shaping.m_visualAttributes[0], &m_runs[i].a,                             &shaping.m_advance[0], &shaping.m_offsets[0],                             &shaping.m_abc);            if (hr != E_PENDING)                break;            // Allocate the DC and run the loop again.            tempDC = GetDC(0);            oldFont = SelectObject(tempDC, shaping.m_hfont);        }        if (FAILED(hr)) {            // Some error we don't know how to handle. Nuke all of our data            // since we can't deal with partially valid data later.            m_runs.clear();            m_shapes.clear();            m_screenOrder.clear();        }        if (tempDC) {            SelectObject(tempDC, oldFont);            ReleaseDC(0, tempDC);        }    }    adjustSpaceAdvances();    if (m_letterSpacing != 0 || m_wordSpacing != 0)        applySpacing();}void UniscribeHelper::fillScreenOrder(){    m_screenOrder.resize(m_runs.size());    // We assume that the input has only one text direction in it.    // TODO(brettw) are we sure we want to keep this restriction?    if (m_isRtl) {        for (int i = 0; i < static_cast<int>(m_screenOrder.size()); i++)            m_screenOrder[static_cast<int>(m_screenOrder.size()) - i - 1] = i;    } else {        for (int i = 0; i < static_cast<int>(m_screenOrder.size()); i++)            m_screenOrder[i] = i;    }}void UniscribeHelper::adjustSpaceAdvances(){    if (m_spaceWidth == 0)        return;    int spaceWidthWithoutLetterSpacing = m_spaceWidth - m_letterSpacing;    // This mostly matches what WebKit's UniscribeController::shapeAndPlaceItem.    for (size_t run = 0; run < m_runs.size(); run++) {        Shaping& shaping = m_shapes[run];        for (int i = 0; i < shaping.charLength(); i++) {            if (!treatAsSpace(m_input[m_runs[run].iCharPos + i]))                continue;            int glyphIndex = shaping.m_logs[i];            int currentAdvance = shaping.m_advance[glyphIndex];            // currentAdvance does not include additional letter-spacing, but            // space_width does. Here we find out how off we are from the            // correct width for the space not including letter-spacing, then            // just subtract that diff.            int diff = currentAdvance - spaceWidthWithoutLetterSpacing;            // The shaping can consist of a run of text, so only subtract the            // difference in the width of the glyph.            shaping.m_advance[glyphIndex] -= diff;            shaping.m_abc.abcB -= diff;        }    }}void UniscribeHelper::applySpacing(){    for (size_t run = 0; run < m_runs.size(); run++) {        Shaping& shaping = m_shapes[run];        bool isRtl = m_runs[run].a.fRTL;        if (m_letterSpacing != 0) {            // RTL text gets padded to the left of each character. We increment            // the run's advance to make this happen. This will be balanced out            // by NOT adding additional advance to the last glyph in the run.            if (isRtl)                shaping.m_prePadding += m_letterSpacing;            // Go through all the glyphs in this run and increase the "advance"            // to account for letter spacing. We adjust letter spacing only on            // cluster boundaries.            //            // This works for most scripts, but may have problems with some            // indic scripts. This behavior is better than Firefox or IE for            // Hebrew.            for (int i = 0; i < shaping.glyphLength(); i++) {                if (shaping.m_visualAttributes[i].fClusterStart) {                    // Ick, we need to assign the extra space so that the glyph                    // comes first, then is followed by the space. This is                    // opposite for RTL.                    if (isRtl) {                        if (i != shaping.glyphLength() - 1) {                            // All but the last character just get the spacing                            // applied to their advance. The last character                            // doesn't get anything,                            shaping.m_advance[i] += m_letterSpacing;                            shaping.m_abc.abcB += m_letterSpacing;                        }                    } else {                        // LTR case is easier, we just add to the advance.                        shaping.m_advance[i] += m_letterSpacing;                        shaping.m_abc.abcB += m_letterSpacing;                    }                }            }        }        // Go through all the characters to find whitespace and insert the        // extra wordspacing amount for the glyphs they correspond to.        if (m_wordSpacing != 0) {            for (int i = 0; i < shaping.charLength(); i++) {                if (!treatAsSpace(m_input[m_runs[run].iCharPos + i]))                    continue;                // The char in question is a word separator...                int glyphIndex = shaping.m_logs[i];                // Spaces will not have a glyph in Uniscribe, it will just add                // additional advance to the character to the left of the                // space. The space's corresponding glyph will be the character                // following it in reading order.                if (isRtl) {                    // In RTL, the glyph to the left of the space is the same                    // as the first glyph of the following character, so we can                    // just increment it.                    shaping.m_advance[glyphIndex] += m_wordSpacing;                    shaping.m_abc.abcB += m_wordSpacing;                } else {                    // LTR is actually more complex here, we apply it to the                    // previous character if there is one, otherwise we have to                    // apply it to the leading space of the run.                    if (glyphIndex == 0)                        shaping.m_prePadding += m_wordSpacing;                    else {                        shaping.m_advance[glyphIndex - 1] += m_wordSpacing;                        shaping.m_abc.abcB += m_wordSpacing;                    }                }            }        }  // m_wordSpacing != 0        // Loop for next run...    }}// The advance is the ABC width of the runint UniscribeHelper::advanceForItem(int itemIndex) const{    int accum = 0;    const Shaping& shaping = m_shapes[itemIndex];    if (shaping.m_justify.size() == 0) {        // Easy case with no justification, the width is just the ABC width of        // the run. (The ABC width is the sum of the advances).        return shaping.m_abc.abcA + shaping.m_abc.abcB +               shaping.m_abc.abcC + shaping.m_prePadding;    }    // With justification, we use the justified amounts instead. The    // justification array contains both the advance and the extra space    // added for justification, so is the width we want.    int justification = 0;    for (size_t i = 0; i < shaping.m_justify.size(); i++)        justification += shaping.m_justify[i];    return shaping.m_prePadding + justification;}}  // namespace WebCore

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -