int RenderTheme::baselinePosition(const RenderBox& box) const { #if USE(NEW_THEME) return box.height() + box.marginTop() + m_theme->baselinePositionAdjustment(box.style().appearance()) * box.style().effectiveZoom(); #else return box.height() + box.marginTop(); #endif }
void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (!paintInfo.shouldPaintWithinRoot(*this)) return; LayoutRect paintRect(paintOffset, size()); RenderBox* legend = findLegend(); if (!legend) return RenderBlockFlow::paintBoxDecorations(paintInfo, paintOffset); // FIXME: We need to work with "rl" and "bt" block flow directions. In those // cases the legend is embedded in the right and bottom borders respectively. // https://bugs.webkit.org/show_bug.cgi?id=47236 if (style().isHorizontalWritingMode()) { LayoutUnit yOff = (legend->y() > 0) ? LayoutUnit() : (legend->height() - borderTop()) / 2; paintRect.setHeight(paintRect.height() - yOff); paintRect.setY(paintRect.y() + yOff); } else { LayoutUnit xOff = (legend->x() > 0) ? LayoutUnit() : (legend->width() - borderLeft()) / 2; paintRect.setWidth(paintRect.width() - xOff); paintRect.setX(paintRect.x() + xOff); } if (!boxShadowShouldBeAppliedToBackground(determineBackgroundBleedAvoidance(paintInfo.context))) paintBoxShadow(paintInfo, paintRect, style(), Normal); paintFillLayers(paintInfo, style().visitedDependentColor(CSSPropertyBackgroundColor), style().backgroundLayers(), paintRect); paintBoxShadow(paintInfo, paintRect, style(), Inset); if (!style().hasBorder()) return; // Create a clipping region around the legend and paint the border as normal GraphicsContext* graphicsContext = paintInfo.context; GraphicsContextStateSaver stateSaver(*graphicsContext); // FIXME: We need to work with "rl" and "bt" block flow directions. In those // cases the legend is embedded in the right and bottom borders respectively. // https://bugs.webkit.org/show_bug.cgi?id=47236 LayoutRect clipRect; if (style().isHorizontalWritingMode()) { clipRect.setX(paintRect.x() + legend->x()); clipRect.setY(paintRect.y()); clipRect.setWidth(legend->width()); clipRect.setHeight(std::max<LayoutUnit>(style().borderTopWidth(), legend->height() - ((legend->height() - borderTop()) / 2))); } else { clipRect.setX(paintRect.x()); clipRect.setY(paintRect.y() + legend->y()); clipRect.setWidth(std::max<LayoutUnit>(style().borderLeftWidth(), legend->width())); clipRect.setHeight(legend->height()); } graphicsContext->clipOut(snapRectToDevicePixels(clipRect, document().deviceScaleFactor())); paintBorder(paintInfo, paintRect, style()); }
void RenderTextControlSingleLine::layout() { int oldHeight = height(); calcHeight(); int oldWidth = width(); calcWidth(); bool relayoutChildren = oldHeight != height() || oldWidth != width(); RenderBox* innerTextRenderer = innerTextElement()->renderBox(); RenderBox* innerBlockRenderer = m_innerBlock ? m_innerBlock->renderBox() : 0; // Set the text block height int desiredHeight = textBlockHeight(); int currentHeight = innerTextRenderer->height(); if (m_innerBlock || currentHeight > height()) { if (desiredHeight != currentHeight) relayoutChildren = true; innerTextRenderer->style()->setHeight(Length(desiredHeight, Fixed)); } if (m_innerBlock) { ASSERT(innerBlockRenderer); if (desiredHeight != innerBlockRenderer->height()) relayoutChildren = true; innerBlockRenderer->style()->setHeight(Length(desiredHeight, Fixed)); } // Set the text block width int desiredWidth = textBlockWidth(); if (desiredWidth != innerTextRenderer->width()) relayoutChildren = true; innerTextRenderer->style()->setWidth(Length(desiredWidth, Fixed)); if (m_innerBlock) { int innerBlockWidth = width() - paddingLeft() - paddingRight() - borderLeft() - borderRight(); if (innerBlockWidth != innerBlockRenderer->width()) relayoutChildren = true; innerBlockRenderer->style()->setWidth(Length(innerBlockWidth, Fixed)); } RenderBlock::layoutBlock(relayoutChildren); // For text fields, center the inner text vertically // Don't do this for search fields, since we don't honor height for them if (!m_innerBlock) { currentHeight = innerTextRenderer->height(); if (currentHeight < height()) innerTextRenderer->setLocation(innerTextRenderer->x(), (height() - currentHeight) / 2); } }
void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty) { if (!paintInfo.shouldPaintWithinRoot(this)) return; int w = width(); int h = height(); RenderBox* legend = findLegend(); if (!legend) return RenderBlock::paintBoxDecorations(paintInfo, tx, ty); // FIXME: We need to work with "rl" and "bt" block flow directions. In those // cases the legend is embedded in the right and bottom borders respectively. // https://bugs.webkit.org/show_bug.cgi?id=47236 if (style()->isHorizontalWritingMode()) { int yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2; h -= yOff; ty += yOff; } else { int xOff = (legend->x() > 0) ? 0 : (legend->width() - borderLeft()) / 2; w -= xOff; tx += xOff; } paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Normal); paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), tx, ty, w, h); paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Inset); if (!style()->hasBorder()) return; // Create a clipping region around the legend and paint the border as normal GraphicsContext* graphicsContext = paintInfo.context; graphicsContext->save(); // FIXME: We need to work with "rl" and "bt" block flow directions. In those // cases the legend is embedded in the right and bottom borders respectively. // https://bugs.webkit.org/show_bug.cgi?id=47236 if (style()->isHorizontalWritingMode()) { int clipTop = ty; int clipHeight = max(static_cast<int>(style()->borderTopWidth()), legend->height()); graphicsContext->clipOut(IntRect(tx + legend->x(), clipTop, legend->width(), clipHeight)); } else { int clipLeft = tx; int clipWidth = max(static_cast<int>(style()->borderLeftWidth()), legend->width()); graphicsContext->clipOut(IntRect(clipLeft, ty + legend->y(), clipWidth, legend->height())); } paintBorder(paintInfo.context, tx, ty, w, h, style(), true, true); graphicsContext->restore(); }
void RenderFieldset::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (style().visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask) return; LayoutRect paintRect = LayoutRect(paintOffset, size()); RenderBox* legend = findLegend(); if (!legend) return RenderBlockFlow::paintMask(paintInfo, paintOffset); // FIXME: We need to work with "rl" and "bt" block flow directions. In those // cases the legend is embedded in the right and bottom borders respectively. // https://bugs.webkit.org/show_bug.cgi?id=47236 if (style().isHorizontalWritingMode()) { LayoutUnit yOff = (legend->y() > 0) ? LayoutUnit() : (legend->height() - borderTop()) / 2; paintRect.expand(0, -yOff); paintRect.move(0, yOff); } else { LayoutUnit xOff = (legend->x() > 0) ? LayoutUnit() : (legend->width() - borderLeft()) / 2; paintRect.expand(-xOff, 0); paintRect.move(xOff, 0); } paintMaskImages(paintInfo, paintRect); }
void RenderSliderContainer::layout() { HTMLInputElement* input = node()->shadowAncestorNode()->toInputElement(); bool isVertical = hasVerticalAppearance(input); style()->setBoxOrient(isVertical ? VERTICAL : HORIZONTAL); // Sets the concrete height if the height of the <input> is not fixed or a // percentage value because a percentage height value of this box won't be // based on the <input> height in such case. Length inputHeight = input->renderer()->style()->height(); RenderObject* trackRenderer = node()->firstChild()->renderer(); if (!isVertical && input->renderer()->isSlider() && !inputHeight.isFixed() && !inputHeight.isPercent()) { RenderObject* thumbRenderer = input->shadowTree()->oldestShadowRoot()->firstChild()->firstChild()->firstChild()->renderer(); if (thumbRenderer) { style()->setHeight(thumbRenderer->style()->height()); if (trackRenderer) trackRenderer->style()->setHeight(thumbRenderer->style()->height()); } } else { style()->setHeight(Length(100, Percent)); if (trackRenderer) trackRenderer->style()->setHeight(Length()); } RenderDeprecatedFlexibleBox::layout(); // Percentage 'top' for the thumb doesn't work if the parent style has no // concrete height. Node* track = node()->firstChild(); if (track && track->renderer()->isBox()) { RenderBox* trackBox = track->renderBox(); trackBox->style()->setHeight(Length(trackBox->height() - trackBox->borderAndPaddingHeight(), Fixed)); } }
void RenderFieldset::paintMask(PaintInfo& paintInfo, int tx, int ty) { if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask) return; int w = width(); int h = height(); RenderBox* legend = findLegend(); if (!legend) return RenderBlock::paintMask(paintInfo, tx, ty); // FIXME: We need to work with "rl" and "bt" block flow directions. In those // cases the legend is embedded in the right and bottom borders respectively. // https://bugs.webkit.org/show_bug.cgi?id=47236 if (style()->isHorizontalWritingMode()) { int yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2; h -= yOff; ty += yOff; } else { int xOff = (legend->x() > 0) ? 0 : (legend->width() - borderLeft()) / 2; w -= xOff; tx += xOff; } paintMaskImages(paintInfo, tx, ty, w, h); }
void SpinButtonElement::defaultEventHandler(Event* event) { if (!event->isMouseEvent()) { if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); return; } RenderBox* box = renderBox(); if (!box) { if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); return; } RefPtr<HTMLInputElement> input(static_cast<HTMLInputElement*>(shadowAncestorNode())); if (input->disabled() || input->isReadOnlyFormControl()) { if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); return; } MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); IntPoint local = roundedIntPoint(box->absoluteToLocal(mouseEvent->absoluteLocation(), false, true)); if (mouseEvent->type() == eventNames().mousedownEvent && mouseEvent->button() == LeftButton) { if (box->borderBoxRect().contains(local)) { // The following functions of HTMLInputElement may run JavaScript // code which detaches this shadow node. We need to take a reference // and check renderer() after such function calls. RefPtr<Node> protector(this); input->focus(); input->select(); if (renderer()) { input->stepUpFromRenderer(m_upDownState == Up ? 1 : -1); if (renderer()) startRepeatingTimer(); } event->setDefaultHandled(); } } else if (mouseEvent->type() == eventNames().mouseupEvent && mouseEvent->button() == LeftButton) stopRepeatingTimer(); else if (event->type() == eventNames().mousemoveEvent) { if (box->borderBoxRect().contains(local)) { if (!m_capturing) { if (Frame* frame = document()->frame()) { frame->eventHandler()->setCapturingMouseEventsNode(this); m_capturing = true; } } UpDownState oldUpDownState = m_upDownState; m_upDownState = local.y() < box->height() / 2 ? Up : Down; if (m_upDownState != oldUpDownState) renderer()->repaint(); } else releaseCapture(); } if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); }
LayoutPoint RenderTheme::volumeSliderOffsetFromMuteButton(const RenderBox& muteButtonBox, const LayoutSize& size) const { LayoutUnit y = -size.height(); FloatPoint absPoint = muteButtonBox.localToAbsolute(FloatPoint(muteButtonBox.offsetLeft(), y), IsFixed | UseTransforms); if (absPoint.y() < 0) y = muteButtonBox.height(); return LayoutPoint(0, y); }
void updateSnapOffsetsForScrollableArea(ScrollableArea& scrollableArea, HTMLElement& scrollingElement, const RenderBox& scrollingElementBox, const RenderStyle& scrollingElementStyle) { if (scrollingElementStyle.scrollSnapType() == ScrollSnapType::None) { scrollableArea.clearHorizontalSnapOffsets(); scrollableArea.clearVerticalSnapOffsets(); return; } LayoutUnit viewWidth = scrollingElementBox.width(); LayoutUnit viewHeight = scrollingElementBox.height(); LayoutUnit scrollWidth = scrollingElementBox.scrollWidth(); LayoutUnit scrollHeight = scrollingElementBox.scrollHeight(); bool canComputeHorizontalOffsets = scrollWidth > 0 && viewWidth > 0 && viewWidth < scrollWidth; bool canComputeVerticalOffsets = scrollHeight > 0 && viewHeight > 0 && viewHeight < scrollHeight; if (!canComputeHorizontalOffsets) scrollableArea.clearHorizontalSnapOffsets(); if (!canComputeVerticalOffsets) scrollableArea.clearVerticalSnapOffsets(); if (!canComputeHorizontalOffsets && !canComputeVerticalOffsets) return; Vector<LayoutUnit> horizontalSnapOffsetSubsequence; Vector<LayoutUnit> verticalSnapOffsetSubsequence; bool scrollSnapPointsXUsesElements = styleUsesElements(ScrollEventAxis::Horizontal, scrollingElementStyle); bool scrollSnapPointsYUsesElements = styleUsesElements(ScrollEventAxis::Vertical , scrollingElementStyle); if (scrollSnapPointsXUsesElements || scrollSnapPointsYUsesElements) { bool shouldAddHorizontalChildOffsets = scrollSnapPointsXUsesElements && canComputeHorizontalOffsets; bool shouldAddVerticalChildOffsets = scrollSnapPointsYUsesElements && canComputeVerticalOffsets; appendChildSnapOffsets(scrollingElement, shouldAddHorizontalChildOffsets, horizontalSnapOffsetSubsequence, shouldAddVerticalChildOffsets, verticalSnapOffsetSubsequence); } if (scrollingElementStyle.scrollSnapPointsX() && !scrollSnapPointsXUsesElements && canComputeHorizontalOffsets) { for (auto& snapLength : scrollingElementStyle.scrollSnapPointsX()->offsets) horizontalSnapOffsetSubsequence.append(valueForLength(snapLength, viewWidth)); } if (scrollingElementStyle.scrollSnapPointsY() && !scrollSnapPointsYUsesElements && canComputeVerticalOffsets) { for (auto& snapLength : scrollingElementStyle.scrollSnapPointsY()->offsets) verticalSnapOffsetSubsequence.append(valueForLength(snapLength, viewHeight)); } if (canComputeHorizontalOffsets) { auto horizontalSnapOffsets = std::make_unique<Vector<LayoutUnit>>(); updateFromStyle(*horizontalSnapOffsets, scrollingElementStyle, ScrollEventAxis::Horizontal, viewWidth, scrollWidth, horizontalSnapOffsetSubsequence); scrollableArea.setHorizontalSnapOffsets(WTF::move(horizontalSnapOffsets)); } if (canComputeVerticalOffsets) { auto verticalSnapOffsets = std::make_unique<Vector<LayoutUnit>>(); updateFromStyle(*verticalSnapOffsets, scrollingElementStyle, ScrollEventAxis::Vertical, viewHeight, scrollHeight, verticalSnapOffsetSubsequence); scrollableArea.setVerticalSnapOffsets(WTF::move(verticalSnapOffsets)); } }
void RenderSliderContainer::layout() { ASSERT(element()->shadowHost()); auto& input = downcast<HTMLInputElement>(*element()->shadowHost()); bool isVertical = hasVerticalAppearance(input); mutableStyle().setFlexDirection(isVertical ? FlowColumn : FlowRow); TextDirection oldTextDirection = style().direction(); if (isVertical) { // FIXME: Work around rounding issues in RTL vertical sliders. We want them to // render identically to LTR vertical sliders. We can remove this work around when // subpixel rendering is enabled on all ports. mutableStyle().setDirection(LTR); } RenderBox* thumb = input.sliderThumbElement() ? input.sliderThumbElement()->renderBox() : nullptr; RenderBox* track = input.sliderTrackElement() ? input.sliderTrackElement()->renderBox() : nullptr; // Force a layout to reset the position of the thumb so the code below doesn't move the thumb to the wrong place. // FIXME: Make a custom Render class for the track and move the thumb positioning code there. if (track) track->setChildNeedsLayout(MarkOnlyThis); RenderFlexibleBox::layout(); mutableStyle().setDirection(oldTextDirection); // These should always exist, unless someone mutates the shadow DOM (e.g., in the inspector). if (!thumb || !track) return; double percentageOffset = sliderPosition(input).toDouble(); LayoutUnit availableExtent = isVertical ? track->contentHeight() : track->contentWidth(); availableExtent -= isVertical ? thumb->height() : thumb->width(); LayoutUnit offset = percentageOffset * availableExtent; LayoutPoint thumbLocation = thumb->location(); if (isVertical) thumbLocation.setY(thumbLocation.y() + track->contentHeight() - thumb->height() - offset); else if (style().isLeftToRightDirection()) thumbLocation.setX(thumbLocation.x() + offset); else thumbLocation.setX(thumbLocation.x() - offset); thumb->setLocation(thumbLocation); thumb->repaint(); }
void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty) { #if PLATFORM(WKC) CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT); #endif int w = width(); int h = height(); RenderBox* legend = findLegend(); if (!legend) return RenderBlock::paintBoxDecorations(paintInfo, tx, ty); int yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2; int legendBottom = ty + legend->y() + legend->height(); h -= yOff; ty += yOff; paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Normal); paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), tx, ty, w, h); paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Inset); if (!style()->hasBorder()) return; // Save time by not saving and restoring the GraphicsContext in the straight border case if (!style()->hasBorderRadius()) return paintBorderMinusLegend(paintInfo.context, tx, ty, w, h, style(), legend->x(), legend->width(), legendBottom); // We have rounded borders, create a clipping region // around the legend and paint the border as normal GraphicsContext* graphicsContext = paintInfo.context; graphicsContext->save(); int clipTop = ty; int clipHeight = max(static_cast<int>(style()->borderTopWidth()), legend->height()); graphicsContext->clipOut(IntRect(tx + legend->x(), clipTop, legend->width(), clipHeight)); paintBorder(paintInfo.context, tx, ty, w, h, style(), true, true); graphicsContext->restore(); }
// Return a set of rectangles that should not be overdrawn by the // plugin ("cutouts"). This helps implement the "iframe shim" // technique of overlaying a windowed plugin with content from the // page. In a nutshell, iframe elements should occlude plugins when // they occur higher in the stacking order. void WebPluginContainerImpl::windowCutOutRects(const IntRect& frameRect, Vector<IntRect>& cutOutRects) { RenderObject* pluginNode = m_element->renderer(); ASSERT(pluginNode); if (!pluginNode->style()) return; Vector<const RenderObject*> pluginZstack; Vector<const RenderObject*> iframeZstack; getObjectStack(pluginNode, &pluginZstack); // Get the parent widget Widget* parentWidget = this->parent(); if (!parentWidget->isFrameView()) return; FrameView* parentFrameView = static_cast<FrameView*>(parentWidget); const HashSet<RefPtr<Widget> >* children = parentFrameView->children(); for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != children->end(); ++it) { // We only care about FrameView's because iframes show up as FrameViews. if (!(*it)->isFrameView()) continue; const FrameView* frameView = static_cast<const FrameView*>((*it).get()); // Check to make sure we can get both the element and the RenderObject // for this FrameView, if we can't just move on to the next object. if (!frameView->frame() || !frameView->frame()->ownerElement() || !frameView->frame()->ownerElement()->renderer()) continue; HTMLElement* element = frameView->frame()->ownerElement(); RenderObject* iframeRenderer = element->renderer(); if (element->hasTagName(HTMLNames::iframeTag) && iframeRenderer->absoluteBoundingBoxRect().intersects(frameRect) && (!iframeRenderer->style() || iframeRenderer->style()->visibility() == VISIBLE)) { getObjectStack(iframeRenderer, &iframeZstack); if (checkStackOnTop(iframeZstack, pluginZstack)) { IntPoint point = roundedIntPoint(iframeRenderer->localToAbsolute()); RenderBox* rbox = toRenderBox(iframeRenderer); IntSize size(rbox->width(), rbox->height()); cutOutRects.append(IntRect(point, size)); } } } }
void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (!paintInfo.shouldPaintWithinRoot(this)) return; LayoutRect paintRect(paintOffset, size()); RenderBox* legend = findLegend(); if (!legend) return RenderBlock::paintBoxDecorations(paintInfo, paintOffset); // FIXME: We need to work with "rl" and "bt" block flow directions. In those // cases the legend is embedded in the right and bottom borders respectively. // https://bugs.webkit.org/show_bug.cgi?id=47236 if (style()->isHorizontalWritingMode()) { LayoutUnit yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2; paintRect.setHeight(paintRect.height() - yOff); paintRect.setY(paintRect.y() + yOff); } else { LayoutUnit xOff = (legend->x() > 0) ? 0 : (legend->width() - borderLeft()) / 2; paintRect.setWidth(paintRect.width() - xOff); paintRect.setX(paintRect.x() + xOff); } paintBoxShadow(paintInfo, paintRect, style(), Normal); paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), paintRect); paintBoxShadow(paintInfo, paintRect, style(), Inset); if (!style()->hasBorder()) return; // Create a clipping region around the legend and paint the border as normal GraphicsContext* graphicsContext = paintInfo.context; GraphicsContextStateSaver stateSaver(*graphicsContext); // FIXME: We need to work with "rl" and "bt" block flow directions. In those // cases the legend is embedded in the right and bottom borders respectively. // https://bugs.webkit.org/show_bug.cgi?id=47236 if (style()->isHorizontalWritingMode()) { LayoutUnit clipTop = paintRect.y(); LayoutUnit clipHeight = max(static_cast<LayoutUnit>(style()->borderTopWidth()), legend->height()); graphicsContext->clipOut(LayoutRect(paintRect.x() + legend->x(), clipTop, legend->width(), clipHeight)); } else { LayoutUnit clipLeft = paintRect.x(); LayoutUnit clipWidth = max(static_cast<LayoutUnit>(style()->borderLeftWidth()), legend->width()); graphicsContext->clipOut(LayoutRect(clipLeft, paintRect.y() + legend->y(), clipWidth, legend->height())); } paintBorder(paintInfo, paintRect, style()); }
int RenderView::docHeight() const { int h = lowestPosition(); // FIXME: This doesn't do any margin collapsing. // Instead of this dh computation we should keep the result // when we call RenderBlock::layout. int dh = 0; for (RenderBox* c = firstChildBox(); c; c = c->nextSiblingBox()) dh += c->height() + c->marginTop() + c->marginBottom(); if (dh > h) h = dh; return h; }
void RenderFrameSet::positionFrames() { RenderBox* child = firstChildBox(); if (!child) return; int rows = frameSetElement().totalRows(); int cols = frameSetElement().totalCols(); int yPos = 0; int borderThickness = frameSetElement().border(); for (int r = 0; r < rows; r++) { int xPos = 0; int height = m_rows.m_sizes[r]; for (int c = 0; c < cols; c++) { child->setLocation(IntPoint(xPos, yPos)); int width = m_cols.m_sizes[c]; // has to be resized and itself resize its contents if (width != child->width() || height != child->height()) { child->setWidth(width); child->setHeight(height); #if PLATFORM(IOS) // FIXME: Is this iOS-specific? child->setNeedsLayout(MarkOnlyThis); #else child->setNeedsLayout(); #endif child->layout(); } xPos += width + borderThickness; child = child->nextSiblingBox(); if (!child) return; } yPos += height + borderThickness; } // all the remaining frames are hidden to avoid ugly spurious unflowed frames for (; child; child = child->nextSiblingBox()) { child->setWidth(0); child->setHeight(0); child->clearNeedsLayout(); } }
void RenderFieldset::paintMask(PaintInfo& paintInfo, int tx, int ty) { if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask) return; int w = width(); int h = height(); RenderBox* legend = findLegend(); if (!legend) return RenderBlock::paintMask(paintInfo, tx, ty); int yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2; h -= yOff; ty += yOff; paintMaskImages(paintInfo, tx, ty, w, h); }
bool SVGLength::determineViewport(const SVGElement* context, float& width, float& height) const { if (!context) return false; // Take size from outermost <svg> element. Document* document = context->document(); if (document->documentElement() == context) { if (RenderView* view = toRenderView(document->renderer())) { width = view->viewWidth(); height = view->viewHeight(); return true; } return false; } // Resolve value against nearest viewport element (common case: inner <svg> elements) SVGElement* viewportElement = context->viewportElement(); if (viewportElement && viewportElement->isSVG()) { const SVGSVGElement* svg = static_cast<const SVGSVGElement*>(viewportElement); if (svg->hasAttribute(SVGNames::viewBoxAttr)) { width = svg->viewBox().width(); height = svg->viewBox().height(); } else { width = svg->width().value(svg); height = svg->height().value(svg); } return true; } // Resolve value against enclosing non-SVG RenderBox if (!context->parentNode() || context->parentNode()->isSVGElement()) return false; RenderObject* renderer = context->renderer(); if (!renderer || !renderer->isBox()) return false; RenderBox* box = toRenderBox(renderer); width = box->width(); height = box->height(); return true; }
float SVGLength::PercentageOfViewport(float value, const SVGElement* context, SVGLengthMode mode) { ASSERT(context); float width = 0.0f, height = 0.0f; SVGElement* viewportElement = context->viewportElement(); // PercentageOfViewport() is used to resolve all relative-positioned values within a SVG document (fragment) Document* doc = context->document(); if (doc->documentElement() == context) { // Resolve value against outermost <svg> element if (RenderView* view = toRenderView(doc->renderer())) { width = view->viewWidth(); height = view->viewHeight(); } } else if (viewportElement && viewportElement->isSVG()) { // Resolve value against nearest viewport element (common case: inner <svg> elements) const SVGSVGElement* svg = static_cast<const SVGSVGElement*>(viewportElement); if (svg->hasAttribute(SVGNames::viewBoxAttr)) { width = svg->viewBox().width(); height = svg->viewBox().height(); } else { width = svg->width().value(svg); height = svg->height().value(svg); } } else if (context->parent() && !context->parent()->isSVGElement()) { // Resolve value against enclosing non-SVG RenderBox if (RenderObject* renderer = context->renderer()) { if (renderer->isBox()) { RenderBox* box = toRenderBox(renderer); width = box->width(); height = box->height(); } } } if (mode == LengthModeWidth) return value * width; else if (mode == LengthModeHeight) return value * height; else if (mode == LengthModeOther) return value * sqrtf(powf(width, 2) + powf(height, 2)) / sqrtf(2.0f); return 0.0f; }
float SVGLength::PercentageOfViewport(float value, const SVGElement* context, SVGLengthMode mode) { ASSERT(context); float width = 0.0f, height = 0.0f; SVGElement* viewportElement = context->viewportElement(); Document* doc = context->document(); if (doc->documentElement() == context) { // We have to ask the canvas for the full "canvas size"... RenderView* view = toRenderView(doc->renderer()); if (view && view->frameView()) { width = view->frameView()->visibleWidth(); // TODO: recheck! height = view->frameView()->visibleHeight(); // TODO: recheck! } } else if (viewportElement && viewportElement->isSVG()) { const SVGSVGElement* svg = static_cast<const SVGSVGElement*>(viewportElement); if (svg->hasAttribute(SVGNames::viewBoxAttr)) { width = svg->viewBox().width(); height = svg->viewBox().height(); } else { width = svg->width().value(svg); height = svg->height().value(svg); } } else if (context->parent() && !context->parent()->isSVGElement()) { if (RenderObject* renderer = context->renderer()) { if (renderer->isBox()) { RenderBox* box = toRenderBox(renderer); width = box->width(); height = box->height(); } } } if (mode == LengthModeWidth) return value * width; else if (mode == LengthModeHeight) return value * height; else if (mode == LengthModeOther) return value * sqrtf(powf(width, 2) + powf(height, 2)) / sqrtf(2.0f); return 0.0f; }
void RenderFrameSet::positionFrames() { RenderBox* child = firstChildBox(); if (!child) return; int rows = frameSet()->totalRows(); int cols = frameSet()->totalCols(); int yPos = 0; int borderThickness = frameSet()->border(); for (int r = 0; r < rows; r++) { int xPos = 0; int height = m_rows.m_sizes[r]; for (int c = 0; c < cols; c++) { child->setLocation(xPos, yPos); int width = m_cols.m_sizes[c]; // has to be resized and itself resize its contents if (width != child->width() || height != child->height()) { child->setWidth(width); child->setHeight(height); child->setNeedsLayout(true); child->layout(); } xPos += width + borderThickness; child = child->nextSiblingBox(); if (!child) return; } yPos += height + borderThickness; } // all the remaining frames are hidden to avoid ugly spurious unflowed frames for (; child; child = child->nextSiblingBox()) { child->setWidth(0); child->setHeight(0); child->setNeedsLayout(false); } }
void RenderSlider::layout() { // FIXME: Find a way to cascade appearance. // http://webkit.org/b/62535 RenderBox* thumbBox = sliderThumbElementOf(node())->renderBox(); if (thumbBox && thumbBox->isSliderThumb()) static_cast<RenderSliderThumb*>(thumbBox)->updateAppearance(style()); if (RenderObject* limiterRenderer = trackLimiterElementOf(node())->renderer()) { if (limiterRenderer->isSliderThumb()) static_cast<RenderSliderThumb*>(limiterRenderer)->updateAppearance(style()); } RenderBlock::layout(); if (!thumbBox) return; LayoutUnit heightDiff = thumbBox->height() - contentHeight(); if (heightDiff > 0) thumbBox->setY(thumbBox->y() - (heightDiff / 2)); }
void RenderFieldset::paintMask(PaintInfo& paintInfo, int tx, int ty) { #if PLATFORM(WKC) CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT); #endif if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask) return; int w = width(); int h = height(); RenderBox* legend = findLegend(); if (!legend) return RenderBlock::paintMask(paintInfo, tx, ty); int yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2; h -= yOff; ty += yOff; paintMaskImages(paintInfo, tx, ty, w, h); }
RenderObject* RenderFieldset::layoutLegend(bool relayoutChildren) { RenderBox* legend = findLegend(); if (legend) { if (relayoutChildren) legend->setNeedsLayout(true); legend->layoutIfNeeded(); int xPos; if (style()->direction() == RTL) { switch (legend->style()->textAlign()) { case LEFT: xPos = borderLeft() + paddingLeft(); break; case CENTER: xPos = (width() - legend->width()) / 2; break; default: xPos = width() - paddingRight() - borderRight() - legend->width() - legend->marginRight(); } } else { switch (legend->style()->textAlign()) { case RIGHT: xPos = width() - paddingRight() - borderRight() - legend->width(); break; case CENTER: xPos = (width() - legend->width()) / 2; break; default: xPos = borderLeft() + paddingLeft() + legend->marginLeft(); } } int b = borderTop(); int h = legend->height(); legend->setLocation(xPos, max((b-h)/2, 0)); setHeight(max(b, h) + paddingTop()); } return legend; }
void RenderFrameSet::positionFramesWithFlattening() { RenderBox* child = firstChildBox(); if (!child) return; int rows = frameSetElement().totalRows(); int cols = frameSetElement().totalCols(); int borderThickness = frameSetElement().border(); bool repaintNeeded = false; // calculate frameset height based on actual content height to eliminate scrolling bool out = false; for (int r = 0; r < rows && !out; r++) { int extra = 0; int height = m_rows.m_sizes[r]; for (int c = 0; c < cols; c++) { IntRect oldFrameRect = pixelSnappedIntRect(child->frameRect()); int width = m_cols.m_sizes[c]; bool fixedWidth = frameSetElement().colLengths() && frameSetElement().colLengths()[c].isFixed(); bool fixedHeight = frameSetElement().rowLengths() && frameSetElement().rowLengths()[r].isFixed(); // has to be resized and itself resize its contents if (!fixedWidth) child->setWidth(width ? width + extra / (cols - c) : 0); else child->setWidth(width); child->setHeight(height); child->setNeedsLayout(); if (child->isFrameSet()) toRenderFrameSet(child)->layout(); else toRenderFrame(child)->layoutWithFlattening(fixedWidth, fixedHeight); if (child->height() > m_rows.m_sizes[r]) m_rows.m_sizes[r] = child->height(); if (child->width() > m_cols.m_sizes[c]) m_cols.m_sizes[c] = child->width(); if (child->frameRect() != oldFrameRect) repaintNeeded = true; // difference between calculated frame width and the width it actually decides to have extra += width - m_cols.m_sizes[c]; child = child->nextSiblingBox(); if (!child) { out = true; break; } } } int xPos = 0; int yPos = 0; out = false; child = firstChildBox(); for (int r = 0; r < rows && !out; r++) { xPos = 0; for (int c = 0; c < cols; c++) { // ensure the rows and columns are filled IntRect oldRect = pixelSnappedIntRect(child->frameRect()); child->setLocation(IntPoint(xPos, yPos)); child->setHeight(m_rows.m_sizes[r]); child->setWidth(m_cols.m_sizes[c]); if (child->frameRect() != oldRect) { repaintNeeded = true; // update to final size child->setNeedsLayout(); if (child->isFrameSet()) toRenderFrameSet(child)->layout(); else toRenderFrame(child)->layoutWithFlattening(true, true); } xPos += m_cols.m_sizes[c] + borderThickness; child = child->nextSiblingBox(); if (!child) { out = true; break; } } yPos += m_rows.m_sizes[r] + borderThickness; } setWidth(xPos - borderThickness); setHeight(yPos - borderThickness); if (repaintNeeded) repaint(); // all the remaining frames are hidden to avoid ugly spurious unflowed frames for (; child; child = child->nextSiblingBox()) { child->setWidth(0); child->setHeight(0); child->clearNeedsLayout(); } }
void RenderTextControlSingleLine::layout() { SubtreeLayoutScope layoutScope(this); // FIXME: We should remove the height-related hacks in layout() and // styleDidChange(). We need them because // - Center the inner elements vertically if the input height is taller than // the intrinsic height of the inner elements. // - Shrink the inner elment heights if the input height is samller than the // intrinsic heights of the inner elements. // We don't honor paddings and borders for textfields without decorations // and type=search if the text height is taller than the contentHeight() // because of compability. RenderBox* innerTextRenderer = innerTextElement()->renderBox(); RenderBox* viewPortRenderer = editingViewPortElement() ? editingViewPortElement()->renderBox() : 0; // To ensure consistency between layouts, we need to reset any conditionally overriden height. if (innerTextRenderer && !innerTextRenderer->style()->logicalHeight().isAuto()) { innerTextRenderer->style()->setLogicalHeight(Length(Auto)); layoutScope.setNeedsLayout(innerTextRenderer); } if (viewPortRenderer && !viewPortRenderer->style()->logicalHeight().isAuto()) { viewPortRenderer->style()->setLogicalHeight(Length(Auto)); layoutScope.setNeedsLayout(viewPortRenderer); } RenderBlockFlow::layoutBlock(false); Element* container = containerElement(); RenderBox* containerRenderer = container ? container->renderBox() : 0; // Set the text block height LayoutUnit desiredLogicalHeight = textBlockLogicalHeight(); LayoutUnit logicalHeightLimit = computeLogicalHeightLimit(); if (innerTextRenderer && innerTextRenderer->logicalHeight() > logicalHeightLimit) { if (desiredLogicalHeight != innerTextRenderer->logicalHeight()) layoutScope.setNeedsLayout(this); m_desiredInnerTextLogicalHeight = desiredLogicalHeight; innerTextRenderer->style()->setLogicalHeight(Length(desiredLogicalHeight, Fixed)); layoutScope.setNeedsLayout(innerTextRenderer); if (viewPortRenderer) { viewPortRenderer->style()->setLogicalHeight(Length(desiredLogicalHeight, Fixed)); layoutScope.setNeedsLayout(viewPortRenderer); } } // The container might be taller because of decoration elements. if (containerRenderer) { containerRenderer->layoutIfNeeded(); LayoutUnit containerLogicalHeight = containerRenderer->logicalHeight(); if (containerLogicalHeight > logicalHeightLimit) { containerRenderer->style()->setLogicalHeight(Length(logicalHeightLimit, Fixed)); layoutScope.setNeedsLayout(this); } else if (containerRenderer->logicalHeight() < contentLogicalHeight()) { containerRenderer->style()->setLogicalHeight(Length(contentLogicalHeight(), Fixed)); layoutScope.setNeedsLayout(this); } else containerRenderer->style()->setLogicalHeight(Length(containerLogicalHeight, Fixed)); } // If we need another layout pass, we have changed one of children's height so we need to relayout them. if (needsLayout()) RenderBlockFlow::layoutBlock(true); // Center the child block in the block progression direction (vertical centering for horizontal text fields). if (!container && innerTextRenderer && innerTextRenderer->height() != contentLogicalHeight()) { LayoutUnit logicalHeightDiff = innerTextRenderer->logicalHeight() - contentLogicalHeight(); innerTextRenderer->setLogicalTop(innerTextRenderer->logicalTop() - (logicalHeightDiff / 2 + layoutMod(logicalHeightDiff, 2))); } else centerContainerIfNeeded(containerRenderer); HTMLElement* placeholderElement = inputElement()->placeholderElement(); if (RenderBox* placeholderBox = placeholderElement ? placeholderElement->renderBox() : 0) { LayoutSize innerTextSize; if (innerTextRenderer) innerTextSize = innerTextRenderer->size(); placeholderBox->style()->setWidth(Length(innerTextSize.width() - placeholderBox->borderAndPaddingWidth(), Fixed)); placeholderBox->style()->setHeight(Length(innerTextSize.height() - placeholderBox->borderAndPaddingHeight(), Fixed)); bool neededLayout = placeholderBox->needsLayout(); bool placeholderBoxHadLayout = placeholderBox->everHadLayout(); placeholderBox->layoutIfNeeded(); LayoutPoint textOffset; if (innerTextRenderer) textOffset = innerTextRenderer->location(); if (editingViewPortElement() && editingViewPortElement()->renderBox()) textOffset += toLayoutSize(editingViewPortElement()->renderBox()->location()); if (containerRenderer) textOffset += toLayoutSize(containerRenderer->location()); placeholderBox->setLocation(textOffset); if (!placeholderBoxHadLayout && placeholderBox->checkForRepaintDuringLayout()) { // This assumes a shadow tree without floats. If floats are added, the // logic should be shared with RenderBlockFlow::layoutBlockChild. placeholderBox->repaint(); } // The placeholder gets layout last, after the parent text control and its other children, // so in order to get the correct overflow from the placeholder we need to recompute it now. if (neededLayout) computeOverflow(clientLogicalBottom()); } }
void RenderTextControlSingleLine::layout() { // FIXME: We should remove the height-related hacks in layout() and // styleDidChange(). We need them because // - Center the inner elements vertically if the input height is taller than // the intrinsic height of the inner elements. // - Shrink the inner elment heights if the input height is samller than the // intrinsic heights of the inner elements. // We don't honor paddings and borders for textfields without decorations // and type=search if the text height is taller than the contentHeight() // because of compability. LayoutUnit oldHeight = height(); computeLogicalHeight(); LayoutUnit oldWidth = width(); computeLogicalWidth(); bool relayoutChildren = oldHeight != height() || oldWidth != width(); RenderBox* innerTextRenderer = innerTextElement()->renderBox(); ASSERT(innerTextRenderer); RenderBox* innerBlockRenderer = innerBlockElement() ? innerBlockElement()->renderBox() : 0; HTMLElement* container = containerElement(); RenderBox* containerRenderer = container ? container->renderBox() : 0; // Set the text block height LayoutUnit desiredHeight = textBlockHeight(); LayoutUnit currentHeight = innerTextRenderer->height(); LayoutUnit heightLimit = (inputElement()->isSearchField() || !container) ? height() : contentHeight(); if (currentHeight > heightLimit) { if (desiredHeight != currentHeight) relayoutChildren = true; innerTextRenderer->style()->setHeight(Length(desiredHeight, Fixed)); m_desiredInnerTextHeight = desiredHeight; if (innerBlockRenderer) innerBlockRenderer->style()->setHeight(Length(desiredHeight, Fixed)); } // The container might be taller because of decoration elements. if (containerRenderer) { containerRenderer->layoutIfNeeded(); LayoutUnit containerHeight = containerRenderer->height(); if (containerHeight > heightLimit) { containerRenderer->style()->setHeight(Length(heightLimit, Fixed)); relayoutChildren = true; } else if (containerRenderer->height() < contentHeight()) { containerRenderer->style()->setHeight(Length(contentHeight(), Fixed)); relayoutChildren = true; } else containerRenderer->style()->setHeight(Length(containerHeight, Fixed)); } RenderBlock::layoutBlock(relayoutChildren); // Center the child block vertically currentHeight = innerTextRenderer->height(); if (!container && currentHeight != contentHeight()) { LayoutUnit heightDiff = currentHeight - contentHeight(); innerTextRenderer->setY(innerTextRenderer->y() - (heightDiff / 2 + layoutMod(heightDiff, 2))); } else if (inputElement()->isSearchField() && containerRenderer && containerRenderer->height() > contentHeight()) { // A quirk for find-in-page box on Safari Windows. // http://webkit.org/b/63157 LayoutUnit heightDiff = containerRenderer->height() - contentHeight(); containerRenderer->setY(containerRenderer->y() - (heightDiff / 2 + layoutMod(heightDiff, 2))); } // Ignores the paddings for the inner spin button. if (RenderBox* innerSpinBox = innerSpinButtonElement() ? innerSpinButtonElement()->renderBox() : 0) { RenderBox* parentBox = innerSpinBox->parentBox(); if (containerRenderer && !containerRenderer->style()->isLeftToRightDirection()) innerSpinBox->setLocation(LayoutPoint(-paddingLeft(), -paddingTop())); else innerSpinBox->setLocation(LayoutPoint(parentBox->width() - innerSpinBox->width() + paddingRight(), -paddingTop())); innerSpinBox->setHeight(height() - borderTop() - borderBottom()); } HTMLElement* placeholderElement = inputElement()->placeholderElement(); if (RenderBox* placeholderBox = placeholderElement ? placeholderElement->renderBox() : 0) { placeholderBox->style()->setWidth(Length(innerTextRenderer->width() - placeholderBox->borderAndPaddingWidth(), Fixed)); placeholderBox->style()->setHeight(Length(innerTextRenderer->height() - placeholderBox->borderAndPaddingHeight(), Fixed)); placeholderBox->layoutIfNeeded(); LayoutPoint textOffset = innerTextRenderer->location(); if (innerBlockElement() && innerBlockElement()->renderBox()) textOffset += toLayoutSize(innerBlockElement()->renderBox()->location()); if (containerRenderer) textOffset += toLayoutSize(containerRenderer->location()); placeholderBox->setLocation(textOffset); } }
void SpinButtonElement::defaultEventHandler(Event* event) { if (!event->isMouseEvent()) { if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); return; } RenderBox* box = renderBox(); if (!box) { if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); return; } if (!shouldRespondToMouseEvents()) { if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); return; } MouseEvent* mouseEvent = toMouseEvent(event); IntPoint local = roundedIntPoint(box->absoluteToLocal(mouseEvent->absoluteLocation(), UseTransforms)); if (mouseEvent->type() == eventNames().mousedownEvent && mouseEvent->button() == LeftButton) { if (box->pixelSnappedBorderBoxRect().contains(local)) { // The following functions of HTMLInputElement may run JavaScript // code which detaches this shadow node. We need to take a reference // and check renderer() after such function calls. Ref<SpinButtonElement> protect(*this); if (m_spinButtonOwner) m_spinButtonOwner->focusAndSelectSpinButtonOwner(); if (renderer()) { if (m_upDownState != Indeterminate) { // A JavaScript event handler called in doStepAction() below // might change the element state and we might need to // cancel the repeating timer by the state change. If we // started the timer after doStepAction(), we would have no // chance to cancel the timer. startRepeatingTimer(); doStepAction(m_upDownState == Up ? 1 : -1); } } event->setDefaultHandled(); } } else if (mouseEvent->type() == eventNames().mouseupEvent && mouseEvent->button() == LeftButton) stopRepeatingTimer(); else if (event->type() == eventNames().mousemoveEvent) { if (box->pixelSnappedBorderBoxRect().contains(local)) { if (!m_capturing) { if (Frame* frame = document().frame()) { frame->eventHandler().setCapturingMouseEventsElement(this); m_capturing = true; if (Page* page = document().page()) page->chrome().registerPopupOpeningObserver(this); } } UpDownState oldUpDownState = m_upDownState; m_upDownState = local.y() < box->height() / 2 ? Up : Down; if (m_upDownState != oldUpDownState) renderer()->repaint(); } else { releaseCapture(); m_upDownState = Indeterminate; } } if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); }
void SpinButtonElement::defaultEventHandler(Event* event) { if (!event->isMouseEvent()) { if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); return; } RenderBox* box = renderBox(); if (!box) { if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); return; } HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowAncestorNode()); if (input->disabled() || input->isReadOnlyFormControl()) { if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); return; } MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); IntPoint local = roundedIntPoint(box->absoluteToLocal(mouseEvent->absoluteLocation(), false, true)); if (mouseEvent->type() == eventNames().mousedownEvent && mouseEvent->button() == LeftButton) { if (box->borderBoxRect().contains(local)) { RefPtr<Node> protector(input); input->focus(); input->select(); input->stepUpFromRenderer(m_upDownState == Up ? 1 : -1); event->setDefaultHandled(); startRepeatingTimer(); } } else if (mouseEvent->type() == eventNames().mouseupEvent && mouseEvent->button() == LeftButton) stopRepeatingTimer(); else if (event->type() == eventNames().mousemoveEvent) { if (box->borderBoxRect().contains(local)) { if (!m_capturing) { if (Frame* frame = document()->frame()) { frame->eventHandler()->setCapturingMouseEventsNode(this); m_capturing = true; } } UpDownState oldUpDownState = m_upDownState; m_upDownState = local.y() < box->height() / 2 ? Up : Down; if (m_upDownState != oldUpDownState) renderer()->repaint(); } else { if (m_capturing) { stopRepeatingTimer(); if (Frame* frame = document()->frame()) { frame->eventHandler()->setCapturingMouseEventsNode(0); m_capturing = false; } } } } if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); }
void RenderView::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&) { // Check to see if we are enclosed by a layer that requires complex painting rules. If so, we cannot blit // when scrolling, and we need to use slow repaints. Examples of layers that require this are transparent layers, // layers with reflections, or transformed layers. // FIXME: This needs to be dynamic. We should be able to go back to blitting if we ever stop being inside // a transform, transparency layer, etc. Element* elt; for (elt = document()->ownerElement(); view() && elt && elt->renderer(); elt = elt->document()->ownerElement()) { RenderLayer* layer = elt->renderer()->enclosingLayer(); if (layer->cannotBlitToWindow()) { frameView()->setCannotBlitToWindow(); break; } #if USE(ACCELERATED_COMPOSITING) if (RenderLayer* compositingLayer = layer->enclosingCompositingLayerForRepaint()) { if (!compositingLayer->backing()->paintsIntoWindow()) { frameView()->setCannotBlitToWindow(); break; } } #endif } if (document()->ownerElement() || !view()) return; bool rootFillsViewport = false; Node* documentElement = document()->documentElement(); if (RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0) { // The document element's renderer is currently forced to be a block, but may not always be. RenderBox* rootBox = rootRenderer->isBox() ? toRenderBox(rootRenderer) : 0; rootFillsViewport = rootBox && !rootBox->x() && !rootBox->y() && rootBox->width() >= width() && rootBox->height() >= height(); } Page* page = document()->page(); float pageScaleFactor = page ? page->pageScaleFactor() : 1; // If painting will entirely fill the view, no need to fill the background. if (rootFillsViewport && rendererObscuresBackground(firstChild()) && pageScaleFactor >= 1) return; // This code typically only executes if the root element's visibility has been set to hidden, // if there is a transform on the <html>, or if there is a page scale factor less than 1. // Only fill with the base background color (typically white) if we're the root document, // since iframes/frames with no background in the child document should show the parent's background. if (frameView()->isTransparent()) // FIXME: This needs to be dynamic. We should be able to go back to blitting if we ever stop being transparent. frameView()->setCannotBlitToWindow(); // The parent must show behind the child. else { Color baseColor = frameView()->baseBackgroundColor(); if (baseColor.alpha() > 0) { CompositeOperator previousOperator = paintInfo.context->compositeOperation(); paintInfo.context->setCompositeOperation(CompositeCopy); paintInfo.context->fillRect(paintInfo.rect, baseColor, style()->colorSpace()); paintInfo.context->setCompositeOperation(previousOperator); } else paintInfo.context->clearRect(paintInfo.rect); } }