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

📄 svgrootinlinebox.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 4 页
字号:
        // Finalize text rendering         if (!flowBox->isRootInlineBox()) {            finishRenderSVGContent(object, m_paintInfo, m_boundingBox, m_filter, m_savedInfo.context);            m_filter = 0;        }        // Restore context & repaint rect        m_paintInfo.context->restore();        m_paintInfo.rect = m_savedInfo.rect;    }    bool chunkSetupFillCallback(InlineBox* box)    {        InlineFlowBox* flowBox = box->parent();        // Setup fill paint server        RenderObject* object = flowBox->renderer();        ASSERT(object);        ASSERT(!m_strokePaintServer);        teardownFillPaintServer();        m_fillPaintServer = SVGPaintServer::fillPaintServer(object->style(), object);        if (m_fillPaintServer) {            m_fillPaintServer->setup(m_paintInfo.context, object, ApplyToFillTargetType, true);            m_fillPaintServerObject = object;            return true;        }        return false;    }    bool chunkSetupStrokeCallback(InlineBox* box)    {        InlineFlowBox* flowBox = box->parent();        // Setup stroke paint server        RenderObject* object = flowBox->renderer();        ASSERT(object);        // If we're both stroked & filled, teardown fill paint server before stroking.        teardownFillPaintServer();        teardownStrokePaintServer();        m_strokePaintServer = SVGPaintServer::strokePaintServer(object->style(), object);        if (m_strokePaintServer) {            m_strokePaintServer->setup(m_paintInfo.context, object, ApplyToStrokeTargetType, true);            m_strokePaintServerObject = object;            return true;        }        return false;    }    void chunkPortionCallback(SVGInlineTextBox* textBox, int startOffset, const TransformationMatrix& chunkCtm,                              const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end)    {        RenderText* text = textBox->textRenderer();        ASSERT(text);        RenderStyle* styleToUse = text->style(textBox->isFirstLineStyle());        ASSERT(styleToUse);        startOffset += textBox->start();        int textDecorations = styleToUse->textDecorationsInEffect();         int textWidth = 0;        IntPoint decorationOrigin;        SVGTextDecorationInfo info;        if (!chunkCtm.isIdentity())            m_paintInfo.context->concatCTM(chunkCtm);        for (Vector<SVGChar>::iterator it = start; it != end; ++it) {            if (it->isHidden())                continue;            // Determine how many characters - starting from the current - can be drawn at once.            Vector<SVGChar>::iterator itSearch = it + 1;            while (itSearch != end) {                if (itSearch->drawnSeperated || itSearch->isHidden())                    break;                itSearch++;            }            const UChar* stringStart = text->characters() + startOffset + (it - start);            unsigned int stringLength = itSearch - it;            // Paint decorations, that have to be drawn before the text gets drawn            if (textDecorations != TDNONE && m_paintInfo.phase != PaintPhaseSelection) {                textWidth = styleToUse->font().width(svgTextRunForInlineTextBox(stringStart, stringLength, styleToUse, textBox, (*it).x));                decorationOrigin = IntPoint((int) (*it).x, (int) (*it).y - styleToUse->font().ascent());                info = m_rootBox->retrievePaintServersForTextDecoration(text);            }            if (textDecorations & UNDERLINE && textWidth != 0.0f)                textBox->paintDecoration(UNDERLINE, m_paintInfo.context, decorationOrigin.x(), decorationOrigin.y(), textWidth, *it, info);            if (textDecorations & OVERLINE && textWidth != 0.0f)                textBox->paintDecoration(OVERLINE, m_paintInfo.context, decorationOrigin.x(), decorationOrigin.y(), textWidth, *it, info);            // Paint text            SVGPaintServer* activePaintServer = m_fillPaintServer;            if (!activePaintServer)                activePaintServer = m_strokePaintServer;            ASSERT(activePaintServer);            textBox->paintCharacters(m_paintInfo, m_tx, m_ty, *it, stringStart, stringLength, activePaintServer);            // Paint decorations, that have to be drawn afterwards            if (textDecorations & LINE_THROUGH && textWidth != 0.0f)                textBox->paintDecoration(LINE_THROUGH, m_paintInfo.context, decorationOrigin.x(), decorationOrigin.y(), textWidth, *it, info);            // Skip processed characters            it = itSearch - 1;        }        if (!chunkCtm.isIdentity())            m_paintInfo.context->concatCTM(chunkCtm.inverse());    }private:    SVGRootInlineBox* m_rootBox;    bool m_chunkStarted : 1;    RenderObject::PaintInfo m_paintInfo;    RenderObject::PaintInfo m_savedInfo;    FloatRect m_boundingBox;    SVGResourceFilter* m_filter;    SVGResourceFilter* m_rootFilter;    SVGPaintServer* m_fillPaintServer;    SVGPaintServer* m_strokePaintServer;    RenderObject* m_fillPaintServerObject;    RenderObject* m_strokePaintServerObject;    int m_tx;    int m_ty;};void SVGRootInlineBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty){    if (paintInfo.context->paintingDisabled() || paintInfo.phase != PaintPhaseForeground)        return;    RenderObject::PaintInfo savedInfo(paintInfo);    paintInfo.context->save();    SVGResourceFilter* filter = 0;    FloatRect boundingBox(tx + x(), ty + y(), width(), height());    // Initialize text rendering    paintInfo.context->concatCTM(renderer()->localTransform());    prepareToRenderSVGContent(renderer(), paintInfo, boundingBox, filter);    paintInfo.context->concatCTM(renderer()->localTransform().inverse());     // Render text, chunk-by-chunk    SVGRootInlineBoxPaintWalker walkerCallback(this, filter, paintInfo, tx, ty);    SVGTextChunkWalker<SVGRootInlineBoxPaintWalker> walker(&walkerCallback,                                                           &SVGRootInlineBoxPaintWalker::chunkPortionCallback,                                                           &SVGRootInlineBoxPaintWalker::chunkStartCallback,                                                           &SVGRootInlineBoxPaintWalker::chunkEndCallback,                                                           &SVGRootInlineBoxPaintWalker::chunkSetupFillCallback,                                                           &SVGRootInlineBoxPaintWalker::chunkSetupStrokeCallback);    walkTextChunks(&walker);    // Finalize text rendering     finishRenderSVGContent(renderer(), paintInfo, boundingBox, filter, savedInfo.context);    paintInfo.context->restore();}int SVGRootInlineBox::placeBoxesHorizontally(int, int& leftPosition, int& rightPosition, bool&){    // Remove any offsets caused by RTL text layout    leftPosition = 0;    rightPosition = 0;    return 0;}int SVGRootInlineBox::verticallyAlignBoxes(int){    // height is set by layoutInlineBoxes.    return height();}float cummulatedWidthOfInlineBoxCharacterRange(SVGInlineBoxCharacterRange& range){    ASSERT(!range.isOpen());    ASSERT(range.isClosed());    ASSERT(range.box->isInlineTextBox());    InlineTextBox* textBox = static_cast<InlineTextBox*>(range.box);    RenderText* text = textBox->textRenderer();    RenderStyle* style = text->style();    return style->font().floatWidth(svgTextRunForInlineTextBox(text->characters() + textBox->start() + range.startOffset, range.endOffset - range.startOffset, style, textBox, 0));}float cummulatedHeightOfInlineBoxCharacterRange(SVGInlineBoxCharacterRange& range){    ASSERT(!range.isOpen());    ASSERT(range.isClosed());    ASSERT(range.box->isInlineTextBox());    InlineTextBox* textBox = static_cast<InlineTextBox*>(range.box);    RenderText* text = textBox->textRenderer();    const Font& font = text->style()->font();    return (range.endOffset - range.startOffset) * (font.ascent() + font.descent());}TextRun svgTextRunForInlineTextBox(const UChar* c, int len, RenderStyle* style, const InlineTextBox* textBox, float xPos){    ASSERT(textBox);    ASSERT(style);    TextRun run(c, len, false, static_cast<int>(xPos), textBox->toAdd(), textBox->direction() == RTL, textBox->m_dirOverride || style->visuallyOrdered());#if ENABLE(SVG_FONTS)    run.setReferencingRenderObject(textBox->textRenderer()->parent());#endif    // We handle letter & word spacing ourselves    run.disableSpacing();    return run;}static float cummulatedWidthOrHeightOfTextChunk(SVGTextChunk& chunk, bool calcWidthOnly){    float length = 0.0f;    Vector<SVGChar>::iterator charIt = chunk.start;    Vector<SVGInlineBoxCharacterRange>::iterator it = chunk.boxes.begin();    Vector<SVGInlineBoxCharacterRange>::iterator end = chunk.boxes.end();    for (; it != end; ++it) {        SVGInlineBoxCharacterRange& range = *it;        SVGInlineTextBox* box = static_cast<SVGInlineTextBox*>(range.box);        RenderStyle* style = box->renderer()->style();        for (int i = range.startOffset; i < range.endOffset; ++i) {            ASSERT(charIt <= chunk.end);            // Determine how many characters - starting from the current - can be measured at once.            // Important for non-absolute positioned non-latin1 text (ie. Arabic) where ie. the width            // of a string is not the sum of the boundaries of all contained glyphs.            Vector<SVGChar>::iterator itSearch = charIt + 1;            Vector<SVGChar>::iterator endSearch = charIt + range.endOffset - i;            while (itSearch != endSearch) {                // No need to check for 'isHidden()' here as this function is not called for text paths.                if (itSearch->drawnSeperated)                    break;                itSearch++;            }            unsigned int positionOffset = itSearch - charIt;            // Calculate width/height of subrange            SVGInlineBoxCharacterRange subRange;            subRange.box = range.box;            subRange.startOffset = i;            subRange.endOffset = i + positionOffset;            if (calcWidthOnly)                length += cummulatedWidthOfInlineBoxCharacterRange(subRange);            else                length += cummulatedHeightOfInlineBoxCharacterRange(subRange);            // Calculate gap between the previous & current range            // <text x="10 50 70">ABCD</text> - we need to take the gaps between A & B into account            // so add "40" as width, and analogous for B & C, add "20" as width.            if (itSearch > chunk.start && itSearch < chunk.end) {                SVGChar& lastCharacter = *(itSearch - 1);                SVGChar& currentCharacter = *itSearch;                int offset = box->direction() == RTL ? box->end() - i - positionOffset + 1 : box->start() + i + positionOffset - 1;                // FIXME: does this need to change to handle multichar glyphs?                int charsConsumed = 1;                String glyphName;                if (calcWidthOnly) {                    float lastGlyphWidth = box->calculateGlyphWidth(style, offset, 0, charsConsumed, glyphName);                    length += currentCharacter.x - lastCharacter.x - lastGlyphWidth;                } else {                    float lastGlyphHeight = box->calculateGlyphHeight(style, offset, 0);                    length += currentCharacter.y - lastCharacter.y - lastGlyphHeight;                }            }            // Advance processed characters            i += positionOffset - 1;            charIt = itSearch;        }    }    ASSERT(charIt == chunk.end);    return length;}static float cummulatedWidthOfTextChunk(SVGTextChunk& chunk){    return cummulatedWidthOrHeightOfTextChunk(chunk, true);}static float cummulatedHeightOfTextChunk(SVGTextChunk& chunk){    return cummulatedWidthOrHeightOfTextChunk(chunk, false);}static float calculateTextAnchorShiftForTextChunk(SVGTextChunk& chunk, ETextAnchor anchor){    float shift = 0.0f;    if (chunk.isVerticalText)        shift = cummulatedHeightOfTextChunk(chunk);    else        shift = cummulatedWidthOfTextChunk(chunk);    if (anchor == TA_MIDDLE)        shift *= -0.5f;    else        shift *= -1.0f;    return shift;}static void applyTextAnchorToTextChunk(SVGTextChunk& chunk){    // This method is not called for chunks containing chars aligned on a path.    // -> all characters are visible, no need to check for "isHidden()" anywhere.    if (chunk.anchor == TA_START)        return;    float shift = calculateTextAnchorShiftForTextChunk(chunk, chunk.anchor);    // Apply correction to chunk    Vector<SVGChar>::iterator chunkIt = chunk.start;    for (; chunkIt != chunk.end; ++chunkIt) {        SVGChar& curChar = *chunkIt;        if (chunk.isVerticalText)            curChar.y += shift;        else            curChar.x += shift;    }    // Move inline boxes    Vector<SVGInlineBoxCharacterRange>::iterator boxIt = chunk.boxes.begin();    Vector<SVGInlineBoxCharacterRange>::iterator boxEnd = chunk.boxes.end();    for (; boxIt != boxEnd; ++boxIt) {        SVGInlineBoxCharacterRange& range = *boxIt;        InlineBox* curBox = range.box;        ASSERT(curBox->isInlineTextBox());        // Move target box        if (chunk.isVerticalText)            curBox->setY(curBox->y() + static_cast<int>(shift));        else            curBox->setX(curBox->x() + static_cast<int>(shift));    }}static float calculateTextLengthCorrectionForTextChunk(SVGTextChunk& chunk, ELengthAdjust lengthAdjust, float& computedLength){    if (chunk.textLength <= 0.0f)        return 0.0f;    float computedWidth = cummulatedWidthOfTextChunk(chunk);    float computedHeight = cummulatedHeightOfTextChunk(chunk);    if ((computedWidth <= 0.0f && !chunk.isVerticalText) ||        (computedHeight <= 0.0f && chunk.isVerticalText))        return 0.0f;    if (chunk.isVerticalText)        computedLength = computedHeight;    else        computedLength = computedWidth;    if (lengthAdjust == SVGTextContentElement::LENGTHADJUST_SPACINGANDGLYPHS) {        if (chunk.isVerticalText)            chunk.ctm.scaleNonUniform(1.0f, chunk.textLength / computedLength);        else            chunk.ctm.scaleNonUniform(chunk.textLength / computedLength, 1.0f);        return 0.0f;    }    return (chunk.textLength - computedLength) / float(chunk.end - chunk.start);}static void applyTextLengthCorrectionToTextChunk(SVGTextChunk& chunk){    // This method is not called for chunks containing chars aligned on a path.    // -> all characters are visible, no need to check for "isHidden()" anywhere.    // lengthAdjust="spacingAndGlyphs" is handled by modifying chunk.ctm    float computedLength = 0.0f;    float spacingToApply = calculateTextLengthCorrectionForTextChunk(chunk, chunk.lengthAdjust, computedLength);    if (!chunk.ctm.isIdentity() && chunk.lengthAdjust == SVGTextContentElement::LENGTHADJUST_SPACINGANDGLYPHS) {        SVGChar& firstChar = *(chunk.start);        // Assure we apply the chunk scaling in the right origin        TransformationMatrix newChunkCtm;        newChunkCtm.translate(firstChar.x, firstChar.y);        newChunkCtm = chunk.ctm * newChunkCtm;        newChunkCtm.translate(-firstChar.x, -firstChar.y);        chunk.ctm = newChunkCtm;    }    // Apply correction to chunk     if (spacingToApply != 0.0f) {        Vector<SVGChar>::iterator chunkIt = chunk.start;        for (; chunkIt != chunk.end; ++chunkIt) {            SVGChar& curChar = *chunkIt;            curChar.drawnSeperated = true;

⌨️ 快捷键说明

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