summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/RenderBlockLineLayout.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-09-10 19:10:20 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-09-10 19:10:20 +0200
commit284837daa07b29d6a63a748544a90b1f5842ac5c (patch)
treeecd258180bde91fe741e0cfd2638beb3c6da7e8e /Source/WebCore/rendering/RenderBlockLineLayout.cpp
parent2e2ba8ff45915f40ed3e014101269c175f2a89a0 (diff)
downloadqtwebkit-284837daa07b29d6a63a748544a90b1f5842ac5c.tar.gz
Imported WebKit commit 68645295d2e3e09af2c942f092556f06aa5f8b0d (http://svn.webkit.org/repository/webkit/trunk@128073)
New snapshot
Diffstat (limited to 'Source/WebCore/rendering/RenderBlockLineLayout.cpp')
-rwxr-xr-xSource/WebCore/rendering/RenderBlockLineLayout.cpp118
1 files changed, 88 insertions, 30 deletions
diff --git a/Source/WebCore/rendering/RenderBlockLineLayout.cpp b/Source/WebCore/rendering/RenderBlockLineLayout.cpp
index 55377d986..c0c3404ad 100755
--- a/Source/WebCore/rendering/RenderBlockLineLayout.cpp
+++ b/Source/WebCore/rendering/RenderBlockLineLayout.cpp
@@ -36,7 +36,6 @@
#include "RenderRubyRun.h"
#include "RenderView.h"
#include "Settings.h"
-#include "TextBreakIterator.h"
#include "TrailingFloatsRootInlineBox.h"
#include "VerticalPositionCache.h"
#include "break_lines.h"
@@ -46,6 +45,10 @@
#include <wtf/Vector.h>
#include <wtf/unicode/CharacterNames.h>
+#if ENABLE(CSS_EXCLUSIONS)
+#include "WrapShapeInfo.h"
+#endif
+
#if ENABLE(SVG)
#include "RenderSVGInlineText.h"
#include "SVGRootInlineBox.h"
@@ -70,9 +73,21 @@ public:
, m_left(0)
, m_right(0)
, m_availableWidth(0)
+#if ENABLE(CSS_EXCLUSIONS)
+ , m_segment(0)
+#endif
, m_isFirstLine(isFirstLine)
{
ASSERT(block);
+#if ENABLE(CSS_EXCLUSIONS)
+ WrapShapeInfo* wrapShapeInfo = m_block->wrapShapeInfo();
+ // FIXME: Bug 91878: Add support for multiple segments, currently we only support one
+ if (wrapShapeInfo && wrapShapeInfo->lineState() == WrapShapeInfo::LINE_INSIDE_SHAPE) {
+ // All interior shape positions should have at least one segment
+ ASSERT(wrapShapeInfo->hasSegments());
+ m_segment = &wrapShapeInfo->segments()[0];
+ }
+#endif
updateAvailableWidth();
}
#if ENABLE(SUBPIXEL_LAYOUT)
@@ -114,6 +129,9 @@ private:
float m_left;
float m_right;
float m_availableWidth;
+#if ENABLE(CSS_EXCLUSIONS)
+ const LineSegment* m_segment;
+#endif
bool m_isFirstLine;
};
@@ -138,6 +156,13 @@ inline void LineWidth::updateAvailableWidth()
m_left = m_block->logicalLeftOffsetForLine(height, m_isFirstLine, logicalHeight);
m_right = m_block->logicalRightOffsetForLine(height, m_isFirstLine, logicalHeight);
+#if ENABLE(CSS_EXCLUSIONS)
+ if (m_segment) {
+ m_left = max<float>(m_segment->logicalLeft, m_left);
+ m_right = min<float>(m_segment->logicalRight, m_right);
+ }
+#endif
+
computeAvailableWidthFromLeftAndRight();
}
@@ -397,9 +422,9 @@ static inline InlineBox* createInlineBoxForRenderer(RenderObject* obj, bool isRo
static inline void dirtyLineBoxesForRenderer(RenderObject* o, bool fullLayout)
{
if (o->isText()) {
- if (o->preferredLogicalWidthsDirty() && (o->isCounter() || o->isQuote()))
- toRenderText(o)->computePreferredLogicalWidths(0); // FIXME: Counters depend on this hack. No clue why. Should be investigated and removed.
- toRenderText(o)->dirtyLineBoxes(fullLayout);
+ RenderText* renderText = toRenderText(o);
+ renderText->updateTextIfNeeded(); // FIXME: Counters depend on this hack. No clue why. Should be investigated and removed.
+ renderText->dirtyLineBoxes(fullLayout);
} else
toRenderInline(o)->dirtyLineBoxes(fullLayout);
}
@@ -777,7 +802,15 @@ void RenderBlock::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox,
// box is only affected if it is the first child of its parent element."
bool firstLine = lineInfo.isFirstLine() && !(isAnonymousBlock() && parent()->firstChild() != this);
float logicalLeft = pixelSnappedLogicalLeftOffsetForLine(logicalHeight(), firstLine, lineLogicalHeight);
- float availableLogicalWidth = pixelSnappedLogicalRightOffsetForLine(logicalHeight(), firstLine, lineLogicalHeight) - logicalLeft;
+ float logicalRight = pixelSnappedLogicalRightOffsetForLine(logicalHeight(), firstLine, lineLogicalHeight);
+#if ENABLE(CSS_EXCLUSIONS)
+ WrapShapeInfo* wrapShapeInfo = this->wrapShapeInfo();
+ if (wrapShapeInfo && wrapShapeInfo->lineState() == WrapShapeInfo::LINE_INSIDE_SHAPE) {
+ logicalLeft = max<float>(roundToInt(wrapShapeInfo->segments()[0].logicalLeft), logicalLeft);
+ logicalRight = min<float>(floorToInt(wrapShapeInfo->segments()[0].logicalRight), logicalRight);
+ }
+#endif
+ float availableLogicalWidth = logicalRight - logicalLeft;
bool needsWordSpacing = false;
float totalLogicalWidth = lineBox->getFlowSpacingLogicalWidth();
@@ -888,12 +921,12 @@ static void setStaticPositions(RenderBlock* block, RenderBox* child)
// A relative positioned inline encloses us. In this case, we also have to determine our
// position as though we were an inline. Set |staticInlinePosition| and |staticBlockPosition| on the relative positioned
// inline so that we can obtain the value later.
- toRenderInline(containerBlock)->layer()->setStaticInlinePosition(block->startAlignedOffsetForLine(child, blockHeight, false));
+ toRenderInline(containerBlock)->layer()->setStaticInlinePosition(block->startAlignedOffsetForLine(blockHeight, false));
toRenderInline(containerBlock)->layer()->setStaticBlockPosition(blockHeight);
}
if (child->style()->isOriginalDisplayInlineType())
- block->setStaticInlinePositionForChild(child, blockHeight, block->startAlignedOffsetForLine(child, blockHeight, false));
+ block->setStaticInlinePositionForChild(child, blockHeight, block->startAlignedOffsetForLine(blockHeight, false));
else
block->setStaticInlinePositionForChild(child, blockHeight, block->startOffsetForContent(blockHeight));
child->layer()->setStaticBlockPosition(blockHeight);
@@ -1240,6 +1273,15 @@ void RenderBlock::layoutRunsAndFloats(LineLayoutState& layoutState, bool hasInli
repaintDirtyFloats(layoutState.floats());
}
+RenderBlock::RenderTextInfo::RenderTextInfo()
+ : m_text(0)
+{
+}
+
+RenderBlock::RenderTextInfo::~RenderTextInfo()
+{
+}
+
void RenderBlock::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, InlineBidiResolver& resolver, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines)
{
RenderStyle* styleToUse = style();
@@ -1247,11 +1289,18 @@ void RenderBlock::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, Inlin
LineMidpointState& lineMidpointState = resolver.midpointState();
InlineIterator end = resolver.position();
bool checkForEndLineMatch = layoutState.endLine();
- LineBreakIteratorInfo lineBreakIteratorInfo;
+ RenderTextInfo renderTextInfo;
VerticalPositionCache verticalPositionCache;
LineBreaker lineBreaker(this);
+#if ENABLE(CSS_EXCLUSIONS)
+ WrapShapeInfo* wrapShapeInfo = this->wrapShapeInfo();
+ // Move to the top of the shape inside to begin layout
+ if (wrapShapeInfo && logicalHeight() < wrapShapeInfo->shapeTop())
+ setLogicalHeight(wrapShapeInfo->shapeTop());
+#endif
+
while (!end.atEnd()) {
// FIXME: Is this check necessary before the first iteration or can it be moved to the end?
if (checkForEndLineMatch) {
@@ -1270,7 +1319,13 @@ void RenderBlock::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, Inlin
const InlineIterator oldEnd = end;
bool isNewUBAParagraph = layoutState.lineInfo().previousLineBrokeCleanly();
FloatingObject* lastFloatFromPreviousLine = (m_floatingObjects && !m_floatingObjects->set().isEmpty()) ? m_floatingObjects->set().last() : 0;
- end = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(), lineBreakIteratorInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines);
+#if ENABLE(CSS_EXCLUSIONS)
+ // FIXME: Bug 89993: If the wrap shape comes from a parent, we will need to adjust
+ // the height coordinate
+ if (wrapShapeInfo)
+ wrapShapeInfo->computeSegmentsForLine(logicalHeight());
+#endif
+ end = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(), renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines);
if (resolver.position().atEnd()) {
// FIXME: We shouldn't be creating any runs in nextLineBreak to begin with!
// Once BidiRunList is separated from BidiResolver this will not be needed.
@@ -1970,11 +2025,14 @@ static bool shouldSkipWhitespaceAfterStartObject(RenderBlock* block, RenderObjec
return false;
}
-static inline float textWidth(RenderText* text, unsigned from, unsigned len, const Font& font, float xPos, bool isFixedPitch, bool collapseWhiteSpace)
+static inline float textWidth(RenderText* text, unsigned from, unsigned len, const Font& font, float xPos, bool isFixedPitch, bool collapseWhiteSpace, TextLayout* layout = 0)
{
if (isFixedPitch || (!from && len == text->textLength()) || text->style()->hasTextCombine())
return text->width(from, len, font, xPos);
+ if (layout)
+ return Font::width(*layout, from, len);
+
TextRun run = RenderBlock::constructTextRun(text, font, text->characters() + from, len, text->style());
run.setCharactersLength(text->textLength() - from);
ASSERT(run.charactersLength() >= run.length());
@@ -2136,8 +2194,7 @@ void RenderBlock::LineBreaker::reset()
m_clear = CNONE;
}
-InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resolver, LineInfo& lineInfo,
- LineBreakIteratorInfo& lineBreakIteratorInfo, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines)
+InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resolver, LineInfo& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines)
{
reset();
@@ -2376,6 +2433,14 @@ InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resol
ASSERT(current.m_pos == t->textLength());
}
+ if (renderTextInfo.m_text != t) {
+ t->updateTextIfNeeded();
+ renderTextInfo.m_text = t;
+ renderTextInfo.m_layout = f.createLayout(t, width.currentWidth(), collapseWhiteSpace);
+ renderTextInfo.m_lineBreakIterator.reset(t->characters(), t->textLength(), style->locale());
+ }
+ TextLayout* textLayout = renderTextInfo.m_layout.get();
+
for (; current.m_pos < t->textLength(); current.fastIncrementInTextNode()) {
bool previousCharacterIsSpace = currentCharacterIsSpace;
bool previousCharacterIsWS = currentCharacterIsWS;
@@ -2397,16 +2462,11 @@ InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resol
if ((breakAll || breakWords) && !midWordBreak) {
wrapW += charWidth;
bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && current.m_pos + 1 < t->textLength() && U16_IS_TRAIL(t->characters()[current.m_pos + 1]);
- charWidth = textWidth(t, current.m_pos, midWordBreakIsBeforeSurrogatePair ? 2 : 1, f, width.committedWidth() + wrapW, isFixedPitch, collapseWhiteSpace);
+ charWidth = textWidth(t, current.m_pos, midWordBreakIsBeforeSurrogatePair ? 2 : 1, f, width.committedWidth() + wrapW, isFixedPitch, collapseWhiteSpace, textLayout);
midWordBreak = width.committedWidth() + wrapW + charWidth > width.availableWidth();
}
- if ((lineBreakIteratorInfo.first != t) || (lineBreakIteratorInfo.second.string() != t->characters())) {
- lineBreakIteratorInfo.first = t;
- lineBreakIteratorInfo.second.reset(t->characters(), t->textLength(), style->locale());
- }
-
- bool betweenWords = c == '\n' || (currWS != PRE && !atStart && isBreakable(lineBreakIteratorInfo.second, current.m_pos, current.m_nextBreakablePosition, breakNBSP)
+ bool betweenWords = c == '\n' || (currWS != PRE && !atStart && isBreakable(renderTextInfo.m_lineBreakIterator, current.m_pos, current.m_nextBreakablePosition, breakNBSP)
&& (style->hyphens() != HyphensNone || (current.previousInSameNode() != softHyphen)));
if (betweenWords || midWordBreak) {
@@ -2428,9 +2488,9 @@ InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resol
float additionalTmpW;
if (wordTrailingSpaceWidth && currentCharacterIsSpace)
- additionalTmpW = textWidth(t, lastSpace, current.m_pos + 1 - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace) - wordTrailingSpaceWidth + lastSpaceWordSpacing;
+ additionalTmpW = textWidth(t, lastSpace, current.m_pos + 1 - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, textLayout) - wordTrailingSpaceWidth + lastSpaceWordSpacing;
else
- additionalTmpW = textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace) + lastSpaceWordSpacing;
+ additionalTmpW = textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, textLayout) + lastSpaceWordSpacing;
width.addUncommittedWidth(additionalTmpW);
if (!appliedStartWidth) {
width.addUncommittedWidth(inlineLogicalWidth(current.m_obj, true, false));
@@ -2447,7 +2507,7 @@ InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resol
// as candidate width for this line.
bool lineWasTooWide = false;
if (width.fitsOnLine() && currentCharacterIsWS && currentStyle->breakOnlyAfterWhiteSpace() && !midWordBreak) {
- float charWidth = textWidth(t, current.m_pos, 1, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace) + (applyWordSpacing ? wordSpacing : 0);
+ float charWidth = textWidth(t, current.m_pos, 1, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, textLayout) + (applyWordSpacing ? wordSpacing : 0);
// Check if line is too big even without the extra space
// at the end of the line. If it is not, do nothing.
// If the line needs the extra whitespace to be too long,
@@ -2573,7 +2633,7 @@ InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resol
}
// IMPORTANT: current.m_pos is > length here!
- float additionalTmpW = ignoringSpaces ? 0 : textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace) + lastSpaceWordSpacing;
+ float additionalTmpW = ignoringSpaces ? 0 : textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, textLayout) + lastSpaceWordSpacing;
width.addUncommittedWidth(additionalTmpW + inlineLogicalWidth(current.m_obj, !appliedStartWidth, includeEndWidth));
includeEndWidth = false;
@@ -2830,7 +2890,7 @@ bool RenderBlock::positionNewFloatOnLine(FloatingObject* newFloat, FloatingObjec
return true;
}
-LayoutUnit RenderBlock::startAlignedOffsetForLine(RenderBox* child, LayoutUnit position, bool firstLine)
+LayoutUnit RenderBlock::startAlignedOffsetForLine(LayoutUnit position, bool firstLine)
{
ETextAlign textAlign = style()->textAlign();
@@ -2838,15 +2898,13 @@ LayoutUnit RenderBlock::startAlignedOffsetForLine(RenderBox* child, LayoutUnit p
return startOffsetForLine(position, firstLine);
// updateLogicalWidthForAlignment() handles the direction of the block so no need to consider it here
- float logicalLeft;
- float availableLogicalWidth;
- logicalLeft = logicalLeftOffsetForLine(logicalHeight(), false);
- availableLogicalWidth = logicalRightOffsetForLine(logicalHeight(), false) - logicalLeft;
- float totalLogicalWidth = logicalWidthForChild(child);
+ float totalLogicalWidth = 0;
+ float logicalLeft = logicalLeftOffsetForLine(logicalHeight(), false);
+ float availableLogicalWidth = logicalRightOffsetForLine(logicalHeight(), false) - logicalLeft;
updateLogicalWidthForAlignment(textAlign, 0, logicalLeft, totalLogicalWidth, availableLogicalWidth, 0);
if (!style()->isLeftToRightDirection())
- return logicalWidth() - (logicalLeft + totalLogicalWidth);
+ return logicalWidth() - logicalLeft;
return logicalLeft;
}