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

📄 fontmacatsui.mm

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 MM
📖 第 1 页 / 共 2 页
字号:
}void ATSULayoutParameters::initialize(const Font* font, const GraphicsContext* graphicsContext){    m_font = font;        const SimpleFontData* fontData = font->primaryFont();    m_fonts.set(new const SimpleFontData*[m_run.length()]);    if (font->isSmallCaps())        m_charBuffer.set(new UChar[m_run.length()]);        ATSUTextLayout layout;    OSStatus status;    ATSULayoutOperationOverrideSpecifier overrideSpecifier;        initializeATSUStyle(fontData);        // FIXME: This is currently missing the following required features that the CoreGraphics code path has:    // - \n, \t, and nonbreaking space render as a space.    UniCharCount runLength = m_run.length();    if (m_charBuffer)        memcpy(m_charBuffer.get(), m_run.characters(), runLength * sizeof(UChar));        status = ATSUCreateTextLayoutWithTextPtr(            (m_charBuffer ? m_charBuffer.get() : m_run.characters()),            0,        // offset            runLength,      // length            runLength,    // total length            1,              // styleRunCount            &runLength,     // length of style run            &fontData->m_ATSUStyle,             &layout);    if (status != noErr)        LOG_ERROR("ATSUCreateTextLayoutWithTextPtr failed(%d)", status);    m_layout = layout;    ATSUSetTextLayoutRefCon(m_layout, (URefCon)this);    // FIXME: There are certain times when this method is called, when we don't have access to a GraphicsContext    // measuring text runs with floatWidthForComplexText is one example.    // ATSUI requires that we pass a valid CGContextRef to it when specifying kATSUCGContextTag (crashes when passed 0)    // ATSUI disables sub-pixel rendering if kATSUCGContextTag is not specified!  So we're in a bind.    // Sometimes [[NSGraphicsContext currentContext] graphicsPort] may return the wrong (or no!) context.  Nothing we can do about it (yet).    CGContextRef cgContext = graphicsContext ? graphicsContext->platformContext() : (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];        ATSLineLayoutOptions lineLayoutOptions = kATSLineKeepSpacesOutOfMargin | kATSLineHasNoHangers;    Boolean rtl = m_run.rtl();    overrideSpecifier.operationSelector = kATSULayoutOperationPostLayoutAdjustment;    overrideSpecifier.overrideUPP = overrideLayoutOperation;    ATSUAttributeTag tags[] = { kATSUCGContextTag, kATSULineLayoutOptionsTag, kATSULineDirectionTag, kATSULayoutOperationOverrideTag };    ByteCount sizes[] = { sizeof(CGContextRef), sizeof(ATSLineLayoutOptions), sizeof(Boolean), sizeof(ATSULayoutOperationOverrideSpecifier) };    ATSUAttributeValuePtr values[] = { &cgContext, &lineLayoutOptions, &rtl, &overrideSpecifier };        status = ATSUSetLayoutControls(layout, (m_run.applyWordRounding() ? 4 : 3), tags, sizes, values);    if (status != noErr)        LOG_ERROR("ATSUSetLayoutControls failed(%d)", status);    status = ATSUSetTransientFontMatching(layout, YES);    if (status != noErr)        LOG_ERROR("ATSUSetTransientFontMatching failed(%d)", status);    m_hasSyntheticBold = false;    ATSUFontID ATSUSubstituteFont;    UniCharArrayOffset substituteOffset = 0;    UniCharCount substituteLength;    UniCharArrayOffset lastOffset;    const SimpleFontData* substituteFontData = 0;    while (substituteOffset < runLength) {        // FIXME: Using ATSUMatchFontsToText() here results in several problems: the CSS font family list is not necessarily followed for the 2nd        // and onwards unmatched characters; segmented fonts do not work correctly; behavior does not match the simple text and Uniscribe code        // paths. Change this function to use Font::glyphDataForCharacter() for each character instead.         lastOffset = substituteOffset;        status = ATSUMatchFontsToText(layout, substituteOffset, kATSUToTextEnd, &ATSUSubstituteFont, &substituteOffset, &substituteLength);        if (status == kATSUFontsMatched || status == kATSUFontsNotMatched) {            const FontData* fallbackFontData = m_font->fontDataForCharacters(m_run.characters() + substituteOffset, substituteLength);            substituteFontData = fallbackFontData ? fallbackFontData->fontDataForCharacter(m_run[0]) : 0;            if (substituteFontData) {                initializeATSUStyle(substituteFontData);                if (substituteFontData->m_ATSUStyle)                    ATSUSetRunStyle(layout, substituteFontData->m_ATSUStyle, substituteOffset, substituteLength);            } else                substituteFontData = fontData;        } else {            substituteOffset = runLength;            substituteLength = 0;        }        bool shapedArabic = false;        bool isSmallCap = false;        UniCharArrayOffset firstSmallCap = 0;        const SimpleFontData *r = fontData;        UniCharArrayOffset i;        for (i = lastOffset;  ; i++) {            if (i == substituteOffset || i == substituteOffset + substituteLength) {                if (isSmallCap) {                    isSmallCap = false;                    initializeATSUStyle(r->smallCapsFontData(m_font->fontDescription()));                    ATSUSetRunStyle(layout, r->smallCapsFontData(m_font->fontDescription())->m_ATSUStyle, firstSmallCap, i - firstSmallCap);                }                if (i == substituteOffset && substituteLength > 0)                    r = substituteFontData;                else                    break;            }            if (!shapedArabic && WTF::Unicode::isArabicChar(m_run[i]) && !r->shapesArabic()) {                shapedArabic = true;                if (!m_charBuffer) {                    m_charBuffer.set(new UChar[runLength]);                    memcpy(m_charBuffer.get(), m_run.characters(), i * sizeof(UChar));                    ATSUTextMoved(layout, m_charBuffer.get());                }                shapeArabic(m_run.characters(), m_charBuffer.get(), runLength, i);            }            if (m_run.rtl() && !r->m_ATSUMirrors) {                UChar mirroredChar = u_charMirror(m_run[i]);                if (mirroredChar != m_run[i]) {                    if (!m_charBuffer) {                        m_charBuffer.set(new UChar[runLength]);                        memcpy(m_charBuffer.get(), m_run.characters(), runLength * sizeof(UChar));                        ATSUTextMoved(layout, m_charBuffer.get());                    }                    m_charBuffer[i] = mirroredChar;                }            }            if (m_font->isSmallCaps()) {                const SimpleFontData* smallCapsData = r->smallCapsFontData(m_font->fontDescription());                UChar c = m_charBuffer[i];                UChar newC;                if (U_GET_GC_MASK(c) & U_GC_M_MASK)                    m_fonts[i] = isSmallCap ? smallCapsData : r;                else if (!u_isUUppercase(c) && (newC = u_toupper(c)) != c) {                    m_charBuffer[i] = newC;                    if (!isSmallCap) {                        isSmallCap = true;                        firstSmallCap = i;                    }                    m_fonts[i] = smallCapsData;                } else {                    if (isSmallCap) {                        isSmallCap = false;                        initializeATSUStyle(smallCapsData);                        ATSUSetRunStyle(layout, smallCapsData->m_ATSUStyle, firstSmallCap, i - firstSmallCap);                    }                    m_fonts[i] = r;                }            } else                m_fonts[i] = r;            if (m_fonts[i]->m_syntheticBoldOffset)                m_hasSyntheticBold = true;        }        substituteOffset += substituteLength;    }    if (m_run.padding()) {        float numSpaces = 0;        unsigned k;        for (k = 0; k < runLength; k++)            if (Font::treatAsSpace(m_run[k]))                numSpaces++;        if (numSpaces == 0)            m_padPerSpace = 0;        else            m_padPerSpace = ceilf(m_run.padding() / numSpaces);    } else        m_padPerSpace = 0;}FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, int from, int to) const{    OwnArrayPtr<UChar> charactersWithOverride;    TextRun adjustedRun = copyRunForDirectionalOverrideIfNecessary(run, charactersWithOverride);    if (run.directionalOverride()) {        from++;        to++;    }    ATSULayoutParameters params(adjustedRun);    params.initialize(this);    ATSTrapezoid firstGlyphBounds;    ItemCount actualNumBounds;        OSStatus status = ATSUGetGlyphBounds(params.m_layout, 0, 0, from, to - from, kATSUseFractionalOrigins, 1, &firstGlyphBounds, &actualNumBounds);    if (status != noErr || actualNumBounds != 1) {        static ATSTrapezoid zeroTrapezoid = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };        firstGlyphBounds = zeroTrapezoid;    }        float beforeWidth = MIN(FixedToFloat(firstGlyphBounds.lowerLeft.x), FixedToFloat(firstGlyphBounds.upperLeft.x));    float afterWidth = MAX(FixedToFloat(firstGlyphBounds.lowerRight.x), FixedToFloat(firstGlyphBounds.upperRight.x));        FloatRect rect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);    return rect;}void Font::drawComplexText(GraphicsContext* graphicsContext, const TextRun& run, const FloatPoint& point, int from, int to) const{    OSStatus status;        int drawPortionLength = to - from;    OwnArrayPtr<UChar> charactersWithOverride;    TextRun adjustedRun = copyRunForDirectionalOverrideIfNecessary(run, charactersWithOverride);    if (run.directionalOverride())        from++;    ATSULayoutParameters params(adjustedRun);    params.initialize(this, graphicsContext);        // ATSUI can't draw beyond -32768 to +32767 so we translate the CTM and tell ATSUI to draw at (0, 0).    CGContextRef context = graphicsContext->platformContext();    CGContextTranslateCTM(context, point.x(), point.y());    IntSize shadowSize;    int shadowBlur;    Color shadowColor;    graphicsContext->getShadow(shadowSize, shadowBlur, shadowColor);    bool hasSimpleShadow = graphicsContext->textDrawingMode() == cTextFill && shadowColor.isValid() && !shadowBlur;    if (hasSimpleShadow) {        // Paint simple shadows ourselves instead of relying on CG shadows, to avoid losing subpixel antialiasing.        graphicsContext->clearShadow();        Color fillColor = graphicsContext->fillColor();        Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);        graphicsContext->setFillColor(shadowFillColor);        CGContextTranslateCTM(context, shadowSize.width(), shadowSize.height());        status = ATSUDrawText(params.m_layout, from, drawPortionLength, 0, 0);        if (status == noErr && params.m_hasSyntheticBold) {            // Force relayout for the bold pass            ATSUClearLayoutCache(params.m_layout, 0);            params.m_syntheticBoldPass = true;            status = ATSUDrawText(params.m_layout, from, drawPortionLength, 0, 0);            // Force relayout for the next pass            ATSUClearLayoutCache(params.m_layout, 0);            params.m_syntheticBoldPass = false;        }        CGContextTranslateCTM(context, -shadowSize.width(), -shadowSize.height());        graphicsContext->setFillColor(fillColor);    }    status = ATSUDrawText(params.m_layout, from, drawPortionLength, 0, 0);    if (status == noErr && params.m_hasSyntheticBold) {        // Force relayout for the bold pass        ATSUClearLayoutCache(params.m_layout, 0);        params.m_syntheticBoldPass = true;        status = ATSUDrawText(params.m_layout, from, drawPortionLength, 0, 0);    }    CGContextTranslateCTM(context, -point.x(), -point.y());    if (status != noErr)        // Nothing to do but report the error (dev build only).        LOG_ERROR("ATSUDrawText() failed(%d)", status);    if (hasSimpleShadow)        graphicsContext->setShadow(shadowSize, shadowBlur, shadowColor);}float Font::floatWidthForComplexText(const TextRun& run) const{    if (run.length() == 0)        return 0;    ATSULayoutParameters params(run);    params.initialize(this);        OSStatus status;        ATSTrapezoid firstGlyphBounds;    ItemCount actualNumBounds;    status = ATSUGetGlyphBounds(params.m_layout, 0, 0, 0, run.length(), kATSUseFractionalOrigins, 1, &firstGlyphBounds, &actualNumBounds);        if (status != noErr)        LOG_ERROR("ATSUGetGlyphBounds() failed(%d)", status);    if (actualNumBounds != 1)        LOG_ERROR("unexpected result from ATSUGetGlyphBounds(): actualNumBounds(%d) != 1", actualNumBounds);    return MAX(FixedToFloat(firstGlyphBounds.upperRight.x), FixedToFloat(firstGlyphBounds.lowerRight.x)) -           MIN(FixedToFloat(firstGlyphBounds.upperLeft.x), FixedToFloat(firstGlyphBounds.lowerLeft.x));}int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool /*includePartialGlyphs*/) const{    OwnArrayPtr<UChar> charactersWithOverride;    TextRun adjustedRun = copyRunForDirectionalOverrideIfNecessary(run, charactersWithOverride);    ATSULayoutParameters params(adjustedRun);    params.initialize(this);    UniCharArrayOffset primaryOffset = 0;        // FIXME: No idea how to avoid including partial glyphs.    // Not even sure if that's the behavior this yields now.    Boolean isLeading;    UniCharArrayOffset secondaryOffset = 0;    OSStatus status = ATSUPositionToOffset(params.m_layout, FloatToFixed(x), FloatToFixed(-1), &primaryOffset, &isLeading, &secondaryOffset);    unsigned offset;    if (status == noErr) {        offset = (unsigned)primaryOffset;        if (run.directionalOverride() && offset > 0)            offset--;    } else        // Failed to find offset!  Return 0 offset.        offset = 0;    return offset;}}#endif // USE(ATSUI)

⌨️ 快捷键说明

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