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

📄 coretextcontroller.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        UChar c = *curr;        bool forceSmallCaps = !isSurrogate && isSmallCaps && (U_GET_GC_MASK(c) & U_GC_M_MASK);        if (isSurrogate) {            if (m_run.ltr()) {                if (!U16_IS_SURROGATE_LEAD(curr[0]) || curr + 1 == end || !U16_IS_TRAIL(curr[1]))                    return;                nextGlyphData = m_font.glyphDataForCharacter(U16_GET_SUPPLEMENTARY(curr[0], curr[1]), false);            } else {                if (!U16_IS_TRAIL(curr[0]) || curr -1 == end || !U16_IS_SURROGATE_LEAD(curr[-1]))                    return;                nextGlyphData = m_font.glyphDataForCharacter(U16_GET_SUPPLEMENTARY(curr[-1], curr[0]), false);            }        } else            nextGlyphData = m_font.glyphDataForCharacter(*curr, false, forceSmallCaps);        if (!isSurrogate && m_font.isSmallCaps()) {            nextIsSmallCaps = forceSmallCaps || (newC = u_toupper(c)) != c;            if (nextIsSmallCaps)                m_smallCapsBuffer[index] = forceSmallCaps ? c : newC;        }        if (nextGlyphData.fontData != glyphData.fontData || nextIsSmallCaps != isSmallCaps || !nextGlyphData.glyph != !glyphData.glyph) {            int itemStart = m_run.rtl() ? index + 1 : indexOfFontTransition;            int itemLength = m_run.rtl() ? indexOfFontTransition - index : index - indexOfFontTransition;            collectCoreTextRunsForCharacters((isSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, glyphData.glyph ? glyphData.fontData : 0);            indexOfFontTransition = index;        }    }    int itemLength = m_run.rtl() ? indexOfFontTransition + 1 : m_end - indexOfFontTransition - (hasTrailingSoftHyphen ? 1 : 0);    if (itemLength) {        int itemStart = m_run.rtl() ? 0 : indexOfFontTransition;        collectCoreTextRunsForCharacters((nextIsSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, nextGlyphData.glyph ? nextGlyphData.fontData : 0);    }    if (hasTrailingSoftHyphen && m_run.ltr())        collectCoreTextRunsForCharacters(&hyphen, 1, m_end - 1, m_font.glyphDataForCharacter(hyphen, false).fontData);}void CoreTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer){    // FIXME: For offsets falling inside a ligature, we should advance only as far as the appropriate "ligature caret"    // or divide the width of the ligature by the number of offsets it encompasses and make an advance proportional    // to the offsets into the ligature. However, Core Text does not expose a low-level API for    // directly finding out how many characters a ligature encompasses (the "attachment count").    if (static_cast<int>(offset) > m_end)        offset = m_end;    if (offset <= m_currentCharacter)        return;    m_currentCharacter = offset;    size_t runCount = m_coreTextRuns.size();    bool ltr = m_run.ltr();    unsigned k = ltr ? m_numGlyphsSoFar : m_adjustedGlyphs.size() - 1 - m_numGlyphsSoFar;    while (m_currentRun < runCount) {        const CoreTextRun& coreTextRun = m_coreTextRuns[ltr ? m_currentRun : runCount - 1 - m_currentRun];        size_t glyphCount = coreTextRun.glyphCount();        unsigned g = ltr ? m_glyphInCurrentRun : glyphCount - 1 - m_glyphInCurrentRun;        while (m_glyphInCurrentRun < glyphCount) {            if (coreTextRun.indexAt(g) + coreTextRun.stringLocation() >= m_currentCharacter)                return;            CGSize adjustedAdvance = m_adjustedAdvances[k];            if (glyphBuffer)                glyphBuffer->add(m_adjustedGlyphs[k], coreTextRun.fontData(), adjustedAdvance);            m_runWidthSoFar += adjustedAdvance.width;            m_numGlyphsSoFar++;            m_glyphInCurrentRun++;            if (ltr) {                g++;                k++;            } else {                g--;                k--;            }        }        m_currentRun++;        m_glyphInCurrentRun = 0;    }    if (!ltr && m_numGlyphsSoFar == m_adjustedAdvances.size())        m_runWidthSoFar += m_finalRoundingWidth;}void CoreTextController::collectCoreTextRunsForCharacters(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData){    if (!fontData) {        // Create a run of missing glyphs from the primary font.        m_coreTextRuns.append(CoreTextRun(m_font.primaryFont(), cp, stringLocation, length, m_run.ltr()));        return;    }    RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(NULL, cp, length, kCFAllocatorNull));    RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(NULL, string.get(), fontData->getCFStringAttributes()));    RetainPtr<CTTypesetterRef> typesetter;    if (!m_mayUseNaturalWritingDirection || m_run.directionalOverride()) {        static const void* optionKeys[] = { kCTTypesetterOptionForcedEmbeddingLevel };        static const void* ltrOptionValues[] = { kCFBooleanFalse };        static const void* rtlOptionValues[] = { kCFBooleanTrue };        static CFDictionaryRef ltrTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, ltrOptionValues, sizeof(optionKeys) / sizeof(*optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);        static CFDictionaryRef rtlTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, rtlOptionValues, sizeof(optionKeys) / sizeof(*optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);        typesetter.adoptCF(CTTypesetterCreateWithAttributedStringAndOptions(attributedString.get(), m_run.ltr() ? ltrTypesetterOptions : rtlTypesetterOptions));    } else        typesetter.adoptCF(CTTypesetterCreateWithAttributedString(attributedString.get()));    RetainPtr<CTLineRef> line(AdoptCF, CTTypesetterCreateLine(typesetter.get(), CFRangeMake(0, 0)));    CFArrayRef runArray = CTLineGetGlyphRuns(line.get());    CFIndex runCount = CFArrayGetCount(runArray);    for (CFIndex r = 0; r < runCount; r++) {        CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));        ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());        m_coreTextRuns.append(CoreTextRun(ctRun, fontData, cp, stringLocation, length));    }}void CoreTextController::adjustGlyphsAndAdvances(){    size_t runCount = m_coreTextRuns.size();    for (size_t r = 0; r < runCount; ++r) {        const CoreTextRun& coreTextRun = m_coreTextRuns[r];        unsigned glyphCount = coreTextRun.glyphCount();        const SimpleFontData* fontData = coreTextRun.fontData();        Vector<CGGlyph, 256> glyphsVector;        const CGGlyph* glyphs;        Vector<CGSize, 256> advancesVector;        const CGSize* advances;        if (coreTextRun.ctRun()) {            glyphs = CTRunGetGlyphsPtr(coreTextRun.ctRun());            if (!glyphs) {                glyphsVector.grow(glyphCount);                CTRunGetGlyphs(coreTextRun.ctRun(), CFRangeMake(0, 0), glyphsVector.data());                glyphs = glyphsVector.data();            }            advances = CTRunGetAdvancesPtr(coreTextRun.ctRun());            if (!advances) {                advancesVector.grow(glyphCount);                CTRunGetAdvances(coreTextRun.ctRun(), CFRangeMake(0, 0), advancesVector.data());                advances = advancesVector.data();            }        } else {            // Synthesize a run of missing glyphs.            glyphsVector.fill(0, glyphCount);            glyphs = glyphsVector.data();            advancesVector.fill(CGSizeMake(fontData->widthForGlyph(0), 0), glyphCount);            advances = advancesVector.data();        }        bool lastRun = r + 1 == runCount;        const UChar* cp = coreTextRun.characters();        CGFloat roundedSpaceWidth = roundCGFloat(fontData->m_spaceWidth);        bool roundsAdvances = !m_font.isPrinterFont() && fontData->platformData().roundsGlyphAdvances();        bool hasExtraSpacing = (m_font.letterSpacing() || m_font.wordSpacing() || m_padding) && !m_run.spacingDisabled();        for (unsigned i = 0; i < glyphCount; i++) {            CFIndex characterIndex = coreTextRun.indexAt(i);            UChar ch = *(cp + characterIndex);            bool lastGlyph = lastRun && i + 1 == glyphCount;            UChar nextCh;            if (lastGlyph)                nextCh = ' ';            else if (i + 1 < glyphCount)                nextCh = *(cp + coreTextRun.indexAt(i + 1));            else                nextCh = *(m_coreTextRuns[r + 1].characters() + m_coreTextRuns[r + 1].indexAt(0));            bool treatAsSpace = Font::treatAsSpace(ch);            CGGlyph glyph = treatAsSpace ? fontData->m_spaceGlyph : glyphs[i];            CGSize advance = treatAsSpace ? CGSizeMake(fontData->m_spaceWidth, advances[i].height) : advances[i];            if (ch == '\t' && m_run.allowTabs()) {                float tabWidth = m_font.tabWidth();                advance.width = tabWidth - fmodf(m_run.xPos() + m_totalWidth, tabWidth);            } else if (ch == zeroWidthSpace || Font::treatAsZeroWidthSpace(ch) && !treatAsSpace) {                advance.width = 0;                glyph = fontData->m_spaceGlyph;            }            float roundedAdvanceWidth = roundf(advance.width);            if (roundsAdvances)                advance.width = roundedAdvanceWidth;            advance.width += fontData->m_syntheticBoldOffset;            // We special case spaces in two ways when applying word rounding.            // First, we round spaces to an adjusted width in all fonts.            // Second, in fixed-pitch fonts we ensure that all glyphs that            // match the width of the space glyph have the same width as the space glyph.            if (roundedAdvanceWidth == roundedSpaceWidth && (fontData->m_treatAsFixedPitch || glyph == fontData->m_spaceGlyph) && m_run.applyWordRounding())                advance.width = fontData->m_adjustedSpaceWidth;            if (hasExtraSpacing) {                // If we're a glyph with an advance, go ahead and add in letter-spacing.                // That way we weed out zero width lurkers.  This behavior matches the fast text code path.                if (advance.width && m_font.letterSpacing())                    advance.width += m_font.letterSpacing();                // Handle justification and word-spacing.                if (glyph == fontData->m_spaceGlyph) {                    // Account for padding. WebCore uses space padding to justify text.                    // We distribute the specified padding over the available spaces in the run.                    if (m_padding) {                        // Use leftover padding if not evenly divisible by number of spaces.                        if (m_padding < m_padPerSpace) {                            advance.width += m_padding;                            m_padding = 0;                        } else {                            advance.width += m_padPerSpace;                            m_padding -= m_padPerSpace;                        }                    }                    // Account for word-spacing.                    if (treatAsSpace && characterIndex > 0 && !Font::treatAsSpace(*m_run.data(characterIndex - 1)) && m_font.wordSpacing())                        advance.width += m_font.wordSpacing();                }            }            // Deal with the float/integer impedance mismatch between CG and WebCore. "Words" (characters             // followed by a character defined by isRoundingHackCharacter()) are always an integer width.            // We adjust the width of the last character of a "word" to ensure an integer width.            // Force characters that are used to determine word boundaries for the rounding hack            // to be integer width, so the following words will start on an integer boundary.            if (m_run.applyWordRounding() && Font::isRoundingHackCharacter(ch))                advance.width = ceilCGFloat(advance.width);            // Check to see if the next character is a "rounding hack character", if so, adjust the            // width so that the total run width will be on an integer boundary.            if (m_run.applyWordRounding() && !lastGlyph && Font::isRoundingHackCharacter(nextCh) || m_run.applyRunRounding() && lastGlyph) {                CGFloat totalWidth = m_totalWidth + advance.width;                CGFloat extraWidth = ceilCGFloat(totalWidth) - totalWidth;                if (m_run.ltr())                    advance.width += extraWidth;                else {                    m_totalWidth += extraWidth;                    if (m_lastRoundingGlyph)                        m_adjustedAdvances[m_lastRoundingGlyph - 1].width += extraWidth;                    else                        m_finalRoundingWidth = extraWidth;                    m_lastRoundingGlyph = m_adjustedAdvances.size() + 1;                }            }            m_totalWidth += advance.width;            advance.height *= -1;            m_adjustedAdvances.append(advance);            m_adjustedGlyphs.append(glyph);        }    }}} // namespace WebCore#endif // USE(CORE_TEXT)

⌨️ 快捷键说明

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