diff options
Diffstat (limited to 'WebCore/rendering')
63 files changed, 534 insertions, 209 deletions
diff --git a/WebCore/rendering/InlineBox.h b/WebCore/rendering/InlineBox.h index c5f1997..991a3ff 100644 --- a/WebCore/rendering/InlineBox.h +++ b/WebCore/rendering/InlineBox.h @@ -120,6 +120,13 @@ public: else adjustPosition(0, delta); } + void adjustBlockDirectionPosition(int delta) + { + if (isHorizontal()) + adjustPosition(0, delta); + else + adjustPosition(delta, 0); + } virtual void paint(PaintInfo&, int tx, int ty); virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty); diff --git a/WebCore/rendering/InlineFlowBox.cpp b/WebCore/rendering/InlineFlowBox.cpp index e67c751..ee9fe9f 100644 --- a/WebCore/rendering/InlineFlowBox.cpp +++ b/WebCore/rendering/InlineFlowBox.cpp @@ -32,6 +32,9 @@ #include "RenderInline.h" #include "RenderLayer.h" #include "RenderListMarker.h" +#include "RenderRubyBase.h" +#include "RenderRubyRun.h" +#include "RenderRubyText.h" #include "RenderTableCell.h" #include "RootInlineBox.h" #include "Text.h" @@ -620,7 +623,8 @@ void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositi } } -void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAscent, bool strictMode, int& lineTop, int& lineBottom, bool& setLineTop, FontBaseline baselineType) +void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAscent, bool strictMode, int& lineTop, int& lineBottom, bool& setLineTop, + int& lineTopIncludingMargins, int& lineBottomIncludingMargins, bool& containsRuby, FontBaseline baselineType) { if (isRootInlineBox()) setLogicalTop(top + maxAscent - baselinePosition(baselineType)); // Place our root box. @@ -633,7 +637,8 @@ void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAs // line-height). bool isInlineFlow = curr->isInlineFlowBox(); if (isInlineFlow) - static_cast<InlineFlowBox*>(curr)->placeBoxesInBlockDirection(top, maxHeight, maxAscent, strictMode, lineTop, lineBottom, setLineTop, baselineType); + static_cast<InlineFlowBox*>(curr)->placeBoxesInBlockDirection(top, maxHeight, maxAscent, strictMode, lineTop, lineBottom, setLineTop, + lineTopIncludingMargins, lineBottomIncludingMargins, containsRuby, baselineType); bool childAffectsTopBottomPos = true; if (curr->logicalTop() == PositionTop) @@ -648,6 +653,10 @@ void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAs } int newLogicalTop = curr->logicalTop(); + int newLogicalTopIncludingMargins; + int boxHeight = curr->logicalHeight(); + int boxHeightIncludingMargins = boxHeight; + if (curr->isText() || curr->isInlineFlowBox()) { const Font& font = curr->renderer()->style(m_firstLine)->font(); newLogicalTop += curr->baselinePosition(baselineType) - font.ascent(baselineType); @@ -656,21 +665,43 @@ void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAs newLogicalTop -= boxObject->style(m_firstLine)->isHorizontalWritingMode() ? boxObject->borderTop() + boxObject->paddingTop() : boxObject->borderRight() + boxObject->paddingRight(); } + newLogicalTopIncludingMargins = newLogicalTop; } else if (!curr->renderer()->isBR()) { RenderBox* box = toRenderBox(curr->renderer()); - newLogicalTop += box->style(m_firstLine)->isHorizontalWritingMode() ? box->marginTop() : box->marginRight(); + newLogicalTopIncludingMargins = newLogicalTop; + int overSideMargin = curr->isHorizontal() ? box->marginTop() : box->marginRight(); + int underSideMargin = curr->isHorizontal() ? box->marginBottom() : box->marginLeft(); + newLogicalTop += overSideMargin; + boxHeightIncludingMargins += overSideMargin + underSideMargin; } curr->setLogicalTop(newLogicalTop); if (childAffectsTopBottomPos) { - int boxHeight = curr->logicalHeight(); + if (curr->renderer()->isRubyRun()) { + // Treat the leading on the first and last lines of ruby runs as not being part of the overall lineTop/lineBottom. + // Really this is a workaround hack for the fact that ruby should have been done as line layout and not done using + // inline-block. + containsRuby = true; + RenderRubyRun* rubyRun = static_cast<RenderRubyRun*>(curr->renderer()); + if (RenderRubyBase* rubyBase = rubyRun->rubyBase()) { + int bottomRubyBaseLeading = (curr->logicalHeight() - rubyBase->logicalBottom()) + rubyBase->logicalHeight() - (rubyBase->lastRootBox() ? rubyBase->lastRootBox()->lineBottom() : 0); + int topRubyBaseLeading = rubyBase->logicalTop() + (rubyBase->firstRootBox() ? rubyBase->firstRootBox()->lineTop() : 0); + newLogicalTop += !renderer()->style()->isFlippedLinesWritingMode() ? topRubyBaseLeading : bottomRubyBaseLeading; + boxHeight -= (topRubyBaseLeading + bottomRubyBaseLeading); + } + } + if (!setLineTop) { setLineTop = true; lineTop = newLogicalTop; - } else + lineTopIncludingMargins = min(lineTop, newLogicalTopIncludingMargins); + } else { lineTop = min(lineTop, newLogicalTop); + lineTopIncludingMargins = min(lineTop, min(lineTopIncludingMargins, newLogicalTopIncludingMargins)); + } lineBottom = max(lineBottom, newLogicalTop + boxHeight); + lineBottomIncludingMargins = max(lineBottom, max(lineBottomIncludingMargins, newLogicalTopIncludingMargins + boxHeightIncludingMargins)); } } @@ -682,13 +713,17 @@ void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAs if (!setLineTop) { setLineTop = true; lineTop = logicalTop(); - } else + lineTopIncludingMargins = lineTop; + } else { lineTop = min(lineTop, logicalTop()); + lineTopIncludingMargins = min(lineTop, lineTopIncludingMargins); + } lineBottom = max(lineBottom, logicalTop() + logicalHeight()); + lineBottomIncludingMargins = max(lineBottom, lineBottomIncludingMargins); } if (renderer()->style()->isFlippedLinesWritingMode()) - flipLinesInBlockDirection(lineTop, lineBottom); + flipLinesInBlockDirection(lineTopIncludingMargins, lineBottomIncludingMargins); } } @@ -1170,6 +1205,40 @@ void InlineFlowBox::clearTruncation() box->clearTruncation(); } +int InlineFlowBox::computeBlockDirectionRubyAdjustment(int allowedPosition) const +{ + int result = 0; + for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { + if (curr->renderer()->isPositioned()) + continue; // Positioned placeholders don't affect calculations. + + if (curr->isInlineFlowBox()) + result = max(result, static_cast<InlineFlowBox*>(curr)->computeBlockDirectionRubyAdjustment(allowedPosition)); + + if (curr->renderer()->isReplaced() && curr->renderer()->isRubyRun()) { + RenderRubyRun* rubyRun = static_cast<RenderRubyRun*>(curr->renderer()); + RenderRubyText* rubyText = rubyRun->rubyText(); + if (!rubyText) + continue; + + if (!rubyRun->style()->isFlippedLinesWritingMode()) { + int topOfFirstRubyTextLine = rubyText->logicalTop() + (rubyText->firstRootBox() ? rubyText->firstRootBox()->lineTop() : 0); + if (topOfFirstRubyTextLine >= 0) + continue; + topOfFirstRubyTextLine += curr->logicalTop(); + result = max(result, allowedPosition - topOfFirstRubyTextLine); + } else { + int bottomOfLastRubyTextLine = rubyText->logicalTop() + (rubyText->lastRootBox() ? rubyText->lastRootBox()->lineBottom() : rubyText->logicalHeight()); + if (bottomOfLastRubyTextLine <= curr->logicalHeight()) + continue; + bottomOfLastRubyTextLine += curr->logicalTop(); + result = max(result, bottomOfLastRubyTextLine - allowedPosition); + } + } + } + return result; +} + #ifndef NDEBUG void InlineFlowBox::checkConsistency() const diff --git a/WebCore/rendering/InlineFlowBox.h b/WebCore/rendering/InlineFlowBox.h index e3127af..6e06a75 100644 --- a/WebCore/rendering/InlineFlowBox.h +++ b/WebCore/rendering/InlineFlowBox.h @@ -160,10 +160,12 @@ public: bool strictMode, GlyphOverflowAndFallbackFontsMap&, FontBaseline, VerticalPositionCache&); void adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent, int maxPositionTop, int maxPositionBottom); - void placeBoxesInBlockDirection(int logicalTop, int maxHeight, int maxAscent, bool strictMode, int& lineTop, int& lineBottom, bool& setLineTop, FontBaseline); + void placeBoxesInBlockDirection(int logicalTop, int maxHeight, int maxAscent, bool strictMode, int& lineTop, int& lineBottom, bool& setLineTop, + int& lineTopIncludingMargins, int& lineBottomIncludingMargins, bool& containsRuby, FontBaseline); void flipLinesInBlockDirection(int lineTop, int lineBottom); void computeBlockDirectionOverflow(int lineTop, int lineBottom, bool strictMode, GlyphOverflowAndFallbackFontsMap&); bool requiresIdeographicBaseline(const GlyphOverflowAndFallbackFontsMap&) const; + int computeBlockDirectionRubyAdjustment(int allowedPosition) const; void removeChild(InlineBox* child); diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp index 575bdf2..d055185 100644 --- a/WebCore/rendering/InlineTextBox.cpp +++ b/WebCore/rendering/InlineTextBox.cpp @@ -1085,10 +1085,11 @@ unsigned InlineTextBox::caretMaxRenderedOffset() const int InlineTextBox::textPos() const { + // When computing the width of a text run, RenderBlock::computeInlineDirectionPositionsForLine() doesn't include the actual offset + // from the containing block edge in its measurement. textPos() should be consistent so the text are rendered in the same width. if (logicalLeft() == 0) return 0; - RenderBlock* blockElement = renderer()->containingBlock(); - return logicalLeft() - blockElement->borderStart() - blockElement->paddingStart(); + return logicalLeft() - root()->logicalLeft(); } int InlineTextBox::offsetForPosition(int lineOffset, bool includePartialGlyphs) const diff --git a/WebCore/rendering/InlineTextBox.h b/WebCore/rendering/InlineTextBox.h index bc2219b..c97a061 100644 --- a/WebCore/rendering/InlineTextBox.h +++ b/WebCore/rendering/InlineTextBox.h @@ -119,7 +119,7 @@ public: private: virtual unsigned caretMaxRenderedOffset() const; - int textPos() const; + int textPos() const; // returns the x position relative to the left start of the text line. public: virtual int offsetForPosition(int x, bool includePartialGlyphs = true) const; diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp index aadc1d4..208a1b9 100644 --- a/WebCore/rendering/RenderBlock.cpp +++ b/WebCore/rendering/RenderBlock.cpp @@ -1262,6 +1262,8 @@ void RenderBlock::layoutBlock(bool relayoutChildren, int pageHeight) if (view()->layoutState()->m_pageHeight) setPageY(view()->layoutState()->pageY(y())); + updateLayerTransform(); + // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if // we overflow or not. updateScrollInfoAfterLayout(); @@ -1780,10 +1782,9 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatLogica MarginInfo marginInfo(this, beforeEdge, afterEdge); // Fieldsets need to find their legend and position it inside the border of the object. - // The legend then gets skipped during normal layout. - // FIXME: Make fieldsets work with block-flow. - // https://bugs.webkit.org/show_bug.cgi?id=46785 - RenderObject* legend = layoutLegend(relayoutChildren); + // The legend then gets skipped during normal layout. The same is true for ruby text. + // It doesn't get included in the normal layout process but is instead skipped. + RenderObject* childToExclude = layoutSpecialExcludedChild(relayoutChildren); int previousFloatLogicalBottom = 0; maxFloatLogicalBottom = 0; @@ -1794,8 +1795,8 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatLogica RenderBox* child = next; next = child->nextSiblingBox(); - if (legend == child) - continue; // Skip the legend, since it has already been positioned up in the fieldset's border. + if (childToExclude == child) + continue; // Skip this child, since it will be positioned by the specialized subclass (fieldsets and ruby runs). // Make sure we layout children if they need it. // FIXME: Technically percentage height objects only need a relayout if their percentage isn't going to be turned into @@ -2007,6 +2008,8 @@ bool RenderBlock::layoutOnlyPositionedObjects() layoutPositionedObjects(false); statePusher.pop(); + + updateLayerTransform(); updateScrollInfoAfterLayout(); @@ -2039,7 +2042,7 @@ void RenderBlock::layoutPositionedObjects(bool relayoutChildren) r->setChildNeedsLayout(true, false); // If relayoutChildren is set and we have percentage padding, we also need to invalidate the child's pref widths. - //if (relayoutChildren && (r->style()->paddingLeft().isPercent() || r->style()->paddingRight().isPercent())) + if (relayoutChildren && (r->style()->paddingStart().isPercent() || r->style()->paddingEnd().isPercent())) r->setPreferredLogicalWidthsDirty(true, false); if (!r->needsLayout()) @@ -2232,7 +2235,7 @@ void RenderBlock::paintContents(PaintInfo& paintInfo, int tx, int ty) // Avoid painting descendants of the root element when stylesheets haven't loaded. This eliminates FOUC. // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document // will do a full repaint(). - if (document()->didLayoutWithPendingStylesheets() && !isRenderView()) + if (document()->mayCauseFlashOfUnstyledContent() && !isRenderView()) return; if (childrenInline()) @@ -4744,11 +4747,22 @@ void RenderBlock::computePreferredLogicalWidths() m_minPreferredLogicalWidth = 0; } + int scrollbarWidth = 0; + if (hasOverflowClip() && style()->overflowY() == OSCROLL) { + layer()->setHasVerticalScrollbar(true); + scrollbarWidth = verticalScrollbarWidth(); + m_maxPreferredLogicalWidth += scrollbarWidth; + } + if (isTableCell()) { Length w = toRenderTableCell(this)->styleOrColLogicalWidth(); - if (w.isFixed() && w.value() > 0) + if (w.isFixed() && w.value() > 0) { m_maxPreferredLogicalWidth = max(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(w.value())); + scrollbarWidth = 0; + } } + + m_minPreferredLogicalWidth += scrollbarWidth; } if (style()->logicalMinWidth().isFixed() && style()->logicalMinWidth().value() > 0) { @@ -4761,14 +4775,9 @@ void RenderBlock::computePreferredLogicalWidths() m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->logicalMaxWidth().value())); } - int toAdd = 0; - toAdd = borderAndPaddingLogicalWidth(); - - if (hasOverflowClip() && style()->overflowY() == OSCROLL) - toAdd += verticalScrollbarWidth(); - - m_minPreferredLogicalWidth += toAdd; - m_maxPreferredLogicalWidth += toAdd; + int borderAndPadding = borderAndPaddingLogicalWidth(); + m_minPreferredLogicalWidth += borderAndPadding; + m_maxPreferredLogicalWidth += borderAndPadding; setPreferredLogicalWidthsDirty(false); } @@ -5245,7 +5254,7 @@ bool RenderBlock::hasLineIfEmpty() const if (node()->isContentEditable() && node()->rootEditableElement() == node()) return true; - if (node()->isShadowNode() && (node()->shadowParentNode()->hasTagName(inputTag) || node()->shadowParentNode()->hasTagName(textareaTag))) + if (node()->isShadowNode() && (node()->shadowParentNode()->hasTagName(inputTag))) return true; return false; diff --git a/WebCore/rendering/RenderBlock.h b/WebCore/rendering/RenderBlock.h index 645c0ec..5153218 100644 --- a/WebCore/rendering/RenderBlock.h +++ b/WebCore/rendering/RenderBlock.h @@ -298,6 +298,8 @@ protected: } #endif + void addOverflowFromBlockChildren(); + private: virtual RenderObjectChildList* virtualChildren() { return children(); } virtual const RenderObjectChildList* virtualChildren() const { return children(); } @@ -336,8 +338,8 @@ private: virtual RootInlineBox* createRootInlineBox(); // Subclassed by SVG and Ruby. - // Called to lay out the legend for a fieldset. - virtual RenderObject* layoutLegend(bool /*relayoutChildren*/) { return 0; } + // Called to lay out the legend for a fieldset or the ruby text of a ruby run. + virtual RenderObject* layoutSpecialExcludedChild(bool /*relayoutChildren*/) { return 0; } struct FloatWithRect { FloatWithRect(RenderBox* f) @@ -468,7 +470,6 @@ private: int afterSideLayoutOverflowForLine(RootInlineBox*) const; // End of functions defined in RenderBlockLineLayout.cpp. - void addOverflowFromBlockChildren(); void addOverflowFromFloats(); void paintFloats(PaintInfo&, int tx, int ty, bool preservePhase = false); diff --git a/WebCore/rendering/RenderBlockLineLayout.cpp b/WebCore/rendering/RenderBlockLineLayout.cpp index 127ffe0..878d1ab 100644 --- a/WebCore/rendering/RenderBlockLineLayout.cpp +++ b/WebCore/rendering/RenderBlockLineLayout.cpp @@ -1043,8 +1043,16 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica } } + // Expand the last line to accommodate Ruby in flipped lines writing modes (the Ruby is on + // the after side in this case). + int lastLineRubyAdjustment = 0; + if (lastRootBox() && style()->isFlippedLinesWritingMode()) { + int lowestAllowedPosition = max(lastRootBox()->lineBottom(), logicalHeight() + paddingAfter()); + lastLineRubyAdjustment = lastRootBox()->computeBlockDirectionRubyAdjustment(lowestAllowedPosition); + } + // Now add in the bottom border/padding. - setLogicalHeight(logicalHeight() + borderAfter() + paddingAfter() + scrollbarLogicalHeight()); + setLogicalHeight(logicalHeight() + lastLineRubyAdjustment + borderAfter() + paddingAfter() + scrollbarLogicalHeight()); if (!firstLineBox() && hasLineIfEmpty()) setLogicalHeight(logicalHeight() + lineHeight(true, style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes)); diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp index 41e2cd5..f0618ea 100644 --- a/WebCore/rendering/RenderBox.cpp +++ b/WebCore/rendering/RenderBox.cpp @@ -459,11 +459,9 @@ void RenderBox::absoluteQuads(Vector<FloatQuad>& quads) IntRect RenderBox::applyLayerTransformToRect(const IntRect& rect) const { - if (layer() && layer()->hasTransform()) { + if (hasLayer() && layer()->hasTransform()) { TransformationMatrix transform; - transform.makeIdentity(); transform.translate(rect.x(), rect.y()); - layer()->updateTransform(); transform.multLeft(layer()->currentTransform()); return transform.mapRect(IntRect(0, 0, rect.width(), rect.height())); } @@ -475,6 +473,13 @@ IntRect RenderBox::transformedFrameRect() const return applyLayerTransformToRect(frameRect()); } +void RenderBox::updateLayerTransform() +{ + // Transform-origin depends on box size, so we need to update the layer transform after layout. + if (hasLayer()) + layer()->updateTransform(); +} + IntRect RenderBox::absoluteContentBox() const { IntRect rect = contentBoxRect(); @@ -774,8 +779,8 @@ void RenderBox::paintRootBoxDecorations(PaintInfo& paintInfo, int tx, int ty) // CSS2 14.2: // The background of the box generated by the root element covers the entire canvas including // its margins. - int bx = tx - marginLeft(); - int by = ty - marginTop(); + int bx = tx - marginLeft() + view()->leftLayoutOverflow(); + int by = ty - marginTop() + view()->topLayoutOverflow(); int bw = max(w + marginLeft() + marginRight() + borderLeft() + borderRight(), rw); int bh = max(h + marginTop() + marginBottom() + borderTop() + borderBottom(), rh); diff --git a/WebCore/rendering/RenderBox.h b/WebCore/rendering/RenderBox.h index 091796b..cc559a3 100644 --- a/WebCore/rendering/RenderBox.h +++ b/WebCore/rendering/RenderBox.h @@ -157,6 +157,8 @@ public: void addOverflowFromChild(RenderBox* child) { addOverflowFromChild(child, IntSize(child->x(), child->y())); } void addOverflowFromChild(RenderBox* child, const IntSize& delta); void clearLayoutOverflow(); + + void updateLayerTransform(); void blockDirectionOverflow(bool isLineHorizontal, int& logicalTopLayoutOverflow, int& logicalBottomLayoutOverflow, int& logicalTopVisualOverflow, int& logicalBottomVisualOverflow); diff --git a/WebCore/rendering/RenderBoxModelObject.cpp b/WebCore/rendering/RenderBoxModelObject.cpp index 1580b49..bd19165 100644 --- a/WebCore/rendering/RenderBoxModelObject.cpp +++ b/WebCore/rendering/RenderBoxModelObject.cpp @@ -50,12 +50,14 @@ bool RenderBoxModelObject::s_layerWasSelfPainting = false; static const double cInterpolationCutoff = 800. * 800.; static const double cLowQualityTimeThreshold = 0.500; // 500 ms -typedef HashMap<RenderBoxModelObject*, IntSize> LastPaintSizeMap; +typedef pair<RenderBoxModelObject*, const void*> LastPaintSizeMapKey; +typedef HashMap<LastPaintSizeMapKey, IntSize> LastPaintSizeMap; class ImageQualityController : public Noncopyable { public: ImageQualityController(); - bool shouldPaintAtLowQuality(GraphicsContext*, RenderBoxModelObject*, Image*, const IntSize&); + bool shouldPaintAtLowQuality(GraphicsContext*, RenderBoxModelObject*, Image*, const void* layer, const IntSize&); + void keyDestroyed(LastPaintSizeMapKey key); void objectDestroyed(RenderBoxModelObject*); private: @@ -73,21 +75,31 @@ ImageQualityController::ImageQualityController() { } -void ImageQualityController::objectDestroyed(RenderBoxModelObject* object) +void ImageQualityController::keyDestroyed(LastPaintSizeMapKey key) { - m_lastPaintSizeMap.remove(object); + m_lastPaintSizeMap.remove(key); if (m_lastPaintSizeMap.isEmpty()) { m_animatedResizeIsActive = false; m_timer.stop(); } } +void ImageQualityController::objectDestroyed(RenderBoxModelObject* object) +{ + Vector<LastPaintSizeMapKey> keysToDie; + for (LastPaintSizeMap::iterator it = m_lastPaintSizeMap.begin(); it != m_lastPaintSizeMap.end(); ++it) + if (it->first.first == object) + keysToDie.append(it->first); + for (Vector<LastPaintSizeMapKey>::iterator it = keysToDie.begin(); it != keysToDie.end(); ++it) + keyDestroyed(*it); +} + void ImageQualityController::highQualityRepaintTimerFired(Timer<ImageQualityController>*) { if (m_animatedResizeIsActive) { m_animatedResizeIsActive = false; for (LastPaintSizeMap::iterator it = m_lastPaintSizeMap.begin(); it != m_lastPaintSizeMap.end(); ++it) - it->first->repaint(); + it->first.first->repaint(); } } @@ -96,7 +108,7 @@ void ImageQualityController::restartTimer() m_timer.startOneShot(cLowQualityTimeThreshold); } -bool ImageQualityController::shouldPaintAtLowQuality(GraphicsContext* context, RenderBoxModelObject* object, Image* image, const IntSize& size) +bool ImageQualityController::shouldPaintAtLowQuality(GraphicsContext* context, RenderBoxModelObject* object, Image* image, const void *layer, const IntSize& size) { // If the image is not a bitmap image, then none of this is relevant and we just paint at high // quality. @@ -108,14 +120,15 @@ bool ImageQualityController::shouldPaintAtLowQuality(GraphicsContext* context, R IntSize imageSize(image->width(), image->height()); // Look ourselves up in the hashtable. - LastPaintSizeMap::iterator i = m_lastPaintSizeMap.find(object); + LastPaintSizeMapKey key(object, layer); + LastPaintSizeMap::iterator i = m_lastPaintSizeMap.find(key); const AffineTransform& currentTransform = context->getCTM(); bool contextIsScaled = !currentTransform.isIdentityOrTranslationOrFlipped(); if (!contextIsScaled && imageSize == size) { // There is no scale in effect. If we had a scale in effect before, we can just remove this object from the list. if (i != m_lastPaintSizeMap.end()) - m_lastPaintSizeMap.remove(object); + m_lastPaintSizeMap.remove(key); return false; } @@ -128,7 +141,7 @@ bool ImageQualityController::shouldPaintAtLowQuality(GraphicsContext* context, R } // If an animated resize is active, paint in low quality and kick the timer ahead. if (m_animatedResizeIsActive) { - m_lastPaintSizeMap.set(object, size); + m_lastPaintSizeMap.set(key, size); restartTimer(); return true; } @@ -137,19 +150,19 @@ bool ImageQualityController::shouldPaintAtLowQuality(GraphicsContext* context, R // size and set the timer. if (i == m_lastPaintSizeMap.end() || size == i->second) { restartTimer(); - m_lastPaintSizeMap.set(object, size); + m_lastPaintSizeMap.set(key, size); return false; } // If the timer is no longer active, draw at high quality and don't // set the timer. if (!m_timer.isActive()) { - objectDestroyed(object); + keyDestroyed(key); return false; } // This object has been resized to two different sizes while the timer // is active, so draw at low quality, set the flag for animated resizes and // the object to the list for high quality redraw. - m_lastPaintSizeMap.set(object, size); + m_lastPaintSizeMap.set(key, size); m_animatedResizeIsActive = true; restartTimer(); return true; @@ -183,9 +196,9 @@ void RenderBoxModelObject::setSelectionState(SelectionState s) cb->setSelectionState(s); } -bool RenderBoxModelObject::shouldPaintAtLowQuality(GraphicsContext* context, Image* image, const IntSize& size) +bool RenderBoxModelObject::shouldPaintAtLowQuality(GraphicsContext* context, Image* image, const void* layer, const IntSize& size) { - return imageQualityController()->shouldPaintAtLowQuality(context, this, image, size); + return imageQualityController()->shouldPaintAtLowQuality(context, this, image, layer, size); } RenderBoxModelObject::RenderBoxModelObject(Node* node) @@ -684,7 +697,7 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co CompositeOperator compositeOp = op == CompositeSourceOver ? bgLayer->composite() : op; RenderObject* clientForBackgroundImage = backgroundObject ? backgroundObject : this; Image* image = bg->image(clientForBackgroundImage, tileSize); - bool useLowQualityScaling = shouldPaintAtLowQuality(context, image, tileSize); + bool useLowQualityScaling = shouldPaintAtLowQuality(context, image, bgLayer, tileSize); context->drawTiledImage(image, style()->colorSpace(), destRect, phase, tileSize, compositeOp, useLowQualityScaling); } } @@ -1051,7 +1064,6 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, graphicsContext->addRoundedRectClip(borderRect, topLeft, topRight, bottomLeft, bottomRight); graphicsContext->clipOutRoundedRect(innerBorderRect, innerTopLeft, innerTopRight, innerBottomLeft, innerBottomRight); roundedPath.addRoundedRect(borderRect, topLeft, topRight, bottomLeft, bottomRight); - graphicsContext->addPath(roundedPath); } } @@ -1792,13 +1804,10 @@ void RenderBoxModelObject::paintBoxShadow(GraphicsContext* context, int tx, int } else path.addRect(holeRect); - context->beginPath(); - context->addPath(path); - context->setFillRule(RULE_EVENODD); context->setFillColor(fillColor, s->colorSpace()); context->setShadow(shadowOffset, shadowBlur, shadowColor, s->colorSpace()); - context->fillPath(); + context->fillPath(path); context->restore(); } diff --git a/WebCore/rendering/RenderBoxModelObject.h b/WebCore/rendering/RenderBoxModelObject.h index f502424..988d61a 100644 --- a/WebCore/rendering/RenderBoxModelObject.h +++ b/WebCore/rendering/RenderBoxModelObject.h @@ -122,7 +122,7 @@ public: protected: void calculateBackgroundImageGeometry(const FillLayer*, int tx, int ty, int w, int h, IntRect& destRect, IntPoint& phase, IntSize& tileSize); - bool shouldPaintAtLowQuality(GraphicsContext*, Image*, const IntSize&); + bool shouldPaintAtLowQuality(GraphicsContext*, Image*, const void*, const IntSize&); private: virtual bool isBoxModelObject() const { return true; } diff --git a/WebCore/rendering/RenderEmbeddedObject.cpp b/WebCore/rendering/RenderEmbeddedObject.cpp index 16613a5..294ffec 100644 --- a/WebCore/rendering/RenderEmbeddedObject.cpp +++ b/WebCore/rendering/RenderEmbeddedObject.cpp @@ -166,11 +166,9 @@ void RenderEmbeddedObject::paintReplaced(PaintInfo& paintInfo, int tx, int ty) context->save(); context->clip(contentRect); - context->beginPath(); - context->addPath(path); context->setAlpha(m_missingPluginIndicatorIsPressed ? replacementTextPressedRoundedRectOpacity : replacementTextRoundedRectOpacity); context->setFillColor(m_missingPluginIndicatorIsPressed ? replacementTextRoundedRectPressedColor() : Color::white, style()->colorSpace()); - context->fillPath(); + context->fillPath(path); float labelX = roundf(replacementTextRect.location().x() + (replacementTextRect.size().width() - textWidth) / 2); float labelY = roundf(replacementTextRect.location().y() + (replacementTextRect.size().height() - font.height()) / 2 + font.ascent()); @@ -223,6 +221,8 @@ void RenderEmbeddedObject::layout() m_overflow.clear(); addShadowOverflow(); + updateLayerTransform(); + if (!widget() && frameView()) frameView()->addWidgetToUpdate(this); diff --git a/WebCore/rendering/RenderFieldset.cpp b/WebCore/rendering/RenderFieldset.cpp index 12386e9..c83396c 100644 --- a/WebCore/rendering/RenderFieldset.cpp +++ b/WebCore/rendering/RenderFieldset.cpp @@ -63,7 +63,7 @@ void RenderFieldset::computePreferredLogicalWidths() } } -RenderObject* RenderFieldset::layoutLegend(bool relayoutChildren) +RenderObject* RenderFieldset::layoutSpecialExcludedChild(bool relayoutChildren) { RenderBox* legend = findLegend(); if (legend) { diff --git a/WebCore/rendering/RenderFieldset.h b/WebCore/rendering/RenderFieldset.h index bada78c..b340794 100644 --- a/WebCore/rendering/RenderFieldset.h +++ b/WebCore/rendering/RenderFieldset.h @@ -38,7 +38,7 @@ private: virtual const char* renderName() const { return "RenderFieldSet"; } virtual bool isFieldset() const { return true; } - virtual RenderObject* layoutLegend(bool relayoutChildren); + virtual RenderObject* layoutSpecialExcludedChild(bool relayoutChildren); virtual void computePreferredLogicalWidths(); virtual bool avoidsFloats() const { return true; } diff --git a/WebCore/rendering/RenderFlexibleBox.cpp b/WebCore/rendering/RenderFlexibleBox.cpp index 841442b..2257d68 100644 --- a/WebCore/rendering/RenderFlexibleBox.cpp +++ b/WebCore/rendering/RenderFlexibleBox.cpp @@ -185,6 +185,13 @@ void RenderFlexibleBox::computePreferredLogicalWidths() m_maxPreferredLogicalWidth = max(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth); } + if (hasOverflowClip() && style()->overflowY() == OSCROLL) { + layer()->setHasVerticalScrollbar(true); + int scrollbarWidth = verticalScrollbarWidth(); + m_maxPreferredLogicalWidth += scrollbarWidth; + m_minPreferredLogicalWidth += scrollbarWidth; + } + if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) { m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->minWidth().value())); m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->minWidth().value())); @@ -195,13 +202,9 @@ void RenderFlexibleBox::computePreferredLogicalWidths() m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->maxWidth().value())); } - int toAdd = borderAndPaddingWidth(); - - if (hasOverflowClip() && style()->overflowY() == OSCROLL) - toAdd += verticalScrollbarWidth(); - - m_minPreferredLogicalWidth += toAdd; - m_maxPreferredLogicalWidth += toAdd; + int borderAndPadding = borderAndPaddingLogicalWidth(); + m_minPreferredLogicalWidth += borderAndPadding; + m_maxPreferredLogicalWidth += borderAndPadding; setPreferredLogicalWidthsDirty(false); } @@ -286,6 +289,8 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, int /*pageHeight FIXM statePusher.pop(); + updateLayerTransform(); + if (view()->layoutState()->m_pageHeight) setPageY(view()->layoutState()->pageY(y())); diff --git a/WebCore/rendering/RenderIFrame.cpp b/WebCore/rendering/RenderIFrame.cpp index a2cf66c..6961a57 100644 --- a/WebCore/rendering/RenderIFrame.cpp +++ b/WebCore/rendering/RenderIFrame.cpp @@ -248,6 +248,7 @@ void RenderIFrame::layout() m_overflow.clear(); addShadowOverflow(); + updateLayerTransform(); setNeedsLayout(false); } diff --git a/WebCore/rendering/RenderImage.cpp b/WebCore/rendering/RenderImage.cpp index 48f21f1..7db8838 100644 --- a/WebCore/rendering/RenderImage.cpp +++ b/WebCore/rendering/RenderImage.cpp @@ -332,10 +332,10 @@ void RenderImage::paint(PaintInfo& paintInfo, int tx, int ty) RenderReplaced::paint(paintInfo, tx, ty); if (paintInfo.phase == PaintPhaseOutline) - paintFocusRings(paintInfo, style()); + paintFocusRing(paintInfo, style()); } -void RenderImage::paintFocusRings(PaintInfo& paintInfo, const RenderStyle* style) +void RenderImage::paintFocusRing(PaintInfo& paintInfo, const RenderStyle* style) { // Don't draw focus rings if printing. if (document()->printing() || !frame()->selection()->isFocusedAndActive()) @@ -367,10 +367,9 @@ void RenderImage::paintFocusRings(PaintInfo& paintInfo, const RenderStyle* style HTMLAreaElement* areaElement = static_cast<HTMLAreaElement*>(areas->item(k)); if (focusedNode != areaElement) continue; - - Vector<Path> focusRingPaths; - focusRingPaths.append(areaElement->getPath(this)); - paintInfo.context->drawFocusRing(focusRingPaths, style->outlineWidth(), style->outlineOffset(), style->visitedDependentColor(CSSPropertyOutlineColor)); + + RenderStyle* styleToUse = areaElement->computedStyle(); + paintInfo.context->drawFocusRing(areaElement->getPath(this), styleToUse->outlineWidth(), styleToUse->outlineOffset(), styleToUse->visitedDependentColor(CSSPropertyOutlineColor)); break; } } @@ -386,7 +385,7 @@ void RenderImage::paintIntoRect(GraphicsContext* context, const IntRect& rect) HTMLImageElement* imageElt = (node() && node()->hasTagName(imgTag)) ? static_cast<HTMLImageElement*>(node()) : 0; CompositeOperator compositeOperator = imageElt ? imageElt->compositeOperator() : CompositeSourceOver; - bool useLowQualityScaling = shouldPaintAtLowQuality(context, m_imageResource->image(), rect.size()); + bool useLowQualityScaling = shouldPaintAtLowQuality(context, m_imageResource->image(), 0, rect.size()); context->drawImage(m_imageResource->image(rect.width(), rect.height()), style()->colorSpace(), rect, compositeOperator, useLowQualityScaling); } diff --git a/WebCore/rendering/RenderImage.h b/WebCore/rendering/RenderImage.h index 86f5621..16ae7ec 100644 --- a/WebCore/rendering/RenderImage.h +++ b/WebCore/rendering/RenderImage.h @@ -57,7 +57,7 @@ protected: virtual void imageChanged(WrappedImagePtr, const IntRect* = 0); virtual void paintIntoRect(GraphicsContext*, const IntRect&); - void paintFocusRings(PaintInfo&, const RenderStyle*); + void paintFocusRing(PaintInfo&, const RenderStyle*); virtual void paint(PaintInfo&, int tx, int ty); bool isLogicalWidthSpecified() const; diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp index 2d2559c..27ff32f 100644 --- a/WebCore/rendering/RenderLayer.cpp +++ b/WebCore/rendering/RenderLayer.cpp @@ -143,8 +143,8 @@ RenderLayer::RenderLayer(RenderBoxModelObject* renderer) , m_height(0) , m_scrollX(0) , m_scrollY(0) - , m_scrollOriginX(0) , m_scrollLeftOverflow(0) + , m_scrollTopOverflow(0) , m_scrollWidth(0) , m_scrollHeight(0) , m_inResizeMode(false) @@ -249,6 +249,15 @@ bool RenderLayer::hasAcceleratedCompositing() const #endif } +bool RenderLayer::canRender3DTransforms() const +{ +#if USE(ACCELERATED_COMPOSITING) + return compositor()->canRender3DTransforms(); +#else + return false; +#endif +} + void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags, IntPoint* cachedOffset) { if (flags & DoFullRepaint) { @@ -310,8 +319,6 @@ void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags, IntPoint updateVisibilityStatus(); - updateTransform(); - if (flags & UpdatePagination) updatePagination(); else @@ -429,7 +436,7 @@ void RenderLayer::updateTransform() ASSERT(box); m_transform->makeIdentity(); box->style()->applyTransform(*m_transform, box->borderBoxRect().size(), RenderStyle::IncludeTransformOrigin); - makeMatrixRenderable(*m_transform, hasAcceleratedCompositing()); + makeMatrixRenderable(*m_transform, canRender3DTransforms()); } if (had3DTransform != has3DTransform()) @@ -446,7 +453,7 @@ TransformationMatrix RenderLayer::currentTransform() const TransformationMatrix currTransform; RefPtr<RenderStyle> style = renderer()->animation()->getAnimatedStyleForRenderer(renderer()); style->applyTransform(currTransform, renderBox()->borderBoxRect().size(), RenderStyle::IncludeTransformOrigin); - makeMatrixRenderable(currTransform, hasAcceleratedCompositing()); + makeMatrixRenderable(currTransform, canRender3DTransforms()); return currTransform; } #endif @@ -1341,11 +1348,12 @@ void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repai // complicated (since it will involve testing whether our layer // is either occluded by another layer or clipped by an enclosing // layer or contains fixed backgrounds, etc.). - int newScrollX = x - m_scrollOriginX; - if (m_scrollY == y && m_scrollX == newScrollX) + int newScrollX = x - m_scrollOrigin.x(); + int newScrollY = y - m_scrollOrigin.y(); + if (m_scrollY == newScrollY && m_scrollX == newScrollX) return; m_scrollX = newScrollX; - m_scrollY = y; + m_scrollY = newScrollY; // Update the positions of our child layers. Don't have updateLayerPositions() update // compositing layers, because we need to do a deep update from the compositing ancestor. @@ -1999,22 +2007,26 @@ void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar) m_scrollDimensionsDirty = false; - bool ltr = renderer()->style()->isLeftToRightDirection(); - int clientWidth = box->clientWidth(); int clientHeight = box->clientHeight(); - m_scrollLeftOverflow = ltr ? 0 : min(0, box->leftmostPosition(true, false) - box->borderLeft()); + bool hasLeftOverflow = (!box->style()->isHorizontalWritingMode() || !box->style()->isLeftToRightDirection()) && box->style()->writingMode() != LeftToRightWritingMode; + bool hasTopOverflow = (box->style()->isHorizontalWritingMode() || !box->style()->isLeftToRightDirection()) && box->style()->writingMode() != TopToBottomWritingMode; + + m_scrollLeftOverflow = !hasLeftOverflow ? 0 : min(0, box->leftmostPosition(true, false) - box->borderLeft()); + m_scrollTopOverflow = !hasTopOverflow ? 0 : min(0, box->topmostPosition(true, false) - box->borderTop()); - int rightPos = ltr ? + int rightPos = !hasLeftOverflow ? box->rightmostPosition(true, false) - box->borderLeft() : clientWidth - m_scrollLeftOverflow; - int bottomPos = box->lowestPosition(true, false) - box->borderTop(); + int bottomPos = !hasTopOverflow ? + box->lowestPosition(true, false) - box->borderTop() : + clientHeight - m_scrollTopOverflow; m_scrollWidth = max(rightPos, clientWidth); m_scrollHeight = max(bottomPos, clientHeight); - m_scrollOriginX = ltr ? 0 : m_scrollWidth - clientWidth; + m_scrollOrigin = IntPoint(!hasLeftOverflow ? 0 : m_scrollWidth - clientWidth, !hasTopOverflow ? 0 : m_scrollHeight - clientHeight); if (needHBar) *needHBar = rightPos > clientWidth; @@ -2028,7 +2040,6 @@ void RenderLayer::updateOverflowStatus(bool horizontalOverflow, bool verticalOve m_horizontalOverflow = horizontalOverflow; m_verticalOverflow = verticalOverflow; m_overflowStatusDirty = false; - return; } @@ -2399,7 +2410,7 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, // Avoid painting layers when stylesheets haven't loaded. This eliminates FOUC. // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document // will do a full repaint(). - if (renderer()->document()->didLayoutWithPendingStylesheets() && !renderer()->isRenderView() && !renderer()->isRoot()) + if (renderer()->document()->mayCauseFlashOfUnstyledContent() && !renderer()->isRenderView() && !renderer()->isRoot()) return; // If this layer is totally invisible then there is nothing to paint. diff --git a/WebCore/rendering/RenderLayer.h b/WebCore/rendering/RenderLayer.h index be3ddc6..db4da64 100644 --- a/WebCore/rendering/RenderLayer.h +++ b/WebCore/rendering/RenderLayer.h @@ -249,14 +249,14 @@ public: // Scrolling methods for layers that can scroll their overflow. void scrollByRecursively(int xDelta, int yDelta); - IntSize scrolledContentOffset() const { return IntSize(scrollXOffset() + m_scrollLeftOverflow, scrollYOffset()); } + IntSize scrolledContentOffset() const { return IntSize(scrollXOffset() + m_scrollLeftOverflow, scrollYOffset() + m_scrollTopOverflow); } - int scrollXOffset() const { return m_scrollX + m_scrollOriginX; } - int scrollYOffset() const { return m_scrollY; } + int scrollXOffset() const { return m_scrollX + m_scrollOrigin.x(); } + int scrollYOffset() const { return m_scrollY + m_scrollOrigin.y(); } void scrollToOffset(int x, int y, bool updateScrollbars = true, bool repaint = true); - void scrollToXOffset(int x) { scrollToOffset(x, m_scrollY); } - void scrollToYOffset(int y) { scrollToOffset(m_scrollX + m_scrollOriginX, y); } + void scrollToXOffset(int x) { scrollToOffset(x, m_scrollY + m_scrollOrigin.y()); } + void scrollToYOffset(int y) { scrollToOffset(m_scrollX + m_scrollOrigin.x(), y); } void scrollRectToVisible(const IntRect&, bool scrollToAnchor = false, const ScrollAlignment& alignX = ScrollAlignment::alignCenterIfNeeded, const ScrollAlignment& alignY = ScrollAlignment::alignCenterIfNeeded); IntRect getRectToExpose(const IntRect& visibleRect, const IntRect& exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY); @@ -308,7 +308,9 @@ public: // Returns true if the accelerated compositing is enabled bool hasAcceleratedCompositing() const; - + + bool canRender3DTransforms() const; + void updateLayerPosition(); enum UpdateLayerPositionsFlag { @@ -642,9 +644,22 @@ protected: // Our scroll offsets if the view is scrolled. int m_scrollX; int m_scrollY; - int m_scrollOriginX; // only non-zero for rtl content - int m_scrollLeftOverflow; // only non-zero for rtl content - + + // There are 8 possible combinations of writing mode and direction. Scroll origin (and its corresponding left/top overflow) + // will be non-zero in the x or y axis if there is any reversed direction or writing-mode. The combinations are: + // writing-mode / direction scrollOrigin.x() set scrollOrigin.y() set + // horizontal-tb / ltr NO NO + // horizontal-tb / rtl YES NO + // horizontal-bt / ltr NO YES + // horizontal-bt / rtl YES YES + // vertical-lr / ltr NO NO + // vertical-lr / rtl NO YES + // vertical-rl / ltr YES NO + // vertical-rl / rtl YES YES + IntPoint m_scrollOrigin; + int m_scrollLeftOverflow; + int m_scrollTopOverflow; + // The width/height of our scrolled area. int m_scrollWidth; int m_scrollHeight; diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp index 215b41f..48aa3ec 100644 --- a/WebCore/rendering/RenderLayerBacking.cpp +++ b/WebCore/rendering/RenderLayerBacking.cpp @@ -132,7 +132,7 @@ void RenderLayerBacking::updateLayerTransform(const RenderStyle* style) TransformationMatrix t; if (m_owningLayer->hasTransform()) { style->applyTransform(t, toRenderBox(renderer())->borderBoxRect().size(), RenderStyle::ExcludeTransformOrigin); - makeMatrixRenderable(t, compositor()->hasAcceleratedCompositing()); + makeMatrixRenderable(t, compositor()->canRender3DTransforms()); } m_graphicsLayer->setTransform(t); diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp index e6ea32a..638c628 100644 --- a/WebCore/rendering/RenderLayerCompositor.cpp +++ b/WebCore/rendering/RenderLayerCompositor.cpp @@ -100,6 +100,7 @@ RenderLayerCompositor::RenderLayerCompositor(RenderView* renderView) , m_rootPlatformLayer(0) , m_updateCompositingLayersTimer(this, &RenderLayerCompositor::updateCompositingLayersTimerFired) , m_hasAcceleratedCompositing(true) + , m_compositingTriggers(static_cast<ChromeClient::CompositingTriggerFlags>(ChromeClient::AllTriggers)) , m_showDebugBorders(false) , m_showRepaintCounter(false) , m_compositingConsultsOverlap(true) @@ -136,7 +137,7 @@ void RenderLayerCompositor::cacheAcceleratedCompositingFlags() bool hasAcceleratedCompositing = false; bool showDebugBorders = false; bool showRepaintCounter = false; - + if (Settings* settings = m_renderView->document()->settings()) { hasAcceleratedCompositing = settings->acceleratedCompositingEnabled(); showDebugBorders = settings->showDebugBorders(); @@ -148,18 +149,26 @@ void RenderLayerCompositor::cacheAcceleratedCompositingFlags() if (hasAcceleratedCompositing) { Frame* frame = m_renderView->frameView()->frame(); Page* page = frame ? frame->page() : 0; - if (page) - hasAcceleratedCompositing = page->chrome()->client()->allowsAcceleratedCompositing(); + if (page) { + ChromeClient* chromeClient = page->chrome()->client(); + m_compositingTriggers = chromeClient->allowedCompositingTriggers(); + hasAcceleratedCompositing = m_compositingTriggers; + } } if (hasAcceleratedCompositing != m_hasAcceleratedCompositing || showDebugBorders != m_showDebugBorders || showRepaintCounter != m_showRepaintCounter) setCompositingLayersNeedRebuild(); - + m_hasAcceleratedCompositing = hasAcceleratedCompositing; m_showDebugBorders = showDebugBorders; m_showRepaintCounter = showRepaintCounter; } +bool RenderLayerCompositor::canRender3DTransforms() const +{ + return hasAcceleratedCompositing() && (m_compositingTriggers & ChromeClient::ThreeDTransformTrigger); +} + void RenderLayerCompositor::setCompositingLayersNeedRebuild(bool needRebuild) { if (inCompositingMode()) @@ -1223,7 +1232,7 @@ bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) c || requiresCompositingForCanvas(renderer) || requiresCompositingForPlugin(renderer) || requiresCompositingForIFrame(renderer) - || renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden + || (canRender3DTransforms() && renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden) || clipsCompositingDescendants(layer) || requiresCompositingForAnimation(renderer); } @@ -1279,6 +1288,9 @@ bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer bool RenderLayerCompositor::requiresCompositingForTransform(RenderObject* renderer) const { + if (!(m_compositingTriggers & ChromeClient::ThreeDTransformTrigger)) + return false; + RenderStyle* style = renderer->style(); // Note that we ask the renderer if it has a transform, because the style may have transforms, // but the renderer may be an inline that doesn't suppport them. @@ -1287,6 +1299,8 @@ bool RenderLayerCompositor::requiresCompositingForTransform(RenderObject* render bool RenderLayerCompositor::requiresCompositingForVideo(RenderObject* renderer) const { + if (!(m_compositingTriggers & ChromeClient::VideoTrigger)) + return false; #if ENABLE(VIDEO) if (renderer->isVideo()) { RenderVideo* video = toRenderVideo(renderer); @@ -1313,6 +1327,9 @@ bool RenderLayerCompositor::requiresCompositingForVideo(RenderObject* renderer) bool RenderLayerCompositor::requiresCompositingForCanvas(RenderObject* renderer) const { + if (!(m_compositingTriggers & ChromeClient::CanvasTrigger)) + return false; + if (renderer->isCanvas()) { HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node()); return canvas->renderingContext() && canvas->renderingContext()->isAccelerated(); @@ -1322,6 +1339,9 @@ bool RenderLayerCompositor::requiresCompositingForCanvas(RenderObject* renderer) bool RenderLayerCompositor::requiresCompositingForPlugin(RenderObject* renderer) const { + if (!(m_compositingTriggers & ChromeClient::PluginTrigger)) + return false; + bool composite = (renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing()) || (renderer->isApplet() && toRenderApplet(renderer)->allowsAcceleratedCompositing()); if (!composite) @@ -1366,6 +1386,9 @@ bool RenderLayerCompositor::requiresCompositingForIFrame(RenderObject* renderer) bool RenderLayerCompositor::requiresCompositingForAnimation(RenderObject* renderer) const { + if (!(m_compositingTriggers & ChromeClient::AnimationTrigger)) + return false; + if (AnimationController* animController = renderer->animation()) { return (animController->isRunningAnimationOnRenderer(renderer, CSSPropertyOpacity) && inCompositingMode()) || animController->isRunningAnimationOnRenderer(renderer, CSSPropertyWebkitTransform); diff --git a/WebCore/rendering/RenderLayerCompositor.h b/WebCore/rendering/RenderLayerCompositor.h index ad1e2e1..e741dec 100644 --- a/WebCore/rendering/RenderLayerCompositor.h +++ b/WebCore/rendering/RenderLayerCompositor.h @@ -26,6 +26,7 @@ #ifndef RenderLayerCompositor_h #define RenderLayerCompositor_h +#include "ChromeClient.h" #include "RenderLayer.h" #include "RenderLayerBacking.h" @@ -67,7 +68,9 @@ public: // Returns true if the accelerated compositing is enabled bool hasAcceleratedCompositing() const { return m_hasAcceleratedCompositing; } - + + bool canRender3DTransforms() const; + bool showDebugBorders() const { return m_showDebugBorders; } bool showRepaintCounter() const { return m_showRepaintCounter; } @@ -237,6 +240,8 @@ private: Timer<RenderLayerCompositor> m_updateCompositingLayersTimer; bool m_hasAcceleratedCompositing; + ChromeClient::CompositingTriggerFlags m_compositingTriggers; + bool m_showDebugBorders; bool m_showRepaintCounter; bool m_compositingConsultsOverlap; diff --git a/WebCore/rendering/RenderListItem.cpp b/WebCore/rendering/RenderListItem.cpp index 2b64f04..ba107064 100644 --- a/WebCore/rendering/RenderListItem.cpp +++ b/WebCore/rendering/RenderListItem.cpp @@ -273,6 +273,7 @@ void RenderListItem::positionListMarker() } } } else { + markerLogicalLeft = m_marker->logicalLeft() + paddingStart() + borderStart() + m_marker->marginEnd(); int rightLineOffset = logicalRightOffsetForLine(blockOffset, logicalRightOffsetForLine(blockOffset, false), false); markerLogicalLeft = rightLineOffset - lineOffset + paddingStart() + borderStart() + m_marker->marginEnd(); m_marker->inlineBoxWrapper()->adjustLineDirectionPosition(markerLogicalLeft - markerOldLogicalLeft); diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp index 503b0a3..c1b1f35 100644 --- a/WebCore/rendering/RenderObject.cpp +++ b/WebCore/rendering/RenderObject.cpp @@ -31,6 +31,7 @@ #include "Chrome.h" #include "CSSStyleSelector.h" #include "DashArray.h" +#include "EditingBoundary.h" #include "FloatQuad.h" #include "Frame.h" #include "FrameView.h" @@ -958,8 +959,7 @@ void RenderObject::drawBoxSideFromPath(GraphicsContext* graphicsContext, IntRect lineDash.append(patWidth); lineDash.append(whiteSpaceWidth); graphicsContext->setLineDash(lineDash, patWidth); - graphicsContext->addPath(borderPath); - graphicsContext->strokePath(); + graphicsContext->strokePath(borderPath); return; } case DOUBLE: { @@ -2642,10 +2642,10 @@ VisiblePosition RenderObject::createVisiblePosition(int offset, EAffinity affini if (!node->isContentEditable()) { // If it can be found, we prefer a visually equivalent position that is editable. Position position(node, offset); - Position candidate = position.downstream(Position::CanCrossEditingBoundary); + Position candidate = position.downstream(CanCrossEditingBoundary); if (candidate.node()->isContentEditable()) return VisiblePosition(candidate, affinity); - candidate = position.upstream(Position::CanCrossEditingBoundary); + candidate = position.upstream(CanCrossEditingBoundary); if (candidate.node()->isContentEditable()) return VisiblePosition(candidate, affinity); } diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h index bfc62fe..e16ad46 100644 --- a/WebCore/rendering/RenderObject.h +++ b/WebCore/rendering/RenderObject.h @@ -1002,14 +1002,6 @@ inline int adjustForAbsoluteZoom(int value, RenderObject* renderer) return adjustForAbsoluteZoom(value, renderer->style()); } -inline void adjustIntRectForAbsoluteZoom(IntRect& rect, RenderObject* renderer) -{ - rect.setX(adjustForAbsoluteZoom(rect.x(), renderer)); - rect.setY(adjustForAbsoluteZoom(rect.y(), renderer)); - rect.setWidth(adjustForAbsoluteZoom(rect.width(), renderer)); - rect.setHeight(adjustForAbsoluteZoom(rect.height(), renderer)); -} - inline FloatPoint adjustFloatPointForAbsoluteZoom(const FloatPoint& point, RenderObject* renderer) { // The result here is in floats, so we don't need the truncation hack from the integer version above. @@ -1027,6 +1019,15 @@ inline void adjustFloatQuadForAbsoluteZoom(FloatQuad& quad, RenderObject* render quad.setP4(adjustFloatPointForAbsoluteZoom(quad.p4(), renderer)); } +inline void adjustFloatRectForAbsoluteZoom(FloatRect& rect, RenderObject* renderer) +{ + RenderStyle* style = renderer->style(); + rect.setX(adjustFloatForAbsoluteZoom(rect.x(), style)); + rect.setY(adjustFloatForAbsoluteZoom(rect.y(), style)); + rect.setWidth(adjustFloatForAbsoluteZoom(rect.width(), style)); + rect.setHeight(adjustFloatForAbsoluteZoom(rect.height(), style)); +} + } // namespace WebCore #ifndef NDEBUG diff --git a/WebCore/rendering/RenderReplaced.cpp b/WebCore/rendering/RenderReplaced.cpp index b1a7711..9a809fc 100644 --- a/WebCore/rendering/RenderReplaced.cpp +++ b/WebCore/rendering/RenderReplaced.cpp @@ -80,6 +80,7 @@ void RenderReplaced::layout() m_overflow.clear(); addShadowOverflow(); + updateLayerTransform(); repainter.repaintAfterLayout(); setNeedsLayout(false); diff --git a/WebCore/rendering/RenderReplica.cpp b/WebCore/rendering/RenderReplica.cpp index 4b11f40..c099d9d 100644 --- a/WebCore/rendering/RenderReplica.cpp +++ b/WebCore/rendering/RenderReplica.cpp @@ -49,6 +49,7 @@ RenderReplica::~RenderReplica() void RenderReplica::layout() { setFrameRect(parentBox()->borderBoxRect()); + updateLayerTransform(); setNeedsLayout(false); } diff --git a/WebCore/rendering/RenderRubyRun.cpp b/WebCore/rendering/RenderRubyRun.cpp index a83a3e2..5c92c04 100644 --- a/WebCore/rendering/RenderRubyRun.cpp +++ b/WebCore/rendering/RenderRubyRun.cpp @@ -220,17 +220,65 @@ RenderRubyRun* RenderRubyRun::staticCreateRubyRun(const RenderObject* parentRuby RefPtr<RenderStyle> newStyle = RenderStyle::create(); newStyle->inheritFrom(parentRuby->style()); newStyle->setDisplay(INLINE_BLOCK); - if (parentRuby->style()->isFlippedLinesWritingMode()) { - // Ruby text is always in the line direction, so invert our block flow relative to the parent to - // ensure that the Ruby ends up on the correct side. - if (parentRuby->style()->isHorizontalWritingMode()) - newStyle->setWritingMode(TopToBottomWritingMode); - else - newStyle->setWritingMode(RightToLeftWritingMode); - } - rr->setStyle(newStyle.release()); return rr; } +RenderObject* RenderRubyRun::layoutSpecialExcludedChild(bool relayoutChildren) +{ + // Don't bother positioning the RenderRubyRun yet. + RenderRubyText* rt = rubyText(); + if (!rt) + return 0; + if (relayoutChildren) + rt->setChildNeedsLayout(true, false); + rt->layoutIfNeeded(); + return rt; +} + +void RenderRubyRun::layout() +{ + RenderBlock::layout(); + + // Place the RenderRubyText such that its bottom is flush with the lineTop of the first line of the RenderRubyBase. + RenderRubyText* rt = rubyText(); + if (!rt) + return; + + int lastLineRubyTextBottom = rt->logicalHeight(); + int firstLineRubyTextTop = 0; + RootInlineBox* rootBox = rt->lastRootBox(); + if (rootBox) { + // In order to align, we have to ignore negative leading. + firstLineRubyTextTop = rt->firstRootBox()->logicalTopLayoutOverflow(); + lastLineRubyTextBottom = rootBox->logicalBottomLayoutOverflow(); + } + + if (!style()->isFlippedLinesWritingMode()) { + int firstLineTop = 0; + if (RenderRubyBase* rb = rubyBase()) { + RootInlineBox* rootBox = rb->firstRootBox(); + if (rootBox) + firstLineTop = rootBox->logicalTopLayoutOverflow(); + firstLineTop += rb->logicalTop(); + } + + rt->setLogicalTop(-lastLineRubyTextBottom + firstLineTop); + } else { + int lastLineBottom = logicalHeight(); + if (RenderRubyBase* rb = rubyBase()) { + RootInlineBox* rootBox = rb->lastRootBox(); + if (rootBox) + lastLineBottom = rootBox->logicalBottomLayoutOverflow(); + lastLineBottom += rb->logicalTop(); + } + + rt->setLogicalTop(-firstLineRubyTextTop + lastLineBottom); + } + + // Update our overflow to account for the new RenderRubyText position. + m_overflow.clear(); + addOverflowFromBlockChildren(); +} + } // namespace WebCore diff --git a/WebCore/rendering/RenderRubyRun.h b/WebCore/rendering/RenderRubyRun.h index 222ddb6..d844bff 100644 --- a/WebCore/rendering/RenderRubyRun.h +++ b/WebCore/rendering/RenderRubyRun.h @@ -55,6 +55,9 @@ public: RenderRubyBase* rubyBase() const; RenderRubyBase* rubyBaseSafe(); // creates the base if it doesn't already exist + virtual RenderObject* layoutSpecialExcludedChild(bool relayoutChildren); + virtual void layout(); + virtual bool isChildAllowed(RenderObject*, RenderStyle*) const; virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); virtual void removeChild(RenderObject* child); diff --git a/WebCore/rendering/RenderSVGResource.h b/WebCore/rendering/RenderSVGResource.h index 0230e98..6fc2dae 100644 --- a/WebCore/rendering/RenderSVGResource.h +++ b/WebCore/rendering/RenderSVGResource.h @@ -48,6 +48,7 @@ enum RenderSVGResourceMode { class Color; class FloatRect; class GraphicsContext; +class Path; class RenderObject; class RenderStyle; class RenderSVGResourceSolidColor; @@ -61,7 +62,7 @@ public: virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true) = 0; virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) = 0; - virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short) { } + virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short, const Path*) { } virtual FloatRect resourceBoundingBox(RenderObject*) = 0; virtual RenderSVGResourceType resourceType() const = 0; diff --git a/WebCore/rendering/RenderSVGResourceClipper.cpp b/WebCore/rendering/RenderSVGResourceClipper.cpp index e7b9fbb..25ed1c3 100644 --- a/WebCore/rendering/RenderSVGResourceClipper.cpp +++ b/WebCore/rendering/RenderSVGResourceClipper.cpp @@ -151,9 +151,7 @@ bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext* context, const // The SVG specification wants us to clip everything, if clip-path doesn't have a child. if (clipPath.isEmpty()) clipPath.addRect(FloatRect()); - context->beginPath(); - context->addPath(clipPath); - context->clipPath(clipRule); + context->clipPath(clipPath, clipRule); return true; } diff --git a/WebCore/rendering/RenderSVGResourceFilter.cpp b/WebCore/rendering/RenderSVGResourceFilter.cpp index 50cf68e..38d2357 100644 --- a/WebCore/rendering/RenderSVGResourceFilter.cpp +++ b/WebCore/rendering/RenderSVGResourceFilter.cpp @@ -88,13 +88,13 @@ void RenderSVGResourceFilter::removeClientFromCache(RenderObject* client, bool m markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation); } -PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives() +PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(Filter* filter) { SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node()); bool primitiveBoundingBoxMode = filterElement->primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX; // Add effects to the builder - RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(); + RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(filter); for (Node* node = filterElement->firstChild(); node; node = node->nextSibling()) { if (!node->isSVGElement()) continue; @@ -104,7 +104,7 @@ PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives() continue; SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(element); - RefPtr<FilterEffect> effect = effectElement->build(builder.get()); + RefPtr<FilterEffect> effect = effectElement->build(builder.get(), filter); if (!effect) { builder->clearEffects(); return 0; @@ -179,7 +179,7 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, filterData->filter = SVGFilter::create(filterData->shearFreeAbsoluteTransform, absoluteDrawingRegion, targetBoundingBox, filterData->boundaries, primitiveBoundingBoxMode); // Create all relevant filter primitives. - filterData->builder = buildPrimitives(); + filterData->builder = buildPrimitives(filterData->filter.get()); if (!filterData->builder) return false; @@ -227,8 +227,12 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, absoluteDrawingRegion.scale(scale.width(), scale.height()); OwnPtr<ImageBuffer> sourceGraphic; - if (!SVGImageBufferTools::createImageBuffer(absoluteDrawingRegion, absoluteDrawingRegion, sourceGraphic, ColorSpaceLinearRGB)) + if (!SVGImageBufferTools::createImageBuffer(absoluteDrawingRegion, absoluteDrawingRegion, sourceGraphic, ColorSpaceLinearRGB)) { + ASSERT(!m_filter.contains(object)); + filterData->savedContext = context; + m_filter.set(object, filterData.leakPtr()); return false; + } GraphicsContext* sourceGraphicContext = sourceGraphic->context(); ASSERT(sourceGraphicContext); @@ -250,7 +254,7 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, return true; } -void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode) +void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode, const Path*) { ASSERT(object); ASSERT(context); @@ -286,7 +290,7 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo // second drawing. if (!filterData->builded) { filterData->filter->setSourceImage(filterData->sourceGraphicBuffer.release()); - lastEffect->apply(filterData->filter.get()); + lastEffect->apply(); #if !PLATFORM(CG) ImageBuffer* resultImage = lastEffect->resultImage(); if (resultImage) diff --git a/WebCore/rendering/RenderSVGResourceFilter.h b/WebCore/rendering/RenderSVGResourceFilter.h index c64f5c6..5950c44 100644 --- a/WebCore/rendering/RenderSVGResourceFilter.h +++ b/WebCore/rendering/RenderSVGResourceFilter.h @@ -70,11 +70,11 @@ public: virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true); virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); - virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); + virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*); virtual FloatRect resourceBoundingBox(RenderObject*); - PassRefPtr<SVGFilterBuilder> buildPrimitives(); + PassRefPtr<SVGFilterBuilder> buildPrimitives(Filter*); SVGUnitTypes::SVGUnitType filterUnits() const { return toUnitType(static_cast<SVGFilterElement*>(node())->filterUnits()); } SVGUnitTypes::SVGUnitType primitiveUnits() const { return toUnitType(static_cast<SVGFilterElement*>(node())->primitiveUnits()); } diff --git a/WebCore/rendering/RenderSVGResourceGradient.cpp b/WebCore/rendering/RenderSVGResourceGradient.cpp index a757147..b76e7f8 100644 --- a/WebCore/rendering/RenderSVGResourceGradient.cpp +++ b/WebCore/rendering/RenderSVGResourceGradient.cpp @@ -230,7 +230,7 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle* return true; } -void RenderSVGResourceGradient::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode) +void RenderSVGResourceGradient::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode, const Path* path) { ASSERT(context); ASSERT(resourceMode != ApplyToDefaultMode); @@ -258,11 +258,11 @@ void RenderSVGResourceGradient::postApplyResource(RenderObject* object, Graphics #else UNUSED_PARAM(object); #endif - } else { + } else if (path) { if (resourceMode & ApplyToFillMode) - context->fillPath(); + context->fillPath(*path); else if (resourceMode & ApplyToStrokeMode) - context->strokePath(); + context->strokePath(*path); } context->restore(); diff --git a/WebCore/rendering/RenderSVGResourceGradient.h b/WebCore/rendering/RenderSVGResourceGradient.h index bc0b864..1c7f52d 100644 --- a/WebCore/rendering/RenderSVGResourceGradient.h +++ b/WebCore/rendering/RenderSVGResourceGradient.h @@ -51,7 +51,7 @@ public: virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true); virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); - virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); + virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*); virtual FloatRect resourceBoundingBox(RenderObject*) { return FloatRect(); } protected: diff --git a/WebCore/rendering/RenderSVGResourcePattern.cpp b/WebCore/rendering/RenderSVGResourcePattern.cpp index d2e4563..83754ad 100644 --- a/WebCore/rendering/RenderSVGResourcePattern.cpp +++ b/WebCore/rendering/RenderSVGResourcePattern.cpp @@ -182,16 +182,16 @@ bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle* return true; } -void RenderSVGResourcePattern::postApplyResource(RenderObject*, GraphicsContext*& context, unsigned short resourceMode) +void RenderSVGResourcePattern::postApplyResource(RenderObject*, GraphicsContext*& context, unsigned short resourceMode, const Path* path) { ASSERT(context); ASSERT(resourceMode != ApplyToDefaultMode); - if (!(resourceMode & ApplyToTextMode)) { + if (path && !(resourceMode & ApplyToTextMode)) { if (resourceMode & ApplyToFillMode) - context->fillPath(); + context->fillPath(*path); else if (resourceMode & ApplyToStrokeMode) - context->strokePath(); + context->strokePath(*path); } context->restore(); diff --git a/WebCore/rendering/RenderSVGResourcePattern.h b/WebCore/rendering/RenderSVGResourcePattern.h index ba4aec4..ee3fb23 100644 --- a/WebCore/rendering/RenderSVGResourcePattern.h +++ b/WebCore/rendering/RenderSVGResourcePattern.h @@ -53,7 +53,7 @@ public: virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true); virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); - virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); + virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*); virtual FloatRect resourceBoundingBox(RenderObject*) { return FloatRect(); } virtual RenderSVGResourceType resourceType() const { return s_resourceType; } diff --git a/WebCore/rendering/RenderSVGResourceSolidColor.cpp b/WebCore/rendering/RenderSVGResourceSolidColor.cpp index 8228c80..f9449bb 100644 --- a/WebCore/rendering/RenderSVGResourceSolidColor.cpp +++ b/WebCore/rendering/RenderSVGResourceSolidColor.cpp @@ -75,17 +75,18 @@ bool RenderSVGResourceSolidColor::applyResource(RenderObject* object, RenderStyl return true; } -void RenderSVGResourceSolidColor::postApplyResource(RenderObject*, GraphicsContext*& context, unsigned short resourceMode) +void RenderSVGResourceSolidColor::postApplyResource(RenderObject*, GraphicsContext*& context, unsigned short resourceMode, const Path* path) { ASSERT(context); ASSERT(resourceMode != ApplyToDefaultMode); - if (!(resourceMode & ApplyToTextMode)) { + if (path && !(resourceMode & ApplyToTextMode)) { if (resourceMode & ApplyToFillMode) - context->fillPath(); + context->fillPath(*path); else if (resourceMode & ApplyToStrokeMode) - context->strokePath(); + context->strokePath(*path); } +<<<<<<< HEAD #if PLATFORM(SKIA) && !PLATFORM(ANDROID) // FIXME: Move this into the GraphicsContext @@ -97,6 +98,8 @@ void RenderSVGResourceSolidColor::postApplyResource(RenderObject*, GraphicsConte context->platformContext()->setFillShader(0); context->platformContext()->setStrokeShader(0); #endif +======= +>>>>>>> webkit.org at r73109 } } diff --git a/WebCore/rendering/RenderSVGResourceSolidColor.h b/WebCore/rendering/RenderSVGResourceSolidColor.h index 44109db..72de3b2 100644 --- a/WebCore/rendering/RenderSVGResourceSolidColor.h +++ b/WebCore/rendering/RenderSVGResourceSolidColor.h @@ -37,7 +37,7 @@ public: virtual void removeClientFromCache(RenderObject*, bool = true) { } virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); - virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); + virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*); virtual FloatRect resourceBoundingBox(RenderObject*) { return FloatRect(); } virtual RenderSVGResourceType resourceType() const { return s_resourceType; } diff --git a/WebCore/rendering/RenderSlider.cpp b/WebCore/rendering/RenderSlider.cpp index d680bc7..72e46cb 100644 --- a/WebCore/rendering/RenderSlider.cpp +++ b/WebCore/rendering/RenderSlider.cpp @@ -281,6 +281,7 @@ void RenderSlider::layout() setSize(baseSize); computeLogicalWidth(); computeLogicalHeight(); + updateLayerTransform(); if (thumb) { if (oldSize != size()) diff --git a/WebCore/rendering/RenderTable.cpp b/WebCore/rendering/RenderTable.cpp index de10680..147baa4 100644 --- a/WebCore/rendering/RenderTable.cpp +++ b/WebCore/rendering/RenderTable.cpp @@ -443,6 +443,8 @@ void RenderTable::layout() // FIXME: Only pass true if width or height changed. layoutPositionedObjects(true); + updateLayerTransform(); + // Add overflow from borders. int rightBorderOverflow = width() + (collapsing ? outerBorderRight() - borderRight() : 0); int leftBorderOverflow = collapsing ? borderLeft() - outerBorderLeft() : 0; diff --git a/WebCore/rendering/RenderTableRow.cpp b/WebCore/rendering/RenderTableRow.cpp index 98544a6..3dd4017 100644 --- a/WebCore/rendering/RenderTableRow.cpp +++ b/WebCore/rendering/RenderTableRow.cpp @@ -145,6 +145,7 @@ void RenderTableRow::layout() } statePusher.pop(); + // RenderTableSection::layoutRows will set our logical height and width later, so it calls updateLayerTransform(). setNeedsLayout(false); } diff --git a/WebCore/rendering/RenderTableSection.cpp b/WebCore/rendering/RenderTableSection.cpp index 30620d2..534fe81 100644 --- a/WebCore/rendering/RenderTableSection.cpp +++ b/WebCore/rendering/RenderTableSection.cpp @@ -579,6 +579,7 @@ int RenderTableSection::layoutRows(int toAdd) rowRenderer->setLocation(0, m_rowPos[r]); rowRenderer->setLogicalWidth(logicalWidth()); rowRenderer->setLogicalHeight(m_rowPos[r + 1] - m_rowPos[r] - vspacing); + rowRenderer->updateLayerTransform(); } for (int c = 0; c < nEffCols; c++) { diff --git a/WebCore/rendering/RenderText.cpp b/WebCore/rendering/RenderText.cpp index 7635d07..0d1bd91 100644 --- a/WebCore/rendering/RenderText.cpp +++ b/WebCore/rendering/RenderText.cpp @@ -429,7 +429,7 @@ VisiblePosition RenderText::positionForPoint(const IntPoint& point) // at the y coordinate of the first line or above // and the x coordinate is to the left of the first text box left edge offset = firstTextBox()->offsetForPosition(pointLineDirection); - return createVisiblePosition(offset + firstTextBox()->start(), DOWNSTREAM); + return createVisiblePosition(offset + firstTextBox()->start(), offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM); } if (lastTextBox() && pointBlockDirection >= lastTextBox()->root()->selectionTop() && pointLineDirection >= lastTextBox()->logicalRight()) { // at the y coordinate of the last line or below diff --git a/WebCore/rendering/RenderTextControl.cpp b/WebCore/rendering/RenderTextControl.cpp index 9b9e51a..2040f10 100644 --- a/WebCore/rendering/RenderTextControl.cpp +++ b/WebCore/rendering/RenderTextControl.cpp @@ -490,11 +490,11 @@ static const char* fontFamiliesWithInvalidCharWidth[] = { bool RenderTextControl::hasValidAvgCharWidth(AtomicString family) { static HashSet<AtomicString>* fontFamiliesWithInvalidCharWidthMap = 0; - + if (!fontFamiliesWithInvalidCharWidthMap) { fontFamiliesWithInvalidCharWidthMap = new HashSet<AtomicString>; - - for (unsigned i = 0; i < sizeof(fontFamiliesWithInvalidCharWidth) / sizeof(fontFamiliesWithInvalidCharWidth[0]); i++) + + for (size_t i = 0; i < WTF_ARRAY_LENGTH(fontFamiliesWithInvalidCharWidth); ++i) fontFamiliesWithInvalidCharWidthMap->add(AtomicString(fontFamiliesWithInvalidCharWidth[i])); } diff --git a/WebCore/rendering/RenderTextControlSingleLine.cpp b/WebCore/rendering/RenderTextControlSingleLine.cpp index da85863..8ba37e9 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.cpp +++ b/WebCore/rendering/RenderTextControlSingleLine.cpp @@ -589,16 +589,15 @@ int RenderTextControlSingleLine::preferredDecorationWidthRight() const void RenderTextControlSingleLine::adjustControlHeightBasedOnLineHeight(int lineHeight) { if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0) { - toRenderBlock(resultsRenderer)->computeLogicalHeight(); + resultsRenderer->computeLogicalHeight(); setHeight(max(height(), resultsRenderer->borderTop() + resultsRenderer->borderBottom() + resultsRenderer->paddingTop() + resultsRenderer->paddingBottom() + resultsRenderer->marginTop() + resultsRenderer->marginBottom())); lineHeight = max(lineHeight, resultsRenderer->height()); } - if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0) { - toRenderBlock(cancelRenderer)->computeLogicalHeight(); + cancelRenderer->computeLogicalHeight(); setHeight(max(height(), cancelRenderer->borderTop() + cancelRenderer->borderBottom() + cancelRenderer->paddingTop() + cancelRenderer->paddingBottom() + @@ -670,6 +669,21 @@ void RenderTextControlSingleLine::createSubtreeIfNeeded() } } +#if ENABLE(INPUT_SPEECH) +void RenderTextControlSingleLine::speechAttributeChanged() +{ + // The inner text element of this renderer has different styles depending on whether the + // speech button is visible or not. So when the speech attribute changes, we reset the + // whole thing and recreate to get the right styles and layout. + if (m_speechButton) + m_speechButton->detach(); + setChildrenInline(true); + RenderStyle* parentStyle = m_innerBlock ? m_innerBlock->renderer()->style() : style(); + setStyle(createInnerTextStyle(parentStyle)); + updateFromElement(); +} +#endif + void RenderTextControlSingleLine::updateFromElement() { createSubtreeIfNeeded(); diff --git a/WebCore/rendering/RenderTextControlSingleLine.h b/WebCore/rendering/RenderTextControlSingleLine.h index 26987fd..d51d7f3 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.h +++ b/WebCore/rendering/RenderTextControlSingleLine.h @@ -59,6 +59,10 @@ public: // Decoration width outside of the text field. int decorationWidthRight() const; +#if ENABLE(INPUT_SPEECH) + void speechAttributeChanged(); +#endif + private: int preferredDecorationWidthRight() const; virtual bool hasControlClip() const; diff --git a/WebCore/rendering/RenderThemeChromiumSkia.cpp b/WebCore/rendering/RenderThemeChromiumSkia.cpp index d90bbc2..7f664eb 100644 --- a/WebCore/rendering/RenderThemeChromiumSkia.cpp +++ b/WebCore/rendering/RenderThemeChromiumSkia.cpp @@ -127,7 +127,8 @@ RenderThemeChromiumSkia::~RenderThemeChromiumSkia() // Use the Windows style sheets to match their metrics. String RenderThemeChromiumSkia::extraDefaultStyleSheet() { - return String(themeWinUserAgentStyleSheet, sizeof(themeWinUserAgentStyleSheet)); + return String(themeWinUserAgentStyleSheet, sizeof(themeWinUserAgentStyleSheet)) + + String(themeChromiumSkiaUserAgentStyleSheet, sizeof(themeChromiumSkiaUserAgentStyleSheet)); } String RenderThemeChromiumSkia::extraQuirksStyleSheet() diff --git a/WebCore/rendering/RenderView.cpp b/WebCore/rendering/RenderView.cpp index 8672ff4..7ed44d4 100644 --- a/WebCore/rendering/RenderView.cpp +++ b/WebCore/rendering/RenderView.cpp @@ -142,7 +142,9 @@ void RenderView::layout() // Reset overflow and then replace it with docWidth and docHeight. m_overflow.clear(); - addLayoutOverflow(IntRect(0, 0, docWidth(), docHeight())); + int leftOverflow = docLeft(); + int topOverflow = docTop(); + addLayoutOverflow(IntRect(leftOverflow, topOverflow, docWidth(leftOverflow), docHeight(topOverflow))); ASSERT(layoutDelta() == IntSize()); ASSERT(m_layoutStateDisableCount == 0); @@ -654,9 +656,18 @@ IntRect RenderView::viewRect() const return IntRect(); } -int RenderView::docHeight() const +int RenderView::docTop() const { - int h = lowestPosition(); + // Clip out top overflow in vertical LTR pages or horizontal-tb pages. + if ((!style()->isHorizontalWritingMode() && style()->isLeftToRightDirection()) || style()->writingMode() == TopToBottomWritingMode) + return 0; + return std::min(0, topmostPosition()); +} + +int RenderView::docHeight(int topOverflow) const +{ + int h = ((!style()->isHorizontalWritingMode() && style()->isLeftToRightDirection()) || style()->writingMode() == TopToBottomWritingMode) ? + lowestPosition() : height() - topOverflow; // FIXME: This doesn't do any margin collapsing. // Instead of this dh computation we should keep the result @@ -671,9 +682,18 @@ int RenderView::docHeight() const return h; } -int RenderView::docWidth() const +int RenderView::docLeft() const +{ + // Clip out left overflow in horizontal LTR pages or vertical-lr pages. + if ((style()->isHorizontalWritingMode() && style()->isLeftToRightDirection()) || style()->writingMode() == LeftToRightWritingMode) + return 0; + return std::min(0, leftmostPosition()); +} + +int RenderView::docWidth(int leftOverflow) const { - int w = rightmostPosition(); + int w = ((style()->isHorizontalWritingMode() && style()->isLeftToRightDirection()) || style()->writingMode() == LeftToRightWritingMode) ? + rightmostPosition() : width() - leftOverflow; for (RenderBox* c = firstChildBox(); c; c = c->nextSiblingBox()) { int dw = c->width() + c->marginLeft() + c->marginRight(); diff --git a/WebCore/rendering/RenderView.h b/WebCore/rendering/RenderView.h index 81cb686..99b6a5e 100644 --- a/WebCore/rendering/RenderView.h +++ b/WebCore/rendering/RenderView.h @@ -175,12 +175,20 @@ protected: private: bool shouldRepaint(const IntRect& r) const; +<<<<<<< HEAD #ifdef ANDROID_FLATTEN_FRAMESET public: // used by layout function #endif int docHeight() const; int docWidth() const; +======= + + int docTop() const; + int docHeight(int topOverflow) const; + int docLeft() const; + int docWidth(int leftOverflow) const; +>>>>>>> webkit.org at r73109 // These functions may only be accessed by LayoutStateMaintainer. bool pushLayoutState(RenderBox* renderer, const IntSize& offset, int pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0) diff --git a/WebCore/rendering/RootInlineBox.cpp b/WebCore/rendering/RootInlineBox.cpp index cdc6525..da7d037 100644 --- a/WebCore/rendering/RootInlineBox.cpp +++ b/WebCore/rendering/RootInlineBox.cpp @@ -48,6 +48,7 @@ RootInlineBox::RootInlineBox(RenderBlock* block) , m_paginationStrut(0) , m_blockLogicalHeight(0) , m_baselineType(AlphabeticBaseline) + , m_containsRuby(false) { setIsHorizontal(block->style()->isHorizontalWritingMode()); } @@ -199,9 +200,10 @@ bool RootInlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re void RootInlineBox::adjustPosition(int dx, int dy) { InlineFlowBox::adjustPosition(dx, dy); - m_lineTop += dy; - m_lineBottom += dy; - m_blockLogicalHeight += dy; + int blockDirectionDelta = isHorizontal() ? dy : dx; + m_lineTop += blockDirectionDelta; + m_lineBottom += blockDirectionDelta; + m_blockLogicalHeight += blockDirectionDelta; } void RootInlineBox::childRemoved(InlineBox* box) @@ -244,11 +246,25 @@ int RootInlineBox::alignBoxesInBlockDirection(int heightOfBlock, GlyphOverflowAn int maxHeight = maxAscent + maxDescent; int lineTop = heightOfBlock; int lineBottom = heightOfBlock; + int lineTopIncludingMargins = heightOfBlock; + int lineBottomIncludingMargins = heightOfBlock; bool setLineTop = false; - placeBoxesInBlockDirection(heightOfBlock, maxHeight, maxAscent, noQuirksMode, lineTop, lineBottom, setLineTop, m_baselineType); + bool containsRuby = false; + placeBoxesInBlockDirection(heightOfBlock, maxHeight, maxAscent, noQuirksMode, lineTop, lineBottom, setLineTop, + lineTopIncludingMargins, lineBottomIncludingMargins, containsRuby, m_baselineType); computeBlockDirectionOverflow(lineTop, lineBottom, noQuirksMode, textBoxDataMap); setLineTopBottomPositions(lineTop, lineBottom); + m_containsRuby = containsRuby; + + int rubyAdjustment = blockDirectionRubyAdjustment(); + if (rubyAdjustment) { + // FIXME: Need to handle pagination here. We might have to move to the next page/column as a result of the + // ruby expansion. + adjustBlockDirectionPosition(rubyAdjustment); + heightOfBlock += rubyAdjustment; + } + // Detect integer overflow. if (heightOfBlock > numeric_limits<int>::max() - maxHeight) return numeric_limits<int>::max(); @@ -256,6 +272,21 @@ int RootInlineBox::alignBoxesInBlockDirection(int heightOfBlock, GlyphOverflowAn return heightOfBlock + maxHeight; } +int RootInlineBox::blockDirectionRubyAdjustment() const +{ + if (!renderer()->style()->isFlippedLinesWritingMode()) { + if (!containsRuby()) + return 0; + int highestAllowedPosition = prevRootBox() ? min(prevRootBox()->lineBottom(), lineTop()) : block()->borderBefore(); + return computeBlockDirectionRubyAdjustment(highestAllowedPosition); + } else if (prevRootBox() && prevRootBox()->containsRuby()) { + // We have to compute the Ruby expansion for the previous line to see how much we should move. + int lowestAllowedPosition = max(prevRootBox()->lineBottom(), lineTop()); + return prevRootBox()->computeBlockDirectionRubyAdjustment(lowestAllowedPosition); + } + return 0; +} + GapRects RootInlineBox::lineSelectionGap(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock, int selTop, int selHeight, const PaintInfo* paintInfo) { diff --git a/WebCore/rendering/RootInlineBox.h b/WebCore/rendering/RootInlineBox.h index 851b4b1..42ad4da 100644 --- a/WebCore/rendering/RootInlineBox.h +++ b/WebCore/rendering/RootInlineBox.h @@ -128,10 +128,14 @@ public: FontBaseline baselineType() const { return m_baselineType; } + bool containsRuby() const { return m_containsRuby; } + private: bool hasEllipsisBox() const { return m_hasEllipsisBoxOrHyphen; } void setHasEllipsisBox(bool hasEllipsisBox) { m_hasEllipsisBoxOrHyphen = hasEllipsisBox; } + int blockDirectionRubyAdjustment() const; + // Where this line ended. The exact object and the position within that object are stored so that // we can create an InlineIterator beginning just after the end of this line. RenderObject* m_lineBreakObj; @@ -153,6 +157,9 @@ private: // Whether or not this line uses alphabetic or ideographic baselines by default. FontBaseline m_baselineType; + // If the line contains any ruby runs, then this will be true. + bool m_containsRuby : 1; + WTF::Unicode::Direction m_lineBreakBidiStatusEor : 5; WTF::Unicode::Direction m_lineBreakBidiStatusLastStrong : 5; WTF::Unicode::Direction m_lineBreakBidiStatusLast : 5; diff --git a/WebCore/rendering/SVGRenderSupport.cpp b/WebCore/rendering/SVGRenderSupport.cpp index 608cf4d..cbde49b 100644 --- a/WebCore/rendering/SVGRenderSupport.cpp +++ b/WebCore/rendering/SVGRenderSupport.cpp @@ -148,7 +148,7 @@ void SVGRenderSupport::finishRenderSVGContent(RenderObject* object, PaintInfo& p SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object); if (resources) { if (RenderSVGResourceFilter* filter = resources->filter()) { - filter->postApplyResource(object, paintInfo.context, ApplyToDefaultMode); + filter->postApplyResource(object, paintInfo.context, ApplyToDefaultMode, /* path */0); paintInfo.context = savedContext; } } diff --git a/WebCore/rendering/SVGRenderTreeAsText.cpp b/WebCore/rendering/SVGRenderTreeAsText.cpp index b9a854d..9393fd6 100644 --- a/WebCore/rendering/SVGRenderTreeAsText.cpp +++ b/WebCore/rendering/SVGRenderTreeAsText.cpp @@ -415,7 +415,8 @@ static TextStream& operator<<(TextStream& ts, const RenderSVGPath& path) } else if (svgElement->hasTagName(SVGNames::pathTag)) { SVGPathElement* element = static_cast<SVGPathElement*>(svgElement); String pathString; - SVGPathParserFactory::self()->buildStringFromSVGPathSegList(element->pathSegList(), pathString, UnalteredParsing); + // FIXME: We should switch to UnalteredParsing here - this will affect the path dumping output of dozens of tests. + SVGPathParserFactory::self()->buildStringFromByteStream(element->pathByteStream(), pathString, NormalizedParsing); writeNameAndQuotedValue(ts, "data", pathString); } else ASSERT_NOT_REACHED(); @@ -558,10 +559,13 @@ void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int i writeNameValuePair(ts, "filterUnits", filter->filterUnits()); writeNameValuePair(ts, "primitiveUnits", filter->primitiveUnits()); ts << "\n"; - if (RefPtr<SVGFilterBuilder> builder = filter->buildPrimitives()) { + // Creating a placeholder filter which is passed to the builder. + FloatRect dummyRect; + RefPtr<SVGFilter> dummyFilter = SVGFilter::create(AffineTransform(), dummyRect, dummyRect, dummyRect, true); + if (RefPtr<SVGFilterBuilder> builder = filter->buildPrimitives(dummyFilter.get())) { if (FilterEffect* lastEffect = builder->lastEffect()) lastEffect->externalRepresentation(ts, indent + 1); - } + } #endif } else if (resource->resourceType() == ClipperResourceType) { RenderSVGResourceClipper* clipper = static_cast<RenderSVGResourceClipper*>(resource); diff --git a/WebCore/rendering/TextControlInnerElements.cpp b/WebCore/rendering/TextControlInnerElements.cpp index fba523e..92c51ee 100644 --- a/WebCore/rendering/TextControlInnerElements.cpp +++ b/WebCore/rendering/TextControlInnerElements.cpp @@ -41,6 +41,7 @@ #include "RenderTextControlSingleLine.h" #include "ScrollbarTheme.h" #include "SpeechInput.h" +#include "SpeechInputEvent.h" namespace WebCore { @@ -51,6 +52,7 @@ public: RenderTextControlInnerBlock(Node* node, bool isMultiLine) : RenderBlock(node), m_multiLine(isMultiLine) { } private: + virtual bool hasLineIfEmpty() const { return true; } virtual VisiblePosition positionForPoint(const IntPoint&); bool m_multiLine; @@ -112,11 +114,6 @@ void TextControlInnerElement::attachInnerElement(Node* parent, PassRefPtr<Render parent->renderer()->addChild(renderer); } -bool TextControlInnerElement::isSpellCheckingEnabled() const -{ - return m_shadowParent && m_shadowParent->isSpellCheckingEnabled(); -} - // ---------------------------- inline TextControlInnerTextElement::TextControlInnerTextElement(Document* document, HTMLElement* shadowParent) @@ -478,7 +475,7 @@ void InputFieldSpeechButtonElement::setRecognitionResult(int, const SpeechInputR // here, we take a temporary reference. RefPtr<HTMLInputElement> holdRef(input); input->setValue(results.isEmpty() ? "" : results[0]->utterance()); - input->dispatchWebkitSpeechChangeEvent(); + input->dispatchEvent(SpeechInputEvent::create(eventNames().webkitspeechchangeEvent, results)); renderer()->repaint(); } diff --git a/WebCore/rendering/TextControlInnerElements.h b/WebCore/rendering/TextControlInnerElements.h index 51c9aff..5af98ed 100644 --- a/WebCore/rendering/TextControlInnerElements.h +++ b/WebCore/rendering/TextControlInnerElements.h @@ -49,7 +49,6 @@ private: virtual bool isMouseFocusable() const { return false; } virtual bool isShadowNode() const { return m_shadowParent.get(); } virtual ContainerNode* shadowParentNode() { return m_shadowParent.get(); } - virtual bool isSpellCheckingEnabled() const; void setShadowParentNode(HTMLElement* shadowParent) { m_shadowParent = shadowParent; } RefPtr<HTMLElement> m_shadowParent; diff --git a/WebCore/rendering/break_lines.cpp b/WebCore/rendering/break_lines.cpp index 054cd43..16bfcc2 100644 --- a/WebCore/rendering/break_lines.cpp +++ b/WebCore/rendering/break_lines.cpp @@ -28,6 +28,7 @@ #include "CharacterNames.h" #include "TextBreakIterator.h" +#include <wtf/StdLibExtras.h> #if PLATFORM(MAC) #include <CoreServices/CoreServices.h> @@ -114,8 +115,7 @@ static const unsigned char asciiLineBreakTable[][(asciiLineBreakTableLastChar - #undef DI #undef AL -COMPILE_ASSERT(sizeof(asciiLineBreakTable) / sizeof(asciiLineBreakTable[0]) == asciiLineBreakTableLastChar - asciiLineBreakTableFirstChar + 1, - TestLineBreakTableConsistency); +COMPILE_ASSERT(WTF_ARRAY_LENGTH(asciiLineBreakTable) == asciiLineBreakTableLastChar - asciiLineBreakTableFirstChar + 1, TestLineBreakTableConsistency); static inline bool shouldBreakAfter(UChar ch, UChar nextCh) { diff --git a/WebCore/rendering/style/RenderStyle.h b/WebCore/rendering/style/RenderStyle.h index c206acd..ad66660 100644 --- a/WebCore/rendering/style/RenderStyle.h +++ b/WebCore/rendering/style/RenderStyle.h @@ -1382,6 +1382,11 @@ inline int adjustForAbsoluteZoom(int value, const RenderStyle* style) return roundForImpreciseConversion<int, INT_MAX, INT_MIN>(value / zoomFactor); } +inline float adjustFloatForAbsoluteZoom(float value, const RenderStyle* style) +{ + return value / style->effectiveZoom(); +} + } // namespace WebCore #endif // RenderStyle_h diff --git a/WebCore/rendering/svg/RenderSVGPath.cpp b/WebCore/rendering/svg/RenderSVGPath.cpp index 483303f..0c8ac0c 100644 --- a/WebCore/rendering/svg/RenderSVGPath.cpp +++ b/WebCore/rendering/svg/RenderSVGPath.cpp @@ -148,19 +148,17 @@ void RenderSVGPath::layout() void RenderSVGPath::fillAndStrokePath(GraphicsContext* context) { - context->beginPath(); RenderStyle* style = this->style(); Color fallbackColor; if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(this, style, fallbackColor)) { - context->addPath(m_path); if (fillPaintingResource->applyResource(this, style, context, ApplyToFillMode)) - fillPaintingResource->postApplyResource(this, context, ApplyToFillMode); + fillPaintingResource->postApplyResource(this, context, ApplyToFillMode, &m_path); else if (fallbackColor.isValid()) { RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource(); fallbackResource->setColor(fallbackColor); if (fallbackResource->applyResource(this, style, context, ApplyToFillMode)) - fallbackResource->postApplyResource(this, context, ApplyToFillMode); + fallbackResource->postApplyResource(this, context, ApplyToFillMode, &m_path); } } @@ -169,30 +167,31 @@ void RenderSVGPath::fillAndStrokePath(GraphicsContext* context) if (!strokePaintingResource) return; + Path path; + + bool nonScalingStroke = style->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE; bool restoreContext = false; - if (style->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE) { + if (nonScalingStroke) { SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node()); AffineTransform nonScalingStrokeTransform = element->getScreenCTM(SVGLocatable::DisallowStyleUpdate); if (!nonScalingStrokeTransform.isInvertible()) return; - Path transformedPath = m_path; - transformedPath.transform(nonScalingStrokeTransform); + path = m_path; + path.transform(nonScalingStrokeTransform); context->save(); context->concatCTM(nonScalingStrokeTransform.inverse()); - context->addPath(transformedPath); restoreContext = true; - } else - context->addPath(m_path); + } if (strokePaintingResource->applyResource(this, style, context, ApplyToStrokeMode)) - strokePaintingResource->postApplyResource(this, context, ApplyToStrokeMode); + strokePaintingResource->postApplyResource(this, context, ApplyToStrokeMode, nonScalingStroke ? &path : &m_path); else if (fallbackColor.isValid()) { RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource(); fallbackResource->setColor(fallbackColor); if (fallbackResource->applyResource(this, style, context, ApplyToStrokeMode)) - fallbackResource->postApplyResource(this, context, ApplyToStrokeMode); + fallbackResource->postApplyResource(this, context, ApplyToStrokeMode, nonScalingStroke ? &path : &m_path); } if (restoreContext) diff --git a/WebCore/rendering/svg/SVGInlineTextBox.cpp b/WebCore/rendering/svg/SVGInlineTextBox.cpp index d1f660a..5d0278b 100644 --- a/WebCore/rendering/svg/SVGInlineTextBox.cpp +++ b/WebCore/rendering/svg/SVGInlineTextBox.cpp @@ -318,14 +318,14 @@ bool SVGInlineTextBox::acquirePaintingResource(GraphicsContext*& context, Render return true; } -void SVGInlineTextBox::releasePaintingResource(GraphicsContext*& context) +void SVGInlineTextBox::releasePaintingResource(GraphicsContext*& context, const Path* path) { ASSERT(m_paintingResource); RenderObject* parentRenderer = parent()->renderer(); ASSERT(parentRenderer); - m_paintingResource->postApplyResource(parentRenderer, context, m_paintingResourceMode); + m_paintingResource->postApplyResource(parentRenderer, context, m_paintingResourceMode, path); m_paintingResource = 0; } @@ -344,7 +344,7 @@ bool SVGInlineTextBox::prepareGraphicsContextForTextPainting(GraphicsContext*& c void SVGInlineTextBox::restoreGraphicsContextAfterTextPainting(GraphicsContext*& context, TextRun& textRun) { - releasePaintingResource(context); + releasePaintingResource(context, /* path */0); #if ENABLE(SVG_FONTS) textRun.setActivePaintingResource(0); @@ -500,11 +500,9 @@ void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, ETextD path.addRect(FloatRect(fragment.x, y, fragment.width, thickness)); context->save(); - context->beginPath(); - context->addPath(path); if (acquirePaintingResource(context, decorationRenderer, decorationStyle)) - releasePaintingResource(context); + releasePaintingResource(context, &path); context->restore(); } diff --git a/WebCore/rendering/svg/SVGInlineTextBox.h b/WebCore/rendering/svg/SVGInlineTextBox.h index 8e82dda..acc5e9f 100644 --- a/WebCore/rendering/svg/SVGInlineTextBox.h +++ b/WebCore/rendering/svg/SVGInlineTextBox.h @@ -68,7 +68,7 @@ private: TextRun constructTextRun(RenderStyle*, const SVGTextFragment&) const; bool acquirePaintingResource(GraphicsContext*&, RenderObject*, RenderStyle*); - void releasePaintingResource(GraphicsContext*&); + void releasePaintingResource(GraphicsContext*&, const Path*); bool prepareGraphicsContextForTextPainting(GraphicsContext*&, TextRun&, RenderStyle*); void restoreGraphicsContextAfterTextPainting(GraphicsContext*&, TextRun&); |