(next);
if (nextText->stringLength() != 0) {
UChar c = nextText->text()[0];
if (c == ' ' || c == '\t' || (c == '\n' && !next->style()->preserveNewline()))
// If the next item on the line is text, and if we did not end with
// a space, then the next text run continues our word (and so it needs to
// keep adding to |tmpW|. Just update and continue.
checkForBreak = true;
}
bool canPlaceOnLine = (w + tmpW <= width) || !autoWrap;
if (canPlaceOnLine && checkForBreak) {
w += tmpW;
tmpW = 0;
lBreak.obj = next;
lBreak.pos = 0;
}
}
}
}
if (checkForBreak && (w + tmpW > width)) {
// if we have floats, try to get below them.
if (currentCharacterIsSpace && !ignoringSpaces && o->style()->collapseWhiteSpace())
trailingSpaceObject = 0;
int fb = nearestFloatBottom(m_height);
int newLineWidth = lineWidth(fb);
// See if |tmpW| will fit on the new line. As long as it does not,
// keep adjusting our float bottom until we find some room.
int lastFloatBottom = m_height;
while (lastFloatBottom < fb && tmpW > newLineWidth) {
lastFloatBottom = fb;
fb = nearestFloatBottom(fb);
newLineWidth = lineWidth(fb);
}
if (!w && m_height < fb && width < newLineWidth) {
m_height = fb;
width = newLineWidth;
}
// |width| may have been adjusted because we got shoved down past a float (thus
// giving us more room), so we need to retest, and only jump to
// the end label if we still don't fit on the line. -dwh
if (w + tmpW > width)
goto end;
}
last = o;
if (!o->isFloating() && (!o->isPositioned() || o->hasStaticX() || o->hasStaticY() || !o->container()->isInlineFlow()))
previous = o;
o = next;
if (!last->isFloatingOrPositioned() && last->isReplaced() && autoWrap &&
(!last->isListMarker() || last->style()->listStylePosition()==INSIDE)) {
// Go ahead and add in tmpW.
w += tmpW;
tmpW = 0;
lBreak.obj = o;
lBreak.pos = 0;
}
// Clear out our character space bool, since inline s don't collapse whitespace
// with adjacent inline normal/nowrap spans.
if (!collapseWhiteSpace)
currentCharacterIsSpace = false;
pos = 0;
atStart = false;
}
if (w + tmpW <= width || lastWS == NOWRAP) {
lBreak.obj = 0;
lBreak.pos = 0;
}
end:
if (lBreak == start && !lBreak.obj->isBR()) {
// we just add as much as possible
if (style()->whiteSpace() == PRE) {
// FIXME: Don't really understand this case.
if (pos != 0) {
lBreak.obj = o;
lBreak.pos = pos - 1;
} else {
lBreak.obj = last;
lBreak.pos = last->isText() ? last->length() : 0;
}
} else if (lBreak.obj) {
if (last != o && !last->isListMarker()) {
// better to break between object boundaries than in the middle of a word (except for list markers)
lBreak.obj = o;
lBreak.pos = 0;
} else {
// Don't ever break in the middle of a word if we can help it.
// There's no room at all. We just have to be on this line,
// even though we'll spill out.
lBreak.obj = o;
lBreak.pos = pos;
}
}
}
// make sure we consume at least one char/object.
if (lBreak == start)
lBreak.increment(bidi);
// Sanity check our midpoints.
checkMidpoints(lBreak, bidi);
if (trailingSpaceObject) {
// This object is either going to be part of the last midpoint, or it is going
// to be the actual endpoint. In both cases we just decrease our pos by 1 level to
// exclude the space, allowing it to - in effect - collapse into the newline.
if (sNumMidpoints%2==1) {
BidiIterator* midpoints = smidpoints->data();
midpoints[sNumMidpoints-1].pos--;
}
//else if (lBreak.pos > 0)
// lBreak.pos--;
else if (lBreak.obj == 0 && trailingSpaceObject->isText()) {
// Add a new end midpoint that stops right at the very end.
RenderText* text = static_cast(trailingSpaceObject);
unsigned pos = text->length() >=2 ? text->length() - 2 : UINT_MAX;
BidiIterator endMid(0, trailingSpaceObject, pos);
addMidpoint(endMid);
}
}
// We might have made lBreak an iterator that points past the end
// of the object. Do this adjustment to make it point to the start
// of the next object instead to avoid confusing the rest of the
// code.
if (lBreak.pos > 0) {
lBreak.pos--;
lBreak.increment(bidi);
}
if (lBreak.obj && lBreak.pos >= 2 && lBreak.obj->isText()) {
// For soft hyphens on line breaks, we have to chop out the midpoints that made us
// ignore the hyphen so that it will render at the end of the line.
UChar c = static_cast(lBreak.obj)->text()[lBreak.pos-1];
if (c == SOFT_HYPHEN)
chopMidpointsAt(lBreak.obj, lBreak.pos-2);
}
return lBreak;
}
void RenderBlock::checkLinesForOverflow()
{
// FIXME: Inline blocks can have overflow. Need to understand when those objects are present on a line
// and factor that in somehow.
m_overflowWidth = m_width;
for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
m_overflowLeft = min(curr->leftOverflow(), m_overflowLeft);
m_overflowTop = min(curr->topOverflow(), m_overflowTop);
m_overflowWidth = max(curr->rightOverflow(), m_overflowWidth);
m_overflowHeight = max(curr->bottomOverflow(), m_overflowHeight);
}
}
void RenderBlock::deleteEllipsisLineBoxes()
{
for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox())
curr->clearTruncation();
}
void RenderBlock::checkLinesForTextOverflow()
{
// Determine the width of the ellipsis using the current font.
const UChar ellipsis = 0x2026; // FIXME: CSS3 says this is configurable, also need to use 0x002E (FULL STOP) if 0x2026 not renderable
TextRun ellipsisRun(&ellipsis, 1);
static AtomicString ellipsisStr(&ellipsis, 1);
const Font& firstLineFont = firstLineStyle()->font();
const Font& font = style()->font();
int firstLineEllipsisWidth = firstLineFont.width(ellipsisRun);
int ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : font.width(ellipsisRun);
// For LTR text truncation, we want to get the right edge of our padding box, and then we want to see
// if the right edge of a line box exceeds that. For RTL, we use the left edge of the padding box and
// check the left edge of the line box to see if it is less
// Include the scrollbar for overflow blocks, which means we want to use "contentWidth()"
bool ltr = style()->direction() == LTR;
for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
int blockEdge = ltr ? rightOffset(curr->yPos()) : leftOffset(curr->yPos());
int lineBoxEdge = ltr ? curr->xPos() + curr->width() : curr->xPos();
if ((ltr && lineBoxEdge > blockEdge) || (!ltr && lineBoxEdge < blockEdge)) {
// This line spills out of our box in the appropriate direction. Now we need to see if the line
// can be truncated. In order for truncation to be possible, the line must have sufficient space to
// accommodate our truncation string, and no replaced elements (images, tables) can overlap the ellipsis
// space.
int width = curr == firstRootBox() ? firstLineEllipsisWidth : ellipsisWidth;
if (curr->canAccommodateEllipsis(ltr, blockEdge, lineBoxEdge, width))
curr->placeEllipsis(ellipsisStr, ltr, blockEdge, width);
}
}
}
}