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

📄 bidi.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    if (obj && obj->isListMarker())        return obj->style()->direction() == LTR ? LeftToRight : RightToLeft;    return OtherNeutral;}// -------------------------------------------------------------------------------------------------static void chopMidpointsAt(RenderObject* obj, unsigned pos){    if (!sNumMidpoints)        return;    InlineIterator* midpoints = smidpoints->data();    for (int i = sNumMidpoints - 1; i >= 0; i--) {        const InlineIterator& point = midpoints[i];        if (point.obj == obj && point.pos == pos) {            sNumMidpoints = i;            break;        }    }}static void checkMidpoints(InlineIterator& lBreak){    // Check to see if our last midpoint is a start point beyond the line break.  If so,    // shave it off the list, and shave off a trailing space if the previous end point doesn't    // preserve whitespace.    if (lBreak.obj && sNumMidpoints && sNumMidpoints % 2 == 0) {        InlineIterator* midpoints = smidpoints->data();        InlineIterator& endpoint = midpoints[sNumMidpoints-2];        const InlineIterator& startpoint = midpoints[sNumMidpoints-1];        InlineIterator currpoint = endpoint;        while (!currpoint.atEnd() && currpoint != startpoint && currpoint != lBreak)            currpoint.increment();        if (currpoint == lBreak) {            // We hit the line break before the start point.  Shave off the start point.            sNumMidpoints--;            if (endpoint.obj->style()->collapseWhiteSpace()) {                if (endpoint.obj->isText()) {                    // Don't shave a character off the endpoint if it was from a soft hyphen.                    RenderText* textObj = toRenderText(endpoint.obj);                    if (endpoint.pos + 1 < textObj->textLength()) {                        if (textObj->characters()[endpoint.pos+1] == softHyphen)                            return;                    } else if (startpoint.obj->isText()) {                        RenderText *startText = toRenderText(startpoint.obj);                        if (startText->textLength() && startText->characters()[0] == softHyphen)                            return;                    }                }                endpoint.pos--;            }        }    }    }static void addMidpoint(const InlineIterator& midpoint){    if (smidpoints->size() <= sNumMidpoints)        smidpoints->grow(sNumMidpoints + 10);    InlineIterator* midpoints = smidpoints->data();    midpoints[sNumMidpoints++] = midpoint;}static void appendRunsForObject(int start, int end, RenderObject* obj, InlineBidiResolver& resolver){    if (start > end || obj->isFloating() ||        (obj->isPositioned() && !obj->style()->hasStaticX() && !obj->style()->hasStaticY() && !obj->container()->isRenderInline()))        return;    bool haveNextMidpoint = (sCurrMidpoint < sNumMidpoints);    InlineIterator nextMidpoint;    if (haveNextMidpoint)        nextMidpoint = smidpoints->at(sCurrMidpoint);    if (betweenMidpoints) {        if (!(haveNextMidpoint && nextMidpoint.obj == obj))            return;        // This is a new start point. Stop ignoring objects and         // adjust our start.        betweenMidpoints = false;        start = nextMidpoint.pos;        sCurrMidpoint++;        if (start < end)            return appendRunsForObject(start, end, obj, resolver);    } else {        if (!haveNextMidpoint || (obj != nextMidpoint.obj)) {            resolver.addRun(new (obj->renderArena()) BidiRun(start, end, obj, resolver.context(), resolver.dir()));            return;        }        // An end midpoint has been encountered within our object.  We        // need to go ahead and append a run with our endpoint.        if (static_cast<int>(nextMidpoint.pos + 1) <= end) {            betweenMidpoints = true;            sCurrMidpoint++;            if (nextMidpoint.pos != UINT_MAX) { // UINT_MAX means stop at the object and don't include any of it.                if (static_cast<int>(nextMidpoint.pos + 1) > start)                    resolver.addRun(new (obj->renderArena())                        BidiRun(start, nextMidpoint.pos + 1, obj, resolver.context(), resolver.dir()));                return appendRunsForObject(nextMidpoint.pos + 1, end, obj, resolver);            }        } else           resolver.addRun(new (obj->renderArena()) BidiRun(start, end, obj, resolver.context(), resolver.dir()));    }}template <>void InlineBidiResolver::appendRun(){    if (!emptyRun && !eor.atEnd()) {        int start = sor.pos;        RenderObject *obj = sor.obj;        while (obj && obj != eor.obj && obj != endOfLine.obj) {            appendRunsForObject(start, obj->length(), obj, *this);                    start = 0;            obj = bidiNext(sor.block, obj);        }        if (obj) {            unsigned pos = obj == eor.obj ? eor.pos : UINT_MAX;            if (obj == endOfLine.obj && endOfLine.pos <= pos) {                reachedEndOfLine = true;                pos = endOfLine.pos;            }            // It's OK to add runs for zero-length RenderObjects, just don't make the run larger than it should be            int end = obj->length() ? pos+1 : 0;            appendRunsForObject(start, end, obj, *this);        }                eor.increment();        sor = eor;    }    m_direction = OtherNeutral;    m_status.eor = OtherNeutral;}static inline InlineBox* createInlineBoxForRenderer(RenderObject* obj, bool isRootLineBox, bool isOnlyRun = false){    if (isRootLineBox)        return toRenderBlock(obj)->createRootInlineBox();        if (obj->isText()) {        InlineTextBox* textBox = toRenderText(obj)->createInlineTextBox();        // We only treat a box as text for a <br> if we are on a line by ourself or in strict mode        // (Note the use of strict mode.  In "almost strict" mode, we don't treat the box for <br> as text.)        if (obj->isBR())            textBox->setIsText(isOnlyRun || obj->document()->inStrictMode());        return textBox;    }        if (obj->isBox())        return toRenderBox(obj)->createInlineBox();        return toRenderInline(obj)->createInlineFlowBox();}static inline void dirtyLineBoxesForRenderer(RenderObject* o, bool fullLayout){    if (o->isText()) {        if (o->prefWidthsDirty() && o->isCounter())            toRenderText(o)->calcPrefWidths(0); // FIXME: Counters depend on this hack. No clue why. Should be investigated and removed.        toRenderText(o)->dirtyLineBoxes(fullLayout);    } else        toRenderInline(o)->dirtyLineBoxes(fullLayout);}InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj, bool firstLine){    // See if we have an unconstructed line box for this object that is also    // the last item on the line.    unsigned lineDepth = 1;    InlineFlowBox* childBox = 0;    InlineFlowBox* parentBox = 0;    InlineFlowBox* result = 0;    do {        ASSERT(obj->isRenderInline() || obj == this);                // Get the last box we made for this render object.        parentBox = obj->isRenderInline() ? toRenderInline(obj)->lastLineBox() : toRenderBlock(obj)->lastLineBox();        // If this box is constructed then it is from a previous line, and we need        // to make a new box for our line.  If this box is unconstructed but it has        // something following it on the line, then we know we have to make a new box        // as well.  In this situation our inline has actually been split in two on        // the same line (this can happen with very fancy language mixtures).        bool constructedNewBox = false;        if (!parentBox || parentBox->isConstructed() || parentBox->nextOnLine()) {            // We need to make a new box for this render object.  Once            // made, we need to place it at the end of the current line.            InlineBox* newBox = createInlineBoxForRenderer(obj, obj == this);            ASSERT(newBox->isInlineFlowBox());            parentBox = static_cast<InlineFlowBox*>(newBox);            parentBox->setFirstLineStyleBit(firstLine);            constructedNewBox = true;        }        if (!result)            result = parentBox;        // If we have hit the block itself, then |box| represents the root        // inline box for the line, and it doesn't have to be appended to any parent        // inline.        if (childBox)            parentBox->addToLine(childBox);        if (!constructedNewBox || obj == this)            break;        childBox = parentBox;                // If we've exceeded our line depth, then jump straight to the root and skip all the remaining        // intermediate inline flows.        obj = (++lineDepth >= cMaxLineDepth) ? this : obj->parent();    } while (true);    return result;}RootInlineBox* RenderBlock::constructLine(unsigned runCount, BidiRun* firstRun, BidiRun* lastRun, bool firstLine, bool lastLine, RenderObject* endObject){    ASSERT(firstRun);    InlineFlowBox* parentBox = 0;    for (BidiRun* r = firstRun; r; r = r->next()) {        // Create a box for our object.        bool isOnlyRun = (runCount == 1);        if (runCount == 2 && !r->m_object->isListMarker())            isOnlyRun = ((style()->direction() == RTL) ? lastRun : firstRun)->m_object->isListMarker();        InlineBox* box = createInlineBoxForRenderer(r->m_object, false, isOnlyRun);        r->m_box = box;        if (box) {            // If we have no parent box yet, or if the run is not simply a sibling,            // then we need to construct inline boxes as necessary to properly enclose the            // run's inline box.            if (!parentBox || parentBox->renderer() != r->m_object->parent())                // Create new inline boxes all the way back to the appropriate insertion point.                parentBox = createLineBoxes(r->m_object->parent(), firstLine);            // Append the inline box to this line.            parentBox->addToLine(box);            bool visuallyOrdered = r->m_object->style()->visuallyOrdered();            box->setBidiLevel(visuallyOrdered ? 0 : r->level());            if (box->isInlineTextBox()) {                InlineTextBox* text = static_cast<InlineTextBox*>(box);                text->setStart(r->m_start);                text->setLen(r->m_stop - r->m_start);                text->m_dirOverride = r->dirOverride(visuallyOrdered);            }        }    }    // We should have a root inline box.  It should be unconstructed and    // be the last continuation of our line list.    ASSERT(lastLineBox() && !lastLineBox()->isConstructed());    // Set bits on our inline flow boxes that indicate which sides should    // paint borders/margins/padding.  This knowledge will ultimately be used when    // we determine the horizontal positions and widths of all the inline boxes on    // the line.    lastLineBox()->determineSpacingForFlowBoxes(lastLine, endObject);    // Now mark the line boxes as being constructed.    lastLineBox()->setConstructed();    // Return the last line.    return lastRootBox();}void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, bool firstLine, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd){    // First determine our total width.    int availableWidth = lineWidth(height(), firstLine);    int totWidth = lineBox->getFlowSpacingWidth();    bool needsWordSpacing = false;    unsigned numSpaces = 0;    ETextAlign textAlign = style()->textAlign();    for (BidiRun* r = firstRun; r; r = r->next()) {        if (!r->m_box || r->m_object->isPositioned() || r->m_box->isLineBreak())            continue; // Positioned objects are only participating to figure out their                      // correct static x position.  They have no effect on the width.                      // Similarly, line break boxes have no effect on the width.        if (r->m_object->isText()) {            RenderText* rt = toRenderText(r->m_object);            if (textAlign == JUSTIFY && r != trailingSpaceRun) {                const UChar* characters = rt->characters();                for (int i = r->m_start; i < r->m_stop; i++) {                    UChar c = characters[i];                    if (c == ' ' || c == '\n' || c == '\t')                        numSpaces++;                }            }            if (int length = rt->textLength()) {                if (!r->m_start && needsWordSpacing && isSpaceOrNewline(rt->characters()[r->m_start]))                    totWidth += rt->style(firstLine)->font().wordSpacing();                needsWordSpacing = !isSpaceOrNewline(rt->characters()[r->m_stop - 1]) && r->m_stop == length;                      }            r->m_box->setWidth(rt->width(r->m_start, r->m_stop - r->m_start, totWidth, firstLine));        } else if (!r->m_object->isRenderInline()) {            RenderBox* renderBox = toRenderBox(r->m_object);            renderBox->calcWidth();            r->m_box->setWidth(renderBox->width());            totWidth += renderBox->marginLeft() + renderBox->marginRight();        }        totWidth += r->m_box->width();    }    // Armed with the total width of the line (without justification),    // we now examine our text-align property in order to determine where to position the    // objects horizontally.  The total width of the line can be increased if we end up    // justifying text.    int x = leftOffset(height(), firstLine);

⌨️ 快捷键说明

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