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

📄 svgrootinlinebox.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 4 页
字号:
                svgChar.angle += orientationAngle;            if (svgChar.angle != 0.0f)                svgChar.drawnSeperated = true;        } else {            svgChar.pathData->orientationAngle = orientationAngle;            if (isVerticalText)                svgChar.angle -= 90.0f;            svgChar.pathData->xShift = info.shiftx + xOrientationShift;            svgChar.pathData->yShift = info.shifty + yOrientationShift;            // Translate to glyph midpoint            if (isVerticalText) {                svgChar.pathData->xShift += info.dx;                svgChar.pathData->yShift -= glyphAdvance / 2.0f;            } else {                svgChar.pathData->xShift -= glyphAdvance / 2.0f;                svgChar.pathData->yShift += info.dy;            }        }        double kerning = 0.0;#if ENABLE(SVG_FONTS)        SVGFontElement* svgFont = 0;        if (style->font().isSVGFont())            svgFont = style->font().svgFont();        if (lastGlyph.isValid && style->font().isSVGFont()) {            SVGHorizontalKerningPair kerningPair;            if (svgFont->getHorizontalKerningPairForStringsAndGlyphs(lastGlyph.unicode, lastGlyph.glyphName, unicodeStr, glyphName, kerningPair))                kerning = kerningPair.kerning;        }        if (style->font().isSVGFont()) {            lastGlyph.unicode = unicodeStr;            lastGlyph.glyphName = glyphName;            lastGlyph.isValid = true;        } else            lastGlyph.isValid = false;#endif        svgChar.x -= (float)kerning;        // Advance to new position        if (isVerticalText) {            svgChar.drawnSeperated = true;            info.cury += glyphAdvance + spacing;        } else            info.curx += glyphAdvance + spacing - (float)kerning;        // Advance to next character group        for (int k = 0; k < charsConsumed; ++k) {            info.svgChars.append(svgChar);            info.processedSingleCharacter();            svgChar.drawnSeperated = false;            svgChar.newTextChunk = false;        }    }}void SVGRootInlineBox::buildTextChunks(Vector<SVGChar>& svgChars, Vector<SVGTextChunk>& svgTextChunks, InlineFlowBox* start){    SVGTextChunkLayoutInfo info(svgTextChunks);    info.it = svgChars.begin();    info.chunk.start = svgChars.begin();    info.chunk.end = svgChars.begin();    buildTextChunks(svgChars, start, info);    ASSERT(info.it == svgChars.end());}void SVGRootInlineBox::buildTextChunks(Vector<SVGChar>& svgChars, InlineFlowBox* start, SVGTextChunkLayoutInfo& info){#if DEBUG_CHUNK_BUILDING > 1    fprintf(stderr, " -> buildTextChunks(start=%p)\n", start);#endif    for (InlineBox* curr = start->firstChild(); curr; curr = curr->nextOnLine()) {        if (curr->renderer()->isText()) {            InlineTextBox* textBox = static_cast<InlineTextBox*>(curr);            unsigned length = textBox->len();            if (!length)                continue;#if DEBUG_CHUNK_BUILDING > 1            fprintf(stderr, " -> Handle inline text box (%p) with %i characters (start: %i, end: %i), handlingTextPath=%i\n",                            textBox, length, textBox->start(), textBox->end(), (int) info.handlingTextPath);#endif            RenderText* text = textBox->textRenderer();            ASSERT(text);            ASSERT(text->node());            SVGTextContentElement* textContent = 0;            Node* node = text->node()->parent();            while (node && node->isSVGElement() && !textContent) {                if (static_cast<SVGElement*>(node)->isTextContent())                    textContent = static_cast<SVGTextContentElement*>(node);                else                    node = node->parentNode();            }            ASSERT(textContent);            // Start new character range for the first chunk            bool isFirstCharacter = info.svgTextChunks.isEmpty() && info.chunk.start == info.it && info.chunk.start == info.chunk.end;            if (isFirstCharacter) {                ASSERT(info.chunk.boxes.isEmpty());                info.chunk.boxes.append(SVGInlineBoxCharacterRange());            } else                ASSERT(!info.chunk.boxes.isEmpty());            // Walk string to find out new chunk positions, if existant            for (unsigned i = 0; i < length; ++i) {                ASSERT(info.it != svgChars.end());                SVGInlineBoxCharacterRange& range = info.chunk.boxes.last();                if (range.isOpen()) {                    range.box = curr;                    range.startOffset = (i == 0 ? 0 : i - 1);#if DEBUG_CHUNK_BUILDING > 1                    fprintf(stderr, " | -> Range is open! box=%p, startOffset=%i\n", range.box, range.startOffset);#endif                }                // If a new (or the first) chunk has been started, record it's text-anchor and writing mode.                if (info.assignChunkProperties) {                    info.assignChunkProperties = false;                    info.chunk.isVerticalText = isVerticalWritingMode(text->style()->svgStyle());                    info.chunk.isTextPath = info.handlingTextPath;                    info.chunk.anchor = text->style()->svgStyle()->textAnchor();                    info.chunk.textLength = textContent->textLength().value(textContent);                    info.chunk.lengthAdjust = (ELengthAdjust) textContent->lengthAdjust();#if DEBUG_CHUNK_BUILDING > 1                    fprintf(stderr, " | -> Assign chunk properties, isVerticalText=%i, anchor=%i\n", info.chunk.isVerticalText, info.chunk.anchor);#endif                }                if (i > 0 && !isFirstCharacter && (*info.it).newTextChunk) {                    // Close mid chunk & character range                    ASSERT(!range.isOpen());                    ASSERT(!range.isClosed());                    range.endOffset = i;                    closeTextChunk(info);#if DEBUG_CHUNK_BUILDING > 1                    fprintf(stderr, " | -> Close mid-text chunk, at endOffset: %i and starting new mid chunk!\n", range.endOffset);#endif                        // Prepare for next chunk, if we're not at the end                    startTextChunk(info);                    if (i + 1 == length) {#if DEBUG_CHUNK_BUILDING > 1                        fprintf(stderr, " | -> Record last chunk of inline text box!\n");#endif                        startTextChunk(info);                        SVGInlineBoxCharacterRange& range = info.chunk.boxes.last();                        info.assignChunkProperties = false;                        info.chunk.isVerticalText = isVerticalWritingMode(text->style()->svgStyle());                        info.chunk.isTextPath = info.handlingTextPath;                        info.chunk.anchor = text->style()->svgStyle()->textAnchor();                        info.chunk.textLength = textContent->textLength().value(textContent);                        info.chunk.lengthAdjust = (ELengthAdjust) textContent->lengthAdjust();                        range.box = curr;                        range.startOffset = i;                        ASSERT(!range.isOpen());                        ASSERT(!range.isClosed());                    }                }                // This should only hold true for the first character of the first chunk                if (isFirstCharacter)                    isFirstCharacter = false;                    ++info.it;            }#if DEBUG_CHUNK_BUILDING > 1                fprintf(stderr, " -> Finished inline text box!\n");#endif            SVGInlineBoxCharacterRange& range = info.chunk.boxes.last();            if (!range.isOpen() && !range.isClosed()) {#if DEBUG_CHUNK_BUILDING > 1                fprintf(stderr, " -> Last range not closed - closing with endOffset: %i\n", length);#endif                // Current text chunk is not yet closed. Finish the current range, but don't start a new chunk.                range.endOffset = length;                if (info.it != svgChars.end()) {#if DEBUG_CHUNK_BUILDING > 1                    fprintf(stderr, " -> Not at last character yet!\n");#endif                    // If we're not at the end of the last box to be processed, and if the next                    // character starts a new chunk, then close the current chunk and start a new one.                    if ((*info.it).newTextChunk) {#if DEBUG_CHUNK_BUILDING > 1                        fprintf(stderr, " -> Next character starts new chunk! Closing current chunk, and starting a new one...\n");#endif                        closeTextChunk(info);                        startTextChunk(info);                    } else {                        // Just start a new character range                        info.chunk.boxes.append(SVGInlineBoxCharacterRange());#if DEBUG_CHUNK_BUILDING > 1                        fprintf(stderr, " -> Next character does NOT start a new chunk! Starting new character range...\n");#endif                    }                } else {#if DEBUG_CHUNK_BUILDING > 1                    fprintf(stderr, " -> Closing final chunk! Finished processing!\n");#endif                    // Close final chunk, once we're at the end of the last box                    closeTextChunk(info);                }            }        } else {            ASSERT(curr->isInlineFlowBox());            InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(curr);            if (!flowBox->renderer()->node())                continue; // Skip generated content.            bool isTextPath = flowBox->renderer()->node()->hasTagName(SVGNames::textPathTag);#if DEBUG_CHUNK_BUILDING > 1            fprintf(stderr, " -> Handle inline flow box (%p), isTextPath=%i\n", flowBox, (int) isTextPath);#endif            if (isTextPath)                info.handlingTextPath = true;            buildTextChunks(svgChars, flowBox, info);            if (isTextPath)                info.handlingTextPath = false;        }    }#if DEBUG_CHUNK_BUILDING > 1    fprintf(stderr, " <- buildTextChunks(start=%p)\n", start);#endif}const Vector<SVGTextChunk>& SVGRootInlineBox::svgTextChunks() const {    return m_svgTextChunks;}void SVGRootInlineBox::layoutTextChunks(){    Vector<SVGTextChunk>::iterator it = m_svgTextChunks.begin();    Vector<SVGTextChunk>::iterator end = m_svgTextChunks.end();    for (; it != end; ++it) {        SVGTextChunk& chunk = *it;#if DEBUG_CHUNK_BUILDING > 0        {            fprintf(stderr, "Handle TEXT CHUNK! anchor=%i, textLength=%f, lengthAdjust=%i, isVerticalText=%i, isTextPath=%i start=%p, end=%p -> dist: %i\n",                    (int) chunk.anchor, chunk.textLength, (int) chunk.lengthAdjust, (int) chunk.isVerticalText,                    (int) chunk.isTextPath, chunk.start, chunk.end, (unsigned int) (chunk.end - chunk.start));            Vector<SVGInlineBoxCharacterRange>::iterator boxIt = chunk.boxes.begin();            Vector<SVGInlineBoxCharacterRange>::iterator boxEnd = chunk.boxes.end();            unsigned int i = 0;            for (; boxIt != boxEnd; ++boxIt) {                SVGInlineBoxCharacterRange& range = *boxIt; i++;                fprintf(stderr, " -> RANGE %i STARTOFFSET: %i, ENDOFFSET: %i, BOX: %p\n", i, range.startOffset, range.endOffset, range.box);            }        }#endif        if (chunk.isTextPath)            continue;        // text-path & textLength, with lengthAdjust="spacing" is already handled for textPath layouts.        applyTextLengthCorrectionToTextChunk(chunk);         // text-anchor is already handled for textPath layouts.        applyTextAnchorToTextChunk(chunk);    }}static inline void addPaintServerToTextDecorationInfo(ETextDecoration decoration, SVGTextDecorationInfo& info, RenderObject* object){    if (object->style()->svgStyle()->hasFill())        info.fillServerMap.set(decoration, object);    if (object->style()->svgStyle()->hasStroke())        info.strokeServerMap.set(decoration, object);}SVGTextDecorationInfo SVGRootInlineBox::retrievePaintServersForTextDecoration(RenderObject* start){    ASSERT(start);    Vector<RenderObject*> parentChain;    while ((start = start->parent())) {        parentChain.prepend(start);        // Stop at our direct <text> parent.        if (start->isSVGText())            break;    }    Vector<RenderObject*>::iterator it = parentChain.begin();    Vector<RenderObject*>::iterator end = parentChain.end();    SVGTextDecorationInfo info;    for (; it != end; ++it) {        RenderObject* object = *it;        ASSERT(object);        RenderStyle* style = object->style();        ASSERT(style);        int decorations = style->textDecoration();        if (decorations != NONE) {            if (decorations & OVERLINE)                addPaintServerToTextDecorationInfo(OVERLINE, info, object);            if (decorations & UNDERLINE)                addPaintServerToTextDecorationInfo(UNDERLINE, info, object);            if (decorations & LINE_THROUGH)                addPaintServerToTextDecorationInfo(LINE_THROUGH, info, object);        }    }    return info;}void SVGRootInlineBox::walkTextChunks(SVGTextChunkWalkerBase* walker, const SVGInlineTextBox* textBox){    ASSERT(walker);    Vector<SVGTextChunk>::iterator it = m_svgTextChunks.begin();    Vector<SVGTextChunk>::iterator itEnd = m_svgTextChunks.end();    for (; it != itEnd; ++it) {        SVGTextChunk& curChunk = *it;        Vector<SVGInlineBoxCharacterRange>::iterator boxIt = curChunk.boxes.begin();        Vector<SVGInlineBoxCharacterRange>::iterator boxEnd = curChunk.boxes.end();        InlineBox* lastNotifiedBox = 0;        InlineBox* prevBox = 0;        unsigned int chunkOffset = 0;        bool startedFirstChunk = false;        for (; boxIt != boxEnd; ++boxIt) {            SVGInlineBoxCharacterRange& range = *boxIt;            ASSERT(range.box->isInlineTextBox());            SVGInlineTextBox* rangeTextBox = static_cast<SVGInlineTextBox*>(range.box);            if (textBox && rangeTextBox != textBox) {                chunkOffset += range.endOffset - range.startOffset;                continue;            }            // Eventually notify that we started a new chunk            if (!textBox && !startedFirstChunk) {                startedFirstChunk = true;                lastNotifiedBox = range.box;                walker->start(range.box);            } else {                // Eventually apply new style, as this chunk spans multiple boxes (with possible different styling)                if (prevBox && prevBox != range.box) {                    lastNotifiedBox = range.box;                    walker->end(prevBox);                    walker->start(lastNotifiedBox);                }            }            unsigned int length = range.endOffset - range.startOffset;            Vector<SVGChar>::iterator itCharBegin = curChunk.start + chunkOffset;            Vector<SVGChar>::iterator itCharEnd = curChunk.start + chunkOffset + length;            ASSERT(itCharEnd <= curChunk.end);            // Process this chunk portion            if (textBox)                (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd);            else {                if (walker->setupFill(range.box))                    (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd);                if (walker->setupStroke(range.box))                    (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd);            }            chunkOffset += length;            if (!textBox)                prevBox = range.box;        }        if (!textBox && startedFirstChunk)            walker->end(lastNotifiedBox);    }}} // namespace WebCore#endif // ENABLE(SVG)

⌨️ 快捷键说明

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