예제 #1
0
InlineTextBox * RenderText::findInlineTextBox( int offset, int &pos, bool checkFirstLetter )
{
    // The text boxes point to parts of the rendertext's str string
    // (they don't include '\n')
    // Find the text box that includes the character at @p offset
    // and return pos, which is the position of the char in the run.

    // FIXME: make this use binary search? Dirk says it won't work :-( (LS)
    (void)checkFirstLetter;
#if 0
    if (checkFirstLetter && forcedMinOffset()) {
//        kdDebug(6040) << "checkFirstLetter: forcedMinOffset: " << forcedMinOffset() << endl;
        RenderFlow *firstLetter = static_cast<RenderFlow *>(previousSibling());
        if (firstLetter && firstLetter->isFlow() && firstLetter->isFirstLetter()) {
            RenderText *letterText = static_cast<RenderText *>(firstLetter->firstChild());
            //kdDebug(6040) << "lettertext: " << letterText << " minOfs: " << letterText->minOffset() << " maxOfs: " << letterText->maxOffset() << endl;
	    if (offset >= letterText->minOffset() && offset <= letterText->maxOffset()) {
	        InlineTextBox *result = letterText->findInlineTextBox(offset, pos, false);
            //kdDebug(6040) << "result: " << result << endl;
		if (result) return result;
	    }
        }
    }
#endif

    if ( m_lines.isEmpty() )
        return 0L;

    // The text boxes don't resemble a contiguous coverage of the text, there
    // may be holes. Therefore, we snap to the nearest previous text box if
    // the given offset happens to point to such a hole.

    InlineTextBox* s = m_lines[0];
    uint count = m_lines.count();
    uint si = 0;
    uint nearest_idx = 0;		// index of nearest text box
    int nearest = INT_MAX;		// nearest distance
//kdDebug(6040) << "s[" << si << "] m_start " << s->m_start << " m_end " << (s->m_start + s->m_len) << endl;
    while(!(offset >= s->m_start && offset <= s->m_start + s->m_len)
    		&& ++si < count)
    {
        int dist = offset - (s->m_start + s->m_len);
//kdDebug(6040) << "dist " << dist << " nearest " << nearest << endl;
	if (dist >= 0 && dist <= nearest) {
	    nearest = dist;
	    nearest_idx = si - 1;
	}/*end if*/
        s = m_lines[si];
//kdDebug(6040) << "s[" << si << "] m_start " << s->m_start << " m_end " << (s->m_start + s->m_len) << endl;
    }
//kdDebug(6040) << "nearest_idx " << nearest_idx << " count " << count << endl;
    if (si >= count) s = m_lines[nearest_idx];
    // we are now in the correct text box
    pos = kMin(offset - s->m_start, int( s->m_len ));
    //kdDebug(6040) << "offset=" << offset << " s->m_start=" << s->m_start << endl;
    return s;
}
예제 #2
0
void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* endObject)
{
    // All boxes start off open.  They will not apply any margins/border/padding on
    // any side.
    bool includeLeftEdge = false;
    bool includeRightEdge = false;

    RenderFlow* flow = static_cast<RenderFlow*>(object());

    if (!flow->firstChild())
        includeLeftEdge = includeRightEdge = true; // Empty inlines never split across lines.
    else if (parent()) { // The root inline box never has borders/margins/padding.
        bool ltr = flow->style()->direction() == LTR;

        // Check to see if all initial lines are unconstructed.  If so, then
        // we know the inline began on this line.
        if (!flow->firstLineBox()->isConstructed()) {
            if (ltr && flow->firstLineBox() == this)
                includeLeftEdge = true;
            else if (!ltr && flow->lastLineBox() == this)
                includeRightEdge = true;
        }

        // In order to determine if the inline ends on this line, we check three things:
        // (1) If we are the last line and we don't have a continuation(), then we can
        // close up.
        // (2) If the last line box for the flow has an object following it on the line (ltr,
        // reverse for rtl), then the inline has closed.
        // (3) The line may end on the inline.  If we are the last child (climbing up
        // the end object's chain), then we just closed as well.
        if (!flow->lastLineBox()->isConstructed()) {
            if (ltr) {
                if (!nextLineBox() &&
                    ((lastLine && !object()->continuation()) || nextOnLineExists()
                     || onEndChain(endObject)))
                    includeRightEdge = true;
            }
            else {
                if ((!prevLineBox() || !prevLineBox()->isConstructed()) &&
                    ((lastLine && !object()->continuation()) ||
                     prevOnLineExists() || onEndChain(endObject)))
                    includeLeftEdge = true;
            }

        }
    }

    setEdges(includeLeftEdge, includeRightEdge);

    // Recur into our children.
    for (InlineBox* currChild = firstChild(); currChild; currChild = currChild->nextOnLine()) {
        if (currChild->isInlineFlowBox()) {
            InlineFlowBox* currFlow = static_cast<InlineFlowBox*>(currChild);
            currFlow->determineSpacingForFlowBoxes(lastLine, endObject);
        }
    }
}
RenderFlow* RenderFlow::continuationBefore(RenderObject* beforeChild)
{
    if (beforeChild && beforeChild->parent() == this)
        return this;
    
    RenderFlow* curr = continuation();
    RenderFlow* nextToLast = this;
    RenderFlow* last = this;
    while (curr) {
        if (beforeChild && beforeChild->parent() == curr) {
            if (curr->firstChild() == beforeChild)
                return last;
            return curr;
        }
        
        nextToLast = last;
        last = curr;
        curr = curr->continuation();
    }
    
    if (!beforeChild && !last->firstChild())
        return nextToLast;
    return last;
}
VisiblePosition RenderInline::positionForCoordinates(int x, int y)
{
    // Translate the coords from the pre-anonymous block to the post-anonymous block.
    RenderBlock* cb = containingBlock();
    int parentBlockX = cb->x() + x;
    int parentBlockY = cb->y() + y;
    for (RenderFlow* c = continuation(); c; c = c->continuation()) {
        RenderFlow* contBlock = c;
        if (c->isInline())
            contBlock = c->containingBlock();
        if (c->isInline() || c->firstChild())
            return c->positionForCoordinates(parentBlockX - contBlock->x(), parentBlockY - contBlock->y());
    }

    return RenderFlow::positionForCoordinates(x, y);
}
예제 #5
0
long CharacterDataImpl::minOffset() const
{
  RenderText *r = static_cast<RenderText *>(renderer());
  if (!r || !r->isText()) return 0;

  // take :first-letter into consideration
#ifdef __GNUC__
#warning FIXME
#endif
#if 0
  if (r->forcedMinOffset()) {
    RenderFlow *firstLetter = static_cast<RenderFlow *>(r->previousSibling());
    if (firstLetter && firstLetter->isFlow() && firstLetter->isFirstLetter()) {
      RenderText *letterText = static_cast<RenderText *>(firstLetter->firstChild());
      return letterText->minOffset();
    }
  }
#endif

  return r->minOffset();
}