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

📄 svgrootinlinebox.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 4 页
字号:
            if (chunk.isVerticalText)                curChar.y += (chunkIt - chunk.start) * spacingToApply;            else                curChar.x += (chunkIt - chunk.start) * spacingToApply;        }    }}void SVGRootInlineBox::computePerCharacterLayoutInformation(){    // Clean up any previous layout information    m_svgChars.clear();    m_svgTextChunks.clear();    // Build layout information for all contained render objects    SVGCharacterLayoutInfo info(m_svgChars);    buildLayoutInformation(this, info);    // Now all layout information are available for every character    // contained in any of our child inline/flow boxes. Build list    // of text chunks now, to be able to apply text-anchor shifts.    buildTextChunks(m_svgChars, m_svgTextChunks, this);    // Layout all text chunks    // text-anchor needs to be applied to individual chunks.    layoutTextChunks();    // Finally the top left position of our box is known.    // Propogate this knownledge to our RenderSVGText parent.    FloatPoint topLeft = topLeftPositionOfCharacterRange(m_svgChars);    block()->setLocation((int) floorf(topLeft.x()), (int) floorf(topLeft.y()));    // Layout all InlineText/Flow boxes    // BEWARE: This requires the root top/left position to be set correctly before!    layoutInlineBoxes();}void SVGRootInlineBox::buildLayoutInformation(InlineFlowBox* start, SVGCharacterLayoutInfo& info){    if (start->isRootInlineBox()) {        ASSERT(start->renderer()->node()->hasTagName(SVGNames::textTag));        SVGTextPositioningElement* positioningElement = static_cast<SVGTextPositioningElement*>(start->renderer()->node());        ASSERT(positioningElement);        ASSERT(positioningElement->parentNode());        info.addLayoutInformation(positioningElement);    }    LastGlyphInfo lastGlyph;        for (InlineBox* curr = start->firstChild(); curr; curr = curr->nextOnLine()) {        if (curr->renderer()->isText())            buildLayoutInformationForTextBox(info, static_cast<InlineTextBox*>(curr), lastGlyph);        else {            ASSERT(curr->isInlineFlowBox());            InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(curr);            if (!flowBox->renderer()->node())                continue; // Skip generated content.            bool isAnchor = flowBox->renderer()->node()->hasTagName(SVGNames::aTag);            bool isTextPath = flowBox->renderer()->node()->hasTagName(SVGNames::textPathTag);            if (!isTextPath && !isAnchor) {                SVGTextPositioningElement* positioningElement = static_cast<SVGTextPositioningElement*>(flowBox->renderer()->node());                ASSERT(positioningElement);                ASSERT(positioningElement->parentNode());                info.addLayoutInformation(positioningElement);            } else if (!isAnchor) {                info.setInPathLayout(true);                // Handle text-anchor/textLength on path, which is special.                SVGTextContentElement* textContent = 0;                Node* node = flowBox->renderer()->node();                if (node && node->isSVGElement())                    textContent = static_cast<SVGTextContentElement*>(node);                ASSERT(textContent);                ELengthAdjust lengthAdjust = (ELengthAdjust) textContent->lengthAdjust();                ETextAnchor anchor = flowBox->renderer()->style()->svgStyle()->textAnchor();                float textAnchorStartOffset = 0.0f;                // Initialize sub-layout. We need to create text chunks from the textPath                // children using our standard layout code, to be able to measure the                // text length using our normal methods and not textPath specific hacks.                Vector<SVGChar> tempChars;                Vector<SVGTextChunk> tempChunks;                SVGCharacterLayoutInfo tempInfo(tempChars);                buildLayoutInformation(flowBox, tempInfo);                buildTextChunks(tempChars, tempChunks, flowBox);                Vector<SVGTextChunk>::iterator it = tempChunks.begin();                Vector<SVGTextChunk>::iterator end = tempChunks.end();                TransformationMatrix ctm;                float computedLength = 0.0f;                 for (; it != end; ++it) {                    SVGTextChunk& chunk = *it;                    // Apply text-length calculation                    info.pathExtraAdvance += calculateTextLengthCorrectionForTextChunk(chunk, lengthAdjust, computedLength);                    if (lengthAdjust == SVGTextContentElement::LENGTHADJUST_SPACINGANDGLYPHS) {                        info.pathTextLength += computedLength;                        info.pathChunkLength += chunk.textLength;                    }                    // Calculate text-anchor start offset                    if (anchor == TA_START)                        continue;                    textAnchorStartOffset += calculateTextAnchorShiftForTextChunk(chunk, anchor);                }                info.addLayoutInformation(flowBox, textAnchorStartOffset);            }            float shiftxSaved = info.shiftx;            float shiftySaved = info.shifty;            buildLayoutInformation(flowBox, info);            info.processedChunk(shiftxSaved, shiftySaved);            if (isTextPath)                info.setInPathLayout(false);        }    }}void SVGRootInlineBox::layoutInlineBoxes(){    int lowX = INT_MAX;    int lowY = INT_MAX;    int highX = INT_MIN;    int highY = INT_MIN;    // Layout all child boxes    Vector<SVGChar>::iterator it = m_svgChars.begin();     layoutInlineBoxes(this, it, lowX, highX, lowY, highY);    ASSERT(it == m_svgChars.end());}void SVGRootInlineBox::layoutInlineBoxes(InlineFlowBox* start, Vector<SVGChar>::iterator& it, int& lowX, int& highX, int& lowY, int& highY){    for (InlineBox* curr = start->firstChild(); curr; curr = curr->nextOnLine()) {        RenderStyle* style = curr->renderer()->style();            if (curr->renderer()->isText()) {            SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(curr);            unsigned length = textBox->len();            SVGChar curChar = *it;             ASSERT(it != m_svgChars.end());              FloatRect stringRect;            for (unsigned i = 0; i < length; ++i) {                ASSERT(it != m_svgChars.end());                if (it->isHidden()) {                    ++it;                    continue;                }                stringRect.unite(textBox->calculateGlyphBoundaries(style, textBox->start() + i, *it));                ++it;            }            IntRect enclosedStringRect = enclosingIntRect(stringRect);            int minX = enclosedStringRect.x();            int maxX = minX + enclosedStringRect.width();            int minY = enclosedStringRect.y();            int maxY = minY + enclosedStringRect.height();            curr->setX(minX - block()->x());            curr->setWidth(enclosedStringRect.width());            curr->setY(minY - block()->y());            textBox->setHeight(enclosedStringRect.height());            if (minX < lowX)                lowX = minX;            if (maxX > highX)                highX = maxX;            if (minY < lowY)                lowY = minY;            if (maxY > highY)                highY = maxY;        } else {            ASSERT(curr->isInlineFlowBox());            int minX = INT_MAX;            int minY = INT_MAX;            int maxX = INT_MIN;            int maxY = INT_MIN;            InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(curr);                        if (!flowBox->renderer()->node())                continue; // Skip generated content.                layoutInlineBoxes(flowBox, it, minX, maxX, minY, maxY);            curr->setX(minX - block()->x());            curr->setWidth(maxX - minX);            curr->setY(minY - block()->y());            static_cast<SVGInlineFlowBox*>(curr)->setHeight(maxY - minY);            if (minX < lowX)                lowX = minX;            if (maxX > highX)                highX = maxX;            if (minY < lowY)                lowY = minY;            if (maxY > highY)                highY = maxY;        }    }    if (start->isSVGRootInlineBox()) {        int top = lowY - block()->y();        int bottom = highY - block()->y();        start->setX(lowX - block()->x());        start->setY(top);        start->setWidth(highX - lowX);        static_cast<SVGRootInlineBox*>(start)->setHeight(highY - lowY);        start->setVerticalOverflowPositions(top, bottom);        start->setVerticalSelectionPositions(top, bottom);    }}void SVGRootInlineBox::buildLayoutInformationForTextBox(SVGCharacterLayoutInfo& info, InlineTextBox* textBox, LastGlyphInfo& lastGlyph){    RenderText* text = textBox->textRenderer();    ASSERT(text);    RenderStyle* style = text->style(textBox->isFirstLineStyle());    ASSERT(style);    const Font& font = style->font();    SVGInlineTextBox* svgTextBox = static_cast<SVGInlineTextBox*>(textBox);    unsigned length = textBox->len();    const SVGRenderStyle* svgStyle = style->svgStyle();    bool isVerticalText = isVerticalWritingMode(svgStyle);    int charsConsumed = 0;    for (unsigned i = 0; i < length; i += charsConsumed) {        SVGChar svgChar;        if (info.inPathLayout())            svgChar.pathData = SVGCharOnPath::create();        float glyphWidth = 0.0f;        float glyphHeight = 0.0f;        int extraCharsAvailable = length - i - 1;        String unicodeStr;        String glyphName;        if (textBox->direction() == RTL) {            glyphWidth = svgTextBox->calculateGlyphWidth(style, textBox->end() - i, extraCharsAvailable, charsConsumed, glyphName);            glyphHeight = svgTextBox->calculateGlyphHeight(style, textBox->end() - i, extraCharsAvailable);            unicodeStr = String(textBox->textRenderer()->text()->characters() + textBox->end() - i, charsConsumed);        } else {            glyphWidth = svgTextBox->calculateGlyphWidth(style, textBox->start() + i, extraCharsAvailable, charsConsumed, glyphName);            glyphHeight = svgTextBox->calculateGlyphHeight(style, textBox->start() + i, extraCharsAvailable);            unicodeStr = String(textBox->textRenderer()->text()->characters() + textBox->start() + i, charsConsumed);        }        bool assignedX = false;        bool assignedY = false;        if (info.xValueAvailable() && (!info.inPathLayout() || (info.inPathLayout() && !isVerticalText))) {            if (!isVerticalText)                svgChar.newTextChunk = true;            assignedX = true;            svgChar.drawnSeperated = true;            info.curx = info.xValueNext();        }        if (info.yValueAvailable() && (!info.inPathLayout() || (info.inPathLayout() && isVerticalText))) {            if (isVerticalText)                svgChar.newTextChunk = true;            assignedY = true;            svgChar.drawnSeperated = true;            info.cury = info.yValueNext();        }        float dx = 0.0f;        float dy = 0.0f;        // Apply x-axis shift        if (info.dxValueAvailable()) {            svgChar.drawnSeperated = true;            dx = info.dxValueNext();            info.dx += dx;            if (!info.inPathLayout())                info.curx += dx;        }        // Apply y-axis shift        if (info.dyValueAvailable()) {            svgChar.drawnSeperated = true;            dy = info.dyValueNext();            info.dy += dy;            if (!info.inPathLayout())                info.cury += dy;        }        // Take letter & word spacing and kerning into account        float spacing = font.letterSpacing() + calculateKerning(textBox->renderer()->node()->renderer());        const UChar* currentCharacter = text->characters() + (textBox->direction() == RTL ? textBox->end() - i : textBox->start() + i);        const UChar* lastCharacter = 0;        if (textBox->direction() == RTL) {            if (i < textBox->end())                lastCharacter = text->characters() + textBox->end() - i +  1;        } else {            if (i > 0)                lastCharacter = text->characters() + textBox->start() + i - 1;        }        if (info.nextDrawnSeperated || spacing != 0.0f) {            info.nextDrawnSeperated = false;            svgChar.drawnSeperated = true;        }        if (currentCharacter && Font::treatAsSpace(*currentCharacter) && lastCharacter && !Font::treatAsSpace(*lastCharacter)) {            spacing += font.wordSpacing();            if (spacing != 0.0f && !info.inPathLayout())                info.nextDrawnSeperated = true;        }        float orientationAngle = glyphOrientationToAngle(svgStyle, isVerticalText, *currentCharacter);        float xOrientationShift = 0.0f;        float yOrientationShift = 0.0f;        float glyphAdvance = calculateGlyphAdvanceAndShiftRespectingOrientation(isVerticalText, orientationAngle, glyphWidth, glyphHeight,                                                                                font, svgChar, xOrientationShift, yOrientationShift);        // Handle textPath layout mode        if (info.inPathLayout()) {            float extraAdvance = isVerticalText ? dy : dx;            float newOffset = FLT_MIN;            if (assignedX && !isVerticalText)                newOffset = info.curx;            else if (assignedY && isVerticalText)                newOffset = info.cury;            float correctedGlyphAdvance = glyphAdvance;            // Handle lengthAdjust="spacingAndGlyphs" by specifying per-character scale operations            if (info.pathTextLength > 0.0f && info.pathChunkLength > 0.0f) {                 if (isVerticalText) {                    svgChar.pathData->yScale = info.pathChunkLength / info.pathTextLength;                    spacing *= svgChar.pathData->yScale;                    correctedGlyphAdvance *= svgChar.pathData->yScale;                } else {                    svgChar.pathData->xScale = info.pathChunkLength / info.pathTextLength;                    spacing *= svgChar.pathData->xScale;                    correctedGlyphAdvance *= svgChar.pathData->xScale;                }            }            // Handle letter & word spacing on text path            float pathExtraAdvance = info.pathExtraAdvance;            info.pathExtraAdvance += spacing;            svgChar.pathData->hidden = !info.nextPathLayoutPointAndAngle(correctedGlyphAdvance, extraAdvance, newOffset);            svgChar.drawnSeperated = true;            info.pathExtraAdvance = pathExtraAdvance;        }        // Apply rotation        if (info.angleValueAvailable())            info.angle = info.angleValueNext();        // Apply baseline-shift        if (info.baselineShiftValueAvailable()) {            svgChar.drawnSeperated = true;            float shift = info.baselineShiftValueNext();            if (isVerticalText)                info.shiftx += shift;            else                info.shifty -= shift;        }        // Take dominant-baseline / alignment-baseline into account        yOrientationShift += alignmentBaselineToShift(isVerticalText, text, font);        svgChar.x = info.curx;        svgChar.y = info.cury;        svgChar.angle = info.angle;        // For text paths any shift (dx/dy/baseline-shift) has to be applied after the rotation        if (!info.inPathLayout()) {            svgChar.x += info.shiftx + xOrientationShift;            svgChar.y += info.shifty + yOrientationShift;            if (orientationAngle != 0.0f)

⌨️ 快捷键说明

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