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

📄 uniscribehelper.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        if (shaping.charLength() == 0 ||            fromChar >= shaping.charLength() || toChar <= 0) {            // No chars in this item to display.            curX += advanceForItem(itemIndex);            continue;        }        // Compute the starting glyph within this span. |from| and |to| are        // global offsets that may intersect arbitrarily with our local run.        int fromGlyph, afterGlyph;        if (item.a.fRTL) {            // To compute the first glyph when going RTL, we use |to|.            if (toChar >= shaping.charLength())                // The end of the text is after (to the left) of us.                fromGlyph = 0;            else {                // Since |to| is exclusive, the first character we draw on the                // left is actually the one right before (to the right) of                // |to|.                fromGlyph = shaping.m_logs[toChar - 1];            }            // The last glyph is actually the first character in the range.            if (fromChar <= 0) {                // The first character to draw is before (to the right) of this                // span, so draw all the way to the end.                afterGlyph = shaping.glyphLength();            } else {                // We want to draw everything up until the character to the                // right of |from|. To the right is - 1, so we look that up                // (remember our character could be more than one glyph, so we                // can't look up our glyph and add one).                afterGlyph = shaping.m_logs[fromChar - 1];            }        } else {            // Easy case, everybody agrees about directions. We only need to            // handle boundary conditions to get a range inclusive at the            // beginning, and exclusive at the ending. We have to do some            // computation to see the glyph one past the end.            fromGlyph = shaping.m_logs[fromChar < 0 ? 0 : fromChar];            if (toChar >= shaping.charLength())                afterGlyph = shaping.glyphLength();            else                afterGlyph = shaping.m_logs[toChar];        }        // Account for the characters that were skipped in this run. When        // WebKit asks us to draw a subset of the run, it actually tells us        // to draw at the X offset of the beginning of the run, since it        // doesn't know the internal position of any of our characters.        const int* effectiveAdvances = shaping.effectiveAdvances();        int innerOffset = 0;        for (int i = 0; i < fromGlyph; i++)            innerOffset += effectiveAdvances[i];        // Actually draw the glyphs we found.        int glyphCount = afterGlyph - fromGlyph;        if (fromGlyph >= 0 && glyphCount > 0) {            // Account for the preceding space we need to add to this run. We            // don't need to count for the following space because that will be            // counted in advanceForItem below when we move to the next run.            innerOffset += shaping.m_prePadding;            // Pass 0 in when there is no justification.            const int* justify = shaping.m_justify.size() == 0 ? 0 : &shaping.m_justify[fromGlyph];            if (firstRun) {                oldFont = SelectObject(dc, shaping.m_hfont);                firstRun = false;            } else                SelectObject(dc, shaping.m_hfont);            // Fonts with different ascents can be used to render different            // runs.  'Across-runs' y-coordinate correction needs to be            // adjusted for each font.            bool textOutOk = false;            for (int executions = 0; executions < 2; ++executions) {                if (useWindowsDrawing) {                    HRESULT hr = ScriptTextOut(dc, shaping.m_scriptCache,                                               curX + innerOffset,                                               y - shaping.m_ascentOffset,                                               0, 0, &item.a, 0, 0,                                               &shaping.m_glyphs[fromGlyph],                                               glyphCount,                                               &shaping.m_advance[fromGlyph],                                               justify,                                               &shaping.m_offsets[fromGlyph]);                    ASSERT(S_OK == hr);                    textOutOk = (hr == S_OK);                } else {                    SkPoint origin;                    origin.fX = curX + + innerOffset;                    origin.fY = y + m_ascent - shaping.m_ascentOffset;                    textOutOk = paintSkiaText(graphicsContext,                                              shaping.m_hfont,                                              glyphCount,                                              &shaping.m_glyphs[fromGlyph],                                              &shaping.m_advance[fromGlyph],                                              &shaping.m_offsets[fromGlyph],                                              &origin);                }                if (!textOutOk && 0 == executions) {                    // If TextOut 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(shaping.m_hfont);                    continue;                }                break;            }        }        curX += advanceForItem(itemIndex);    }    if (oldFont)        SelectObject(dc, oldFont);}WORD UniscribeHelper::firstGlyphForCharacter(int charOffset) const{    // Find the run for the given character.    for (int i = 0; i < static_cast<int>(m_runs.size()); i++) {        int firstChar = m_runs[i].iCharPos;        const Shaping& shaping = m_shapes[i];        int localOffset = charOffset - firstChar;        if (localOffset >= 0 && localOffset < shaping.charLength()) {            // The character is in this run, return the first glyph for it            // (should generally be the only glyph). It seems Uniscribe gives            // glyph 0 for empty, which is what we want to return in the            // "missing" case.            size_t glyphIndex = shaping.m_logs[localOffset];            if (glyphIndex >= shaping.m_glyphs.size()) {                // The glyph should be in this run, but the run has too few                // actual characters. This can happen when shaping the run                // fails, in which case, we should have no data in the logs at                // all.                ASSERT(shaping.m_glyphs.size() == 0);                return 0;            }            return shaping.m_glyphs[glyphIndex];        }    }    return 0;}void UniscribeHelper::fillRuns(){    HRESULT hr;    m_runs.resize(UNISCRIBE_HELPER_STACK_RUNS);    SCRIPT_STATE inputState;    inputState.uBidiLevel = m_isRtl;    inputState.fOverrideDirection = m_directionalOverride;    inputState.fInhibitSymSwap = false;    inputState.fCharShape = false;  // Not implemented in Uniscribe    inputState.fDigitSubstitute = false;  // Do we want this for Arabic?    inputState.fInhibitLigate = m_inhibitLigate;    inputState.fDisplayZWG = false;  // Don't draw control characters.    inputState.fArabicNumContext = m_isRtl;  // Do we want this for Arabic?    inputState.fGcpClusters = false;    inputState.fReserved = 0;    inputState.fEngineReserved = 0;    // The psControl argument to ScriptItemize should be non-0 for RTL text,    // per http://msdn.microsoft.com/en-us/library/ms776532.aspx . So use a    // SCRIPT_CONTROL that is set to all zeros.  Zero as a locale ID means the    // neutral locale per http://msdn.microsoft.com/en-us/library/ms776294.aspx    static SCRIPT_CONTROL inputControl = {0, // uDefaultLanguage    :16;                                           0, // fContextDigits      :1;                                           0, // fInvertPreBoundDir  :1;                                           0, // fInvertPostBoundDir :1;                                           0, // fLinkStringBefore   :1;                                           0, // fLinkStringAfter    :1;                                           0, // fNeutralOverride    :1;                                           0, // fNumericOverride    :1;                                           0, // fLegacyBidiClass    :1;                                           0, // fMergeNeutralItems  :1;                                           0};// fReserved           :7;    // Calling ScriptApplyDigitSubstitution( 0, &inputControl, &inputState)    // here would be appropriate if we wanted to set the language ID, and get    // local digit substitution behavior.  For now, don't do it.    while (true) {        int numberOfItems = 0;        // Ideally, we would have a way to know the runs before and after this        // one, and put them into the control parameter of ScriptItemize. This        // would allow us to shape characters properly that cross style        // boundaries (WebKit bug 6148).        //        // We tell ScriptItemize that the output list of items is one smaller        // than it actually is. According to Mozilla bug 366643, if there is        // not enough room in the array on pre-SP2 systems, ScriptItemize will        // write one past the end of the buffer.        //        // ScriptItemize is very strange. It will often require a much larger        // ITEM buffer internally than it will give us as output. For example,        // it will say a 16-item buffer is not big enough, and will write        // interesting numbers into all those items. But when we give it a 32        // item buffer and it succeeds, it only has one item output.        //        // It seems to be doing at least two passes, the first where it puts a        // lot of intermediate data into our items, and the second where it        // collates them.        hr = ScriptItemize(m_input, m_inputLength,                           static_cast<int>(m_runs.size()) - 1, &inputControl,                           &inputState,                           &m_runs[0], &numberOfItems);        if (SUCCEEDED(hr)) {            m_runs.resize(numberOfItems);            break;        }        if (hr != E_OUTOFMEMORY) {            // Some kind of unexpected error.            m_runs.resize(0);            break;        }        // There was not enough items for it to write into, expand.        m_runs.resize(m_runs.size() * 2);    }}bool UniscribeHelper::shape(const UChar* input,                            int itemLength,                            int numGlyphs,                            SCRIPT_ITEM& run,                            Shaping& shaping){    HFONT hfont = m_hfont;    SCRIPT_CACHE* scriptCache = m_scriptCache;    SCRIPT_FONTPROPERTIES* fontProperties = m_fontProperties;    int ascent = m_ascent;    HDC tempDC = 0;    HGDIOBJ oldFont = 0;    HRESULT hr;    // When used to fill up glyph pages for simple scripts in non-BMP,    // we don't want any font fallback in this class. The simple script    // font path can take care of font fallback.    bool lastFallbackTried = m_disableFontFallback;    bool result;    int generatedGlyphs = 0;    // In case HFONT passed in ctor cannot render this run, we have to scan    // other fonts from the beginning of the font list.    resetFontIndex();    // Compute shapes.    while (true) {        shaping.m_logs.resize(itemLength);        shaping.m_glyphs.resize(numGlyphs);        shaping.m_visualAttributes.resize(numGlyphs);#ifdef PURIFY        // http://code.google.com/p/chromium/issues/detail?id=5309        // Purify isn't able to track the assignments that ScriptShape makes to        // shaping.m_glyphs. Consequently, any bytes with value 0xCD that it        // writes, will be considered un-initialized data.        //        // This hack avoid the false-positive UMRs by marking the buffer as        // initialized.        //        // FIXME: A better solution would be to use Purify's API and mark only        // the populated range as initialized:        //        //     PurifyMarkAsInitialized(        //         &shaping.m_glyphs[0],        //         sizeof(shaping.m_glyphs[0] * generatedGlyphs);        ZeroMemory(&shaping.m_glyphs[0],                   sizeof(shaping.m_glyphs[0]) * shaping.m_glyphs.size());#endif        // Firefox sets SCRIPT_ANALYSIS.SCRIPT_STATE.fDisplayZWG to true        // here. Is that what we want? It will display control characters.        hr = ScriptShape(tempDC, scriptCache, input, itemLength,                         numGlyphs, &run.a,                         &shaping.m_glyphs[0], &shaping.m_logs[0],                         &shaping.m_visualAttributes[0], &generatedGlyphs);        if (hr == E_PENDING) {            // Allocate the DC.            tempDC = GetDC(0);            oldFont = SelectObject(tempDC, hfont);            continue;        } else if (hr == E_OUTOFMEMORY) {            numGlyphs *= 2;            continue;        } else if (SUCCEEDED(hr) && (lastFallbackTried || !containsMissingGlyphs(&shaping.m_glyphs[0], generatedGlyphs, fontProperties)))            break;        // The current font can't render this run. clear DC and try        // next font.        if (tempDC) {            SelectObject(tempDC, oldFont);            ReleaseDC(0, tempDC);            tempDC = 0;        }        if (!m_disableFontFallback &&            nextWinFontData(&hfont, &scriptCache, &fontProperties, &ascent)) {            // The primary font does not support this run. Try next font.            // In case of web page rendering, they come from fonts specified in            // CSS stylesheets.            continue;        } else if (!lastFallbackTried) {            lastFallbackTried = true;

⌨️ 快捷键说明

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