summaryrefslogtreecommitdiffstats
path: root/WebCore/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/rendering')
-rw-r--r--WebCore/rendering/FixedTableLayout.cpp3
-rw-r--r--WebCore/rendering/InlineFlowBox.cpp24
-rw-r--r--WebCore/rendering/InlineFlowBox.h9
-rw-r--r--WebCore/rendering/InlineTextBox.cpp44
-rw-r--r--WebCore/rendering/InlineTextBox.h15
-rw-r--r--WebCore/rendering/RenderArena.cpp12
-rw-r--r--WebCore/rendering/RenderBlock.cpp84
-rw-r--r--WebCore/rendering/RenderBlock.h4
-rw-r--r--WebCore/rendering/RenderBlockLineLayout.cpp24
-rw-r--r--WebCore/rendering/RenderBox.h1
-rw-r--r--WebCore/rendering/RenderBoxModelObject.h2
-rw-r--r--WebCore/rendering/RenderImage.cpp2
-rw-r--r--WebCore/rendering/RenderLayer.cpp105
-rw-r--r--WebCore/rendering/RenderLayerBacking.cpp36
-rw-r--r--WebCore/rendering/RenderLayerBacking.h3
-rw-r--r--WebCore/rendering/RenderLayerCompositor.cpp401
-rw-r--r--WebCore/rendering/RenderLayerCompositor.h38
-rw-r--r--WebCore/rendering/RenderLineBoxList.cpp32
-rw-r--r--WebCore/rendering/RenderMeter.cpp62
-rw-r--r--WebCore/rendering/RenderMeter.h57
-rw-r--r--WebCore/rendering/RenderObject.cpp29
-rw-r--r--WebCore/rendering/RenderObject.h3
-rw-r--r--WebCore/rendering/RenderProgress.cpp7
-rw-r--r--WebCore/rendering/RenderProgress.h7
-rw-r--r--WebCore/rendering/RenderSVGImage.cpp8
-rw-r--r--WebCore/rendering/RenderSVGResource.h2
-rw-r--r--WebCore/rendering/RenderSVGResourceClipper.cpp31
-rw-r--r--WebCore/rendering/RenderSVGResourceClipper.h4
-rw-r--r--WebCore/rendering/RenderSVGResourceFilter.cpp2
-rw-r--r--WebCore/rendering/RenderSVGResourceFilter.h2
-rw-r--r--WebCore/rendering/RenderSVGResourceGradient.h2
-rw-r--r--WebCore/rendering/RenderSVGResourceMarker.cpp3
-rw-r--r--WebCore/rendering/RenderSVGResourceMarker.h2
-rw-r--r--WebCore/rendering/RenderSVGResourceMasker.cpp74
-rw-r--r--WebCore/rendering/RenderSVGResourceMasker.h4
-rw-r--r--WebCore/rendering/RenderSVGResourcePattern.h2
-rw-r--r--WebCore/rendering/RenderSVGResourceSolidColor.h2
-rw-r--r--WebCore/rendering/RenderTextControlMultiLine.cpp2
-rw-r--r--WebCore/rendering/RenderTextControlSingleLine.cpp4
-rw-r--r--WebCore/rendering/RenderTheme.cpp75
-rw-r--r--WebCore/rendering/RenderTheme.h5
-rw-r--r--WebCore/rendering/RenderThemeChromiumWin.cpp57
-rw-r--r--WebCore/rendering/RenderThemeChromiumWin.h8
-rw-r--r--WebCore/rendering/RenderTreeAsText.cpp6
-rw-r--r--WebCore/rendering/RenderTreeAsText.h1
-rw-r--r--WebCore/rendering/RenderView.cpp13
-rw-r--r--WebCore/rendering/RenderView.h2
-rw-r--r--WebCore/rendering/RenderWidget.cpp13
-rw-r--r--WebCore/rendering/RootInlineBox.cpp6
-rw-r--r--WebCore/rendering/RootInlineBox.h2
-rw-r--r--WebCore/rendering/SVGInlineFlowBox.cpp8
-rw-r--r--WebCore/rendering/SVGInlineFlowBox.h3
-rw-r--r--WebCore/rendering/SVGInlineTextBox.cpp250
-rw-r--r--WebCore/rendering/SVGInlineTextBox.h93
-rw-r--r--WebCore/rendering/SVGRenderTreeAsText.cpp44
-rw-r--r--WebCore/rendering/SVGRootInlineBox.cpp594
-rw-r--r--WebCore/rendering/SVGRootInlineBox.h23
-rw-r--r--WebCore/rendering/SVGTextLayoutUtilities.cpp374
-rw-r--r--WebCore/rendering/SVGTextLayoutUtilities.h90
-rw-r--r--WebCore/rendering/style/FillLayer.cpp8
-rw-r--r--WebCore/rendering/style/FillLayer.h4
-rw-r--r--WebCore/rendering/style/RenderStyle.cpp25
-rw-r--r--WebCore/rendering/style/RenderStyle.h27
-rw-r--r--WebCore/rendering/style/StyleInheritedData.cpp27
-rw-r--r--WebCore/rendering/style/StyleInheritedData.h10
-rw-r--r--WebCore/rendering/style/StyleRareInheritedData.cpp23
-rw-r--r--WebCore/rendering/style/StyleRareInheritedData.h11
-rw-r--r--WebCore/rendering/style/StyleRareNonInheritedData.cpp6
-rw-r--r--WebCore/rendering/style/StyleRareNonInheritedData.h6
-rw-r--r--WebCore/rendering/style/StyleVisualData.cpp4
-rw-r--r--WebCore/rendering/style/StyleVisualData.h5
71 files changed, 1770 insertions, 1201 deletions
diff --git a/WebCore/rendering/FixedTableLayout.cpp b/WebCore/rendering/FixedTableLayout.cpp
index 09af518..4d6b88c 100644
--- a/WebCore/rendering/FixedTableLayout.cpp
+++ b/WebCore/rendering/FixedTableLayout.cpp
@@ -166,8 +166,7 @@ int FixedTableLayout::calcWidthArray(int)
int usedSpan = 0;
int i = 0;
- while (usedSpan < span) {
- ASSERT(cCol + i < nEffCols);
+ while (usedSpan < span && cCol + i < nEffCols) {
int eSpan = m_table->spanOfEffCol(cCol + i);
// Only set if no col element has already set it.
if (m_width[cCol + i].isAuto() && w.type() != Auto) {
diff --git a/WebCore/rendering/InlineFlowBox.cpp b/WebCore/rendering/InlineFlowBox.cpp
index e31bf4f..05d8fcd 100644
--- a/WebCore/rendering/InlineFlowBox.cpp
+++ b/WebCore/rendering/InlineFlowBox.cpp
@@ -252,7 +252,7 @@ void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* en
}
}
-int InlineFlowBox::placeBoxesHorizontally(int xPos, bool& needsWordSpacing)
+int InlineFlowBox::placeBoxesHorizontally(int xPos, bool& needsWordSpacing, GlyphOverflowAndFallbackFontsMap& textBoxDataMap)
{
// Set our x position.
setX(xPos);
@@ -289,7 +289,8 @@ int InlineFlowBox::placeBoxesHorizontally(int xPos, bool& needsWordSpacing)
int letterSpacing = min(0, (int)rt->style(m_firstLine)->font().letterSpacing());
rightLayoutOverflow = max(xPos + text->width() - letterSpacing, rightLayoutOverflow);
- GlyphOverflow* glyphOverflow = static_cast<InlineTextBox*>(curr)->glyphOverflow();
+ GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.find(static_cast<InlineTextBox*>(curr));
+ GlyphOverflow* glyphOverflow = it == textBoxDataMap.end() ? 0 : &it->second.second;
int leftGlyphOverflow = -strokeOverflow - (glyphOverflow ? glyphOverflow->left : 0);
int rightGlyphOverflow = strokeOverflow - letterSpacing + (glyphOverflow ? glyphOverflow->right : 0);
@@ -319,7 +320,7 @@ int InlineFlowBox::placeBoxesHorizontally(int xPos, bool& needsWordSpacing)
if (curr->renderer()->isRenderInline()) {
InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr);
xPos += flow->marginLeft();
- xPos = flow->placeBoxesHorizontally(xPos, needsWordSpacing);
+ xPos = flow->placeBoxesHorizontally(xPos, needsWordSpacing, textBoxDataMap);
xPos += flow->marginRight();
leftLayoutOverflow = min(leftLayoutOverflow, flow->leftLayoutOverflow());
rightLayoutOverflow = max(rightLayoutOverflow, flow->rightLayoutOverflow());
@@ -391,7 +392,7 @@ static int verticalPositionForBox(InlineBox* curr, bool firstLine)
}
void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom,
- int& maxAscent, int& maxDescent, bool strictMode)
+ int& maxAscent, int& maxDescent, bool strictMode, GlyphOverflowAndFallbackFontsMap& textBoxDataMap)
{
if (isRootInlineBox()) {
// Examine our root box.
@@ -416,8 +417,10 @@ void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositi
int lineHeight;
int baseline;
Vector<const SimpleFontData*>* usedFonts = 0;
- if (curr->isInlineTextBox())
- usedFonts = static_cast<InlineTextBox*>(curr)->fallbackFonts();
+ if (curr->isInlineTextBox()) {
+ GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.find(static_cast<InlineTextBox*>(curr));
+ usedFonts = it == textBoxDataMap.end() ? 0 : &it->second.first;
+ }
if (usedFonts) {
usedFonts->append(curr->renderer()->style(m_firstLine)->font().primaryFont());
@@ -468,7 +471,7 @@ void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositi
}
if (curr->isInlineFlowBox())
- static_cast<InlineFlowBox*>(curr)->computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode);
+ static_cast<InlineFlowBox*>(curr)->computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode, textBoxDataMap);
}
}
@@ -529,7 +532,7 @@ void InlineFlowBox::placeBoxesVertically(int yPos, int maxHeight, int maxAscent,
}
}
-void InlineFlowBox::computeVerticalOverflow(int lineTop, int lineBottom, bool strictMode)
+void InlineFlowBox::computeVerticalOverflow(int lineTop, int lineBottom, bool strictMode, GlyphOverflowAndFallbackFontsMap& textBoxDataMap)
{
int boxHeight = height();
@@ -566,7 +569,8 @@ void InlineFlowBox::computeVerticalOverflow(int lineTop, int lineBottom, bool st
int strokeOverflow = static_cast<int>(ceilf(rt->style()->textStrokeWidth() / 2.0f));
- GlyphOverflow* glyphOverflow = static_cast<InlineTextBox*>(curr)->glyphOverflow();
+ GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.find(static_cast<InlineTextBox*>(curr));
+ GlyphOverflow* glyphOverflow = it == textBoxDataMap.end() ? 0 : &it->second.second;
int topGlyphOverflow = -strokeOverflow - (glyphOverflow ? glyphOverflow->top : 0);
int bottomGlyphOverflow = strokeOverflow + (glyphOverflow ? glyphOverflow->bottom : 0);
@@ -582,7 +586,7 @@ void InlineFlowBox::computeVerticalOverflow(int lineTop, int lineBottom, bool st
bottomVisualOverflow = max(curr->y() + text->height() + childOverflowBottom, bottomVisualOverflow);
} else if (curr->renderer()->isRenderInline()) {
InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr);
- flow->computeVerticalOverflow(lineTop, lineBottom, strictMode);
+ flow->computeVerticalOverflow(lineTop, lineBottom, strictMode, textBoxDataMap);
topLayoutOverflow = min(topLayoutOverflow, flow->topLayoutOverflow());
bottomLayoutOverflow = max(bottomLayoutOverflow, flow->bottomLayoutOverflow());
topVisualOverflow = min(topVisualOverflow, flow->topVisualOverflow());
diff --git a/WebCore/rendering/InlineFlowBox.h b/WebCore/rendering/InlineFlowBox.h
index ecb4724..e939fb4 100644
--- a/WebCore/rendering/InlineFlowBox.h
+++ b/WebCore/rendering/InlineFlowBox.h
@@ -28,8 +28,11 @@ namespace WebCore {
class HitTestRequest;
class HitTestResult;
+class InlineTextBox;
class RenderLineBoxList;
+typedef HashMap<const InlineTextBox*, pair<Vector<const SimpleFontData*>, GlyphOverflow> > GlyphOverflowAndFallbackFontsMap;
+
class InlineFlowBox : public InlineBox {
public:
InlineFlowBox(RenderObject* obj)
@@ -124,13 +127,13 @@ public:
void determineSpacingForFlowBoxes(bool lastLine, RenderObject* endObject);
int getFlowSpacingWidth();
bool onEndChain(RenderObject* endObject);
- virtual int placeBoxesHorizontally(int x, bool& needsWordSpacing);
+ virtual int placeBoxesHorizontally(int x, bool& needsWordSpacing, GlyphOverflowAndFallbackFontsMap&);
void computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom,
- int& maxAscent, int& maxDescent, bool strictMode);
+ int& maxAscent, int& maxDescent, bool strictMode, GlyphOverflowAndFallbackFontsMap&);
void adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
int maxPositionTop, int maxPositionBottom);
void placeBoxesVertically(int y, int maxHeight, int maxAscent, bool strictMode, int& lineTop, int& lineBottom);
- void computeVerticalOverflow(int lineTop, int lineBottom, bool strictMode);
+ void computeVerticalOverflow(int lineTop, int lineBottom, bool strictMode, GlyphOverflowAndFallbackFontsMap&);
void removeChild(InlineBox* child);
diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp
index 0c5df41..292a9ac 100644
--- a/WebCore/rendering/InlineTextBox.cpp
+++ b/WebCore/rendering/InlineTextBox.cpp
@@ -1037,48 +1037,4 @@ bool InlineTextBox::containsCaretOffset(int offset) const
return true;
}
-void InlineTextBox::setFallbackFonts(const HashSet<const SimpleFontData*>& fallbackFonts)
-{
- if (!s_glyphOverflowAndFallbackFontsMap)
- s_glyphOverflowAndFallbackFontsMap = new GlyphOverflowAndFallbackFontsMap;
-
- GlyphOverflowAndFallbackFontsMap::iterator it = s_glyphOverflowAndFallbackFontsMap->add(this, make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).first;
- ASSERT(it->second.first.isEmpty());
- copyToVector(fallbackFonts, it->second.first);
-}
-
-Vector<const SimpleFontData*>* InlineTextBox::fallbackFonts() const
-{
- if (!s_glyphOverflowAndFallbackFontsMap)
- return 0;
-
- GlyphOverflowAndFallbackFontsMap::iterator it = s_glyphOverflowAndFallbackFontsMap->find(this);
- if (it == s_glyphOverflowAndFallbackFontsMap->end())
- return 0;
-
- return &it->second.first;
-}
-
-InlineTextBox::GlyphOverflowAndFallbackFontsMap* InlineTextBox::s_glyphOverflowAndFallbackFontsMap = 0;
-
-void InlineTextBox::setGlyphOverflow(const GlyphOverflow& glyphOverflow)
-{
- if (!s_glyphOverflowAndFallbackFontsMap)
- s_glyphOverflowAndFallbackFontsMap = new GlyphOverflowAndFallbackFontsMap;
-
- GlyphOverflowAndFallbackFontsMap::iterator it = s_glyphOverflowAndFallbackFontsMap->add(this, make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).first;
- it->second.second = glyphOverflow;
-}
-
-GlyphOverflow* InlineTextBox::glyphOverflow() const
-{
- if (!s_glyphOverflowAndFallbackFontsMap)
- return 0;
- GlyphOverflowAndFallbackFontsMap::iterator it = s_glyphOverflowAndFallbackFontsMap->find(this);
- if (it == s_glyphOverflowAndFallbackFontsMap->end())
- return 0;
-
- return &it->second.second;
-}
-
} // namespace WebCore
diff --git a/WebCore/rendering/InlineTextBox.h b/WebCore/rendering/InlineTextBox.h
index 2eb0c42..d03de85 100644
--- a/WebCore/rendering/InlineTextBox.h
+++ b/WebCore/rendering/InlineTextBox.h
@@ -63,18 +63,6 @@ public:
void offsetRun(int d) { m_start += d; }
- void setFallbackFonts(const HashSet<const SimpleFontData*>&);
- Vector<const SimpleFontData*>* fallbackFonts() const;
-
- void setGlyphOverflow(const GlyphOverflow&);
- GlyphOverflow* glyphOverflow() const;
-
- static void clearGlyphOverflowAndFallbackFontMap()
- {
- if (s_glyphOverflowAndFallbackFontsMap)
- s_glyphOverflowAndFallbackFontsMap->clear();
- }
-
unsigned short truncation() { return m_truncation; }
private:
@@ -138,9 +126,6 @@ private:
unsigned short m_truncation; // Where to truncate when text overflow is applied. We use special constants to
// denote no truncation (the whole run paints) and full truncation (nothing paints at all).
- typedef HashMap<const InlineTextBox*, pair<Vector<const SimpleFontData*>, GlyphOverflow> > GlyphOverflowAndFallbackFontsMap;
- static GlyphOverflowAndFallbackFontsMap* s_glyphOverflowAndFallbackFontsMap;
-
protected:
void paintCompositionBackground(GraphicsContext*, int tx, int ty, RenderStyle*, const Font&, int startPos, int endPos);
void paintDocumentMarkers(GraphicsContext*, int tx, int ty, RenderStyle*, const Font&, bool background);
diff --git a/WebCore/rendering/RenderArena.cpp b/WebCore/rendering/RenderArena.cpp
index 41f33de..57ed978 100644
--- a/WebCore/rendering/RenderArena.cpp
+++ b/WebCore/rendering/RenderArena.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Apple Computer, Inc.
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
*
* Portions are Copyright (C) 1998 Netscape Communications Corporation.
*
@@ -54,6 +55,8 @@ typedef struct {
int signature;
} RenderArenaDebugHeader;
+static const size_t debugHeaderSize = ARENA_ALIGN(sizeof(RenderArenaDebugHeader));
+
#endif
RenderArena::RenderArena(unsigned arenaSize)
@@ -75,12 +78,12 @@ void* RenderArena::allocate(size_t size)
#ifndef NDEBUG
// Use standard malloc so that memory debugging tools work.
ASSERT(this);
- void* block = ::malloc(sizeof(RenderArenaDebugHeader) + size);
+ void* block = ::malloc(debugHeaderSize + size);
RenderArenaDebugHeader* header = static_cast<RenderArenaDebugHeader*>(block);
header->arena = this;
header->size = size;
header->signature = signature;
- return header + 1;
+ return static_cast<char*>(block) + debugHeaderSize;
#else
void* result = 0;
@@ -112,12 +115,13 @@ void RenderArena::free(size_t size, void* ptr)
{
#ifndef NDEBUG
// Use standard free so that memory debugging tools work.
- RenderArenaDebugHeader* header = static_cast<RenderArenaDebugHeader*>(ptr) - 1;
+ void* block = static_cast<char*>(ptr) - debugHeaderSize;
+ RenderArenaDebugHeader* header = static_cast<RenderArenaDebugHeader*>(block);
ASSERT(header->signature == signature);
ASSERT_UNUSED(size, header->size == size);
ASSERT(header->arena == this);
header->signature = signatureDead;
- ::free(header);
+ ::free(block);
#else
// Ensure we have correct alignment for pointers. Important for Tru64
size = ROUNDUP(size, sizeof(void*));
diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp
index f8c8b8d..7b6c817 100644
--- a/WebCore/rendering/RenderBlock.cpp
+++ b/WebCore/rendering/RenderBlock.cpp
@@ -756,6 +756,8 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
int repaintTop = 0;
int repaintBottom = 0;
int maxFloatBottom = 0;
+ if (!firstChild())
+ setChildrenInline(true);
if (childrenInline())
layoutInlineChildren(relayoutChildren, repaintTop, repaintBottom);
else
@@ -992,11 +994,13 @@ bool RenderBlock::handleRunInChild(RenderBox* child)
// Move the nodes from the old child to the new child, but skip any :before/:after content. It has already
// been regenerated by the new inline.
- for (RenderObject* runInChild = blockRunIn->firstChild(); runInChild; runInChild = runInChild->nextSibling()) {
+ for (RenderObject* runInChild = blockRunIn->firstChild(); runInChild;) {
+ RenderObject* nextSibling = runInChild->nextSibling();
if (runInIsGenerated || (runInChild->style()->styleType() != BEFORE && runInChild->style()->styleType() != AFTER)) {
blockRunIn->children()->removeChildNode(blockRunIn, runInChild, false);
inlineRunIn->addChild(runInChild); // Use addChild instead of appendChildNode since it handles correct placement of the children relative to :after-generated content.
}
+ runInChild = nextSibling;
}
// Now insert the new child under |currBlock|.
@@ -1167,9 +1171,8 @@ int RenderBlock::estimateVerticalPosition(RenderBox* child, const MarginInfo& ma
void RenderBlock::determineHorizontalPosition(RenderBox* child)
{
+ int xPos = borderLeft() + paddingLeft();
if (style()->direction() == LTR) {
- int xPos = borderLeft() + paddingLeft();
-
// Add in our left margin.
int chPos = xPos + child->marginLeft();
@@ -1195,7 +1198,7 @@ void RenderBlock::determineHorizontalPosition(RenderBox* child)
view()->addLayoutDelta(IntSize(child->x() - chPos, 0));
child->setLocation(chPos, child->y());
} else {
- int xPos = width() - borderRight() - paddingRight() - verticalScrollbarWidth();
+ xPos += availableWidth();
int chPos = xPos - (child->width() + child->marginRight());
if (child->avoidsFloats()) {
int rightOff = rightOffset(height(), false);
@@ -1579,13 +1582,12 @@ void RenderBlock::paintColumnRules(PaintInfo& paintInfo, int tx, int ty)
return;
// We need to do multiple passes, breaking up our child painting into strips.
- int currXOffset = 0;
- int ruleAdd = borderLeft() + paddingLeft();
- int ruleX = 0;
Vector<IntRect>* colRects = columnRects();
unsigned colCount = colRects->size();
+ int currXOffset = style()->direction() == LTR ? 0 : contentWidth();
+ int ruleAdd = borderLeft() + paddingLeft();
+ int ruleX = style()->direction() == LTR ? 0 : contentWidth();
for (unsigned i = 0; i < colCount; i++) {
- // For each rect, we clip to the rect, and then we adjust our coords.
IntRect colRect = colRects->at(i);
// Move to the next position.
@@ -1615,11 +1617,13 @@ void RenderBlock::paintColumnContents(PaintInfo& paintInfo, int tx, int ty, bool
{
// We need to do multiple passes, breaking up our child painting into strips.
GraphicsContext* context = paintInfo.context;
- int currXOffset = 0;
- int currYOffset = 0;
int colGap = columnGap();
Vector<IntRect>* colRects = columnRects();
unsigned colCount = colRects->size();
+ if (!colCount)
+ return;
+ int currXOffset = style()->direction() == LTR ? 0 : contentWidth() - colRects->at(0).width();
+ int currYOffset = 0;
for (unsigned i = 0; i < colCount; i++) {
// For each rect, we clip to the rect, and then we adjust our coords.
IntRect colRect = colRects->at(i);
@@ -3356,12 +3360,16 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
}
// Hit test contents if we don't have columns.
- if (!hasColumns() && hitTestContents(request, result, _x, _y, scrolledX, scrolledY, hitTestAction))
+ if (!hasColumns() && hitTestContents(request, result, _x, _y, scrolledX, scrolledY, hitTestAction)) {
+ updateHitTestResult(result, IntPoint(_x - tx, _y - ty));
return true;
-
+ }
+
// Hit test our columns if we do have them.
- if (hasColumns() && hitTestColumns(request, result, _x, _y, scrolledX, scrolledY, hitTestAction))
+ if (hasColumns() && hitTestColumns(request, result, _x, _y, scrolledX, scrolledY, hitTestAction)) {
+ updateHitTestResult(result, IntPoint(_x - tx, _y - ty));
return true;
+ }
// Hit test floats.
if (hitTestAction == HitTestFloat && m_floatingObjects) {
@@ -3414,11 +3422,14 @@ bool RenderBlock::hitTestColumns(const HitTestRequest& request, HitTestResult& r
// We need to do multiple passes, breaking up our hit testing into strips.
// We can always go left to right, since column contents are clipped (meaning that there
// can't be any overlap).
- int currXOffset = 0;
+ Vector<IntRect>* colRects = columnRects();
+ unsigned colCount = colRects->size();
+ if (!colCount)
+ return false;
+ int currXOffset = style()->direction() == LTR ? 0 : contentWidth() - colRects->at(0).width();
int currYOffset = 0;
int colGap = columnGap();
- Vector<IntRect>* colRects = columnRects();
- for (unsigned i = 0; i < colRects->size(); i++) {
+ for (unsigned i = 0; i < colCount; i++) {
IntRect colRect = colRects->at(i);
colRect.move(tx, ty);
@@ -3456,20 +3467,16 @@ bool RenderBlock::hitTestContents(const HitTestRequest& request, HitTestResult&
{
if (childrenInline() && !isTable()) {
// We have to hit-test our line boxes.
- if (m_lineBoxes.hitTest(this, request, result, x, y, tx, ty, hitTestAction)) {
- updateHitTestResult(result, IntPoint(x - tx, y - ty));
+ if (m_lineBoxes.hitTest(this, request, result, x, y, tx, ty, hitTestAction))
return true;
- }
} else {
// Hit test our children.
HitTestAction childHitTest = hitTestAction;
if (hitTestAction == HitTestChildBlockBackgrounds)
childHitTest = HitTestChildBlockBackground;
for (RenderBox* child = lastChildBox(); child; child = child->previousSiblingBox()) {
- if (!child->hasSelfPaintingLayer() && !child->isFloating() && child->nodeAtPoint(request, result, x, y, tx, ty, childHitTest)) {
- updateHitTestResult(result, IntPoint(x - tx, y - ty));
+ if (!child->hasSelfPaintingLayer() && !child->isFloating() && child->nodeAtPoint(request, result, x, y, tx, ty, childHitTest))
return true;
- }
}
}
@@ -3824,7 +3831,7 @@ int RenderBlock::layoutColumns(int endOfContent, int requestedColumnHeight)
int truncationPoint = visibleTopOfHighestFloatExtendingBelow(currY + colHeight, colHeight);
// For the simulated paint, we pretend like everything is in one long strip.
- IntRect pageRect(left, currY, desiredColumnWidth, truncationPoint - currY);
+ IntRect pageRect(left, currY, contentWidth(), truncationPoint - currY);
v->setPrintRect(pageRect);
v->setTruncatedAt(truncationPoint);
GraphicsContext context((PlatformGraphicsContext*)0);
@@ -3952,10 +3959,13 @@ void RenderBlock::adjustRectForColumns(IntRect& r) const
IntRect result;
// Determine which columns we intersect.
- int currXOffset = 0;
+ unsigned colCount = colRects->size();
+ if (!colCount)
+ return;
+ int currXOffset = style()->direction() == LTR ? 0 : contentWidth() - colRects->at(0).width();
int currYOffset = 0;
int colGap = columnGap();
- for (unsigned i = 0; i < colRects->size(); i++) {
+ for (unsigned i = 0; i < colCount; i++) {
IntRect colRect = colRects->at(i);
IntRect repaintRect = r;
@@ -3982,12 +3992,11 @@ void RenderBlock::adjustForColumns(IntSize& offset, const IntPoint& point) const
if (!hasColumns())
return;
- // FIXME: This is incorrect for right-to-left columns.
-
Vector<IntRect>& columnRects = *this->columnRects();
int gapWidth = columnGap();
- int xOffset = 0;
+
+ int xOffset = style()->direction() == LTR ? 0 : contentWidth() - columnRects[0].width();
int yOffset = 0;
size_t columnCount = columnRects.size();
for (size_t i = 0; i < columnCount; ++i) {
@@ -3997,7 +4006,10 @@ void RenderBlock::adjustForColumns(IntSize& offset, const IntPoint& point) const
return;
}
- xOffset += columnRect.width() + gapWidth;
+ if (style()->direction() == LTR)
+ xOffset += columnRect.width() + gapWidth;
+ else
+ xOffset -= columnRect.width() + gapWidth;
yOffset += columnRect.height();
}
}
@@ -4704,10 +4716,12 @@ void RenderBlock::updateFirstLetter()
// Drill into inlines looking for our first text child.
RenderObject* currChild = firstLetterBlock->firstChild();
- while (currChild && currChild->needsLayout() && ((!currChild->isReplaced() && !currChild->isRenderButton() && !currChild->isMenuList()) || currChild->isFloatingOrPositioned()) && !currChild->isText()) {
+ while (currChild && ((!currChild->isReplaced() && !currChild->isRenderButton() && !currChild->isMenuList()) || currChild->isFloatingOrPositioned()) && !currChild->isText()) {
if (currChild->isFloatingOrPositioned()) {
- if (currChild->style()->styleType() == FIRST_LETTER)
+ if (currChild->style()->styleType() == FIRST_LETTER) {
+ currChild = currChild->firstChild();
break;
+ }
currChild = currChild->nextSibling();
} else
currChild = currChild->firstChild();
@@ -4724,11 +4738,11 @@ void RenderBlock::updateFirstLetter()
// If the child already has style, then it has already been created, so we just want
// to update it.
- if (currChild->style()->styleType() == FIRST_LETTER) {
+ if (firstLetterContainer->style()->styleType() == FIRST_LETTER) {
RenderStyle* pseudo = firstLetterBlock->getCachedPseudoStyle(FIRST_LETTER,
- firstLetterContainer->firstLineStyle());
- currChild->setStyle(pseudo);
- for (RenderObject* genChild = currChild->firstChild(); genChild; genChild = genChild->nextSibling()) {
+ firstLetterContainer->parent()->firstLineStyle());
+ firstLetterContainer->setStyle(pseudo);
+ for (RenderObject* genChild = firstLetterContainer->firstChild(); genChild; genChild = genChild->nextSibling()) {
if (genChild->isText())
genChild->setStyle(pseudo);
}
diff --git a/WebCore/rendering/RenderBlock.h b/WebCore/rendering/RenderBlock.h
index 751a1df..b54f66d 100644
--- a/WebCore/rendering/RenderBlock.h
+++ b/WebCore/rendering/RenderBlock.h
@@ -264,8 +264,8 @@ private:
InlineIterator findNextLineBreak(InlineBidiResolver&, bool firstLine, bool& isLineEmpty, bool& previousLineBrokeCleanly, EClear* clear = 0);
RootInlineBox* constructLine(unsigned runCount, BidiRun* firstRun, BidiRun* lastRun, bool firstLine, bool lastLine, RenderObject* endObject);
InlineFlowBox* createLineBoxes(RenderObject*, bool firstLine);
- void computeHorizontalPositionsForLine(RootInlineBox*, bool firstLine, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd);
- void computeVerticalPositionsForLine(RootInlineBox*, BidiRun*);
+ void computeHorizontalPositionsForLine(RootInlineBox*, bool firstLine, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&);
+ void computeVerticalPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&);
void deleteEllipsisLineBoxes();
void checkLinesForTextOverflow();
void addOverflowFromInlineChildren();
diff --git a/WebCore/rendering/RenderBlockLineLayout.cpp b/WebCore/rendering/RenderBlockLineLayout.cpp
index 895db66..ec138b9 100644
--- a/WebCore/rendering/RenderBlockLineLayout.cpp
+++ b/WebCore/rendering/RenderBlockLineLayout.cpp
@@ -317,7 +317,7 @@ RootInlineBox* RenderBlock::constructLine(unsigned runCount, BidiRun* firstRun,
return lastRootBox();
}
-void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, bool firstLine, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd)
+void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, bool firstLine, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap& textBoxDataMap)
{
// First determine our total width.
int availableWidth = lineWidth(height(), firstLine);
@@ -357,7 +357,9 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, bool
#endif
) {
ASSERT(r->m_box->isText());
- static_cast<InlineTextBox*>(r->m_box)->setFallbackFonts(fallbackFonts);
+ GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(static_cast<InlineTextBox*>(r->m_box), make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).first;
+ ASSERT(it->second.first.isEmpty());
+ copyToVector(fallbackFonts, it->second.first);
}
if ((glyphOverflow.top || glyphOverflow.bottom || glyphOverflow.left || glyphOverflow.right)
#if ENABLE(SVG)
@@ -365,7 +367,8 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, bool
#endif
) {
ASSERT(r->m_box->isText());
- static_cast<InlineTextBox*>(r->m_box)->setGlyphOverflow(glyphOverflow);
+ GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(static_cast<InlineTextBox*>(r->m_box), make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).first;
+ it->second.second = glyphOverflow;
}
} else if (!r->m_object->isRenderInline()) {
RenderBox* renderBox = toRenderBox(r->m_object);
@@ -482,12 +485,12 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, bool
// The widths of all runs are now known. We can now place every inline box (and
// compute accurate widths for the inline flow boxes).
needsWordSpacing = false;
- lineBox->placeBoxesHorizontally(x, needsWordSpacing);
+ lineBox->placeBoxesHorizontally(x, needsWordSpacing, textBoxDataMap);
}
-void RenderBlock::computeVerticalPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun)
+void RenderBlock::computeVerticalPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap)
{
- setHeight(lineBox->verticallyAlignBoxes(height()));
+ setHeight(lineBox->verticallyAlignBoxes(height(), textBoxDataMap));
lineBox->setBlockHeight(height());
// Now make sure we place replaced render objects correctly.
@@ -846,11 +849,11 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
lineBox->setEndsWithBreak(previousLineBrokeCleanly);
// Now we position all of our text runs horizontally.
- computeHorizontalPositionsForLine(lineBox, firstLine, resolver.firstRun(), trailingSpaceRun, end.atEnd());
+ GlyphOverflowAndFallbackFontsMap textBoxDataMap;
+ computeHorizontalPositionsForLine(lineBox, firstLine, resolver.firstRun(), trailingSpaceRun, end.atEnd(), textBoxDataMap);
// Now position our text runs vertically.
- computeVerticalPositionsForLine(lineBox, resolver.firstRun());
- InlineTextBox::clearGlyphOverflowAndFallbackFontMap();
+ computeVerticalPositionsForLine(lineBox, resolver.firstRun(), textBoxDataMap);
#if ENABLE(SVG)
// Special SVG text layout code
@@ -946,7 +949,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
TrailingFloatsRootInlineBox* trailingFloatsLineBox = new (renderArena()) TrailingFloatsRootInlineBox(this);
m_lineBoxes.appendLineBox(trailingFloatsLineBox);
trailingFloatsLineBox->setConstructed();
- trailingFloatsLineBox->verticallyAlignBoxes(height());
+ GlyphOverflowAndFallbackFontsMap textBoxDataMap;
+ trailingFloatsLineBox->verticallyAlignBoxes(height(), textBoxDataMap);
trailingFloatsLineBox->setVerticalOverflowPositions(height(), bottomLayoutOverflow, height(), bottomVisualOverflow, 0);
trailingFloatsLineBox->setBlockHeight(height());
}
diff --git a/WebCore/rendering/RenderBox.h b/WebCore/rendering/RenderBox.h
index 1c766aa..c033275 100644
--- a/WebCore/rendering/RenderBox.h
+++ b/WebCore/rendering/RenderBox.h
@@ -51,6 +51,7 @@ public:
void setHeight(int height) { m_frameRect.setHeight(height); }
IntPoint location() const { return m_frameRect.location(); }
+ IntSize locationOffset() const { return IntSize(x(), y()); }
IntSize size() const { return m_frameRect.size(); }
void setLocation(const IntPoint& location) { m_frameRect.setLocation(location); }
diff --git a/WebCore/rendering/RenderBoxModelObject.h b/WebCore/rendering/RenderBoxModelObject.h
index a4cf54a..62f1009 100644
--- a/WebCore/rendering/RenderBoxModelObject.h
+++ b/WebCore/rendering/RenderBoxModelObject.h
@@ -59,7 +59,7 @@ public:
bool hasSelfPaintingLayer() const;
RenderLayer* layer() const { return m_layer; }
- virtual bool requiresLayer() const { return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasMask() || hasReflection(); }
+ virtual bool requiresLayer() const { return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasMask() || hasReflection() || style()->specifiesColumns(); }
// This will work on inlines to return the bounding box of all of the lines' border boxes.
virtual IntRect borderBoundingBox() const = 0;
diff --git a/WebCore/rendering/RenderImage.cpp b/WebCore/rendering/RenderImage.cpp
index 237dfb6..6fd38a6 100644
--- a/WebCore/rendering/RenderImage.cpp
+++ b/WebCore/rendering/RenderImage.cpp
@@ -508,7 +508,7 @@ int RenderImage::minimumReplacedHeight() const
HTMLMapElement* RenderImage::imageMap() const
{
HTMLImageElement* i = node() && node()->hasTagName(imgTag) ? static_cast<HTMLImageElement*>(node()) : 0;
- return i ? i->document()->getImageMap(i->getAttribute(usemapAttr)) : 0;
+ return i ? i->document()->getImageMap(i->fastGetAttribute(usemapAttr)) : 0;
}
bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp
index 37dbd38..80e334a 100644
--- a/WebCore/rendering/RenderLayer.cpp
+++ b/WebCore/rendering/RenderLayer.cpp
@@ -587,14 +587,32 @@ bool RenderLayer::update3DTransformedDescendantStatus()
void RenderLayer::updateLayerPosition()
{
- // Clear our cached clip rect information.
- clearClipRects();
+ IntPoint localPoint;
+ IntSize inlineBoundingBoxOffset; // We don't put this into the RenderLayer x/y for inlines, so we need to subtract it out when done.
+ if (renderer()->isRenderInline()) {
+ RenderInline* inlineFlow = toRenderInline(renderer());
+ IntRect lineBox = inlineFlow->linesBoundingBox();
+ setWidth(lineBox.width());
+ setHeight(lineBox.height());
+ inlineBoundingBoxOffset = IntSize(lineBox.x(), lineBox.y());
+ localPoint += inlineBoundingBoxOffset;
+ } else if (RenderBox* box = renderBox()) {
+ setWidth(box->width());
+ setHeight(box->height());
- RenderBox* rendererBox = renderBox();
-
- int x = rendererBox ? rendererBox->x() : 0;
- int y = rendererBox ? rendererBox->y() : 0;
+ if (!box->hasOverflowClip()) {
+ if (box->rightLayoutOverflow() > box->width())
+ setWidth(box->rightLayoutOverflow());
+ if (box->bottomLayoutOverflow() > box->height())
+ setHeight(box->bottomLayoutOverflow());
+ }
+
+ localPoint += box->locationOffset();
+ }
+ // Clear our cached clip rect information.
+ clearClipRects();
+
if (!renderer()->isPositioned() && renderer()->parent()) {
// We must adjust our position by walking up the render tree looking for the
// nearest enclosing object with a layer.
@@ -603,26 +621,15 @@ void RenderLayer::updateLayerPosition()
if (curr->isBox() && !curr->isTableRow()) {
// Rows and cells share the same coordinate space (that of the section).
// Omit them when computing our xpos/ypos.
- RenderBox* currBox = toRenderBox(curr);
- x += currBox->x();
- y += currBox->y();
+ localPoint += toRenderBox(curr)->locationOffset();
}
curr = curr->parent();
}
if (curr->isBox() && curr->isTableRow()) {
// Put ourselves into the row coordinate space.
- RenderBox* currBox = toRenderBox(curr);
- x -= currBox->x();
- y -= currBox->y();
+ localPoint -= toRenderBox(curr)->locationOffset();
}
}
-
- m_relX = m_relY = 0;
- if (renderer()->isRelPositioned()) {
- m_relX = renderer()->relativePositionOffsetX();
- m_relY = renderer()->relativePositionOffsetY();
- x += m_relX; y += m_relY;
- }
// Subtract our parent's scroll offset.
if (renderer()->isPositioned() && enclosingPositionedAncestor()) {
@@ -630,40 +637,31 @@ void RenderLayer::updateLayerPosition()
// For positioned layers, we subtract out the enclosing positioned layer's scroll offset.
IntSize offset = positionedParent->scrolledContentOffset();
- x -= offset.width();
- y -= offset.height();
+ localPoint -= offset;
if (renderer()->isPositioned() && positionedParent->renderer()->isRelPositioned() && positionedParent->renderer()->isRenderInline()) {
IntSize offset = toRenderInline(positionedParent->renderer())->relativePositionedInlineOffset(toRenderBox(renderer()));
- x += offset.width();
- y += offset.height();
+ localPoint += offset;
}
} else if (parent()) {
- IntSize offset = parent()->scrolledContentOffset();
- x -= offset.width();
- y -= offset.height();
+ IntSize columnOffset;
+ parent()->renderer()->adjustForColumns(columnOffset, localPoint);
+ localPoint += columnOffset;
+
+ IntSize scrollOffset = parent()->scrolledContentOffset();
+ localPoint -= scrollOffset;
}
-
- // FIXME: We'd really like to just get rid of the concept of a layer rectangle and rely on the renderers.
-
- setLocation(x, y);
-
- if (renderer()->isRenderInline()) {
- RenderInline* inlineFlow = toRenderInline(renderer());
- IntRect lineBox = inlineFlow->linesBoundingBox();
- setWidth(lineBox.width());
- setHeight(lineBox.height());
- } else if (RenderBox* box = renderBox()) {
- setWidth(box->width());
- setHeight(box->height());
-
- if (!box->hasOverflowClip()) {
- if (box->rightLayoutOverflow() > box->width())
- setWidth(box->rightLayoutOverflow());
- if (box->bottomLayoutOverflow() > box->height())
- setHeight(box->bottomLayoutOverflow());
- }
+
+ m_relX = m_relY = 0;
+ if (renderer()->isRelPositioned()) {
+ m_relX = renderer()->relativePositionOffsetX();
+ m_relY = renderer()->relativePositionOffsetY();
+ localPoint.move(m_relX, m_relY);
}
+
+ // FIXME: We'd really like to just get rid of the concept of a layer rectangle and rely on the renderers.
+ localPoint -= inlineBoundingBoxOffset;
+ setLocation(localPoint.x(), localPoint.y());
}
TransformationMatrix RenderLayer::perspectiveTransform() const
@@ -1158,7 +1156,7 @@ RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& xPos, i
return;
parentLayer->convertToLayerCoords(ancestorLayer, xPos, yPos);
-
+
xPos += x();
yPos += y();
}
@@ -3507,16 +3505,17 @@ void RenderLayer::repaintIncludingNonCompositingDescendants(RenderBoxModelObject
bool RenderLayer::shouldBeNormalFlowOnly() const
{
- return (renderer()->hasOverflowClip() || renderer()->hasReflection() || renderer()->hasMask() || renderer()->isVideo() || renderer()->isEmbeddedObject()) &&
- !renderer()->isPositioned() &&
- !renderer()->isRelPositioned() &&
- !renderer()->hasTransform() &&
- !isTransparent();
+ return (renderer()->hasOverflowClip() || renderer()->hasReflection() || renderer()->hasMask() || renderer()->isVideo() || renderer()->isEmbeddedObject() ||
+ renderer()->isRenderIFrame() || renderer()->style()->specifiesColumns())
+ && !renderer()->isPositioned()
+ && !renderer()->isRelPositioned()
+ && !renderer()->hasTransform()
+ && !isTransparent();
}
bool RenderLayer::isSelfPaintingLayer() const
{
- return !isNormalFlowOnly() || renderer()->hasReflection() || renderer()->hasMask() || renderer()->isTableRow() || renderer()->isVideo() || renderer()->isEmbeddedObject();
+ return !isNormalFlowOnly() || renderer()->hasReflection() || renderer()->hasMask() || renderer()->isTableRow() || renderer()->isVideo() || renderer()->isEmbeddedObject() || renderer()->isRenderIFrame();
}
void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle*)
diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp
index b857420..4957265 100644
--- a/WebCore/rendering/RenderLayerBacking.cpp
+++ b/WebCore/rendering/RenderLayerBacking.cpp
@@ -45,6 +45,7 @@
#include "KeyframeList.h"
#include "PluginWidget.h"
#include "RenderBox.h"
+#include "RenderIFrame.h"
#include "RenderImage.h"
#include "RenderLayerCompositor.h"
#include "RenderEmbeddedObject.h"
@@ -232,6 +233,9 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration()
}
#endif
+ if (renderer()->isRenderIFrame())
+ layerConfigChanged = RenderLayerCompositor::parentIFrameContentLayers(toRenderIFrame(renderer()));
+
return layerConfigChanged;
}
@@ -384,25 +388,13 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
}
m_graphicsLayer->setContentsRect(contentsBox());
- m_graphicsLayer->setDrawsContent(containsPaintedContent());
+ updateDrawsContent();
// If this is an iframe parent, update the iframe content's box
- RenderLayerCompositor* innerCompositor = innerRenderLayerCompositor();
- if (innerCompositor)
- innerCompositor->setRootPlatformLayerClippingBox(contentsBox());
-}
-
-RenderLayerCompositor* RenderLayerBacking::innerRenderLayerCompositor() const
-{
if (renderer()->isRenderIFrame()) {
- HTMLIFrameElement* element = static_cast<HTMLIFrameElement*>(renderer()->node());
- if (Document* contentDocument = element->contentDocument()) {
- if (RenderView* view = contentDocument->renderView())
- return view->compositor();
- }
+ if (RenderLayerCompositor* innerCompositor = RenderLayerCompositor::iframeContentsCompositor(toRenderIFrame(renderer())))
+ innerCompositor->updateContentLayerOffset(contentsBox().location());
}
-
- return 0;
}
void RenderLayerBacking::updateInternalHierarchy()
@@ -421,6 +413,11 @@ void RenderLayerBacking::updateInternalHierarchy()
}
}
+void RenderLayerBacking::updateDrawsContent()
+{
+ m_graphicsLayer->setDrawsContent(containsPaintedContent());
+}
+
// Return true if the layers changed.
bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip)
{
@@ -842,11 +839,10 @@ FloatPoint RenderLayerBacking::contentsToGraphicsLayerCoordinates(const Graphics
bool RenderLayerBacking::paintingGoesToWindow() const
{
- if (!m_owningLayer->isRootLayer())
- return false;
-
- // Iframe root layers paint into backing store.
- return !toRenderView(renderer())->document()->ownerElement();
+ if (m_owningLayer->isRootLayer())
+ return compositor()->rootLayerAttachment() == RenderLayerCompositor::RootLayerAttachedViaChromeClient;
+
+ return false;
}
void RenderLayerBacking::setContentsNeedDisplay()
diff --git a/WebCore/rendering/RenderLayerBacking.h b/WebCore/rendering/RenderLayerBacking.h
index 8e0ee23..ff8c76c 100644
--- a/WebCore/rendering/RenderLayerBacking.h
+++ b/WebCore/rendering/RenderLayerBacking.h
@@ -62,6 +62,7 @@ public:
void updateGraphicsLayerGeometry(); // make private
// Update contents and clipping structure.
void updateInternalHierarchy(); // make private
+ void updateDrawsContent();
GraphicsLayer* graphicsLayer() const { return m_graphicsLayer.get(); }
@@ -124,8 +125,6 @@ public:
IntRect contentsBox() const;
- RenderLayerCompositor* innerRenderLayerCompositor() const;
-
private:
void createGraphicsLayer();
void destroyGraphicsLayer();
diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp
index e96e375..ff6e3b2 100644
--- a/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/WebCore/rendering/RenderLayerCompositor.cpp
@@ -42,6 +42,7 @@
#include "HTMLMediaElement.h"
#include "HTMLNames.h"
#endif
+#include "NodeList.h"
#include "Page.h"
#include "RenderEmbeddedObject.h"
#include "RenderIFrame.h"
@@ -99,8 +100,8 @@ RenderLayerCompositor::RenderLayerCompositor(RenderView* renderView)
, m_showRepaintCounter(false)
, m_compositingConsultsOverlap(true)
, m_compositing(false)
- , m_rootLayerAttached(false)
, m_compositingLayersNeedRebuild(false)
+ , m_rootLayerAttachment(RootLayerUnattached)
#if PROFILE_LAYER_REBUILD
, m_rootLayerUpdateCount(0)
#endif // PROFILE_LAYER_REBUILD
@@ -109,7 +110,7 @@ RenderLayerCompositor::RenderLayerCompositor(RenderView* renderView)
RenderLayerCompositor::~RenderLayerCompositor()
{
- ASSERT(!m_rootLayerAttached);
+ ASSERT(m_rootLayerAttachment == RootLayerUnattached);
}
void RenderLayerCompositor::enableCompositingMode(bool enable /* = true */)
@@ -117,20 +118,11 @@ void RenderLayerCompositor::enableCompositingMode(bool enable /* = true */)
if (enable != m_compositing) {
m_compositing = enable;
- // We never go out of compositing mode for a given page,
- // but if all the layers disappear, we'll just be left with
- // the empty root layer, which has minimal overhead.
- if (m_compositing)
+ if (m_compositing) {
ensureRootPlatformLayer();
- else
+ notifyIFramesOfCompositingChange();
+ } else
destroyRootPlatformLayer();
-
- if (shouldPropagateCompositingToIFrameParent()) {
- if (Element* ownerElement = m_renderView->document()->ownerElement()) {
- // Trigger a recalcStyle in the parent document, to update compositing in that document.
- ownerElement->setNeedsStyleRecalc(SyntheticStyleChange);
- }
- }
}
}
@@ -237,10 +229,9 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
// Host the document layer in the RenderView's root layer.
if (updateRoot == rootRenderLayer()) {
- if (childList.isEmpty()) {
- willMoveOffscreen();
- m_rootPlatformLayer = 0;
- } else
+ if (childList.isEmpty())
+ destroyRootPlatformLayer();
+ else
m_rootPlatformLayer->setChildren(childList);
}
} else if (needGeometryUpdate) {
@@ -314,6 +305,13 @@ bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeR
video->acceleratedRenderingStateChanged();
}
#endif
+
+ if (layerChanged && layer->renderer()->isRenderIFrame()) {
+ RenderLayerCompositor* innerCompositor = iframeContentsCompositor(toRenderIFrame(layer->renderer()));
+ if (innerCompositor && innerCompositor->inCompositingMode())
+ innerCompositor->updateRootLayerAttachment();
+ }
+
return layerChanged;
}
@@ -332,7 +330,7 @@ bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer, Comp
void RenderLayerCompositor::repaintOnCompositingChange(RenderLayer* layer)
{
// If the renderer is not attached yet, no need to repaint.
- if (!layer->renderer()->parent())
+ if (layer->renderer() != m_renderView && !layer->renderer()->parent())
return;
RenderBoxModelObject* repaintContainer = layer->renderer()->containerForRepaint();
@@ -355,8 +353,21 @@ IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* laye
if (!canBeComposited(layer))
return IntRect();
- IntRect boundingBoxRect, unionBounds;
- boundingBoxRect = unionBounds = layer->localBoundingBox();
+ IntRect boundingBoxRect = layer->localBoundingBox();
+ if (layer->renderer()->isRoot()) {
+ // If the root layer becomes composited (e.g. because some descendant with negative z-index is composited),
+ // then it has to be big enough to cover the viewport in order to display the background. This is akin
+ // to the code in RenderBox::paintRootBoxDecorations().
+ if (m_renderView->frameView()) {
+ int rw = m_renderView->frameView()->contentsWidth();
+ int rh = m_renderView->frameView()->contentsHeight();
+
+ boundingBoxRect.setWidth(max(boundingBoxRect.width(), rw - boundingBoxRect.x()));
+ boundingBoxRect.setHeight(max(boundingBoxRect.height(), rh - boundingBoxRect.y()));
+ }
+ }
+
+ IntRect unionBounds = boundingBoxRect;
if (layer->renderer()->hasOverflowClip() || layer->renderer()->hasMask()) {
int ancestorRelX = 0, ancestorRelY = 0;
@@ -795,30 +806,65 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, cons
}
if (layerBacking) {
- if (shouldPropagateCompositingToIFrameParent() && layer->renderer()->isRenderIFrame()) {
- // This is an iframe parent. Make it the parent of the iframe document's root
- layerBacking->parentForSublayers()->removeAllChildren();
-
- RenderLayerCompositor* innerCompositor = layerBacking->innerRenderLayerCompositor();
- if (innerCompositor) {
- GraphicsLayer* innerRootLayer = innerCompositor->rootPlatformLayer();
- if (innerRootLayer)
- layerBacking->parentForSublayers()->addChild(innerRootLayer);
- }
- } else
+ bool parented = false;
+ if (layer->renderer()->isRenderIFrame())
+ parented = parentIFrameContentLayers(toRenderIFrame(layer->renderer()));
+
+ if (!parented)
layerBacking->parentForSublayers()->setChildren(layerChildren);
+
childLayersOfEnclosingLayer.append(layerBacking->childForSuperlayers());
}
}
-void RenderLayerCompositor::setRootPlatformLayerClippingBox(const IntRect& contentsBox)
+void RenderLayerCompositor::updateContentLayerOffset(const IntPoint& contentsOffset)
{
- if (m_clippingLayer) {
- m_clippingLayer->setPosition(FloatPoint(contentsBox.x(), contentsBox.y()));
- m_clippingLayer->setSize(FloatSize(contentsBox.width(), contentsBox.height()));
+ if (m_clipLayer) {
+ FrameView* frameView = m_renderView->frameView();
+ m_clipLayer->setPosition(contentsOffset);
+ m_clipLayer->setSize(FloatSize(frameView->layoutWidth(), frameView->layoutHeight()));
+
+ IntPoint scrollPosition = frameView->scrollPosition();
+ m_scrollLayer->setPosition(FloatPoint(-scrollPosition.x(), -scrollPosition.y()));
}
}
+void RenderLayerCompositor::updateContentLayerScrollPosition(const IntPoint& scrollPosition)
+{
+ if (m_scrollLayer)
+ m_scrollLayer->setPosition(FloatPoint(-scrollPosition.x(), -scrollPosition.y()));
+}
+
+RenderLayerCompositor* RenderLayerCompositor::iframeContentsCompositor(RenderIFrame* renderer)
+{
+ HTMLIFrameElement* element = static_cast<HTMLIFrameElement*>(renderer->node());
+ if (Document* contentDocument = element->contentDocument()) {
+ if (RenderView* view = contentDocument->renderView())
+ return view->compositor();
+ }
+ return 0;
+}
+
+bool RenderLayerCompositor::parentIFrameContentLayers(RenderIFrame* renderer)
+{
+ RenderLayerCompositor* innerCompositor = iframeContentsCompositor(renderer);
+ if (!innerCompositor || !innerCompositor->inCompositingMode() || innerCompositor->rootLayerAttachment() != RootLayerAttachedViaEnclosingIframe)
+ return false;
+
+ RenderLayer* layer = renderer->layer();
+ if (!layer->isComposited())
+ return false;
+
+ RenderLayerBacking* backing = layer->backing();
+ GraphicsLayer* hostingLayer = backing->parentForSublayers();
+ GraphicsLayer* rootLayer = innerCompositor->rootPlatformLayer();
+ if (hostingLayer->children().size() != 1 || hostingLayer->children()[0] != rootLayer) {
+ hostingLayer->removeAllChildren();
+ hostingLayer->addChild(rootLayer);
+ }
+ return true;
+}
+
// This just updates layer geometry without changing the hierarchy.
void RenderLayerCompositor::updateLayerTreeGeometry(RenderLayer* layer)
{
@@ -972,82 +1018,32 @@ RenderLayer* RenderLayerCompositor::rootRenderLayer() const
GraphicsLayer* RenderLayerCompositor::rootPlatformLayer() const
{
- return m_clippingLayer ? m_clippingLayer.get() : m_rootPlatformLayer.get();
+ return m_clipLayer ? m_clipLayer.get() : m_rootPlatformLayer.get();
}
void RenderLayerCompositor::didMoveOnscreen()
{
- if (!m_rootPlatformLayer)
+ if (!inCompositingMode() || m_rootLayerAttachment != RootLayerUnattached)
return;
- bool attached = false;
- if (shouldPropagateCompositingToIFrameParent()) {
- if (Element* ownerElement = m_renderView->document()->ownerElement()) {
- RenderObject* renderer = ownerElement->renderer();
- if (renderer && renderer->isRenderIFrame()) {
- // The layer will get hooked up via RenderLayerBacking::updateGraphicsLayerConfiguration()
- // for the iframe's renderer in the parent document.
- ownerElement->setNeedsStyleRecalc(SyntheticStyleChange);
- attached = true;
- }
- }
- }
-
- if (!attached) {
- Frame* frame = m_renderView->frameView()->frame();
- Page* page = frame ? frame->page() : 0;
- if (!page)
- return;
-
- page->chrome()->client()->attachRootGraphicsLayer(frame, m_rootPlatformLayer.get());
- }
- m_rootLayerAttached = true;
+ RootLayerAttachment attachment = shouldPropagateCompositingToEnclosingIFrame() ? RootLayerAttachedViaEnclosingIframe : RootLayerAttachedViaChromeClient;
+ attachRootPlatformLayer(attachment);
}
void RenderLayerCompositor::willMoveOffscreen()
{
- if (!m_rootPlatformLayer || !m_rootLayerAttached)
+ if (!inCompositingMode() || m_rootLayerAttachment == RootLayerUnattached)
return;
- bool detached = false;
- if (shouldPropagateCompositingToIFrameParent()) {
- if (Element* ownerElement = m_renderView->document()->ownerElement()) {
- RenderObject* renderer = ownerElement->renderer();
- if (renderer->isRenderIFrame()) {
- // The layer will get hooked up via RenderLayerBacking::updateGraphicsLayerConfiguration()
- // for the iframe's renderer in the parent document.
- ownerElement->setNeedsStyleRecalc(SyntheticStyleChange);
- detached = true;
- }
- }
- }
-
- if (!detached) {
- Frame* frame = m_renderView->frameView()->frame();
- Page* page = frame ? frame->page() : 0;
- if (!page)
- return;
-
- page->chrome()->client()->attachRootGraphicsLayer(frame, 0);
- }
- m_rootLayerAttached = false;
+ detachRootPlatformLayer();
}
void RenderLayerCompositor::updateRootLayerPosition()
{
- if (m_rootPlatformLayer) {
- // FIXME: Adjust the y position of the m_rootPlatformLayer if we are clipping by its top edge
- // Eventually this will be taken care of by scrolling logic
- // https://bugs.webkit.org/show_bug.cgi?id=38518
- float height = m_renderView->bottomLayoutOverflow();
- float yOffset = 0;
-
- if (m_clippingLayer && height > m_clippingLayer->size().height())
- yOffset = m_clippingLayer->size().height() - height;
-
- m_rootPlatformLayer->setPosition(FloatPoint(0, yOffset));
- m_rootPlatformLayer->setSize(FloatSize(m_renderView->rightLayoutOverflow(), height));
- }
+ // Eventually we will need to account for scrolling here.
+ // https://bugs.webkit.org/show_bug.cgi?id=38518
+ if (m_rootPlatformLayer)
+ m_rootPlatformLayer->setSize(FloatSize(m_renderView->rightLayoutOverflow(), m_renderView->bottomLayoutOverflow()));
}
void RenderLayerCompositor::didStartAcceleratedAnimation()
@@ -1063,18 +1059,47 @@ bool RenderLayerCompositor::has3DContent() const
return layerHas3DContent(rootRenderLayer());
}
-bool RenderLayerCompositor::shouldPropagateCompositingToIFrameParent()
+bool RenderLayerCompositor::shouldPropagateCompositingToEnclosingIFrame() const
{
// Parent document content needs to be able to render on top of a composited iframe, so correct behavior
// is to have the parent document become composited too. However, this can cause problems on platforms that
// use native views for frames (like Mac), so disable that behavior on those platforms for now.
+ Element* ownerElement = enclosingIFrameElement();
+ RenderObject* renderer = ownerElement ? ownerElement->renderer() : 0;
+ if (!renderer || !renderer->isRenderIFrame())
+ return false;
+
#if !PLATFORM(MAC)
+ // On non-Mac platforms, let compositing propagate for all iframes.
return true;
#else
+ // On Mac, only propagate compositing if the iframe is overlapped in the parent
+ // document, or the parent is already compositing.
+ RenderIFrame* iframeRenderer = toRenderIFrame(renderer);
+ if (iframeRenderer->widget()) {
+ ASSERT(iframeRenderer->widget()->isFrameView());
+ FrameView* view = static_cast<FrameView*>(iframeRenderer->widget());
+ if (view->isOverlapped())
+ return true;
+
+ if (RenderView* view = iframeRenderer->view()) {
+ if (view->compositor()->inCompositingMode())
+ return true;
+ }
+ }
+
return false;
#endif
}
+Element* RenderLayerCompositor::enclosingIFrameElement() const
+{
+ if (Element* ownerElement = m_renderView->document()->ownerElement())
+ return ownerElement->hasTagName(iframeTag) ? ownerElement : 0;
+
+ return 0;
+}
+
bool RenderLayerCompositor::needsToBeComposited(const RenderLayer* layer) const
{
if (!canBeComposited(layer))
@@ -1262,9 +1287,16 @@ bool RenderLayerCompositor::requiresCompositingForPlugin(RenderObject* renderer)
bool RenderLayerCompositor::requiresCompositingForIFrame(RenderObject* renderer) const
{
- return shouldPropagateCompositingToIFrameParent()
- && renderer->isRenderIFrame()
- && toRenderIFrame(renderer)->requiresAcceleratedCompositing();
+ if (!renderer->isRenderIFrame())
+ return false;
+
+ RenderIFrame* iframe = toRenderIFrame(renderer);
+
+ if (!iframe->requiresAcceleratedCompositing())
+ return false;
+
+ RenderLayerCompositor* innerCompositor = iframeContentsCompositor(iframe);
+ return innerCompositor->shouldPropagateCompositingToEnclosingIFrame();
}
bool RenderLayerCompositor::requiresCompositingForAnimation(RenderObject* renderer) const
@@ -1291,37 +1323,59 @@ bool RenderLayerCompositor::needsContentsCompositingLayer(const RenderLayer* lay
void RenderLayerCompositor::ensureRootPlatformLayer()
{
- if (m_rootPlatformLayer)
- return;
+ RootLayerAttachment expectedAttachment = shouldPropagateCompositingToEnclosingIFrame() ? RootLayerAttachedViaEnclosingIframe : RootLayerAttachedViaChromeClient;
+ if (expectedAttachment == m_rootLayerAttachment)
+ return;
- m_rootPlatformLayer = GraphicsLayer::create(0);
- m_rootPlatformLayer->setSize(FloatSize(m_renderView->rightLayoutOverflow(), m_renderView->bottomLayoutOverflow()));
- m_rootPlatformLayer->setPosition(FloatPoint());
+ if (!m_rootPlatformLayer) {
+ m_rootPlatformLayer = GraphicsLayer::create(0);
+#ifndef NDEBUG
+ m_rootPlatformLayer->setName("Root platform");
+#endif
+ m_rootPlatformLayer->setSize(FloatSize(m_renderView->rightLayoutOverflow(), m_renderView->bottomLayoutOverflow()));
+ m_rootPlatformLayer->setPosition(FloatPoint());
- // The root layer does flipping if we need it on this platform.
- m_rootPlatformLayer->setGeometryOrientation(GraphicsLayer::compositingCoordinatesOrientation());
+ // Need to clip to prevent transformed content showing outside this frame
+ m_rootPlatformLayer->setMasksToBounds(true);
+ }
- // Need to clip to prevent transformed content showing outside this frame
- m_rootPlatformLayer->setMasksToBounds(true);
+ // The root layer does flipping if we need it on this platform.
+ m_rootPlatformLayer->setGeometryOrientation(expectedAttachment == RootLayerAttachedViaEnclosingIframe ? GraphicsLayer::CompositingCoordinatesTopDown : GraphicsLayer::compositingCoordinatesOrientation());
- if (shouldPropagateCompositingToIFrameParent()) {
- // Create a clipping layer if this is an iframe
- if (Element* ownerElement = m_renderView->document()->ownerElement()) {
- RenderObject* renderer = ownerElement->renderer();
- if (renderer && renderer->isRenderIFrame()) {
- m_clippingLayer = GraphicsLayer::create(0);
- m_clippingLayer->setGeometryOrientation(GraphicsLayer::compositingCoordinatesOrientation());
+ if (expectedAttachment == RootLayerAttachedViaEnclosingIframe) {
+ if (!m_clipLayer) {
+ ASSERT(!m_scrollLayer);
+ // Create a clipping layer if this is an iframe
+ m_clipLayer = GraphicsLayer::create(0);
#ifndef NDEBUG
- m_clippingLayer->setName("iframe Clipping");
+ m_clipLayer->setName("iframe Clipping");
#endif
- m_clippingLayer->setMasksToBounds(true);
- m_clippingLayer->setAnchorPoint(FloatPoint());
- m_clippingLayer->addChild(m_rootPlatformLayer.get());
- }
+ m_clipLayer->setMasksToBounds(true);
+
+ m_scrollLayer = GraphicsLayer::create(0);
+#ifndef NDEBUG
+ m_scrollLayer->setName("iframe scrolling");
+#endif
+ // Hook them up
+ m_clipLayer->addChild(m_scrollLayer.get());
+ m_scrollLayer->addChild(m_rootPlatformLayer.get());
+
+ updateContentLayerScrollPosition(m_renderView->frameView()->scrollPosition());
}
+ } else if (m_clipLayer) {
+ m_clipLayer->removeAllChildren();
+ m_clipLayer->removeFromParent();
+ m_clipLayer = 0;
+
+ m_scrollLayer->removeAllChildren();
+ m_scrollLayer = 0;
}
- didMoveOnscreen();
+ // Check to see if we have to change the attachment
+ if (m_rootLayerAttachment != RootLayerUnattached)
+ detachRootPlatformLayer();
+
+ attachRootPlatformLayer(expectedAttachment);
}
void RenderLayerCompositor::destroyRootPlatformLayer()
@@ -1329,10 +1383,111 @@ void RenderLayerCompositor::destroyRootPlatformLayer()
if (!m_rootPlatformLayer)
return;
- willMoveOffscreen();
+ detachRootPlatformLayer();
+ if (m_clipLayer) {
+ m_clipLayer->removeAllChildren();
+ m_clipLayer = 0;
+
+ m_scrollLayer->removeAllChildren();
+ m_scrollLayer = 0;
+ }
+ ASSERT(!m_scrollLayer);
m_rootPlatformLayer = 0;
}
+void RenderLayerCompositor::attachRootPlatformLayer(RootLayerAttachment attachment)
+{
+ if (!m_rootPlatformLayer)
+ return;
+
+ switch (attachment) {
+ case RootLayerUnattached:
+ ASSERT_NOT_REACHED();
+ break;
+ case RootLayerAttachedViaChromeClient: {
+ Frame* frame = m_renderView->frameView()->frame();
+ Page* page = frame ? frame->page() : 0;
+ if (!page)
+ return;
+
+ page->chrome()->client()->attachRootGraphicsLayer(frame, m_rootPlatformLayer.get());
+ break;
+ }
+ case RootLayerAttachedViaEnclosingIframe: {
+ // The layer will get hooked up via RenderLayerBacking::updateGraphicsLayerConfiguration()
+ // for the iframe's renderer in the parent document.
+ m_renderView->document()->ownerElement()->setNeedsStyleRecalc(SyntheticStyleChange);
+ break;
+ }
+ }
+
+ m_rootLayerAttachment = attachment;
+ rootLayerAttachmentChanged();
+}
+
+void RenderLayerCompositor::detachRootPlatformLayer()
+{
+ if (!m_rootPlatformLayer || m_rootLayerAttachment == RootLayerUnattached)
+ return;
+
+ switch (m_rootLayerAttachment) {
+ case RootLayerAttachedViaEnclosingIframe: {
+ // The layer will get unhooked up via RenderLayerBacking::updateGraphicsLayerConfiguration()
+ // for the iframe's renderer in the parent document.
+ if (m_clipLayer)
+ m_clipLayer->removeFromParent();
+ else
+ m_rootPlatformLayer->removeFromParent();
+
+ m_renderView->document()->ownerElement()->setNeedsStyleRecalc(SyntheticStyleChange);
+ break;
+ }
+ case RootLayerAttachedViaChromeClient: {
+ Frame* frame = m_renderView->frameView()->frame();
+ Page* page = frame ? frame->page() : 0;
+ if (!page)
+ return;
+
+ page->chrome()->client()->attachRootGraphicsLayer(frame, 0);
+ }
+ break;
+ case RootLayerUnattached:
+ break;
+ }
+
+ m_rootLayerAttachment = RootLayerUnattached;
+ rootLayerAttachmentChanged();
+}
+
+void RenderLayerCompositor::updateRootLayerAttachment()
+{
+ ensureRootPlatformLayer();
+}
+
+void RenderLayerCompositor::rootLayerAttachmentChanged()
+{
+ // The attachment can affect whether the RenderView layer's paintingGoesToWindow() behavior,
+ // so call updateGraphicsLayerGeometry() to udpate that.
+ RenderLayer* layer = m_renderView->layer();
+ if (RenderLayerBacking* backing = layer ? layer->backing() : 0)
+ backing->updateDrawsContent();
+}
+
+// IFrames are special, because we hook compositing layers together across iframe boundaries
+// when both parent and iframe content are composited. So when this frame becomes composited, we have
+// to use a synthetic style change to get the iframes into RenderLayers in order to allow them to composite.
+void RenderLayerCompositor::notifyIFramesOfCompositingChange()
+{
+ Frame* frame = m_renderView->frameView() ? m_renderView->frameView()->frame() : 0;
+ if (!frame)
+ return;
+
+ for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
+ if (child->document() && child->document()->ownerElement())
+ child->document()->ownerElement()->setNeedsStyleRecalc(SyntheticStyleChange);
+ }
+}
+
bool RenderLayerCompositor::layerHas3DContent(const RenderLayer* layer) const
{
const RenderStyle* style = layer->renderer()->style();
diff --git a/WebCore/rendering/RenderLayerCompositor.h b/WebCore/rendering/RenderLayerCompositor.h
index 36f7c15..81f2058 100644
--- a/WebCore/rendering/RenderLayerCompositor.h
+++ b/WebCore/rendering/RenderLayerCompositor.h
@@ -34,6 +34,7 @@ namespace WebCore {
#define PROFILE_LAYER_REBUILD 0
class GraphicsLayer;
+class RenderIFrame;
#if ENABLE(VIDEO)
class RenderVideo;
#endif
@@ -121,11 +122,19 @@ public:
RenderLayer* rootRenderLayer() const;
GraphicsLayer* rootPlatformLayer() const;
- void didMoveOnscreen();
- void willMoveOffscreen();
+ enum RootLayerAttachment {
+ RootLayerUnattached,
+ RootLayerAttachedViaChromeClient,
+ RootLayerAttachedViaEnclosingIframe
+ };
+ RootLayerAttachment rootLayerAttachment() const { return m_rootLayerAttachment; }
+ void updateRootLayerAttachment();
void updateRootLayerPosition();
+ void didMoveOnscreen();
+ void willMoveOffscreen();
+
void didStartAcceleratedAnimation();
#if ENABLE(VIDEO)
@@ -139,9 +148,17 @@ public:
// Some platforms may wish to connect compositing layer trees between iframes and
// their parent document.
- static bool shouldPropagateCompositingToIFrameParent();
+ bool shouldPropagateCompositingToEnclosingIFrame() const;
+
+ Element* enclosingIFrameElement() const;
- void setRootPlatformLayerClippingBox(const IntRect& contentsBox);
+ static RenderLayerCompositor* iframeContentsCompositor(RenderIFrame*);
+ // Return true if the layers changed.
+ static bool parentIFrameContentLayers(RenderIFrame*);
+
+ // Update the geometry of the layers used for clipping and scrolling in frames.
+ void updateContentLayerOffset(const IntPoint& contentsOffset);
+ void updateContentLayerScrollPosition(const IntPoint&);
private:
// Whether the given RL needs a compositing layer.
@@ -178,7 +195,14 @@ private:
void ensureRootPlatformLayer();
void destroyRootPlatformLayer();
+
+ void attachRootPlatformLayer(RootLayerAttachment);
+ void detachRootPlatformLayer();
+
+ void rootLayerAttachmentChanged();
+ void notifyIFramesOfCompositingChange();
+
// Whether a running transition or animation enforces the need for a compositing layer.
bool requiresCompositingForAnimation(RenderObject*) const;
bool requiresCompositingForTransform(RenderObject*) const;
@@ -201,11 +225,13 @@ private:
bool m_showRepaintCounter;
bool m_compositingConsultsOverlap;
bool m_compositing;
- bool m_rootLayerAttached;
bool m_compositingLayersNeedRebuild;
+
+ RootLayerAttachment m_rootLayerAttachment;
// Enclosing clipping layer for iframe content
- OwnPtr<GraphicsLayer> m_clippingLayer;
+ OwnPtr<GraphicsLayer> m_clipLayer;
+ OwnPtr<GraphicsLayer> m_scrollLayer;
#if PROFILE_LAYER_REBUILD
int m_rootLayerUpdateCount;
diff --git a/WebCore/rendering/RenderLineBoxList.cpp b/WebCore/rendering/RenderLineBoxList.cpp
index 3395347..92952b7 100644
--- a/WebCore/rendering/RenderLineBoxList.cpp
+++ b/WebCore/rendering/RenderLineBoxList.cpp
@@ -161,12 +161,21 @@ void RenderLineBoxList::paint(RenderBoxModelObject* renderer, RenderObject::Pain
if (!firstLineBox())
return;
+ RenderView* v = renderer->view();
+ bool usePrintRect = !v->printRect().isEmpty();
+
// We can check the first box and last box and avoid painting if we don't
// intersect. This is a quick short-circuit that we can take to avoid walking any lines.
// FIXME: This check is flawed in the following extremely obscure way:
// if some line in the middle has a huge overflow, it might actually extend below the last line.
- int yPos = firstLineBox()->topVisibleOverflow() - renderer->maximalOutlineSize(paintInfo.phase);
- int h = renderer->maximalOutlineSize(paintInfo.phase) + lastLineBox()->bottomVisibleOverflow() - yPos;
+ int firstLineTop = firstLineBox()->topVisibleOverflow();
+ if (usePrintRect && !firstLineBox()->parent())
+ firstLineTop = min(firstLineTop, firstLineBox()->root()->lineTop());
+ int lastLineBottom = lastLineBox()->bottomVisibleOverflow();
+ if (usePrintRect && !lastLineBox()->parent())
+ lastLineBottom = max(lastLineBottom, lastLineBox()->root()->lineBottom());
+ int yPos = firstLineTop - renderer->maximalOutlineSize(paintInfo.phase);
+ int h = renderer->maximalOutlineSize(paintInfo.phase) + lastLineBottom - yPos;
yPos += ty;
if (yPos >= paintInfo.rect.bottom() || yPos + h <= paintInfo.rect.y())
return;
@@ -178,8 +187,6 @@ void RenderLineBoxList::paint(RenderBoxModelObject* renderer, RenderObject::Pain
// See if our root lines intersect with the dirty rect. If so, then we paint
// them. Note that boxes can easily overlap, so we can't make any assumptions
// based off positions of our first line box or our last line box.
- RenderView* v = renderer->view();
- bool usePrintRect = !v->printRect().isEmpty();
for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
if (usePrintRect) {
// FIXME: This is a feeble effort to avoid splitting a line across two pages.
@@ -187,12 +194,19 @@ void RenderLineBoxList::paint(RenderBoxModelObject* renderer, RenderObject::Pain
// The whole way objects break across pages needs to be redone.
// Try to avoid splitting a line vertically, but only if it's less than the height
// of the entire page.
- if (curr->bottomVisibleOverflow() - curr->topVisibleOverflow() <= v->printRect().height()) {
- if (ty + curr->bottomVisibleOverflow() > v->printRect().bottom()) {
- if (ty + curr->topVisibleOverflow() < v->truncatedAt())
- v->setBestTruncatedAt(ty + curr->root()->topVisibleOverflow(), renderer);
+ int topForPaginationCheck = curr->topVisibleOverflow();
+ int bottomForPaginationCheck = curr->bottomVisibleOverflow();
+ if (!curr->parent()) {
+ // We're a root box. Use lineTop and lineBottom as well here.
+ topForPaginationCheck = min(topForPaginationCheck, curr->root()->lineTop());
+ bottomForPaginationCheck = max(bottomForPaginationCheck, curr->root()->lineBottom());
+ }
+ if (bottomForPaginationCheck - topForPaginationCheck <= v->printRect().height()) {
+ if (ty + bottomForPaginationCheck > v->printRect().bottom()) {
+ if (ty + topForPaginationCheck < v->truncatedAt())
+ v->setBestTruncatedAt(ty + topForPaginationCheck, renderer);
// If we were able to truncate, don't paint.
- if (ty + curr->topVisibleOverflow() >= v->truncatedAt())
+ if (ty + topForPaginationCheck >= v->truncatedAt())
break;
}
}
diff --git a/WebCore/rendering/RenderMeter.cpp b/WebCore/rendering/RenderMeter.cpp
new file mode 100644
index 0000000..9dc6a26
--- /dev/null
+++ b/WebCore/rendering/RenderMeter.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#if ENABLE(METER_TAG)
+
+#include "RenderMeter.h"
+
+#include "HTMLMeterElement.h"
+#include "RenderTheme.h"
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderMeter::RenderMeter(HTMLMeterElement* element)
+ : RenderBlock(element)
+{
+}
+
+void RenderMeter::layout()
+{
+ ASSERT(needsLayout());
+
+ LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+
+ calcWidth();
+ calcHeight();
+
+ m_overflow.clear();
+
+ repainter.repaintAfterLayout();
+
+ setNeedsLayout(false);
+}
+
+void RenderMeter::updateFromElement()
+{
+ repaint();
+}
+
+} // namespace WebCore
+#endif
diff --git a/WebCore/rendering/RenderMeter.h b/WebCore/rendering/RenderMeter.h
new file mode 100644
index 0000000..2fc7844
--- /dev/null
+++ b/WebCore/rendering/RenderMeter.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderMeter_h
+#define RenderMeter_h
+
+#if ENABLE(METER_TAG)
+#include "RenderBlock.h"
+#include "RenderWidget.h"
+
+namespace WebCore {
+
+class HTMLMeterElement;
+
+class RenderMeter : public RenderBlock {
+public:
+ RenderMeter(HTMLMeterElement*);
+
+private:
+ virtual const char* renderName() const { return "RenderMeter"; }
+ virtual bool isMeter() const { return true; }
+ virtual void layout();
+ virtual void updateFromElement();
+};
+
+inline RenderMeter* toRenderMeter(RenderObject* object)
+{
+ ASSERT(!object || object->isMeter());
+ return static_cast<RenderMeter*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderMeter(const RenderMeter*);
+
+} // namespace WebCore
+
+#endif
+
+#endif // RenderMeter_h
+
diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp
index 1c93ac4..d7df436 100644
--- a/WebCore/rendering/RenderObject.cpp
+++ b/WebCore/rendering/RenderObject.cpp
@@ -1099,20 +1099,29 @@ RenderBoxModelObject* RenderObject::containerForRepaint() const
void RenderObject::repaintUsingContainer(RenderBoxModelObject* repaintContainer, const IntRect& r, bool immediate)
{
- if (!repaintContainer || repaintContainer->isRenderView()) {
- RenderView* v = repaintContainer ? toRenderView(repaintContainer) : view();
- v->repaintViewRectangle(r, immediate);
- } else {
+ if (!repaintContainer) {
+ view()->repaintViewRectangle(r, immediate);
+ return;
+ }
+
#if USE(ACCELERATED_COMPOSITING)
- RenderView* v = view();
- if (v->usesCompositing()) {
- ASSERT(repaintContainer->hasLayer() && repaintContainer->layer()->isComposited());
- repaintContainer->layer()->setBackingNeedsRepaintInRect(r);
+ RenderView* v = view();
+ if (repaintContainer->isRenderView()) {
+ ASSERT(repaintContainer == v);
+ if (!v->hasLayer() || !v->layer()->isComposited() || v->layer()->backing()->paintingGoesToWindow()) {
+ v->repaintViewRectangle(r, immediate);
+ return;
}
+ }
+
+ if (v->usesCompositing()) {
+ ASSERT(repaintContainer->hasLayer() && repaintContainer->layer()->isComposited());
+ repaintContainer->layer()->setBackingNeedsRepaintInRect(r);
+ }
#else
- ASSERT_NOT_REACHED();
+ if (repaintContainer->isRenderView())
+ toRenderView(repaintContainer)->repaintViewRectangle(r, immediate);
#endif
- }
}
void RenderObject::repaint(bool immediate)
diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h
index 9d8a306..3fce1ee 100644
--- a/WebCore/rendering/RenderObject.h
+++ b/WebCore/rendering/RenderObject.h
@@ -276,6 +276,9 @@ public:
virtual bool isListMarker() const { return false; }
virtual bool isMedia() const { return false; }
virtual bool isMenuList() const { return false; }
+#if ENABLE(METER_TAG)
+ virtual bool isMeter() const { return false; }
+#endif
#if ENABLE(PROGRESS_TAG)
virtual bool isProgress() const { return false; }
#endif
diff --git a/WebCore/rendering/RenderProgress.cpp b/WebCore/rendering/RenderProgress.cpp
index b42cc8b..cf98f18 100644
--- a/WebCore/rendering/RenderProgress.cpp
+++ b/WebCore/rendering/RenderProgress.cpp
@@ -167,11 +167,16 @@ PassRefPtr<RenderStyle> RenderProgress::createStyleForValuePart(RenderStyle* par
return styleForValuePart.release();
}
-double RenderProgress::animationProgress()
+double RenderProgress::animationProgress() const
{
return m_animating ? (fmod((currentTime() - m_animationStartTime), m_animationDuration) / m_animationDuration) : 0;
}
+bool RenderProgress::isDeterminate() const
+{
+ return 0 <= position();
+}
+
void RenderProgress::animationTimerFired(Timer<RenderProgress>*)
{
repaint();
diff --git a/WebCore/rendering/RenderProgress.h b/WebCore/rendering/RenderProgress.h
index 0d93ae7..2070974 100644
--- a/WebCore/rendering/RenderProgress.h
+++ b/WebCore/rendering/RenderProgress.h
@@ -34,9 +34,10 @@ public:
RenderProgress(HTMLProgressElement*);
virtual ~RenderProgress();
- double position() { return m_position; }
- double animationProgress();
-
+ double position() const { return m_position; }
+ double animationProgress() const;
+ bool isDeterminate() const;
+
HTMLProgressElement* progressElement() const;
private:
diff --git a/WebCore/rendering/RenderSVGImage.cpp b/WebCore/rendering/RenderSVGImage.cpp
index 1fb7c0f..006142c 100644
--- a/WebCore/rendering/RenderSVGImage.cpp
+++ b/WebCore/rendering/RenderSVGImage.cpp
@@ -33,6 +33,8 @@
#include "GraphicsContext.h"
#include "PointerEventsHitRules.h"
#include "RenderLayer.h"
+#include "RenderSVGResourceContainer.h"
+#include "RenderSVGResourceFilter.h"
#include "SVGImageElement.h"
#include "SVGLength.h"
#include "SVGPreserveAspectRatio.h"
@@ -174,6 +176,12 @@ FloatRect RenderSVGImage::repaintRectInLocalCoordinates() const
void RenderSVGImage::imageChanged(WrappedImagePtr image, const IntRect* rect)
{
RenderImage::imageChanged(image, rect);
+#if ENABLE(FILTERS)
+ // The image resource defaults to nullImage until the resource arrives.
+ // This empty image may be cached by SVG filter effects which must be invalidated.
+ if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(document(), style()->svgStyle()->filterResource()))
+ filter->invalidateClient(this);
+#endif
repaint();
}
diff --git a/WebCore/rendering/RenderSVGResource.h b/WebCore/rendering/RenderSVGResource.h
index f14fa4a..4e33e55 100644
--- a/WebCore/rendering/RenderSVGResource.h
+++ b/WebCore/rendering/RenderSVGResource.h
@@ -60,7 +60,7 @@ public:
virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) = 0;
virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short) { }
- virtual FloatRect resourceBoundingBox(const FloatRect&) const = 0;
+ virtual FloatRect resourceBoundingBox(const FloatRect&) = 0;
virtual RenderSVGResourceType resourceType() const = 0;
diff --git a/WebCore/rendering/RenderSVGResourceClipper.cpp b/WebCore/rendering/RenderSVGResourceClipper.cpp
index 2759976..0f82903 100644
--- a/WebCore/rendering/RenderSVGResourceClipper.cpp
+++ b/WebCore/rendering/RenderSVGResourceClipper.cpp
@@ -21,6 +21,7 @@
*/
#include "config.h"
+#if ENABLE(SVG)
#include "RenderSVGResourceClipper.h"
#include "AffineTransform.h"
@@ -65,6 +66,7 @@ void RenderSVGResourceClipper::invalidateClients()
}
deleteAllValues(m_clipper);
m_clipper.clear();
+ m_clipBoundaries = FloatRect();
}
void RenderSVGResourceClipper::invalidateClient(RenderObject* object)
@@ -237,11 +239,10 @@ bool RenderSVGResourceClipper::createClipData(ClipperData* clipperData, const Fl
svgStyle->setMaskerResource(String());
renderer->setStyle(newRenderStyle.release());
- // Get the renderer of the element, that is referenced by the <use>-element.
- if (isUseElement)
- renderer = childNode->renderer();
-
- renderSubtreeToImage(clipperData->clipMaskImage.get(), renderer);
+ // In the case of a <use> element, we obtained its renderere above, to retrieve its clipRule.
+ // We hsve to pass the <use> renderer itself to renderSubtreeToImage() to apply it's x/y/transform/etc. values when rendering.
+ // So if isUseElement is true, refetch the childNode->renderer(), as renderer got overriden above.
+ renderSubtreeToImage(clipperData->clipMaskImage.get(), isUseElement ? childNode->renderer() : renderer);
renderer->setStyle(oldRenderStyle.release());
}
@@ -251,27 +252,37 @@ bool RenderSVGResourceClipper::createClipData(ClipperData* clipperData, const Fl
return true;
}
-FloatRect RenderSVGResourceClipper::resourceBoundingBox(const FloatRect& objectBoundingBox) const
+void RenderSVGResourceClipper::calculateClipContentRepaintRect()
{
// This is a rough heuristic to appraise the clip size and doesn't consider clip on clip.
- FloatRect clipRect;
for (Node* childNode = node()->firstChild(); childNode; childNode = childNode->nextSibling()) {
RenderObject* renderer = childNode->renderer();
if (!childNode->isSVGElement() || !static_cast<SVGElement*>(childNode)->isStyled() || !renderer)
continue;
if (!renderer->isRenderPath() && !renderer->isSVGText() && !renderer->isSVGShadowTreeRootContainer())
continue;
- clipRect.unite(renderer->localToParentTransform().mapRect(renderer->repaintRectInLocalCoordinates()));
+ RenderStyle* style = renderer->style();
+ if (!style || style->display() == NONE || style->visibility() != VISIBLE)
+ continue;
+ m_clipBoundaries.unite(renderer->localToParentTransform().mapRect(renderer->repaintRectInLocalCoordinates()));
}
+}
+
+FloatRect RenderSVGResourceClipper::resourceBoundingBox(const FloatRect& objectBoundingBox)
+{
+ if (m_clipBoundaries.isEmpty())
+ calculateClipContentRepaintRect();
if (static_cast<SVGClipPathElement*>(node())->clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
AffineTransform transform;
transform.translate(objectBoundingBox.x(), objectBoundingBox.y());
transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
- return transform.mapRect(clipRect);
+ return transform.mapRect(m_clipBoundaries);
}
- return clipRect;
+ return m_clipBoundaries;
}
}
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGResourceClipper.h b/WebCore/rendering/RenderSVGResourceClipper.h
index 0b6f2b3..d8e2eed 100644
--- a/WebCore/rendering/RenderSVGResourceClipper.h
+++ b/WebCore/rendering/RenderSVGResourceClipper.h
@@ -51,7 +51,7 @@ public:
virtual void invalidateClient(RenderObject*);
virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode);
- virtual FloatRect resourceBoundingBox(const FloatRect&) const;
+ virtual FloatRect resourceBoundingBox(const FloatRect&);
virtual RenderSVGResourceType resourceType() const { return ClipperResourceType; }
@@ -64,7 +64,9 @@ private:
bool applyClippingToContext(RenderObject*, const FloatRect&, const FloatRect&, GraphicsContext*);
bool pathOnlyClipping(GraphicsContext*, const FloatRect&);
bool createClipData(ClipperData*, const FloatRect&, const FloatRect&);
+ void calculateClipContentRepaintRect();
+ FloatRect m_clipBoundaries;
HashMap<RenderObject*, ClipperData*> m_clipper;
};
diff --git a/WebCore/rendering/RenderSVGResourceFilter.cpp b/WebCore/rendering/RenderSVGResourceFilter.cpp
index ac3ea49..ea30d77 100644
--- a/WebCore/rendering/RenderSVGResourceFilter.cpp
+++ b/WebCore/rendering/RenderSVGResourceFilter.cpp
@@ -281,7 +281,7 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo
m_sourceGraphicBuffer.clear();
}
-FloatRect RenderSVGResourceFilter::resourceBoundingBox(const FloatRect& objectBoundingBox) const
+FloatRect RenderSVGResourceFilter::resourceBoundingBox(const FloatRect& objectBoundingBox)
{
if (SVGFilterElement* element = static_cast<SVGFilterElement*>(node()))
return element->filterBoundingBox(objectBoundingBox);
diff --git a/WebCore/rendering/RenderSVGResourceFilter.h b/WebCore/rendering/RenderSVGResourceFilter.h
index ce4a7e1..6e98492 100644
--- a/WebCore/rendering/RenderSVGResourceFilter.h
+++ b/WebCore/rendering/RenderSVGResourceFilter.h
@@ -68,7 +68,7 @@ public:
virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode);
virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode);
- virtual FloatRect resourceBoundingBox(const FloatRect&) const;
+ virtual FloatRect resourceBoundingBox(const FloatRect&);
PassOwnPtr<SVGFilterBuilder> buildPrimitives();
diff --git a/WebCore/rendering/RenderSVGResourceGradient.h b/WebCore/rendering/RenderSVGResourceGradient.h
index 2fd9cf4..4d848af 100644
--- a/WebCore/rendering/RenderSVGResourceGradient.h
+++ b/WebCore/rendering/RenderSVGResourceGradient.h
@@ -54,7 +54,7 @@ public:
virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode);
virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode);
- virtual FloatRect resourceBoundingBox(const FloatRect&) const { return FloatRect(); }
+ virtual FloatRect resourceBoundingBox(const FloatRect&) { return FloatRect(); }
protected:
void addStops(GradientData*, const Vector<Gradient::ColorStop>&) const;
diff --git a/WebCore/rendering/RenderSVGResourceMarker.cpp b/WebCore/rendering/RenderSVGResourceMarker.cpp
index 460239b..4a300c2 100644
--- a/WebCore/rendering/RenderSVGResourceMarker.cpp
+++ b/WebCore/rendering/RenderSVGResourceMarker.cpp
@@ -21,6 +21,7 @@
*/
#include "config.h"
+#if ENABLE(SVG)
#include "RenderSVGResourceMarker.h"
#include "GraphicsContext.h"
@@ -198,3 +199,5 @@ void RenderSVGResourceMarker::calcViewport()
}
}
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGResourceMarker.h b/WebCore/rendering/RenderSVGResourceMarker.h
index efbbdfa..fe848a9 100644
--- a/WebCore/rendering/RenderSVGResourceMarker.h
+++ b/WebCore/rendering/RenderSVGResourceMarker.h
@@ -58,7 +58,7 @@ public:
AffineTransform markerTransformation(const FloatPoint& origin, float angle, float strokeWidth) const;
virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short) { return false; }
- virtual FloatRect resourceBoundingBox(const FloatRect&) const { return FloatRect(); }
+ virtual FloatRect resourceBoundingBox(const FloatRect&) { return FloatRect(); }
FloatPoint referencePoint() const;
float angle() const;
diff --git a/WebCore/rendering/RenderSVGResourceMasker.cpp b/WebCore/rendering/RenderSVGResourceMasker.cpp
index abf8e48..2bfb283 100644
--- a/WebCore/rendering/RenderSVGResourceMasker.cpp
+++ b/WebCore/rendering/RenderSVGResourceMasker.cpp
@@ -19,6 +19,7 @@
*/
#include "config.h"
+#if ENABLE(SVG)
#include "RenderSVGResourceMasker.h"
#include "AffineTransform.h"
@@ -65,6 +66,7 @@ void RenderSVGResourceMasker::invalidateClients()
deleteAllValues(m_masker);
m_masker.clear();
+ m_maskBoundaries = FloatRect();
}
void RenderSVGResourceMasker::invalidateClient(RenderObject* object)
@@ -111,14 +113,6 @@ bool RenderSVGResourceMasker::applyResource(RenderObject* object, RenderStyle*,
return true;
}
-FloatRect RenderSVGResourceMasker::resourceBoundingBox(const FloatRect& objectBoundingBox) const
-{
- if (SVGMaskElement* element = static_cast<SVGMaskElement*>(node()))
- return element->maskBoundingBox(objectBoundingBox);
-
- return FloatRect();
-}
-
void RenderSVGResourceMasker::createMaskImage(MaskerData* maskerData, const SVGMaskElement* maskElement, RenderObject* object)
{
FloatRect objectBoundingBox = object->objectBoundingBox();
@@ -129,19 +123,11 @@ void RenderSVGResourceMasker::createMaskImage(MaskerData* maskerData, const SVGM
maskerData->emptyMask = true;
return;
}
+
+ if (m_maskBoundaries.isEmpty())
+ calculateMaskContentRepaintRect();
- // Calculate the smallest rect for the mask ImageBuffer.
- FloatRect repaintRect;
- Vector<RenderObject*> rendererList;
- for (Node* node = maskElement->firstChild(); node; node = node->nextSibling()) {
- RenderObject* renderer = node->renderer();
- if (!node->isSVGElement() || !static_cast<SVGElement*>(node)->isStyled() || !renderer)
- continue;
-
- rendererList.append(renderer);
- repaintRect.unite(renderer->localToParentTransform().mapRect(renderer->repaintRectInLocalCoordinates()));
- }
-
+ FloatRect repaintRect = m_maskBoundaries;
AffineTransform contextTransform;
// We need to scale repaintRect for objectBoundingBox to get the drawing area.
if (maskElement->maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
@@ -180,9 +166,15 @@ void RenderSVGResourceMasker::createMaskImage(MaskerData* maskerData, const SVGM
maskImageContext->concatCTM(contextTransform);
// draw the content into the ImageBuffer
- Vector<RenderObject*>::iterator end = rendererList.end();
- for (Vector<RenderObject*>::iterator it = rendererList.begin(); it != end; it++)
- renderSubtreeToImage(maskerData->maskImage.get(), *it);
+ for (Node* node = maskElement->firstChild(); node; node = node->nextSibling()) {
+ RenderObject* renderer = node->renderer();
+ if (!node->isSVGElement() || !static_cast<SVGElement*>(node)->isStyled() || !renderer)
+ continue;
+ RenderStyle* style = renderer->style();
+ if (!style || style->display() == NONE || style->visibility() != VISIBLE)
+ continue;
+ renderSubtreeToImage(maskerData->maskImage.get(), renderer);
+ }
maskImageContext->restore();
@@ -205,4 +197,40 @@ void RenderSVGResourceMasker::createMaskImage(MaskerData* maskerData, const SVGM
maskerData->maskImage->putUnmultipliedImageData(imageData.get(), maskImageRect, IntPoint());
}
+void RenderSVGResourceMasker::calculateMaskContentRepaintRect()
+{
+ for (Node* childNode = node()->firstChild(); childNode; childNode = childNode->nextSibling()) {
+ RenderObject* renderer = childNode->renderer();
+ if (!childNode->isSVGElement() || !static_cast<SVGElement*>(childNode)->isStyled() || !renderer)
+ continue;
+ RenderStyle* style = renderer->style();
+ if (!style || style->display() == NONE || style->visibility() != VISIBLE)
+ continue;
+ m_maskBoundaries.unite(renderer->localToParentTransform().mapRect(renderer->repaintRectInLocalCoordinates()));
+ }
}
+
+FloatRect RenderSVGResourceMasker::resourceBoundingBox(const FloatRect& objectBoundingBox)
+{
+ if (m_maskBoundaries.isEmpty())
+ calculateMaskContentRepaintRect();
+
+ SVGMaskElement* maskElement = static_cast<SVGMaskElement*>(node());
+ if (!maskElement)
+ return FloatRect();
+
+ FloatRect maskRect = m_maskBoundaries;
+ if (maskElement->maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
+ AffineTransform transform;
+ transform.translate(objectBoundingBox.x(), objectBoundingBox.y());
+ transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
+ maskRect = transform.mapRect(maskRect);
+ }
+
+ maskRect.intersect(maskElement->maskBoundingBox(objectBoundingBox));
+ return maskRect;
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGResourceMasker.h b/WebCore/rendering/RenderSVGResourceMasker.h
index b022f7b..2de5f3f 100644
--- a/WebCore/rendering/RenderSVGResourceMasker.h
+++ b/WebCore/rendering/RenderSVGResourceMasker.h
@@ -57,7 +57,7 @@ public:
virtual void invalidateClient(RenderObject*);
virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode);
- virtual FloatRect resourceBoundingBox(const FloatRect&) const;
+ virtual FloatRect resourceBoundingBox(const FloatRect&);
SVGUnitTypes::SVGUnitType maskUnits() const { return toUnitType(static_cast<SVGMaskElement*>(node())->maskUnits()); }
SVGUnitTypes::SVGUnitType maskContentUnits() const { return toUnitType(static_cast<SVGMaskElement*>(node())->maskContentUnits()); }
@@ -67,7 +67,9 @@ public:
private:
void createMaskImage(MaskerData*, const SVGMaskElement*, RenderObject*);
+ void calculateMaskContentRepaintRect();
+ FloatRect m_maskBoundaries;
HashMap<RenderObject*, MaskerData*> m_masker;
};
diff --git a/WebCore/rendering/RenderSVGResourcePattern.h b/WebCore/rendering/RenderSVGResourcePattern.h
index 2f9d553..4129934 100644
--- a/WebCore/rendering/RenderSVGResourcePattern.h
+++ b/WebCore/rendering/RenderSVGResourcePattern.h
@@ -54,7 +54,7 @@ public:
virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode);
virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode);
- virtual FloatRect resourceBoundingBox(const FloatRect&) const { return FloatRect(); }
+ virtual FloatRect resourceBoundingBox(const FloatRect&) { return FloatRect(); }
virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
static RenderSVGResourceType s_resourceType;
diff --git a/WebCore/rendering/RenderSVGResourceSolidColor.h b/WebCore/rendering/RenderSVGResourceSolidColor.h
index a1a8863..a4de62d 100644
--- a/WebCore/rendering/RenderSVGResourceSolidColor.h
+++ b/WebCore/rendering/RenderSVGResourceSolidColor.h
@@ -38,7 +38,7 @@ public:
virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode);
virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode);
- virtual FloatRect resourceBoundingBox(const FloatRect&) const { return FloatRect(); }
+ virtual FloatRect resourceBoundingBox(const FloatRect&) { return FloatRect(); }
virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
static RenderSVGResourceType s_resourceType;
diff --git a/WebCore/rendering/RenderTextControlMultiLine.cpp b/WebCore/rendering/RenderTextControlMultiLine.cpp
index 9fbde3a..76bf612 100644
--- a/WebCore/rendering/RenderTextControlMultiLine.cpp
+++ b/WebCore/rendering/RenderTextControlMultiLine.cpp
@@ -114,7 +114,7 @@ void RenderTextControlMultiLine::updateFromElement()
HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(node());
if (m_placeholderVisible)
- setInnerTextValue(textArea->getAttribute(HTMLNames::placeholderAttr));
+ setInnerTextValue(textArea->strippedPlaceholder());
else
setInnerTextValue(textArea->value());
}
diff --git a/WebCore/rendering/RenderTextControlSingleLine.cpp b/WebCore/rendering/RenderTextControlSingleLine.cpp
index 37d44c4..f454c63 100644
--- a/WebCore/rendering/RenderTextControlSingleLine.cpp
+++ b/WebCore/rendering/RenderTextControlSingleLine.cpp
@@ -569,8 +569,10 @@ void RenderTextControlSingleLine::updateFromElement()
updateCancelButtonVisibility();
if (m_placeholderVisible) {
+ // node() must be an HTMLInputElement. WMLInputElement doesn't support placeholder.
+ ASSERT(node()->isHTMLElement());
ExceptionCode ec = 0;
- innerTextElement()->setInnerText(static_cast<Element*>(node())->getAttribute(placeholderAttr), ec);
+ innerTextElement()->setInnerText(static_cast<HTMLInputElement*>(node())->strippedPlaceholder(), ec);
ASSERT(!ec);
} else {
if (!inputElement()->suggestedValue().isNull())
diff --git a/WebCore/rendering/RenderTheme.cpp b/WebCore/rendering/RenderTheme.cpp
index 76af001..b1c23b1 100644
--- a/WebCore/rendering/RenderTheme.cpp
+++ b/WebCore/rendering/RenderTheme.cpp
@@ -24,6 +24,7 @@
#include "CSSValueKeywords.h"
#include "Document.h"
+#include "FloatConversion.h"
#include "FocusController.h"
#include "FontSelector.h"
#include "Frame.h"
@@ -38,6 +39,11 @@
#include "Settings.h"
#include "TextControlInnerElements.h"
+#if ENABLE(METER_TAG)
+#include "HTMLMeterElement.h"
+#include "RenderMeter.h"
+#endif
+
// The methods in this file are shared by all themes on every platform.
namespace WebCore {
@@ -218,6 +224,10 @@ void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, El
case ProgressBarPart:
return adjustProgressBarStyle(selector, style, e);
#endif
+#if ENABLE(Meter_TAG)
+ case MeterPart:
+ return adjustMeterStyle(selector, style, e);
+#endif
default:
break;
}
@@ -276,6 +286,10 @@ bool RenderTheme::paint(RenderObject* o, const RenderObject::PaintInfo& paintInf
#endif
case MenulistPart:
return paintMenuList(o, paintInfo, r);
+#if ENABLE(METER_TAG)
+ case MeterPart:
+ return paintMeter(o, paintInfo, r);
+#endif
#if ENABLE(PROGRESS_TAG)
case ProgressBarPart:
return paintProgressBar(o, paintInfo, r);
@@ -370,6 +384,9 @@ bool RenderTheme::paintBorderOnly(RenderObject* o, const RenderObject::PaintInfo
case DefaultButtonPart:
case ButtonPart:
case MenulistPart:
+#if ENABLE(METER_TAG)
+ case MeterPart:
+#endif
#if ENABLE(PROGRESS_TAG)
case ProgressBarPart:
#endif
@@ -408,6 +425,9 @@ bool RenderTheme::paintDecorations(RenderObject* o, const RenderObject::PaintInf
case DefaultButtonPart:
case ButtonPart:
case MenulistPart:
+#if ENABLE(METER_TAG)
+ case MeterPart:
+#endif
#if ENABLE(PROGRESS_TAG)
case ProgressBarPart:
#endif
@@ -871,6 +891,61 @@ void RenderTheme::adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*)
{
}
+#if ENABLE(METER_TAG)
+void RenderTheme::adjustMeterStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+{
+ style->setBoxShadow(0);
+}
+
+bool RenderTheme::paintMeter(RenderObject* renderObject, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
+{
+ // Some platforms do not have a native gauge widget, so we draw here a default implementation.
+ RenderMeter* renderMeter = toRenderMeter(renderObject);
+ RenderStyle* style = renderObject->style();
+ int left = style->borderLeft().width() + style->paddingLeft().value();
+ int top = style->borderTop().width() + style->paddingTop().value();
+ int right = style->borderRight().width() + style->paddingRight().value();
+ int bottom = style->borderBottom().width() + style->paddingBottom().value();
+ FloatRect innerRect(rect.x() + left, rect.y() + top, rect.width() - left - right, rect.height() - top - bottom);
+
+ HTMLMeterElement* element = static_cast<HTMLMeterElement*>(renderMeter->node());
+ double min = element->min();
+ double max = element->max();
+ double value = element->value();
+
+ if (min >= max) {
+ paintInfo.context->fillRect(innerRect, Color::black, style->colorSpace());
+ return false;
+ }
+
+ // Paint the background first
+ paintInfo.context->fillRect(innerRect, Color::lightGray, style->colorSpace());
+
+ FloatRect valueRect;
+
+ if (rect.width() < rect.height()) {
+ // Vertical gauge
+ double scale = innerRect.height() / (max - min);
+ valueRect.setLocation(FloatPoint(innerRect.x(), innerRect.y() + narrowPrecisionToFloat((max - value) * scale)));
+ valueRect.setSize(FloatSize(innerRect.width(), narrowPrecisionToFloat((value - min) * scale)));
+ } else if (renderMeter->style()->direction() == RTL) {
+ // right to left horizontal gauge
+ double scale = innerRect.width() / (max - min);
+ valueRect.setLocation(FloatPoint(innerRect.x() + narrowPrecisionToFloat((max - value) * scale), innerRect.y()));
+ valueRect.setSize(FloatSize(narrowPrecisionToFloat((value - min) * scale), innerRect.height()));
+ } else {
+ // left to right horizontal gauge
+ double scale = innerRect.width() / (max - min);
+ valueRect.setLocation(innerRect.location());
+ valueRect.setSize(FloatSize(narrowPrecisionToFloat((value - min)) * scale, innerRect.height()));
+ }
+ if (!valueRect.isEmpty())
+ paintInfo.context->fillRect(valueRect, Color::black, style->colorSpace());
+
+ return false;
+}
+#endif
+
#if ENABLE(PROGRESS_TAG)
double RenderTheme::animationRepeatIntervalForProgressBar(RenderProgress*) const
{
diff --git a/WebCore/rendering/RenderTheme.h b/WebCore/rendering/RenderTheme.h
index 6edc878..a4514a5 100644
--- a/WebCore/rendering/RenderTheme.h
+++ b/WebCore/rendering/RenderTheme.h
@@ -240,6 +240,11 @@ protected:
virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+#if ENABLE(METER_TAG)
+ virtual void adjustMeterStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintMeter(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+#endif
+
#if ENABLE(PROGRESS_TAG)
virtual void adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
virtual bool paintProgressBar(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
diff --git a/WebCore/rendering/RenderThemeChromiumWin.cpp b/WebCore/rendering/RenderThemeChromiumWin.cpp
index db31825..5d39698 100644
--- a/WebCore/rendering/RenderThemeChromiumWin.cpp
+++ b/WebCore/rendering/RenderThemeChromiumWin.cpp
@@ -38,6 +38,7 @@
#include "HTMLNames.h"
#include "MediaControlElements.h"
#include "RenderBox.h"
+#include "RenderProgress.h"
#include "RenderSlider.h"
#include "ScrollbarTheme.h"
#include "TransparencyWin.h"
@@ -653,4 +654,60 @@ bool RenderThemeChromiumWin::paintTextFieldInternal(RenderObject* o,
return false;
}
+#if ENABLE(PROGRESS_TAG)
+
+// MSDN says that update intervals for the bar is 30ms.
+// http://msdn.microsoft.com/en-us/library/bb760842(v=VS.85).aspx
+static const double progressAnimationFrameRate = 0.033;
+// There is no documentation about the animation speed, frame-rate, nor
+// size of moving overlay of the indeterminate progress bar.
+// So we just observed real-world programs and guessed following parameters.
+static const double progressIndeterminateOverlayPixelsPerSecond = 175;
+static const int progressIndeterminateOverlayWidth = 120;
+
+double RenderThemeChromiumWin::animationRepeatIntervalForProgressBar(RenderProgress*) const
+{
+ return progressAnimationFrameRate;
+}
+
+double RenderThemeChromiumWin::animationDurationForProgressBar(RenderProgress* renderProgress) const
+{
+ if (renderProgress->isDeterminate())
+ return 0;
+ return (renderProgress->width() + progressIndeterminateOverlayWidth) / progressIndeterminateOverlayPixelsPerSecond;
+}
+
+void RenderThemeChromiumWin::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+{
+}
+
+bool RenderThemeChromiumWin::paintProgressBar(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ RenderProgress* renderProgress = toRenderProgress(o);
+
+ int valuePart;
+ IntRect valueRect;
+ if (renderProgress->isDeterminate()) {
+ valuePart = PP_FILL;
+ int dx = r.width() * renderProgress->position();
+ if (renderProgress->style()->direction() == RTL)
+ valueRect = IntRect(r.x() + r.width() - dx, r.y(), dx, r.height());
+ else
+ valueRect = IntRect(r.x(), r.y(), dx, r.height());
+ } else {
+ valuePart = PP_MOVEOVERLAY;
+ int dx = (r.width() + progressIndeterminateOverlayWidth) * renderProgress->animationProgress() - progressIndeterminateOverlayWidth;
+ valueRect = IntRect(r.x() + dx, r.y(), progressIndeterminateOverlayWidth, r.height());
+ }
+
+ ThemePainter painter(i.context, r);
+ ChromiumBridge::paintProgressBar(painter.context(),
+ r,
+ valuePart,
+ valueRect);
+ return true;
+}
+
+#endif
+
} // namespace WebCore
diff --git a/WebCore/rendering/RenderThemeChromiumWin.h b/WebCore/rendering/RenderThemeChromiumWin.h
index bbc54a7..131314a 100644
--- a/WebCore/rendering/RenderThemeChromiumWin.h
+++ b/WebCore/rendering/RenderThemeChromiumWin.h
@@ -86,6 +86,14 @@ namespace WebCore {
// See comment in RenderThemeChromiumSkia::setDefaultFontSize() regarding ugliness of this hack.
static void setDefaultFontSize(int);
+
+#if ENABLE(PROGRESS_TAG)
+ virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const;
+ virtual double animationDurationForProgressBar(RenderProgress*) const;
+ virtual void adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintProgressBar(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+#endif
+
protected:
virtual double caretBlinkIntervalInternal() const;
diff --git a/WebCore/rendering/RenderTreeAsText.cpp b/WebCore/rendering/RenderTreeAsText.cpp
index 311854e..fd63c0e 100644
--- a/WebCore/rendering/RenderTreeAsText.cpp
+++ b/WebCore/rendering/RenderTreeAsText.cpp
@@ -81,7 +81,7 @@ static TextStream &operator<<(TextStream& ts, const IntRect& r)
}
#endif
-static void writeIndent(TextStream& ts, int indent)
+void writeIndent(TextStream& ts, int indent)
{
for (int i = 0; i != indent; ++i)
ts << " ";
@@ -185,7 +185,7 @@ static void writeRenderObject(TextStream& ts, const RenderObject& o, RenderAsTex
ts << o.renderName();
if (behavior & RenderAsTextShowAddresses)
- ts << " " << &o;
+ ts << " " << static_cast<const void*>(&o);
if (o.style() && o.style()->zIndex())
ts << " zI: " << o.style()->zIndex();
@@ -476,7 +476,7 @@ static void write(TextStream& ts, RenderLayer& l,
ts << "layer ";
if (behavior & RenderAsTextShowAddresses)
- ts << &l << " ";
+ ts << static_cast<const void*>(&l) << " ";
ts << layerBounds;
diff --git a/WebCore/rendering/RenderTreeAsText.h b/WebCore/rendering/RenderTreeAsText.h
index 1427342..ecee7f9 100644
--- a/WebCore/rendering/RenderTreeAsText.h
+++ b/WebCore/rendering/RenderTreeAsText.h
@@ -47,6 +47,7 @@ typedef unsigned RenderAsTextBehavior;
// You don't need pageWidthInPixels if you don't specify RenderAsTextInPrintingMode.
String externalRepresentation(Frame*, RenderAsTextBehavior = RenderAsTextBehaviorNormal);
void write(TextStream&, const RenderObject&, int indent = 0, RenderAsTextBehavior = RenderAsTextBehaviorNormal);
+void writeIndent(TextStream&, int indent);
// Helper function shared with SVGRenderTreeAsText
String quoteAndEscapeNonPrintables(const String&);
diff --git a/WebCore/rendering/RenderView.cpp b/WebCore/rendering/RenderView.cpp
index 449e293..7a38e41 100644
--- a/WebCore/rendering/RenderView.cpp
+++ b/WebCore/rendering/RenderView.cpp
@@ -73,10 +73,6 @@ RenderView::RenderView(Node* node, FrameView* view)
setPrefWidthsDirty(true, false);
setPositioned(true); // to 0,0 :)
-
- // Create a new root layer for our layer hierarchy.
- m_layer = new (node->document()->renderArena()) RenderLayer(this);
- setHasLayer(true);
}
RenderView::~RenderView()
@@ -216,6 +212,15 @@ void RenderView::paintBoxDecorations(PaintInfo& paintInfo, int, int)
frameView()->setUseSlowRepaints();
break;
}
+
+#if USE(ACCELERATED_COMPOSITING)
+ if (RenderLayer* compositingLayer = layer->enclosingCompositingLayer()) {
+ if (!compositingLayer->backing()->paintingGoesToWindow()) {
+ frameView()->setUseSlowRepaints();
+ break;
+ }
+ }
+#endif
}
// If painting will entirely fill the view, no need to fill the background.
diff --git a/WebCore/rendering/RenderView.h b/WebCore/rendering/RenderView.h
index 05c3876..799b206 100644
--- a/WebCore/rendering/RenderView.h
+++ b/WebCore/rendering/RenderView.h
@@ -44,6 +44,8 @@ public:
virtual bool isRenderView() const { return true; }
+ virtual bool requiresLayer() const { return true; }
+
virtual void layout();
virtual void calcWidth();
virtual void calcHeight();
diff --git a/WebCore/rendering/RenderWidget.cpp b/WebCore/rendering/RenderWidget.cpp
index 2c53da4..e477676 100644
--- a/WebCore/rendering/RenderWidget.cpp
+++ b/WebCore/rendering/RenderWidget.cpp
@@ -282,10 +282,15 @@ void RenderWidget::paint(PaintInfo& paintInfo, int tx, int ty)
if (!paintOffset.isZero())
paintInfo.context->translate(-paintOffset);
}
- if (m_widget->isFrameView() && paintInfo.overlapTestRequests && !static_cast<FrameView*>(m_widget.get())->useSlowRepaintsIfNotOverlapped()) {
- ASSERT(!paintInfo.overlapTestRequests->contains(this));
- paintInfo.overlapTestRequests->set(this, m_widget->frameRect());
- }
+
+ if (m_widget->isFrameView()) {
+ FrameView* frameView = static_cast<FrameView*>(m_widget.get());
+ bool runOverlapTests = !frameView->useSlowRepaintsIfNotOverlapped() || frameView->hasCompositedContent();
+ if (paintInfo.overlapTestRequests && runOverlapTests) {
+ ASSERT(!paintInfo.overlapTestRequests->contains(this));
+ paintInfo.overlapTestRequests->set(this, m_widget->frameRect());
+ }
+ }
}
if (style()->hasBorderRadius())
diff --git a/WebCore/rendering/RootInlineBox.cpp b/WebCore/rendering/RootInlineBox.cpp
index 23316f7..691179d 100644
--- a/WebCore/rendering/RootInlineBox.cpp
+++ b/WebCore/rendering/RootInlineBox.cpp
@@ -202,7 +202,7 @@ void RootInlineBox::childRemoved(InlineBox* box)
}
}
-int RootInlineBox::verticallyAlignBoxes(int heightOfBlock)
+int RootInlineBox::verticallyAlignBoxes(int heightOfBlock, GlyphOverflowAndFallbackFontsMap& textBoxDataMap)
{
int maxPositionTop = 0;
int maxPositionBottom = 0;
@@ -216,7 +216,7 @@ int RootInlineBox::verticallyAlignBoxes(int heightOfBlock)
curr = curr->container();
bool strictMode = (curr && curr->document()->inStrictMode());
- computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode);
+ computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode, textBoxDataMap);
if (maxAscent + maxDescent < max(maxPositionTop, maxPositionBottom))
adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom);
@@ -225,7 +225,7 @@ int RootInlineBox::verticallyAlignBoxes(int heightOfBlock)
int lineTop = heightOfBlock;
int lineBottom = heightOfBlock;
placeBoxesVertically(heightOfBlock, maxHeight, maxAscent, strictMode, lineTop, lineBottom);
- computeVerticalOverflow(lineTop, lineBottom, strictMode);
+ computeVerticalOverflow(lineTop, lineBottom, strictMode, textBoxDataMap);
setLineTopBottomPositions(lineTop, lineBottom);
heightOfBlock += maxHeight;
diff --git a/WebCore/rendering/RootInlineBox.h b/WebCore/rendering/RootInlineBox.h
index fae0cba..cfa550b 100644
--- a/WebCore/rendering/RootInlineBox.h
+++ b/WebCore/rendering/RootInlineBox.h
@@ -61,7 +61,7 @@ public:
int selectionBottom() const { return lineBottom(); }
int selectionHeight() const { return max(0, selectionBottom() - selectionTop()); }
- virtual int verticallyAlignBoxes(int heightOfBlock);
+ virtual int verticallyAlignBoxes(int heightOfBlock, GlyphOverflowAndFallbackFontsMap&);
void setLineTopBottomPositions(int top, int bottom);
virtual RenderLineBoxList* rendererLineBoxes() const;
diff --git a/WebCore/rendering/SVGInlineFlowBox.cpp b/WebCore/rendering/SVGInlineFlowBox.cpp
index 2649664..bbd61b3 100644
--- a/WebCore/rendering/SVGInlineFlowBox.cpp
+++ b/WebCore/rendering/SVGInlineFlowBox.cpp
@@ -37,13 +37,7 @@ void SVGInlineFlowBox::paint(RenderObject::PaintInfo&, int, int)
ASSERT_NOT_REACHED();
}
-int SVGInlineFlowBox::placeBoxesHorizontally(int, int&, int&, bool&)
-{
- // no-op
- return 0;
-}
-
-int SVGInlineFlowBox::verticallyAlignBoxes(int)
+int SVGInlineFlowBox::placeBoxesHorizontally(int, int&, int&, bool&, GlyphOverflowAndFallbackFontsMap&)
{
// no-op
return 0;
diff --git a/WebCore/rendering/SVGInlineFlowBox.h b/WebCore/rendering/SVGInlineFlowBox.h
index f6eb87a..17ad528 100644
--- a/WebCore/rendering/SVGInlineFlowBox.h
+++ b/WebCore/rendering/SVGInlineFlowBox.h
@@ -41,8 +41,7 @@ public:
void setHeight(int h) { m_height = h; }
virtual void paint(RenderObject::PaintInfo&, int tx, int ty);
- virtual int placeBoxesHorizontally(int x, int& leftPosition, int& rightPosition, bool& needsWordSpacing);
- virtual int verticallyAlignBoxes(int heightOfBlock);
+ virtual int placeBoxesHorizontally(int x, int& leftPosition, int& rightPosition, bool& needsWordSpacing, GlyphOverflowAndFallbackFontsMap&);
private:
int m_height;
diff --git a/WebCore/rendering/SVGInlineTextBox.cpp b/WebCore/rendering/SVGInlineTextBox.cpp
index 8b35507..3ae272e 100644
--- a/WebCore/rendering/SVGInlineTextBox.cpp
+++ b/WebCore/rendering/SVGInlineTextBox.cpp
@@ -1,6 +1,7 @@
/**
* Copyright (C) 2007 Rob Buis <buis@kde.org>
* (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -24,14 +25,12 @@
#if ENABLE(SVG)
#include "SVGInlineTextBox.h"
-#include "Document.h"
-#include "Editor.h"
#include "Frame.h"
#include "GraphicsContext.h"
#include "InlineFlowBox.h"
-#include "Range.h"
#include "RenderSVGResource.h"
#include "SVGRootInlineBox.h"
+#include "SVGTextLayoutUtilities.h"
#include "Text.h"
#include <float.h>
@@ -44,16 +43,6 @@ SVGInlineTextBox::SVGInlineTextBox(RenderObject* obj)
{
}
-int SVGInlineTextBox::selectionTop()
-{
- return m_y;
-}
-
-int SVGInlineTextBox::selectionHeight()
-{
- return m_height;
-}
-
SVGRootInlineBox* SVGInlineTextBox::svgRootInlineBox() const
{
// Find associated root inline box
@@ -74,7 +63,7 @@ SVGRootInlineBox* SVGInlineTextBox::svgRootInlineBox() const
float SVGInlineTextBox::calculateGlyphWidth(RenderStyle* style, int offset, int extraCharsAvailable, int& charsConsumed, String& glyphName) const
{
ASSERT(style);
- return style->font().floatWidth(svgTextRunForInlineTextBox(textRenderer()->text()->characters() + offset, 1, style, this, 0), extraCharsAvailable, charsConsumed, glyphName);
+ return style->font().floatWidth(svgTextRunForInlineTextBox(textRenderer()->characters() + offset, 1, style, this, 0), extraCharsAvailable, charsConsumed, glyphName);
}
float SVGInlineTextBox::calculateGlyphHeight(RenderStyle* style, int, int) const
@@ -260,7 +249,7 @@ bool SVGInlineTextBox::svgCharacterHitsPosition(int x, int y, int& closestOffset
if (x < charAtPos.x) {
if (closestOffsetInBox > 0 && direction() == LTR)
return true;
- else if (closestOffsetInBox < (int) end() && direction() == RTL)
+ if (closestOffsetInBox < static_cast<int>(end()) && direction() == RTL)
return true;
return false;
@@ -490,7 +479,7 @@ void SVGInlineTextBox::paintSelection(int boxStartOffset, const SVGChar& svgChar
Color textColor = style->color();
Color color = renderer()->selectionBackgroundColor();
- if (!color.isValid() || color.alpha() == 0)
+ if (!color.isValid() || !color.alpha())
return;
// If the text color ends up being the same as the selection background, invert the selection
@@ -516,7 +505,7 @@ void SVGInlineTextBox::paintSelection(int boxStartOffset, const SVGChar& svgChar
p->save();
int adjust = startPos >= boxStartOffset ? boxStartOffset : 0;
- p->drawHighlightForText(font, svgTextRunForInlineTextBox(textRenderer()->text()->characters() + start() + boxStartOffset, length, style, this, svgChar.x),
+ p->drawHighlightForText(font, svgTextRunForInlineTextBox(textRenderer()->characters() + start() + boxStartOffset, length, style, this, svgChar.x),
IntPoint((int) svgChar.x, (int) svgChar.y - font.ascent()),
font.ascent() + font.descent(), color, style->colorSpace(), startPos - adjust, endPos - adjust);
@@ -589,6 +578,233 @@ void SVGInlineTextBox::paintDecoration(ETextDecoration decoration, GraphicsConte
context->restore();
}
+void SVGInlineTextBox::buildLayoutInformation(SVGCharacterLayoutInfo& info, SVGLastGlyphInfo& lastGlyph)
+{
+ RenderText* textRenderer = this->textRenderer();
+ ASSERT(textRenderer);
+
+ RenderStyle* style = textRenderer->style(isFirstLineStyle());
+ ASSERT(style);
+
+ const Font& font = style->font();
+ const UChar* characters = textRenderer->characters();
+
+ TextDirection textDirection = direction();
+ unsigned startPosition = start();
+ unsigned endPosition = end();
+ unsigned length = len();
+
+ const SVGRenderStyle* svgStyle = style->svgStyle();
+ bool isVerticalText = isVerticalWritingMode(svgStyle);
+
+ int charsConsumed = 0;
+ for (unsigned i = 0; i < length; i += charsConsumed) {
+ SVGChar svgChar;
+
+ if (info.inPathLayout())
+ svgChar.pathData = SVGCharOnPath::create();
+
+ float glyphWidth = 0.0f;
+ float glyphHeight = 0.0f;
+
+ int extraCharsAvailable = length - i - 1;
+
+ String unicodeStr;
+ String glyphName;
+ if (textDirection == RTL) {
+ glyphWidth = calculateGlyphWidth(style, endPosition - i, extraCharsAvailable, charsConsumed, glyphName);
+ glyphHeight = calculateGlyphHeight(style, endPosition - i, extraCharsAvailable);
+ unicodeStr = String(characters + endPosition - i, charsConsumed);
+ } else {
+ glyphWidth = calculateGlyphWidth(style, startPosition + i, extraCharsAvailable, charsConsumed, glyphName);
+ glyphHeight = calculateGlyphHeight(style, startPosition + i, extraCharsAvailable);
+ unicodeStr = String(characters + startPosition + i, charsConsumed);
+ }
+
+ bool assignedX = false;
+ bool assignedY = false;
+
+ if (info.xValueAvailable() && (!info.inPathLayout() || (info.inPathLayout() && !isVerticalText))) {
+ if (!isVerticalText)
+ svgChar.newTextChunk = true;
+
+ assignedX = true;
+ svgChar.drawnSeperated = true;
+ info.curx = info.xValueNext();
+ }
+
+ if (info.yValueAvailable() && (!info.inPathLayout() || (info.inPathLayout() && isVerticalText))) {
+ if (isVerticalText)
+ svgChar.newTextChunk = true;
+
+ assignedY = true;
+ svgChar.drawnSeperated = true;
+ info.cury = info.yValueNext();
+ }
+
+ float dx = 0.0f;
+ float dy = 0.0f;
+
+ // Apply x-axis shift
+ if (info.dxValueAvailable()) {
+ svgChar.drawnSeperated = true;
+
+ dx = info.dxValueNext();
+ info.dx += dx;
+
+ if (!info.inPathLayout())
+ info.curx += dx;
+ }
+
+ // Apply y-axis shift
+ if (info.dyValueAvailable()) {
+ svgChar.drawnSeperated = true;
+
+ dy = info.dyValueNext();
+ info.dy += dy;
+
+ if (!info.inPathLayout())
+ info.cury += dy;
+ }
+
+ // Take letter & word spacing and kerning into account
+ float spacing = font.letterSpacing() + calculateCSSKerning(style);
+
+ const UChar* currentCharacter = characters + (textDirection == RTL ? endPosition - i : startPosition + i);
+ const UChar* lastCharacter = 0;
+
+ if (textDirection == RTL) {
+ if (i < endPosition)
+ lastCharacter = characters + endPosition - i + 1;
+ } else {
+ if (i > 0)
+ lastCharacter = characters + startPosition + i - 1;
+ }
+
+ // FIXME: SVG Kerning doesn't get applied on texts on path.
+ bool appliedSVGKerning = applySVGKerning(info, style, lastGlyph, unicodeStr, glyphName, isVerticalText);
+ if (info.nextDrawnSeperated || spacing != 0.0f || appliedSVGKerning) {
+ info.nextDrawnSeperated = false;
+ svgChar.drawnSeperated = true;
+ }
+
+ if (currentCharacter && Font::treatAsSpace(*currentCharacter) && lastCharacter && !Font::treatAsSpace(*lastCharacter)) {
+ spacing += font.wordSpacing();
+
+ if (spacing != 0.0f && !info.inPathLayout())
+ info.nextDrawnSeperated = true;
+ }
+
+ float orientationAngle = glyphOrientationToAngle(svgStyle, isVerticalText, *currentCharacter);
+
+ float xOrientationShift = 0.0f;
+ float yOrientationShift = 0.0f;
+ float glyphAdvance = applyGlyphAdvanceAndShiftRespectingOrientation(isVerticalText, orientationAngle, glyphWidth, glyphHeight,
+ font, svgChar, xOrientationShift, yOrientationShift);
+
+ // Handle textPath layout mode
+ if (info.inPathLayout()) {
+ float extraAdvance = isVerticalText ? dy : dx;
+ float newOffset = FLT_MIN;
+
+ if (assignedX && !isVerticalText)
+ newOffset = info.curx;
+ else if (assignedY && isVerticalText)
+ newOffset = info.cury;
+
+ float correctedGlyphAdvance = glyphAdvance;
+
+ // Handle lengthAdjust="spacingAndGlyphs" by specifying per-character scale operations
+ if (info.pathTextLength && info.pathChunkLength) {
+ if (isVerticalText) {
+ svgChar.pathData->yScale = info.pathChunkLength / info.pathTextLength;
+ spacing *= svgChar.pathData->yScale;
+ correctedGlyphAdvance *= svgChar.pathData->yScale;
+ } else {
+ svgChar.pathData->xScale = info.pathChunkLength / info.pathTextLength;
+ spacing *= svgChar.pathData->xScale;
+ correctedGlyphAdvance *= svgChar.pathData->xScale;
+ }
+ }
+
+ // Handle letter & word spacing on text path
+ float pathExtraAdvance = info.pathExtraAdvance;
+ info.pathExtraAdvance += spacing;
+
+ svgChar.pathData->hidden = !info.nextPathLayoutPointAndAngle(correctedGlyphAdvance, extraAdvance, newOffset);
+ svgChar.drawnSeperated = true;
+
+ info.pathExtraAdvance = pathExtraAdvance;
+ }
+
+ // Apply rotation
+ if (info.angleValueAvailable())
+ info.angle = info.angleValueNext();
+
+ // Apply baseline-shift
+ if (info.baselineShiftValueAvailable()) {
+ svgChar.drawnSeperated = true;
+ float shift = info.baselineShiftValueNext();
+
+ if (isVerticalText)
+ info.shiftx += shift;
+ else
+ info.shifty -= shift;
+ }
+
+ // Take dominant-baseline / alignment-baseline into account
+ yOrientationShift += alignmentBaselineToShift(isVerticalText, textRenderer, font);
+
+ svgChar.x = info.curx;
+ svgChar.y = info.cury;
+ svgChar.angle = info.angle;
+
+ // For text paths any shift (dx/dy/baseline-shift) has to be applied after the rotation
+ if (!info.inPathLayout()) {
+ svgChar.x += info.shiftx + xOrientationShift;
+ svgChar.y += info.shifty + yOrientationShift;
+
+ if (orientationAngle != 0.0f)
+ 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;
+ }
+ }
+
+ // Advance to new position
+ if (isVerticalText) {
+ svgChar.drawnSeperated = true;
+ info.cury += glyphAdvance + spacing;
+ } else
+ info.curx += glyphAdvance + spacing;
+
+ // Advance to next character group
+ for (int k = 0; k < charsConsumed; ++k) {
+ info.svgChars.append(svgChar);
+ info.processedSingleCharacter();
+ svgChar.drawnSeperated = false;
+ svgChar.newTextChunk = false;
+ }
+ }
+}
+
} // namespace WebCore
#endif
diff --git a/WebCore/rendering/SVGInlineTextBox.h b/WebCore/rendering/SVGInlineTextBox.h
index c586ddd..77b6498 100644
--- a/WebCore/rendering/SVGInlineTextBox.h
+++ b/WebCore/rendering/SVGInlineTextBox.h
@@ -28,72 +28,57 @@
namespace WebCore {
- class SVGRootInlineBox;
+class SVGRootInlineBox;
- struct SVGChar;
- struct SVGTextDecorationInfo;
+struct SVGChar;
+struct SVGCharacterLayoutInfo;
+struct SVGLastGlyphInfo;
+struct SVGTextDecorationInfo;
+struct SVGTextPaintInfo;
- enum SVGTextPaintSubphase {
- SVGTextPaintSubphaseBackground,
- SVGTextPaintSubphaseGlyphFill,
- SVGTextPaintSubphaseGlyphFillSelection,
- SVGTextPaintSubphaseGlyphStroke,
- SVGTextPaintSubphaseGlyphStrokeSelection,
- SVGTextPaintSubphaseForeground
- };
+class SVGInlineTextBox : public InlineTextBox {
+public:
+ SVGInlineTextBox(RenderObject* obj);
- struct SVGTextPaintInfo {
- SVGTextPaintInfo()
- : activePaintingResource(0)
- , subphase(SVGTextPaintSubphaseBackground)
- {
- }
+ virtual int virtualHeight() const { return m_height; }
+ void setHeight(int h) { m_height = h; }
- RenderSVGResource* activePaintingResource;
- SVGTextPaintSubphase subphase;
- };
+ virtual int selectionTop() { return m_y; }
+ virtual int selectionHeight() { return m_height; }
- class SVGInlineTextBox : public InlineTextBox {
- public:
- SVGInlineTextBox(RenderObject* obj);
+ virtual int offsetForPosition(int x, bool includePartialGlyphs = true) const;
+ virtual int positionForOffset(int offset) const;
- virtual int virtualHeight() const { return m_height; }
- void setHeight(int h) { m_height = h; }
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty);
+ virtual IntRect selectionRect(int absx, int absy, int startPos, int endPos);
- virtual int selectionTop();
- virtual int selectionHeight();
+ // SVGs custom paint text method
+ void paintCharacters(RenderObject::PaintInfo&, int tx, int ty, const SVGChar&, const UChar* chars, int length, SVGTextPaintInfo&);
- virtual int offsetForPosition(int x, bool includePartialGlyphs = true) const;
- virtual int positionForOffset(int offset) const;
+ // SVGs custom paint selection method
+ void paintSelection(int boxStartOffset, const SVGChar&, const UChar*, int length, GraphicsContext*, RenderStyle*, const Font&);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty);
- virtual IntRect selectionRect(int absx, int absy, int startPos, int endPos);
+ // SVGs custom paint decoration method
+ void paintDecoration(ETextDecoration, GraphicsContext*, int tx, int ty, int width, const SVGChar&, const SVGTextDecorationInfo&);
+
+ SVGRootInlineBox* svgRootInlineBox() const;
- // SVGs custom paint text method
- void paintCharacters(RenderObject::PaintInfo&, int tx, int ty, const SVGChar&, const UChar* chars, int length, SVGTextPaintInfo&);
+ // Helper functions shared with SVGRootInlineBox
+ float calculateGlyphWidth(RenderStyle* style, int offset, int extraCharsAvailable, int& charsConsumed, String& glyphName) const;
+ float calculateGlyphHeight(RenderStyle*, int offset, int extraCharsAvailable) const;
- // SVGs custom paint selection method
- void paintSelection(int boxStartOffset, const SVGChar&, const UChar*, int length, GraphicsContext*, RenderStyle*, const Font&);
+ FloatRect calculateGlyphBoundaries(RenderStyle*, int offset, const SVGChar&) const;
+ SVGChar* closestCharacterToPosition(int x, int y, int& offset) const;
- // SVGs custom paint decoration method
- void paintDecoration(ETextDecoration, GraphicsContext*, int tx, int ty, int width, const SVGChar&, const SVGTextDecorationInfo&);
-
- SVGRootInlineBox* svgRootInlineBox() const;
-
- // Helper functions shared with SVGRootInlineBox
- float calculateGlyphWidth(RenderStyle* style, int offset, int extraCharsAvailable, int& charsConsumed, String& glyphName) const;
- float calculateGlyphHeight(RenderStyle*, int offset, int extraCharsAvailable) const;
-
- FloatRect calculateGlyphBoundaries(RenderStyle*, int offset, const SVGChar&) const;
- SVGChar* closestCharacterToPosition(int x, int y, int& offset) const;
-
- private:
- friend class RenderSVGInlineText;
- bool svgCharacterHitsPosition(int x, int y, int& offset) const;
- bool chunkSelectionStartEnd(const UChar* chunk, int chunkLength, int& selectionStart, int& selectionEnd);
-
- int m_height;
- };
+ void buildLayoutInformation(SVGCharacterLayoutInfo&, SVGLastGlyphInfo&);
+
+private:
+ friend class RenderSVGInlineText;
+ bool svgCharacterHitsPosition(int x, int y, int& offset) const;
+ bool chunkSelectionStartEnd(const UChar* chunk, int chunkLength, int& selectionStart, int& selectionEnd);
+
+ int m_height;
+};
} // namespace WebCore
diff --git a/WebCore/rendering/SVGRenderTreeAsText.cpp b/WebCore/rendering/SVGRenderTreeAsText.cpp
index f6fbae2..8b4c563 100644
--- a/WebCore/rendering/SVGRenderTreeAsText.cpp
+++ b/WebCore/rendering/SVGRenderTreeAsText.cpp
@@ -64,6 +64,7 @@
#include "SVGRootInlineBox.h"
#include "SVGStopElement.h"
#include "SVGStyledElement.h"
+#include "SVGTextLayoutUtilities.h"
#include <math.h>
@@ -264,12 +265,6 @@ TextStream& operator<<(TextStream& ts, const Color& c)
return ts << c.name();
}
-static void writeIndent(TextStream& ts, int indent)
-{
- for (int i = 0; i != indent; ++i)
- ts << " ";
-}
-
// FIXME: Maybe this should be in KCanvasRenderingStyle.cpp
static TextStream& operator<<(TextStream& ts, const DashArray& a)
{
@@ -596,44 +591,31 @@ void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int i
RenderSVGResourceMasker* masker = static_cast<RenderSVGResourceMasker*>(resource);
writeNameValuePair(ts, "maskUnits", masker->maskUnits());
writeNameValuePair(ts, "maskContentUnits", masker->maskContentUnits());
+ ts << "\n";
#if ENABLE(FILTERS)
} else if (resource->resourceType() == FilterResourceType) {
RenderSVGResourceFilter* filter = static_cast<RenderSVGResourceFilter*>(resource);
writeNameValuePair(ts, "filterUnits", filter->filterUnits());
writeNameValuePair(ts, "primitiveUnits", filter->primitiveUnits());
+ ts << "\n";
if (OwnPtr<SVGFilterBuilder> builder = filter->buildPrimitives()) {
- ts << "\n";
- const HashMap<AtomicString, RefPtr<FilterEffect> >& effects = builder->namedEffects();
- HashMap<AtomicString, RefPtr<FilterEffect> >::const_iterator end = effects.end();
- for (HashMap<AtomicString, RefPtr<FilterEffect> >::const_iterator it = effects.begin(); it != end; ++it) {
- writeIndent(ts, indent);
- ts << " [primitve=\"" << it->first << "\" ";
- it->second->externalRepresentation(ts);
- ts << "]\n";
- }
- writeIndent(ts, indent);
- // FIXME: Some effects don't give a representation back. So we miss some more informations
- // after '[last primitive' .
- // We also just dump named effects and the last effect at the moment, more effects
- // without a name might be in the pipe.
- ts << " [last primitive ";
if (FilterEffect* lastEffect = builder->lastEffect())
- lastEffect->externalRepresentation(ts);
- ts << "]";
- }
+ lastEffect->externalRepresentation(ts, indent + 1);
+ }
#endif
} else if (resource->resourceType() == ClipperResourceType) {
RenderSVGResourceClipper* clipper = static_cast<RenderSVGResourceClipper*>(resource);
writeNameValuePair(ts, "clipPathUnits", clipper->clipPathUnits());
+ ts << "\n";
} else if (resource->resourceType() == MarkerResourceType) {
RenderSVGResourceMarker* marker = static_cast<RenderSVGResourceMarker*>(resource);
writeNameValuePair(ts, "markerUnits", marker->markerUnits());
ts << " [ref at " << marker->referencePoint() << "]";
ts << " [angle=";
if (marker->angle() == -1)
- ts << "auto" << "]";
+ ts << "auto" << "]\n";
else
- ts << marker->angle() << "]";
+ ts << marker->angle() << "]\n";
} else if (resource->resourceType() == PatternResourceType) {
RenderSVGResourcePattern* pattern = static_cast<RenderSVGResourcePattern*>(resource);
@@ -646,6 +628,7 @@ void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int i
AffineTransform transform = attributes.patternTransform();
if (!transform.isIdentity())
ts << " [patternTransform=" << transform << "]";
+ ts << "\n";
} else if (resource->resourceType() == LinearGradientResourceType) {
RenderSVGResourceLinearGradient* gradient = static_cast<RenderSVGResourceLinearGradient*>(resource);
@@ -660,7 +643,7 @@ void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int i
FloatPoint endPoint;
linearGradientElement->calculateStartEndPoints(attributes, startPoint, endPoint);
- ts << " [start=" << startPoint << "] [end=" << endPoint << "]";
+ ts << " [start=" << startPoint << "] [end=" << endPoint << "]\n";
} else if (resource->resourceType() == RadialGradientResourceType) {
RenderSVGResourceRadialGradient* gradient = static_cast<RenderSVGResourceRadialGradient*>(resource);
@@ -676,10 +659,9 @@ void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int i
float radius;
radialGradientElement->calculateFocalCenterPointsAndRadius(attributes, focalPoint, centerPoint, radius);
- ts << " [center=" << centerPoint << "] [focal=" << focalPoint << "] [radius=" << radius << "]";
- }
-
- ts << "\n";
+ ts << " [center=" << centerPoint << "] [focal=" << focalPoint << "] [radius=" << radius << "]\n";
+ } else
+ ts << "\n";
writeChildren(ts, object, indent);
}
diff --git a/WebCore/rendering/SVGRootInlineBox.cpp b/WebCore/rendering/SVGRootInlineBox.cpp
index 6c99b1a..8760fe5 100644
--- a/WebCore/rendering/SVGRootInlineBox.cpp
+++ b/WebCore/rendering/SVGRootInlineBox.cpp
@@ -1,6 +1,4 @@
/*
- * This file is part of the WebKit project.
- *
* Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
* (C) 2006 Apple Computer Inc.
* (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
@@ -28,25 +26,15 @@
#if ENABLE(SVG)
#include "SVGRootInlineBox.h"
-#include "Editor.h"
-#include "FloatConversion.h"
-#include "Frame.h"
#include "GraphicsContext.h"
#include "RenderBlock.h"
-#include "RenderSVGResource.h"
#include "RenderSVGResourceFilter.h"
#include "RenderSVGRoot.h"
#include "SVGInlineFlowBox.h"
#include "SVGInlineTextBox.h"
-#include "SVGFontElement.h"
-#include "SVGRenderStyleDefs.h"
#include "SVGRenderSupport.h"
+#include "SVGTextLayoutUtilities.h"
#include "SVGTextPositioningElement.h"
-#include "SVGURIReference.h"
-#include "Text.h"
-#include "UnicodeRange.h"
-
-#include <float.h>
// Text chunk creation is complex and the whole process
// can easily be traced by setting this variable > 0.
@@ -54,217 +42,6 @@
namespace WebCore {
-static inline bool isVerticalWritingMode(const SVGRenderStyle* style)
-{
- return style->writingMode() == WM_TBRL || style->writingMode() == WM_TB;
-}
-
-static inline EAlignmentBaseline dominantBaselineToShift(bool isVerticalText, const RenderObject* text, const Font& font)
-{
- ASSERT(text);
-
- const SVGRenderStyle* style = text->style() ? text->style()->svgStyle() : 0;
- ASSERT(style);
-
- const SVGRenderStyle* parentStyle = text->parent() && text->parent()->style() ? text->parent()->style()->svgStyle() : 0;
-
- EDominantBaseline baseline = style->dominantBaseline();
- if (baseline == DB_AUTO) {
- if (isVerticalText)
- baseline = DB_CENTRAL;
- else
- baseline = DB_ALPHABETIC;
- }
-
- switch (baseline) {
- case DB_USE_SCRIPT:
- // TODO: The dominant-baseline and the baseline-table components are set by
- // determining the predominant script of the character data content.
- return AB_ALPHABETIC;
- case DB_NO_CHANGE:
- {
- if (parentStyle)
- return dominantBaselineToShift(isVerticalText, text->parent(), font);
-
- ASSERT_NOT_REACHED();
- return AB_AUTO;
- }
- case DB_RESET_SIZE:
- {
- if (parentStyle)
- return dominantBaselineToShift(isVerticalText, text->parent(), font);
-
- ASSERT_NOT_REACHED();
- return AB_AUTO;
- }
- case DB_IDEOGRAPHIC:
- return AB_IDEOGRAPHIC;
- case DB_ALPHABETIC:
- return AB_ALPHABETIC;
- case DB_HANGING:
- return AB_HANGING;
- case DB_MATHEMATICAL:
- return AB_MATHEMATICAL;
- case DB_CENTRAL:
- return AB_CENTRAL;
- case DB_MIDDLE:
- return AB_MIDDLE;
- case DB_TEXT_AFTER_EDGE:
- return AB_TEXT_AFTER_EDGE;
- case DB_TEXT_BEFORE_EDGE:
- return AB_TEXT_BEFORE_EDGE;
- default:
- ASSERT_NOT_REACHED();
- return AB_AUTO;
- }
-}
-
-static inline float alignmentBaselineToShift(bool isVerticalText, const RenderObject* text, const Font& font)
-{
- ASSERT(text);
-
- const SVGRenderStyle* style = text->style() ? text->style()->svgStyle() : 0;
- ASSERT(style);
-
- const SVGRenderStyle* parentStyle = text->parent() && text->parent()->style() ? text->parent()->style()->svgStyle() : 0;
-
- EAlignmentBaseline baseline = style->alignmentBaseline();
- if (baseline == AB_AUTO) {
- if (parentStyle && style->dominantBaseline() == DB_AUTO)
- baseline = dominantBaselineToShift(isVerticalText, text->parent(), font);
- else
- baseline = dominantBaselineToShift(isVerticalText, text, font);
-
- ASSERT(baseline != AB_AUTO);
- }
-
- // Note: http://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling
- switch (baseline) {
- case AB_BASELINE:
- {
- if (parentStyle)
- return dominantBaselineToShift(isVerticalText, text->parent(), font);
-
- return 0.0f;
- }
- case AB_BEFORE_EDGE:
- case AB_TEXT_BEFORE_EDGE:
- return font.ascent();
- case AB_MIDDLE:
- return font.xHeight() / 2.0f;
- case AB_CENTRAL:
- // Not needed, we're taking this into account already for vertical text!
- // return (font.ascent() - font.descent()) / 2.0f;
- return 0.0f;
- case AB_AFTER_EDGE:
- case AB_TEXT_AFTER_EDGE:
- case AB_IDEOGRAPHIC:
- return font.descent();
- case AB_ALPHABETIC:
- return 0.0f;
- case AB_HANGING:
- return font.ascent() * 8.0f / 10.0f;
- case AB_MATHEMATICAL:
- return font.ascent() / 2.0f;
- default:
- ASSERT_NOT_REACHED();
- return 0.0f;
- }
-}
-
-static inline float glyphOrientationToAngle(const SVGRenderStyle* svgStyle, bool isVerticalText, const UChar& character)
-{
- switch (isVerticalText ? svgStyle->glyphOrientationVertical() : svgStyle->glyphOrientationHorizontal()) {
- case GO_AUTO:
- {
- // Spec: Fullwidth ideographic and fullwidth Latin text will be set with a glyph-orientation of 0-degrees.
- // Text which is not fullwidth will be set with a glyph-orientation of 90-degrees.
- unsigned int unicodeRange = findCharUnicodeRange(character);
- if (unicodeRange == cRangeSetLatin || unicodeRange == cRangeArabic)
- return 90.0f;
-
- return 0.0f;
- }
- case GO_90DEG:
- return 90.0f;
- case GO_180DEG:
- return 180.0f;
- case GO_270DEG:
- return 270.0f;
- case GO_0DEG:
- default:
- return 0.0f;
- }
-}
-
-static inline bool glyphOrientationIsMultiplyOf180Degrees(float orientationAngle)
-{
- return fabsf(fmodf(orientationAngle, 180.0f)) == 0.0f;
-}
-
-static inline float calculateGlyphAdvanceAndShiftRespectingOrientation(bool isVerticalText, float orientationAngle, float glyphWidth, float glyphHeight, const Font& font, SVGChar& svgChar, float& xOrientationShift, float& yOrientationShift)
-{
- bool orientationIsMultiplyOf180Degrees = glyphOrientationIsMultiplyOf180Degrees(orientationAngle);
-
- // The function is based on spec requirements:
- //
- // Spec: If the 'glyph-orientation-horizontal' results in an orientation angle that is not a multiple of
- // of 180 degrees, then the current text position is incremented according to the vertical metrics of the glyph.
- //
- // Spec: If if the 'glyph-orientation-vertical' results in an orientation angle that is not a multiple of
- // 180 degrees,then the current text position is incremented according to the horizontal metrics of the glyph.
-
- // vertical orientation handling
- if (isVerticalText) {
- if (orientationAngle == 0.0f) {
- xOrientationShift = -glyphWidth / 2.0f;
- yOrientationShift = font.ascent();
- } else if (orientationAngle == 90.0f) {
- xOrientationShift = -glyphHeight;
- yOrientationShift = font.descent();
- svgChar.orientationShiftY = -font.ascent();
- } else if (orientationAngle == 270.0f) {
- xOrientationShift = glyphHeight;
- yOrientationShift = font.descent();
- svgChar.orientationShiftX = -glyphWidth;
- svgChar.orientationShiftY = -font.ascent();
- } else if (orientationAngle == 180.0f) {
- yOrientationShift = font.ascent();
- svgChar.orientationShiftX = -glyphWidth / 2.0f;
- svgChar.orientationShiftY = font.ascent() - font.descent();
- }
-
- // vertical advance calculation
- if (orientationAngle != 0.0f && !orientationIsMultiplyOf180Degrees)
- return glyphWidth;
-
- return glyphHeight;
- }
-
- // horizontal orientation handling
- if (orientationAngle == 90.0f) {
- xOrientationShift = glyphWidth / 2.0f;
- yOrientationShift = -font.descent();
- svgChar.orientationShiftX = -glyphWidth / 2.0f - font.descent();
- svgChar.orientationShiftY = font.descent();
- } else if (orientationAngle == 270.0f) {
- xOrientationShift = -glyphWidth / 2.0f;
- yOrientationShift = -font.descent();
- svgChar.orientationShiftX = -glyphWidth / 2.0f + font.descent();
- svgChar.orientationShiftY = glyphHeight;
- } else if (orientationAngle == 180.0f) {
- xOrientationShift = glyphWidth / 2.0f;
- svgChar.orientationShiftX = -glyphWidth / 2.0f;
- svgChar.orientationShiftY = font.ascent() - font.descent();
- }
-
- // horizontal advance calculation
- if (orientationAngle != 0.0f && !orientationIsMultiplyOf180Degrees)
- return glyphHeight;
-
- return glyphWidth;
-}
-
static inline void startTextChunk(SVGTextChunkLayoutInfo& info)
{
info.chunk.boxes.clear();
@@ -294,82 +71,6 @@ RenderSVGRoot* findSVGRootObject(RenderObject* start)
return toRenderSVGRoot(start);
}
-static inline FloatPoint topLeftPositionOfCharacterRange(Vector<SVGChar>& chars)
-{
- return topLeftPositionOfCharacterRange(chars.begin(), chars.end());
-}
-
-FloatPoint topLeftPositionOfCharacterRange(Vector<SVGChar>::iterator it, Vector<SVGChar>::iterator end)
-{
- float lowX = FLT_MAX, lowY = FLT_MAX;
- for (; it != end; ++it) {
- if (it->isHidden())
- continue;
-
- float x = (*it).x;
- float y = (*it).y;
-
- if (x < lowX)
- lowX = x;
-
- if (y < lowY)
- lowY = y;
- }
-
- return FloatPoint(lowX, lowY);
-}
-
-// Helper function
-static float calculateCSSKerning(RenderObject* item)
-{
- const Font& font = item->style()->font();
- const SVGRenderStyle* svgStyle = item->style()->svgStyle();
-
- float kerning = 0.0f;
- if (CSSPrimitiveValue* primitive = static_cast<CSSPrimitiveValue*>(svgStyle->kerning())) {
- kerning = primitive->getFloatValue();
-
- if (primitive->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE && font.pixelSize() > 0)
- kerning = kerning / 100.0f * font.pixelSize();
- }
-
- return kerning;
-}
-
-static bool applySVGKerning(SVGCharacterLayoutInfo& info, RenderObject* item, LastGlyphInfo& lastGlyph, const String& unicodeString, const String& glyphName)
-{
-#if ENABLE(SVG_FONTS)
- float kerning = 0.0f;
- const RenderStyle* style = item->style();
- SVGFontElement* svgFont = 0;
- if (style->font().isSVGFont())
- svgFont = style->font().svgFont();
-
- if (lastGlyph.isValid && style->font().isSVGFont())
- kerning = svgFont->getHorizontalKerningPairForStringsAndGlyphs(lastGlyph.unicode, lastGlyph.glyphName, unicodeString, glyphName);
-
- if (style->font().isSVGFont()) {
- lastGlyph.unicode = unicodeString;
- lastGlyph.glyphName = glyphName;
- lastGlyph.isValid = true;
- kerning *= style->font().size() / style->font().primaryFont()->unitsPerEm();
- } else
- lastGlyph.isValid = false;
-
- if (kerning != 0.0f) {
- info.curx -= kerning;
- return true;
- }
-#else
- UNUSED_PARAM(info);
- UNUSED_PARAM(item);
- UNUSED_PARAM(lastGlyph);
- UNUSED_PARAM(unicodeString);
- UNUSED_PARAM(glyphName);
-#endif
- return false;
-}
-
// Helper class for paint()
struct SVGRootInlineBoxPaintWalker {
SVGRootInlineBoxPaintWalker(SVGRootInlineBox* rootBox, RenderSVGResourceFilter* rootFilter, RenderObject::PaintInfo paintInfo, int tx, int ty)
@@ -744,7 +445,7 @@ void SVGRootInlineBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
paintInfo.context->restore();
}
-int SVGRootInlineBox::placeBoxesHorizontally(int, int& leftPosition, int& rightPosition, bool&)
+int SVGRootInlineBox::placeBoxesHorizontally(int, int& leftPosition, int& rightPosition, bool&, GlyphOverflowAndFallbackFontsMap&)
{
// Remove any offsets caused by RTL text layout
leftPosition = 0;
@@ -752,54 +453,12 @@ int SVGRootInlineBox::placeBoxesHorizontally(int, int& leftPosition, int& rightP
return 0;
}
-int SVGRootInlineBox::verticallyAlignBoxes(int)
+int SVGRootInlineBox::verticallyAlignBoxes(int, GlyphOverflowAndFallbackFontsMap&)
{
// height is set by layoutInlineBoxes.
return height();
}
-float cummulatedWidthOfInlineBoxCharacterRange(SVGInlineBoxCharacterRange& range)
-{
- ASSERT(!range.isOpen());
- ASSERT(range.isClosed());
- ASSERT(range.box->isInlineTextBox());
-
- InlineTextBox* textBox = static_cast<InlineTextBox*>(range.box);
- RenderText* text = textBox->textRenderer();
- RenderStyle* style = text->style();
-
- return style->font().floatWidth(svgTextRunForInlineTextBox(text->characters() + textBox->start() + range.startOffset, range.endOffset - range.startOffset, style, textBox, 0));
-}
-
-float cummulatedHeightOfInlineBoxCharacterRange(SVGInlineBoxCharacterRange& range)
-{
- ASSERT(!range.isOpen());
- ASSERT(range.isClosed());
- ASSERT(range.box->isInlineTextBox());
-
- InlineTextBox* textBox = static_cast<InlineTextBox*>(range.box);
- RenderText* text = textBox->textRenderer();
- const Font& font = text->style()->font();
-
- return (range.endOffset - range.startOffset) * (font.ascent() + font.descent());
-}
-
-TextRun svgTextRunForInlineTextBox(const UChar* c, int len, RenderStyle* style, const InlineTextBox* textBox, float xPos)
-{
- ASSERT(textBox);
- ASSERT(style);
-
- TextRun run(c, len, false, static_cast<int>(xPos), textBox->toAdd(), textBox->direction() == RTL, textBox->m_dirOverride || style->visuallyOrdered());
-
-#if ENABLE(SVG_FONTS)
- run.setReferencingRenderObject(textBox->textRenderer()->parent());
-#endif
-
- // We handle letter & word spacing ourselves
- run.disableSpacing();
- return run;
-}
-
static float cummulatedWidthOrHeightOfTextChunk(SVGTextChunk& chunk, bool calcWidthOnly)
{
float length = 0.0f;
@@ -948,8 +607,8 @@ static float calculateTextLengthCorrectionForTextChunk(SVGTextChunk& chunk, ELen
float computedWidth = cummulatedWidthOfTextChunk(chunk);
float computedHeight = cummulatedHeightOfTextChunk(chunk);
- if ((computedWidth <= 0.0f && !chunk.isVerticalText) ||
- (computedHeight <= 0.0f && chunk.isVerticalText))
+ if ((computedWidth <= 0.0f && !chunk.isVerticalText)
+ || (computedHeight <= 0.0f && chunk.isVerticalText))
return 0.0f;
if (chunk.isVerticalText)
@@ -1025,7 +684,7 @@ void SVGRootInlineBox::computePerCharacterLayoutInformation()
// Finally the top left position of our box is known.
// Propogate this knownledge to our RenderSVGText parent.
- FloatPoint topLeft = topLeftPositionOfCharacterRange(m_svgChars);
+ FloatPoint topLeft = topLeftPositionOfCharacterRange(m_svgChars.begin(), m_svgChars.end());
block()->setLocation((int) floorf(topLeft.x()), (int) floorf(topLeft.y()));
// Layout all InlineText/Flow boxes
@@ -1045,11 +704,11 @@ void SVGRootInlineBox::buildLayoutInformation(InlineFlowBox* start, SVGCharacter
info.addLayoutInformation(positioningElement);
}
- LastGlyphInfo lastGlyph;
+ SVGLastGlyphInfo lastGlyph;
for (InlineBox* curr = start->firstChild(); curr; curr = curr->nextOnLine()) {
if (curr->renderer()->isText())
- buildLayoutInformationForTextBox(info, static_cast<InlineTextBox*>(curr), lastGlyph);
+ static_cast<SVGInlineTextBox*>(curr)->buildLayoutInformation(info, lastGlyph);
else {
ASSERT(curr->isInlineFlowBox());
InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(curr);
@@ -1236,235 +895,12 @@ void SVGRootInlineBox::layoutInlineBoxes(InlineFlowBox* start, Vector<SVGChar>::
start->setWidth(highX - lowX);
static_cast<SVGRootInlineBox*>(start)->setHeight(highY - lowY);
- start->computeVerticalOverflow(top, bottom, true);
+ GlyphOverflowAndFallbackFontsMap textBoxDataMap;
+ start->computeVerticalOverflow(top, bottom, true, textBoxDataMap);
static_cast<SVGRootInlineBox*>(start)->setLineTopBottomPositions(top, bottom);
}
}
-void SVGRootInlineBox::buildLayoutInformationForTextBox(SVGCharacterLayoutInfo& info, InlineTextBox* textBox, LastGlyphInfo& lastGlyph)
-{
- RenderText* text = textBox->textRenderer();
- ASSERT(text);
-
- RenderStyle* style = text->style(textBox->isFirstLineStyle());
- ASSERT(style);
-
- const Font& font = style->font();
- SVGInlineTextBox* svgTextBox = static_cast<SVGInlineTextBox*>(textBox);
-
- unsigned length = textBox->len();
-
- const SVGRenderStyle* svgStyle = style->svgStyle();
- bool isVerticalText = isVerticalWritingMode(svgStyle);
-
- int charsConsumed = 0;
- for (unsigned i = 0; i < length; i += charsConsumed) {
- SVGChar svgChar;
-
- if (info.inPathLayout())
- svgChar.pathData = SVGCharOnPath::create();
-
- float glyphWidth = 0.0f;
- float glyphHeight = 0.0f;
-
- int extraCharsAvailable = length - i - 1;
-
- String unicodeStr;
- String glyphName;
- if (textBox->direction() == RTL) {
- glyphWidth = svgTextBox->calculateGlyphWidth(style, textBox->end() - i, extraCharsAvailable, charsConsumed, glyphName);
- glyphHeight = svgTextBox->calculateGlyphHeight(style, textBox->end() - i, extraCharsAvailable);
- unicodeStr = String(textBox->textRenderer()->text()->characters() + textBox->end() - i, charsConsumed);
- } else {
- glyphWidth = svgTextBox->calculateGlyphWidth(style, textBox->start() + i, extraCharsAvailable, charsConsumed, glyphName);
- glyphHeight = svgTextBox->calculateGlyphHeight(style, textBox->start() + i, extraCharsAvailable);
- unicodeStr = String(textBox->textRenderer()->text()->characters() + textBox->start() + i, charsConsumed);
- }
-
- bool assignedX = false;
- bool assignedY = false;
-
- if (info.xValueAvailable() && (!info.inPathLayout() || (info.inPathLayout() && !isVerticalText))) {
- if (!isVerticalText)
- svgChar.newTextChunk = true;
-
- assignedX = true;
- svgChar.drawnSeperated = true;
- info.curx = info.xValueNext();
- }
-
- if (info.yValueAvailable() && (!info.inPathLayout() || (info.inPathLayout() && isVerticalText))) {
- if (isVerticalText)
- svgChar.newTextChunk = true;
-
- assignedY = true;
- svgChar.drawnSeperated = true;
- info.cury = info.yValueNext();
- }
-
- float dx = 0.0f;
- float dy = 0.0f;
-
- // Apply x-axis shift
- if (info.dxValueAvailable()) {
- svgChar.drawnSeperated = true;
-
- dx = info.dxValueNext();
- info.dx += dx;
-
- if (!info.inPathLayout())
- info.curx += dx;
- }
-
- // Apply y-axis shift
- if (info.dyValueAvailable()) {
- svgChar.drawnSeperated = true;
-
- dy = info.dyValueNext();
- info.dy += dy;
-
- if (!info.inPathLayout())
- info.cury += dy;
- }
-
- // Take letter & word spacing and kerning into account
- float spacing = font.letterSpacing() + calculateCSSKerning(textBox->renderer()->node()->renderer());
-
- const UChar* currentCharacter = text->characters() + (textBox->direction() == RTL ? textBox->end() - i : textBox->start() + i);
- const UChar* lastCharacter = 0;
-
- if (textBox->direction() == RTL) {
- if (i < textBox->end())
- lastCharacter = text->characters() + textBox->end() - i + 1;
- } else {
- if (i > 0)
- lastCharacter = text->characters() + textBox->start() + i - 1;
- }
-
- // FIXME: SVG Kerning doesn't get applied on texts on path.
- bool appliedSVGKerning = applySVGKerning(info, textBox->renderer()->node()->renderer(), lastGlyph, unicodeStr, glyphName);
- if (info.nextDrawnSeperated || spacing != 0.0f || appliedSVGKerning) {
- info.nextDrawnSeperated = false;
- svgChar.drawnSeperated = true;
- }
-
- if (currentCharacter && Font::treatAsSpace(*currentCharacter) && lastCharacter && !Font::treatAsSpace(*lastCharacter)) {
- spacing += font.wordSpacing();
-
- if (spacing != 0.0f && !info.inPathLayout())
- info.nextDrawnSeperated = true;
- }
-
- float orientationAngle = glyphOrientationToAngle(svgStyle, isVerticalText, *currentCharacter);
-
- float xOrientationShift = 0.0f;
- float yOrientationShift = 0.0f;
- float glyphAdvance = calculateGlyphAdvanceAndShiftRespectingOrientation(isVerticalText, orientationAngle, glyphWidth, glyphHeight,
- font, svgChar, xOrientationShift, yOrientationShift);
-
- // Handle textPath layout mode
- if (info.inPathLayout()) {
- float extraAdvance = isVerticalText ? dy : dx;
- float newOffset = FLT_MIN;
-
- if (assignedX && !isVerticalText)
- newOffset = info.curx;
- else if (assignedY && isVerticalText)
- newOffset = info.cury;
-
- float correctedGlyphAdvance = glyphAdvance;
-
- // Handle lengthAdjust="spacingAndGlyphs" by specifying per-character scale operations
- if (info.pathTextLength > 0.0f && info.pathChunkLength > 0.0f) {
- if (isVerticalText) {
- svgChar.pathData->yScale = info.pathChunkLength / info.pathTextLength;
- spacing *= svgChar.pathData->yScale;
- correctedGlyphAdvance *= svgChar.pathData->yScale;
- } else {
- svgChar.pathData->xScale = info.pathChunkLength / info.pathTextLength;
- spacing *= svgChar.pathData->xScale;
- correctedGlyphAdvance *= svgChar.pathData->xScale;
- }
- }
-
- // Handle letter & word spacing on text path
- float pathExtraAdvance = info.pathExtraAdvance;
- info.pathExtraAdvance += spacing;
-
- svgChar.pathData->hidden = !info.nextPathLayoutPointAndAngle(correctedGlyphAdvance, extraAdvance, newOffset);
- svgChar.drawnSeperated = true;
-
- info.pathExtraAdvance = pathExtraAdvance;
- }
-
- // Apply rotation
- if (info.angleValueAvailable())
- info.angle = info.angleValueNext();
-
- // Apply baseline-shift
- if (info.baselineShiftValueAvailable()) {
- svgChar.drawnSeperated = true;
- float shift = info.baselineShiftValueNext();
-
- if (isVerticalText)
- info.shiftx += shift;
- else
- info.shifty -= shift;
- }
-
- // Take dominant-baseline / alignment-baseline into account
- yOrientationShift += alignmentBaselineToShift(isVerticalText, text, font);
-
- svgChar.x = info.curx;
- svgChar.y = info.cury;
- svgChar.angle = info.angle;
-
- // For text paths any shift (dx/dy/baseline-shift) has to be applied after the rotation
- if (!info.inPathLayout()) {
- svgChar.x += info.shiftx + xOrientationShift;
- svgChar.y += info.shifty + yOrientationShift;
-
- if (orientationAngle != 0.0f)
- 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;
- }
- }
-
- // Advance to new position
- if (isVerticalText) {
- svgChar.drawnSeperated = true;
- info.cury += glyphAdvance + spacing;
- } else
- info.curx += glyphAdvance + spacing;
-
- // 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);
@@ -1524,7 +960,7 @@ void SVGRootInlineBox::buildTextChunks(Vector<SVGChar>& svgChars, InlineFlowBox*
SVGInlineBoxCharacterRange& range = info.chunk.boxes.last();
if (range.isOpen()) {
range.box = curr;
- range.startOffset = (i == 0 ? 0 : i - 1);
+ 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);
@@ -1662,11 +1098,6 @@ void SVGRootInlineBox::buildTextChunks(Vector<SVGChar>& svgChars, InlineFlowBox*
#endif
}
-const Vector<SVGTextChunk>& SVGRootInlineBox::svgTextChunks() const
-{
- return m_svgTextChunks;
-}
-
void SVGRootInlineBox::layoutTextChunks()
{
Vector<SVGTextChunk>::iterator it = m_svgTextChunks.begin();
@@ -1686,7 +1117,8 @@ void SVGRootInlineBox::layoutTextChunks()
unsigned int i = 0;
for (; boxIt != boxEnd; ++boxIt) {
- SVGInlineBoxCharacterRange& range = *boxIt; i++;
+ SVGInlineBoxCharacterRange& range = *boxIt;
+ ++i;
fprintf(stderr, " -> RANGE %i STARTOFFSET: %i, ENDOFFSET: %i, BOX: %p\n", i, range.startOffset, range.endOffset, range.box);
}
}
diff --git a/WebCore/rendering/SVGRootInlineBox.h b/WebCore/rendering/SVGRootInlineBox.h
index 73c88a1..c3e1028 100644
--- a/WebCore/rendering/SVGRootInlineBox.h
+++ b/WebCore/rendering/SVGRootInlineBox.h
@@ -29,22 +29,15 @@
#include "RootInlineBox.h"
#include "SVGCharacterData.h"
#include "SVGCharacterLayoutInfo.h"
-#include "SVGTextChunkLayoutInfo.h"
#include "SVGRenderSupport.h"
+#include "SVGTextChunkLayoutInfo.h"
namespace WebCore {
class InlineTextBox;
class RenderSVGRoot;
class SVGInlineTextBox;
-
-struct LastGlyphInfo {
- LastGlyphInfo() : isValid(false) { }
-
- String unicode;
- String glyphName;
- bool isValid;
-};
+struct SVGLastGlyphInfo;
class SVGRootInlineBox : public RootInlineBox, protected SVGRenderBase {
public:
@@ -61,8 +54,8 @@ public:
virtual void paint(RenderObject::PaintInfo&, int tx, int ty);
- virtual int placeBoxesHorizontally(int x, int& leftPosition, int& rightPosition, bool& needsWordSpacing);
- virtual int verticallyAlignBoxes(int heightOfBlock);
+ virtual int placeBoxesHorizontally(int x, int& leftPosition, int& rightPosition, bool& needsWordSpacing, GlyphOverflowAndFallbackFontsMap&);
+ virtual int verticallyAlignBoxes(int heightOfBlock, GlyphOverflowAndFallbackFontsMap&);
virtual void computePerCharacterLayoutInformation();
@@ -70,7 +63,7 @@ public:
virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(); }
// Used by SVGInlineTextBox
- const Vector<SVGTextChunk>& svgTextChunks() const;
+ const Vector<SVGTextChunk>& svgTextChunks() const { return m_svgTextChunks; }
void walkTextChunks(SVGTextChunkWalkerBase*, const SVGInlineTextBox* textBox = 0);
@@ -81,7 +74,6 @@ private:
void layoutInlineBoxes(InlineFlowBox* start, Vector<SVGChar>::iterator& it, int& minX, int& maxX, int& minY, int& maxY);
void buildLayoutInformation(InlineFlowBox* start, SVGCharacterLayoutInfo&);
- void buildLayoutInformationForTextBox(SVGCharacterLayoutInfo&, InlineTextBox*, LastGlyphInfo&);
void buildTextChunks(Vector<SVGChar>&, Vector<SVGTextChunk>&, InlineFlowBox* start);
void buildTextChunks(Vector<SVGChar>&, InlineFlowBox* start, SVGTextChunkLayoutInfo&);
@@ -96,11 +88,6 @@ private:
};
// Shared with SVGRenderTreeAsText / SVGInlineTextBox
-TextRun svgTextRunForInlineTextBox(const UChar*, int len, RenderStyle* style, const InlineTextBox* textBox, float xPos);
-FloatPoint topLeftPositionOfCharacterRange(Vector<SVGChar>::iterator start, Vector<SVGChar>::iterator end);
-float cummulatedWidthOfInlineBoxCharacterRange(SVGInlineBoxCharacterRange& range);
-float cummulatedHeightOfInlineBoxCharacterRange(SVGInlineBoxCharacterRange& range);
-
RenderSVGRoot* findSVGRootObject(RenderObject* start);
} // namespace WebCore
diff --git a/WebCore/rendering/SVGTextLayoutUtilities.cpp b/WebCore/rendering/SVGTextLayoutUtilities.cpp
new file mode 100644
index 0000000..39705e9
--- /dev/null
+++ b/WebCore/rendering/SVGTextLayoutUtilities.cpp
@@ -0,0 +1,374 @@
+/*
+ Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ Copyright (C) Research In Motion Limited 2010. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "SVGTextLayoutUtilities.h"
+
+#if ENABLE(SVG)
+#include "FloatPoint.h"
+#include "InlineTextBox.h"
+#include "RenderObject.h"
+#include "SVGCharacterData.h"
+#include "SVGCharacterLayoutInfo.h"
+#include "SVGFontElement.h"
+#include "SVGRenderStyle.h"
+#include "SVGTextChunkLayoutInfo.h"
+#include "TextRun.h"
+#include "UnicodeRange.h"
+
+#include <float.h>
+
+namespace WebCore {
+
+bool isVerticalWritingMode(const SVGRenderStyle* style)
+{
+ return style->writingMode() == WM_TBRL || style->writingMode() == WM_TB;
+}
+
+static inline EAlignmentBaseline dominantBaselineToShift(bool isVerticalText, const RenderObject* text, const Font& font)
+{
+ ASSERT(text);
+
+ const SVGRenderStyle* style = text->style() ? text->style()->svgStyle() : 0;
+ ASSERT(style);
+
+ const SVGRenderStyle* parentStyle = text->parent() && text->parent()->style() ? text->parent()->style()->svgStyle() : 0;
+
+ EDominantBaseline baseline = style->dominantBaseline();
+ if (baseline == DB_AUTO) {
+ if (isVerticalText)
+ baseline = DB_CENTRAL;
+ else
+ baseline = DB_ALPHABETIC;
+ }
+
+ switch (baseline) {
+ case DB_USE_SCRIPT:
+ // TODO: The dominant-baseline and the baseline-table components are set by
+ // determining the predominant script of the character data content.
+ return AB_ALPHABETIC;
+ case DB_NO_CHANGE:
+ {
+ if (parentStyle)
+ return dominantBaselineToShift(isVerticalText, text->parent(), font);
+
+ ASSERT_NOT_REACHED();
+ return AB_AUTO;
+ }
+ case DB_RESET_SIZE:
+ {
+ if (parentStyle)
+ return dominantBaselineToShift(isVerticalText, text->parent(), font);
+
+ ASSERT_NOT_REACHED();
+ return AB_AUTO;
+ }
+ case DB_IDEOGRAPHIC:
+ return AB_IDEOGRAPHIC;
+ case DB_ALPHABETIC:
+ return AB_ALPHABETIC;
+ case DB_HANGING:
+ return AB_HANGING;
+ case DB_MATHEMATICAL:
+ return AB_MATHEMATICAL;
+ case DB_CENTRAL:
+ return AB_CENTRAL;
+ case DB_MIDDLE:
+ return AB_MIDDLE;
+ case DB_TEXT_AFTER_EDGE:
+ return AB_TEXT_AFTER_EDGE;
+ case DB_TEXT_BEFORE_EDGE:
+ return AB_TEXT_BEFORE_EDGE;
+ default:
+ ASSERT_NOT_REACHED();
+ return AB_AUTO;
+ }
+}
+
+float alignmentBaselineToShift(bool isVerticalText, const RenderObject* text, const Font& font)
+{
+ ASSERT(text);
+
+ const SVGRenderStyle* style = text->style() ? text->style()->svgStyle() : 0;
+ ASSERT(style);
+
+ const SVGRenderStyle* parentStyle = text->parent() && text->parent()->style() ? text->parent()->style()->svgStyle() : 0;
+
+ EAlignmentBaseline baseline = style->alignmentBaseline();
+ if (baseline == AB_AUTO) {
+ if (parentStyle && style->dominantBaseline() == DB_AUTO)
+ baseline = dominantBaselineToShift(isVerticalText, text->parent(), font);
+ else
+ baseline = dominantBaselineToShift(isVerticalText, text, font);
+
+ ASSERT(baseline != AB_AUTO);
+ }
+
+ // Note: http://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling
+ switch (baseline) {
+ case AB_BASELINE:
+ {
+ if (parentStyle)
+ return dominantBaselineToShift(isVerticalText, text->parent(), font);
+
+ return 0.0f;
+ }
+ case AB_BEFORE_EDGE:
+ case AB_TEXT_BEFORE_EDGE:
+ return font.ascent();
+ case AB_MIDDLE:
+ return font.xHeight() / 2.0f;
+ case AB_CENTRAL:
+ // Not needed, we're taking this into account already for vertical text!
+ // return (font.ascent() - font.descent()) / 2.0f;
+ return 0.0f;
+ case AB_AFTER_EDGE:
+ case AB_TEXT_AFTER_EDGE:
+ case AB_IDEOGRAPHIC:
+ return font.descent();
+ case AB_ALPHABETIC:
+ return 0.0f;
+ case AB_HANGING:
+ return font.ascent() * 8.0f / 10.0f;
+ case AB_MATHEMATICAL:
+ return font.ascent() / 2.0f;
+ default:
+ ASSERT_NOT_REACHED();
+ return 0.0f;
+ }
+}
+
+float glyphOrientationToAngle(const SVGRenderStyle* svgStyle, bool isVerticalText, const UChar& character)
+{
+ switch (isVerticalText ? svgStyle->glyphOrientationVertical() : svgStyle->glyphOrientationHorizontal()) {
+ case GO_AUTO:
+ {
+ // Spec: Fullwidth ideographic and fullwidth Latin text will be set with a glyph-orientation of 0-degrees.
+ // Text which is not fullwidth will be set with a glyph-orientation of 90-degrees.
+ unsigned int unicodeRange = findCharUnicodeRange(character);
+ if (unicodeRange == cRangeSetLatin || unicodeRange == cRangeArabic)
+ return 90.0f;
+
+ return 0.0f;
+ }
+ case GO_90DEG:
+ return 90.0f;
+ case GO_180DEG:
+ return 180.0f;
+ case GO_270DEG:
+ return 270.0f;
+ case GO_0DEG:
+ default:
+ return 0.0f;
+ }
+}
+
+static inline bool glyphOrientationIsMultiplyOf180Degrees(float orientationAngle)
+{
+ return fabsf(fmodf(orientationAngle, 180.0f)) == 0.0f;
+}
+
+float applyGlyphAdvanceAndShiftRespectingOrientation(bool isVerticalText, float orientationAngle, float glyphWidth, float glyphHeight, const Font& font, SVGChar& svgChar, float& xOrientationShift, float& yOrientationShift)
+{
+ bool orientationIsMultiplyOf180Degrees = glyphOrientationIsMultiplyOf180Degrees(orientationAngle);
+
+ // The function is based on spec requirements:
+ //
+ // Spec: If the 'glyph-orientation-horizontal' results in an orientation angle that is not a multiple of
+ // of 180 degrees, then the current text position is incremented according to the vertical metrics of the glyph.
+ //
+ // Spec: If if the 'glyph-orientation-vertical' results in an orientation angle that is not a multiple of
+ // 180 degrees,then the current text position is incremented according to the horizontal metrics of the glyph.
+
+ // vertical orientation handling
+ if (isVerticalText) {
+ if (orientationAngle == 0.0f) {
+ xOrientationShift = -glyphWidth / 2.0f;
+ yOrientationShift = font.ascent();
+ } else if (orientationAngle == 90.0f) {
+ xOrientationShift = -glyphHeight;
+ yOrientationShift = font.descent();
+ svgChar.orientationShiftY = -font.ascent();
+ } else if (orientationAngle == 270.0f) {
+ xOrientationShift = glyphHeight;
+ yOrientationShift = font.descent();
+ svgChar.orientationShiftX = -glyphWidth;
+ svgChar.orientationShiftY = -font.ascent();
+ } else if (orientationAngle == 180.0f) {
+ yOrientationShift = font.ascent();
+ svgChar.orientationShiftX = -glyphWidth / 2.0f;
+ svgChar.orientationShiftY = font.ascent() - font.descent();
+ }
+
+ // vertical advance calculation
+ if (orientationAngle != 0.0f && !orientationIsMultiplyOf180Degrees)
+ return glyphWidth;
+
+ return glyphHeight;
+ }
+
+ // horizontal orientation handling
+ if (orientationAngle == 90.0f) {
+ xOrientationShift = glyphWidth / 2.0f;
+ yOrientationShift = -font.descent();
+ svgChar.orientationShiftX = -glyphWidth / 2.0f - font.descent();
+ svgChar.orientationShiftY = font.descent();
+ } else if (orientationAngle == 270.0f) {
+ xOrientationShift = -glyphWidth / 2.0f;
+ yOrientationShift = -font.descent();
+ svgChar.orientationShiftX = -glyphWidth / 2.0f + font.descent();
+ svgChar.orientationShiftY = glyphHeight;
+ } else if (orientationAngle == 180.0f) {
+ xOrientationShift = glyphWidth / 2.0f;
+ svgChar.orientationShiftX = -glyphWidth / 2.0f;
+ svgChar.orientationShiftY = font.ascent() - font.descent();
+ }
+
+ // horizontal advance calculation
+ if (orientationAngle != 0.0f && !orientationIsMultiplyOf180Degrees)
+ return glyphHeight;
+
+ return glyphWidth;
+}
+
+FloatPoint topLeftPositionOfCharacterRange(Vector<SVGChar>::iterator it, Vector<SVGChar>::iterator end)
+{
+ float lowX = FLT_MAX, lowY = FLT_MAX;
+ for (; it != end; ++it) {
+ if (it->isHidden())
+ continue;
+
+ float x = (*it).x;
+ float y = (*it).y;
+
+ if (x < lowX)
+ lowX = x;
+
+ if (y < lowY)
+ lowY = y;
+ }
+
+ return FloatPoint(lowX, lowY);
+}
+
+float cummulatedWidthOfInlineBoxCharacterRange(SVGInlineBoxCharacterRange& range)
+{
+ ASSERT(!range.isOpen());
+ ASSERT(range.isClosed());
+ ASSERT(range.box->isInlineTextBox());
+
+ InlineTextBox* textBox = static_cast<InlineTextBox*>(range.box);
+ RenderText* text = textBox->textRenderer();
+ RenderStyle* style = text->style();
+
+ return style->font().floatWidth(svgTextRunForInlineTextBox(text->characters() + textBox->start() + range.startOffset, range.endOffset - range.startOffset, style, textBox, 0));
+}
+
+float cummulatedHeightOfInlineBoxCharacterRange(SVGInlineBoxCharacterRange& range)
+{
+ ASSERT(!range.isOpen());
+ ASSERT(range.isClosed());
+ ASSERT(range.box->isInlineTextBox());
+
+ InlineTextBox* textBox = static_cast<InlineTextBox*>(range.box);
+ RenderText* text = textBox->textRenderer();
+ const Font& font = text->style()->font();
+
+ return (range.endOffset - range.startOffset) * (font.ascent() + font.descent());
+}
+
+TextRun svgTextRunForInlineTextBox(const UChar* characters, int length, const RenderStyle* style, const InlineTextBox* textBox, float xPosition)
+{
+ ASSERT(textBox);
+ ASSERT(style);
+
+ TextRun run(characters, length, false, static_cast<int>(xPosition), textBox->toAdd(), textBox->direction() == RTL, textBox->m_dirOverride || style->visuallyOrdered());
+
+#if ENABLE(SVG_FONTS)
+ run.setReferencingRenderObject(textBox->textRenderer()->parent());
+#endif
+
+ // We handle letter & word spacing ourselves
+ run.disableSpacing();
+ return run;
+}
+
+float calculateCSSKerning(const RenderStyle* style)
+{
+ const Font& font = style->font();
+ const SVGRenderStyle* svgStyle = style->svgStyle();
+
+ float kerning = 0.0f;
+ if (CSSPrimitiveValue* primitive = static_cast<CSSPrimitiveValue*>(svgStyle->kerning())) {
+ kerning = primitive->getFloatValue();
+
+ if (primitive->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE && font.pixelSize())
+ kerning = kerning / 100.0f * font.pixelSize();
+ }
+
+ return kerning;
+}
+
+bool applySVGKerning(SVGCharacterLayoutInfo& info, const RenderStyle* style, SVGLastGlyphInfo& lastGlyph, const String& unicodeString, const String& glyphName, bool isVerticalText)
+{
+#if ENABLE(SVG_FONTS)
+ float kerning = 0.0f;
+
+ const Font& font = style->font();
+ if (!font.isSVGFont()) {
+ lastGlyph.isValid = false;
+ return false;
+ }
+
+ SVGFontElement* svgFont = font.svgFont();
+ ASSERT(svgFont);
+
+ if (lastGlyph.isValid) {
+ if (isVerticalText)
+ kerning = svgFont->verticalKerningForPairOfStringsAndGlyphs(lastGlyph.unicode, lastGlyph.glyphName, unicodeString, glyphName);
+ else
+ kerning = svgFont->horizontalKerningForPairOfStringsAndGlyphs(lastGlyph.unicode, lastGlyph.glyphName, unicodeString, glyphName);
+ }
+
+ lastGlyph.unicode = unicodeString;
+ lastGlyph.glyphName = glyphName;
+ lastGlyph.isValid = true;
+ kerning *= style->font().size() / style->font().primaryFont()->unitsPerEm();
+
+ if (kerning != 0.0f) {
+ if (isVerticalText)
+ info.cury -= kerning;
+ else
+ info.curx -= kerning;
+ return true;
+ }
+#else
+ UNUSED_PARAM(info);
+ UNUSED_PARAM(item);
+ UNUSED_PARAM(lastGlyph);
+ UNUSED_PARAM(unicodeString);
+ UNUSED_PARAM(glyphName);
+#endif
+ return false;
+}
+
+}
+
+#endif
diff --git a/WebCore/rendering/SVGTextLayoutUtilities.h b/WebCore/rendering/SVGTextLayoutUtilities.h
new file mode 100644
index 0000000..196a09c
--- /dev/null
+++ b/WebCore/rendering/SVGTextLayoutUtilities.h
@@ -0,0 +1,90 @@
+/*
+ Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ Copyright (C) Research In Motion Limited 2010. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef SVGTextLayoutUtilities_h
+#define SVGTextLayoutUtilities_h
+
+#if ENABLE(SVG)
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class FloatPoint;
+class Font;
+class InlineTextBox;
+class RenderObject;
+class RenderStyle;
+class RenderSVGResource;
+class SVGRenderStyle;
+class TextRun;
+
+struct SVGChar;
+struct SVGCharacterLayoutInfo;
+struct SVGInlineBoxCharacterRange;
+
+enum SVGTextPaintSubphase {
+ SVGTextPaintSubphaseBackground,
+ SVGTextPaintSubphaseGlyphFill,
+ SVGTextPaintSubphaseGlyphFillSelection,
+ SVGTextPaintSubphaseGlyphStroke,
+ SVGTextPaintSubphaseGlyphStrokeSelection,
+ SVGTextPaintSubphaseForeground
+};
+
+struct SVGTextPaintInfo {
+ SVGTextPaintInfo()
+ : activePaintingResource(0)
+ , subphase(SVGTextPaintSubphaseBackground)
+ {
+ }
+
+ RenderSVGResource* activePaintingResource;
+ SVGTextPaintSubphase subphase;
+};
+
+struct SVGLastGlyphInfo {
+ SVGLastGlyphInfo()
+ : isValid(false)
+ {
+ }
+
+ bool isValid;
+ String unicode;
+ String glyphName;
+};
+
+bool isVerticalWritingMode(const SVGRenderStyle*);
+float alignmentBaselineToShift(bool isVerticalText, const RenderObject* text, const Font&);
+float glyphOrientationToAngle(const SVGRenderStyle*, bool isVerticalText, const UChar&);
+float applyGlyphAdvanceAndShiftRespectingOrientation(bool isVerticalText, float orientationAngle, float glyphWidth, float glyphHeight, const Font&,
+ SVGChar&, float& xOrientationShift, float& yOrientationShift);
+FloatPoint topLeftPositionOfCharacterRange(Vector<SVGChar>::iterator start, Vector<SVGChar>::iterator end);
+float cummulatedWidthOfInlineBoxCharacterRange(SVGInlineBoxCharacterRange&);
+float cummulatedHeightOfInlineBoxCharacterRange(SVGInlineBoxCharacterRange&);
+TextRun svgTextRunForInlineTextBox(const UChar*, int length, const RenderStyle*, const InlineTextBox*, float xPos);
+
+float calculateCSSKerning(const RenderStyle*);
+bool applySVGKerning(SVGCharacterLayoutInfo&, const RenderStyle*, SVGLastGlyphInfo&, const String& unicodeString, const String& glyphName, bool isVerticalText);
+
+}
+
+#endif
+#endif
diff --git a/WebCore/rendering/style/FillLayer.cpp b/WebCore/rendering/style/FillLayer.cpp
index 597e919..59f3bb2 100644
--- a/WebCore/rendering/style/FillLayer.cpp
+++ b/WebCore/rendering/style/FillLayer.cpp
@@ -25,7 +25,8 @@
namespace WebCore {
FillLayer::FillLayer(EFillLayerType type)
- : m_image(FillLayer::initialFillImage(type))
+ : m_next(0)
+ , m_image(FillLayer::initialFillImage(type))
, m_xPosition(FillLayer::initialFillXPosition(type))
, m_yPosition(FillLayer::initialFillYPosition(type))
, m_attachment(FillLayer::initialFillAttachment(type))
@@ -46,12 +47,12 @@ FillLayer::FillLayer(EFillLayerType type)
, m_yPosSet(false)
, m_compositeSet(type == MaskFillLayer)
, m_type(type)
- , m_next(0)
{
}
FillLayer::FillLayer(const FillLayer& o)
- : m_image(o.m_image)
+ : m_next(o.m_next ? new FillLayer(*o.m_next) : 0)
+ , m_image(o.m_image)
, m_xPosition(o.m_xPosition)
, m_yPosition(o.m_yPosition)
, m_attachment(o.m_attachment)
@@ -72,7 +73,6 @@ FillLayer::FillLayer(const FillLayer& o)
, m_yPosSet(o.m_yPosSet)
, m_compositeSet(o.m_compositeSet)
, m_type(o.m_type)
- , m_next(o.m_next ? new FillLayer(*o.m_next) : 0)
{
}
diff --git a/WebCore/rendering/style/FillLayer.h b/WebCore/rendering/style/FillLayer.h
index eb21ec3..49fb294 100644
--- a/WebCore/rendering/style/FillLayer.h
+++ b/WebCore/rendering/style/FillLayer.h
@@ -166,6 +166,8 @@ private:
FillLayer() { }
+ FillLayer* m_next;
+
RefPtr<StyleImage> m_image;
Length m_xPosition;
@@ -192,8 +194,6 @@ private:
bool m_compositeSet : 1;
unsigned m_type : 1; // EFillLayerType
-
- FillLayer* m_next;
};
} // namespace WebCore
diff --git a/WebCore/rendering/style/RenderStyle.cpp b/WebCore/rendering/style/RenderStyle.cpp
index f3b3f0c..7ef580f 100644
--- a/WebCore/rendering/style/RenderStyle.cpp
+++ b/WebCore/rendering/style/RenderStyle.cpp
@@ -379,6 +379,8 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon
if (rareInheritedData.get() != other->rareInheritedData.get()) {
if (rareInheritedData->highlight != other->rareInheritedData->highlight ||
+ rareInheritedData->indent != other->rareInheritedData->indent ||
+ rareInheritedData->m_effectiveZoom != other->rareInheritedData->m_effectiveZoom ||
rareInheritedData->textSizeAdjust != other->rareInheritedData->textSizeAdjust ||
rareInheritedData->wordBreak != other->rareInheritedData->wordBreak ||
rareInheritedData->wordWrap != other->rareInheritedData->wordWrap ||
@@ -394,8 +396,7 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon
return StyleDifferenceLayout;
}
- if (inherited->indent != other->inherited->indent ||
- inherited->line_height != other->inherited->line_height ||
+ if (inherited->line_height != other->inherited->line_height ||
inherited->list_style_image != other->inherited->list_style_image ||
inherited->font != other->inherited->font ||
inherited->horizontal_border_spacing != other->inherited->horizontal_border_spacing ||
@@ -461,11 +462,8 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon
const CounterDirectiveMap* mapB = other->rareNonInheritedData->m_counterDirectives.get();
if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB)))
return StyleDifferenceLayout;
- if (visual->counterIncrement != other->visual->counterIncrement ||
- visual->counterReset != other->visual->counterReset)
- return StyleDifferenceLayout;
-
- if (inherited->m_effectiveZoom != other->inherited->m_effectiveZoom)
+ if (rareNonInheritedData->m_counterIncrement != other->rareNonInheritedData->m_counterIncrement ||
+ rareNonInheritedData->m_counterReset != other->rareNonInheritedData->m_counterReset)
return StyleDifferenceLayout;
if ((rareNonInheritedData->opacity == 1 && other->rareNonInheritedData->opacity < 1) ||
@@ -553,20 +551,20 @@ void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
void RenderStyle::addCursor(CachedImage* image, const IntPoint& hotSpot)
{
- if (!inherited.access()->cursorData)
- inherited.access()->cursorData = CursorList::create();
- inherited.access()->cursorData->append(CursorData(image, hotSpot));
+ if (!rareInheritedData.access()->cursorData)
+ rareInheritedData.access()->cursorData = CursorList::create();
+ rareInheritedData.access()->cursorData->append(CursorData(image, hotSpot));
}
void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
{
- inherited.access()->cursorData = other;
+ rareInheritedData.access()->cursorData = other;
}
void RenderStyle::clearCursorList()
{
- if (inherited->cursorData)
- inherited.access()->cursorData = 0;
+ if (rareInheritedData->cursorData)
+ rareInheritedData.access()->cursorData = 0;
}
void RenderStyle::clearContent()
@@ -1035,7 +1033,6 @@ static Color colorIncludingFallback(const RenderStyle* style, int colorProperty,
result = style->textStrokeColor();
break;
default:
- // FIXME: Add SVG fill and stroke.
ASSERT_NOT_REACHED();
break;
}
diff --git a/WebCore/rendering/style/RenderStyle.h b/WebCore/rendering/style/RenderStyle.h
index 815fb30..970b26a 100644
--- a/WebCore/rendering/style/RenderStyle.h
+++ b/WebCore/rendering/style/RenderStyle.h
@@ -452,7 +452,7 @@ public:
int fontSize() const { return inherited->font.pixelSize(); }
const Color& color() const { return inherited->color; }
- Length textIndent() const { return inherited->indent; }
+ Length textIndent() const { return rareInheritedData->indent; }
ETextAlign textAlign() const { return static_cast<ETextAlign>(inherited_flags._text_align); }
ETextTransform textTransform() const { return static_cast<ETextTransform>(inherited_flags._text_transform); }
int textDecorationsInEffect() const { return inherited_flags._text_decorations; }
@@ -461,7 +461,7 @@ public:
int letterSpacing() const { return inherited->font.letterSpacing(); }
float zoom() const { return visual->m_zoom; }
- float effectiveZoom() const { return inherited->m_effectiveZoom; }
+ float effectiveZoom() const { return rareInheritedData->m_effectiveZoom; }
TextDirection direction() const { return static_cast<TextDirection>(inherited_flags._direction); }
Length lineHeight() const { return inherited->line_height; }
@@ -572,8 +572,8 @@ public:
EEmptyCell emptyCells() const { return static_cast<EEmptyCell>(inherited_flags._empty_cells); }
ECaptionSide captionSide() const { return static_cast<ECaptionSide>(inherited_flags._caption_side); }
- short counterIncrement() const { return visual->counterIncrement; }
- short counterReset() const { return visual->counterReset; }
+ short counterIncrement() const { return rareNonInheritedData->m_counterIncrement; }
+ short counterReset() const { return rareNonInheritedData->m_counterReset; }
EListStyleType listStyleType() const { return static_cast<EListStyleType>(inherited_flags._list_style_type); }
StyleImage* listStyleImage() const { return inherited->list_style_image.get(); }
@@ -592,13 +592,13 @@ public:
ECursor cursor() const { return static_cast<ECursor>(inherited_flags._cursor_style); }
- CursorList* cursors() const { return inherited->cursorData.get(); }
+ CursorList* cursors() const { return rareInheritedData->cursorData.get(); }
EInsideLink insideLink() const { return static_cast<EInsideLink>(inherited_flags._insideLink); }
bool isLink() const { return noninherited_flags._isLink; }
- short widows() const { return inherited->widows; }
- short orphans() const { return inherited->orphans; }
+ short widows() const { return rareInheritedData->widows; }
+ short orphans() const { return rareInheritedData->orphans; }
EPageBreak pageBreakInside() const { return static_cast<EPageBreak>(noninherited_flags._page_break_inside); }
EPageBreak pageBreakBefore() const { return static_cast<EPageBreak>(noninherited_flags._page_break_before); }
EPageBreak pageBreakAfter() const { return static_cast<EPageBreak>(noninherited_flags._page_break_after); }
@@ -661,6 +661,7 @@ public:
bool hasAutoColumnWidth() const { return rareNonInheritedData->m_multiCol->m_autoWidth; }
unsigned short columnCount() const { return rareNonInheritedData->m_multiCol->m_count; }
bool hasAutoColumnCount() const { return rareNonInheritedData->m_multiCol->m_autoCount; }
+ bool specifiesColumns() const { return !hasAutoColumnCount() || !hasAutoColumnWidth(); }
float columnGap() const { return rareNonInheritedData->m_multiCol->m_gap; }
bool hasNormalColumnGap() const { return rareNonInheritedData->m_multiCol->m_normalGap; }
const Color& columnRuleColor() const { return rareNonInheritedData->m_multiCol->m_rule.color(); }
@@ -852,7 +853,7 @@ public:
void setBlendedFontSize(int);
void setColor(const Color& v) { SET_VAR(inherited, color, v) }
- void setTextIndent(Length v) { SET_VAR(inherited, indent, v) }
+ void setTextIndent(Length v) { SET_VAR(rareInheritedData, indent, v) }
void setTextAlign(ETextAlign v) { inherited_flags._text_align = v; }
void setTextTransform(ETextTransform v) { inherited_flags._text_transform = v; }
void addToTextDecorationsInEffect(int v) { inherited_flags._text_decorations |= v; }
@@ -861,7 +862,7 @@ public:
void setDirection(TextDirection v) { inherited_flags._direction = v; }
void setLineHeight(Length v) { SET_VAR(inherited, line_height, v) }
void setZoom(float f) { SET_VAR(visual, m_zoom, f); setEffectiveZoom(effectiveZoom() * zoom()); }
- void setEffectiveZoom(float f) { SET_VAR(inherited, m_effectiveZoom, f) }
+ void setEffectiveZoom(float f) { SET_VAR(rareInheritedData, m_effectiveZoom, f) }
void setWhiteSpace(EWhiteSpace v) { inherited_flags._white_space = v; }
@@ -901,8 +902,8 @@ public:
void setEmptyCells(EEmptyCell v) { inherited_flags._empty_cells = v; }
void setCaptionSide(ECaptionSide v) { inherited_flags._caption_side = v; }
- void setCounterIncrement(short v) { SET_VAR(visual, counterIncrement, v) }
- void setCounterReset(short v) { SET_VAR(visual, counterReset, v) }
+ void setCounterIncrement(short v) { SET_VAR(rareNonInheritedData, m_counterIncrement, v) }
+ void setCounterReset(short v) { SET_VAR(rareNonInheritedData, m_counterReset, v) }
void setListStyleType(EListStyleType v) { inherited_flags._list_style_type = v; }
void setListStyleImage(StyleImage* v) { if (inherited->list_style_image != v) inherited.access()->list_style_image = v; }
@@ -940,8 +941,8 @@ public:
int zIndex() const { return m_box->zIndex(); }
void setZIndex(int v) { SET_VAR(m_box, m_hasAutoZIndex, false); SET_VAR(m_box, m_zIndex, v) }
- void setWidows(short w) { SET_VAR(inherited, widows, w); }
- void setOrphans(short o) { SET_VAR(inherited, orphans, o); }
+ void setWidows(short w) { SET_VAR(rareInheritedData, widows, w); }
+ void setOrphans(short o) { SET_VAR(rareInheritedData, orphans, o); }
void setPageBreakInside(EPageBreak b) { noninherited_flags._page_break_inside = b; }
void setPageBreakBefore(EPageBreak b) { noninherited_flags._page_break_before = b; }
void setPageBreakAfter(EPageBreak b) { noninherited_flags._page_break_after = b; }
diff --git a/WebCore/rendering/style/StyleInheritedData.cpp b/WebCore/rendering/style/StyleInheritedData.cpp
index c73497f..874d053 100644
--- a/WebCore/rendering/style/StyleInheritedData.cpp
+++ b/WebCore/rendering/style/StyleInheritedData.cpp
@@ -28,15 +28,11 @@
namespace WebCore {
StyleInheritedData::StyleInheritedData()
- : indent(RenderStyle::initialTextIndent())
- , line_height(RenderStyle::initialLineHeight())
+ : line_height(RenderStyle::initialLineHeight())
, list_style_image(RenderStyle::initialListStyleImage())
, color(RenderStyle::initialColor())
- , m_effectiveZoom(RenderStyle::initialZoom())
, horizontal_border_spacing(RenderStyle::initialHorizontalBorderSpacing())
, vertical_border_spacing(RenderStyle::initialVerticalBorderSpacing())
- , widows(RenderStyle::initialWidows())
- , orphans(RenderStyle::initialOrphans())
{
}
@@ -46,43 +42,24 @@ StyleInheritedData::~StyleInheritedData()
StyleInheritedData::StyleInheritedData(const StyleInheritedData& o)
: RefCounted<StyleInheritedData>()
- , indent(o.indent)
, line_height(o.line_height)
, list_style_image(o.list_style_image)
- , cursorData(o.cursorData)
, font(o.font)
, color(o.color)
- , m_effectiveZoom(o.m_effectiveZoom)
, horizontal_border_spacing(o.horizontal_border_spacing)
, vertical_border_spacing(o.vertical_border_spacing)
- , widows(o.widows)
- , orphans(o.orphans)
{
}
-static bool cursorDataEquivalent(const CursorList* c1, const CursorList* c2)
-{
- if (c1 == c2)
- return true;
- if ((!c1 && c2) || (c1 && !c2))
- return false;
- return (*c1 == *c2);
-}
-
bool StyleInheritedData::operator==(const StyleInheritedData& o) const
{
return
- indent == o.indent &&
line_height == o.line_height &&
StyleImage::imagesEquivalent(list_style_image.get(), o.list_style_image.get()) &&
- cursorDataEquivalent(cursorData.get(), o.cursorData.get()) &&
font == o.font &&
color == o.color &&
- m_effectiveZoom == o.m_effectiveZoom &&
horizontal_border_spacing == o.horizontal_border_spacing &&
- vertical_border_spacing == o.vertical_border_spacing &&
- widows == o.widows &&
- orphans == o.orphans;
+ vertical_border_spacing == o.vertical_border_spacing;
}
} // namespace WebCore
diff --git a/WebCore/rendering/style/StyleInheritedData.h b/WebCore/rendering/style/StyleInheritedData.h
index 3b30b8f..ea398db 100644
--- a/WebCore/rendering/style/StyleInheritedData.h
+++ b/WebCore/rendering/style/StyleInheritedData.h
@@ -35,7 +35,6 @@
namespace WebCore {
class StyleImage;
-class CursorList;
class StyleInheritedData : public RefCounted<StyleInheritedData> {
public:
@@ -49,26 +48,17 @@ public:
return !(*this == o);
}
- Length indent;
// could be packed in a short but doesn't
// make a difference currently because of padding
Length line_height;
RefPtr<StyleImage> list_style_image;
- RefPtr<CursorList> cursorData;
Font font;
Color color;
-
- float m_effectiveZoom;
short horizontal_border_spacing;
short vertical_border_spacing;
-
- // Paged media properties.
- short widows;
- short orphans;
-
private:
StyleInheritedData();
StyleInheritedData(const StyleInheritedData&);
diff --git a/WebCore/rendering/style/StyleRareInheritedData.cpp b/WebCore/rendering/style/StyleRareInheritedData.cpp
index ff626b7..04923d5 100644
--- a/WebCore/rendering/style/StyleRareInheritedData.cpp
+++ b/WebCore/rendering/style/StyleRareInheritedData.cpp
@@ -33,6 +33,10 @@ StyleRareInheritedData::StyleRareInheritedData()
, tapHighlightColor(RenderStyle::initialTapHighlightColor())
#endif
, textShadow(0)
+ , indent(RenderStyle::initialTextIndent())
+ , m_effectiveZoom(RenderStyle::initialZoom())
+ , widows(RenderStyle::initialWidows())
+ , orphans(RenderStyle::initialOrphans())
, textSecurity(RenderStyle::initialTextSecurity())
, userModify(READ_ONLY)
, wordBreak(RenderStyle::initialWordBreak())
@@ -56,6 +60,11 @@ StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o)
#endif
, textShadow(o.textShadow ? new ShadowData(*o.textShadow) : 0)
, highlight(o.highlight)
+ , cursorData(o.cursorData)
+ , indent(o.indent)
+ , m_effectiveZoom(o.m_effectiveZoom)
+ , widows(o.widows)
+ , orphans(o.orphans)
, textSecurity(o.textSecurity)
, userModify(o.userModify)
, wordBreak(o.wordBreak)
@@ -74,6 +83,15 @@ StyleRareInheritedData::~StyleRareInheritedData()
delete textShadow;
}
+static bool cursorDataEquivalent(const CursorList* c1, const CursorList* c2)
+{
+ if (c1 == c2)
+ return true;
+ if ((!c1 && c2) || (c1 && !c2))
+ return false;
+ return (*c1 == *c2);
+}
+
bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const
{
return textStrokeColor == o.textStrokeColor
@@ -81,6 +99,11 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const
&& textFillColor == o.textFillColor
&& shadowDataEquivalent(o)
&& highlight == o.highlight
+ && cursorDataEquivalent(cursorData.get(), o.cursorData.get())
+ && indent == o.indent
+ && m_effectiveZoom == o.m_effectiveZoom
+ && widows == o.widows
+ && orphans == o.orphans
&& textSecurity == o.textSecurity
&& userModify == o.userModify
&& wordBreak == o.wordBreak
diff --git a/WebCore/rendering/style/StyleRareInheritedData.h b/WebCore/rendering/style/StyleRareInheritedData.h
index 8f128fd..3ad8b0b 100644
--- a/WebCore/rendering/style/StyleRareInheritedData.h
+++ b/WebCore/rendering/style/StyleRareInheritedData.h
@@ -27,11 +27,13 @@
#include "AtomicString.h"
#include "Color.h"
+#include "Length.h"
#include <wtf/RefCounted.h>
#include <wtf/PassRefPtr.h>
namespace WebCore {
+class CursorList;
class ShadowData;
// This struct is for rarely used inherited CSS3, CSS2, and WebKit-specific properties.
@@ -59,6 +61,15 @@ public:
ShadowData* textShadow; // Our text shadow information for shadowed text drawing.
AtomicString highlight; // Apple-specific extension for custom highlight rendering.
+
+ RefPtr<CursorList> cursorData;
+ Length indent;
+ float m_effectiveZoom;
+
+ // Paged media properties.
+ short widows;
+ short orphans;
+
unsigned textSecurity : 2; // ETextSecurity
unsigned userModify : 2; // EUserModify (editing)
unsigned wordBreak : 2; // EWordBreak
diff --git a/WebCore/rendering/style/StyleRareNonInheritedData.cpp b/WebCore/rendering/style/StyleRareNonInheritedData.cpp
index 401c04f..e3367d1 100644
--- a/WebCore/rendering/style/StyleRareNonInheritedData.cpp
+++ b/WebCore/rendering/style/StyleRareNonInheritedData.cpp
@@ -42,6 +42,8 @@ StyleRareNonInheritedData::StyleRareNonInheritedData()
, matchNearestMailBlockquoteColor(RenderStyle::initialMatchNearestMailBlockquoteColor())
, m_appearance(RenderStyle::initialAppearance())
, m_borderFit(RenderStyle::initialBorderFit())
+ , m_counterIncrement(0)
+ , m_counterReset(0)
#if USE(ACCELERATED_COMPOSITING)
, m_runningAcceleratedAnimation(false)
#endif
@@ -77,6 +79,8 @@ StyleRareNonInheritedData::StyleRareNonInheritedData(const StyleRareNonInherited
, matchNearestMailBlockquoteColor(o.matchNearestMailBlockquoteColor)
, m_appearance(o.m_appearance)
, m_borderFit(o.m_borderFit)
+ , m_counterIncrement(o.m_counterIncrement)
+ , m_counterReset(o.m_counterReset)
#if USE(ACCELERATED_COMPOSITING)
, m_runningAcceleratedAnimation(o.m_runningAcceleratedAnimation)
#endif
@@ -133,6 +137,8 @@ bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) c
&& matchNearestMailBlockquoteColor == o.matchNearestMailBlockquoteColor
&& m_appearance == o.m_appearance
&& m_borderFit == o.m_borderFit
+ && m_counterIncrement == o.m_counterIncrement
+ && m_counterReset == o.m_counterReset
#if USE(ACCELERATED_COMPOSITING)
&& !m_runningAcceleratedAnimation && !o.m_runningAcceleratedAnimation
#endif
diff --git a/WebCore/rendering/style/StyleRareNonInheritedData.h b/WebCore/rendering/style/StyleRareNonInheritedData.h
index 21bbe94..d6fe96e 100644
--- a/WebCore/rendering/style/StyleRareNonInheritedData.h
+++ b/WebCore/rendering/style/StyleRareNonInheritedData.h
@@ -100,9 +100,13 @@ public:
unsigned matchNearestMailBlockquoteColor : 1; // EMatchNearestMailBlockquoteColor, FIXME: This property needs to be eliminated. It should never have been added.
unsigned m_appearance : 6; // EAppearance
unsigned m_borderFit : 1; // EBorderFit
+
+ short m_counterIncrement;
+ short m_counterReset;
+
#if USE(ACCELERATED_COMPOSITING)
bool m_runningAcceleratedAnimation : 1;
-#endif
+#endif
OwnPtr<ShadowData> m_boxShadow; // For box-shadow decorations.
RefPtr<StyleReflection> m_boxReflect;
diff --git a/WebCore/rendering/style/StyleVisualData.cpp b/WebCore/rendering/style/StyleVisualData.cpp
index 91690cf..14996c9 100644
--- a/WebCore/rendering/style/StyleVisualData.cpp
+++ b/WebCore/rendering/style/StyleVisualData.cpp
@@ -29,8 +29,6 @@ namespace WebCore {
StyleVisualData::StyleVisualData()
: hasClip(false)
, textDecoration(RenderStyle::initialTextDecoration())
- , counterIncrement(0)
- , counterReset(0)
, m_zoom(RenderStyle::initialZoom())
{
}
@@ -44,8 +42,6 @@ StyleVisualData::StyleVisualData(const StyleVisualData& o)
, clip(o.clip)
, hasClip(o.hasClip)
, textDecoration(o.textDecoration)
- , counterIncrement(o.counterIncrement)
- , counterReset(o.counterReset)
, m_zoom(RenderStyle::initialZoom())
{
}
diff --git a/WebCore/rendering/style/StyleVisualData.h b/WebCore/rendering/style/StyleVisualData.h
index 613ef2f..d1f0f83 100644
--- a/WebCore/rendering/style/StyleVisualData.h
+++ b/WebCore/rendering/style/StyleVisualData.h
@@ -41,8 +41,6 @@ public:
{
return ( clip == o.clip &&
hasClip == o.hasClip &&
- counterIncrement == o.counterIncrement &&
- counterReset == o.counterReset &&
textDecoration == o.textDecoration &&
m_zoom == o.m_zoom);
}
@@ -52,9 +50,6 @@ public:
bool hasClip : 1;
unsigned textDecoration : 4; // Text decorations defined *only* by this element.
- short counterIncrement; // ok, so these are not visual mode specific
- short counterReset; // can't go to inherited, since these are not inherited
-
float m_zoom;
private: