void RenderFrameSet::layout() { StackStats::LayoutCheckPoint layoutCheckPoint; ASSERT(needsLayout()); bool doFullRepaint = selfNeedsLayout() && checkForRepaintDuringLayout(); LayoutRect oldBounds; RenderLayerModelObject* repaintContainer = 0; if (doFullRepaint) { repaintContainer = containerForRepaint(); oldBounds = clippedOverflowRectForRepaint(repaintContainer); } if (!parent()->isFrameSet() && !document().printing()) { setWidth(view().viewWidth()); setHeight(view().viewHeight()); } unsigned cols = frameSetElement().totalCols(); unsigned rows = frameSetElement().totalRows(); if (m_rows.m_sizes.size() != rows || m_cols.m_sizes.size() != cols) { m_rows.resize(rows); m_cols.resize(cols); } LayoutUnit borderThickness = frameSetElement().border(); layOutAxis(m_rows, frameSetElement().rowLengths(), height() - (rows - 1) * borderThickness); layOutAxis(m_cols, frameSetElement().colLengths(), width() - (cols - 1) * borderThickness); if (flattenFrameSet()) positionFramesWithFlattening(); else positionFrames(); RenderBox::layout(); computeEdgeInfo(); updateLayerTransform(); if (doFullRepaint) { repaintUsingContainer(repaintContainer, snappedIntRect(oldBounds)); LayoutRect newBounds = clippedOverflowRectForRepaint(repaintContainer); if (newBounds != oldBounds) repaintUsingContainer(repaintContainer, snappedIntRect(newBounds)); } clearNeedsLayout(); }
void RenderSnapshottedPlugIn::paintSnapshot(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { Image* image = m_snapshotResource->image().get(); if (!image || image->isNull()) return; LayoutUnit cWidth = contentWidth(); LayoutUnit cHeight = contentHeight(); if (!cWidth || !cHeight) return; GraphicsContext& context = paintInfo.context(); LayoutSize contentSize(cWidth, cHeight); LayoutPoint contentLocation = location() + paintOffset; contentLocation.move(borderLeft() + paddingLeft(), borderTop() + paddingTop()); LayoutRect rect(contentLocation, contentSize); IntRect alignedRect = snappedIntRect(rect); if (alignedRect.width() <= 0 || alignedRect.height() <= 0) return; InterpolationQuality interpolation = chooseInterpolationQuality(context, *image, image, alignedRect.size()); ImageOrientationDescription orientationDescription(shouldRespectImageOrientation(), style().imageOrientation()); context.drawImage(*image, alignedRect, ImagePaintingOptions(orientationDescription, interpolation)); }
void RenderSnapshottedPlugIn::paintSnapshot(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { Image* image = m_snapshotResource->image().get(); if (!image || image->isNull()) return; LayoutUnit cWidth = contentWidth(); LayoutUnit cHeight = contentHeight(); if (!cWidth || !cHeight) return; GraphicsContext& context = paintInfo.context(); LayoutSize contentSize(cWidth, cHeight); LayoutPoint contentLocation = location() + paintOffset; contentLocation.move(borderLeft() + paddingLeft(), borderTop() + paddingTop()); LayoutRect rect(contentLocation, contentSize); IntRect alignedRect = snappedIntRect(rect); if (alignedRect.width() <= 0 || alignedRect.height() <= 0) return; bool useLowQualityScaling = shouldPaintAtLowQuality(context, *image, image, alignedRect.size()); ImageOrientationDescription orientationDescription(shouldRespectImageOrientation()); #if ENABLE(CSS_IMAGE_ORIENTATION) orientationDescription.setImageOrientationEnum(style().imageOrientation()); #endif context.drawImage(*image, alignedRect, ImagePaintingOptions(orientationDescription, useLowQualityScaling)); }
void RenderWidget::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { IntPoint contentPaintOffset = roundedIntPoint(paintOffset + location() + contentBoxRect().location()); // Tell the widget to paint now. This is the only time the widget is allowed // to paint itself. That way it will composite properly with z-indexed layers. LayoutRect paintRect = paintInfo.rect; IntPoint widgetLocation = m_widget->frameRect().location(); IntSize widgetPaintOffset = contentPaintOffset - widgetLocation; // When painting widgets into compositing layers, tx and ty are relative to the enclosing compositing layer, // not the root. In this case, shift the CTM and adjust the paintRect to be root-relative to fix plug-in drawing. if (!widgetPaintOffset.isZero()) { paintInfo.context().translate(widgetPaintOffset); paintRect.move(-widgetPaintOffset); } // FIXME: Remove repaintrect encolsing/integral snapping when RenderWidget becomes device pixel snapped. m_widget->paint(paintInfo.context(), snappedIntRect(paintRect)); if (!widgetPaintOffset.isZero()) paintInfo.context().translate(-widgetPaintOffset); if (is<FrameView>(*m_widget)) { FrameView& frameView = downcast<FrameView>(*m_widget); bool runOverlapTests = !frameView.useSlowRepaintsIfNotOverlapped(); if (paintInfo.overlapTestRequests && runOverlapTests) { ASSERT(!paintInfo.overlapTestRequests->contains(this)); paintInfo.overlapTestRequests->set(this, m_widget->frameRect()); } } }
PassRefPtr<WebImage> InjectedBundleNodeHandle::renderedImage(SnapshotOptions options) { Frame* frame = m_node->document().frame(); if (!frame) return nullptr; FrameView* frameView = frame->view(); if (!frameView) return nullptr; m_node->document().updateLayout(); RenderObject* renderer = m_node->renderer(); if (!renderer) return nullptr; LayoutRect topLevelRect; IntRect paintingRect = snappedIntRect(renderer->paintingRootRect(topLevelRect)); frameView->setNodeToDraw(m_node.ptr()); auto image = imageForRect(frameView, paintingRect, options); frameView->setNodeToDraw(0); return image; }
IntRect RenderScrollbar::buttonRect(ScrollbarPart partType) { RenderScrollbarPart* partRenderer = m_parts.get(partType); if (!partRenderer) return IntRect(); partRenderer->layout(); bool isHorizontal = orientation() == HorizontalScrollbar; IntSize pixelSnappedIntSize = snappedIntRect(partRenderer->frameRect()).size(); if (partType == BackButtonStartPart) return IntRect(location(), IntSize(isHorizontal ? pixelSnappedIntSize.width() : width(), isHorizontal ? height() : pixelSnappedIntSize.height())); if (partType == ForwardButtonEndPart) return IntRect(isHorizontal ? x() + width() - pixelSnappedIntSize.width() : x(), isHorizontal ? y() : y() + height() - pixelSnappedIntSize.height(), isHorizontal ? pixelSnappedIntSize.width() : width(), isHorizontal ? height() : pixelSnappedIntSize.height()); if (partType == ForwardButtonStartPart) { IntRect previousButton = buttonRect(BackButtonStartPart); return IntRect(isHorizontal ? x() + previousButton.width() : x(), isHorizontal ? y() : y() + previousButton.height(), isHorizontal ? pixelSnappedIntSize.width() : width(), isHorizontal ? height() : pixelSnappedIntSize.height()); } IntRect followingButton = buttonRect(ForwardButtonEndPart); return IntRect(isHorizontal ? x() + width() - followingButton.width() - pixelSnappedIntSize.width() : x(), isHorizontal ? y() : y() + height() - followingButton.height() - pixelSnappedIntSize.height(), isHorizontal ? pixelSnappedIntSize.width() : width(), isHorizontal ? height() : pixelSnappedIntSize.height()); }
IntRect RenderedPosition::absoluteRect(LayoutUnit* extraWidthToEndOfLine) const { if (isNull()) return IntRect(); IntRect localRect = snappedIntRect(m_renderer->localCaretRect(m_inlineBox, m_offset, extraWidthToEndOfLine)); return localRect == IntRect() ? IntRect() : m_renderer->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoundingBox(); }
bool RenderTheme::paintDecorations(const RenderBox& box, const PaintInfo& paintInfo, const LayoutRect& rect) { if (paintInfo.context().paintingDisabled()) return false; IntRect integralSnappedRect = snappedIntRect(rect); FloatRect devicePixelSnappedRect = snapRectToDevicePixels(rect, box.document().deviceScaleFactor()); // Call the appropriate paint method based off the appearance value. switch (box.style().appearance()) { case MenulistButtonPart: return paintMenuListButtonDecorations(box, paintInfo, devicePixelSnappedRect); case TextFieldPart: return paintTextFieldDecorations(box, paintInfo, devicePixelSnappedRect); case TextAreaPart: return paintTextAreaDecorations(box, paintInfo, devicePixelSnappedRect); case CheckboxPart: return paintCheckboxDecorations(box, paintInfo, integralSnappedRect); case RadioPart: return paintRadioDecorations(box, paintInfo, integralSnappedRect); case PushButtonPart: return paintPushButtonDecorations(box, paintInfo, integralSnappedRect); case SquareButtonPart: return paintSquareButtonDecorations(box, paintInfo, integralSnappedRect); case ButtonPart: return paintButtonDecorations(box, paintInfo, integralSnappedRect); case MenulistPart: return paintMenuListDecorations(box, paintInfo, integralSnappedRect); case SliderThumbHorizontalPart: case SliderThumbVerticalPart: return paintSliderThumbDecorations(box, paintInfo, integralSnappedRect); case SearchFieldPart: return paintSearchFieldDecorations(box, paintInfo, integralSnappedRect); #if ENABLE(METER_ELEMENT) case MeterPart: case RelevancyLevelIndicatorPart: case ContinuousCapacityLevelIndicatorPart: case DiscreteCapacityLevelIndicatorPart: case RatingLevelIndicatorPart: #endif case ProgressBarPart: case SliderHorizontalPart: case SliderVerticalPart: case ListboxPart: case DefaultButtonPart: case SearchFieldCancelButtonPart: case SearchFieldDecorationPart: case SearchFieldResultsDecorationPart: case SearchFieldResultsButtonPart: #if ENABLE(SERVICE_CONTROLS) case ImageControlsButtonPart: #endif default: break; } return false; }
std::unique_ptr<Shape> Shape::createRasterShape(Image* image, float threshold, const LayoutRect& imageR, const LayoutRect& marginR, WritingMode writingMode, float margin) { IntRect imageRect = snappedIntRect(imageR); IntRect marginRect = snappedIntRect(marginR); auto intervals = std::make_unique<RasterShapeIntervals>(marginRect.height(), -marginRect.y()); std::unique_ptr<ImageBuffer> imageBuffer = ImageBuffer::create(imageRect.size()); if (imageBuffer) { GraphicsContext* graphicsContext = imageBuffer->context(); graphicsContext->drawImage(image, ColorSpaceDeviceRGB, IntRect(IntPoint(), imageRect.size())); RefPtr<Uint8ClampedArray> pixelArray = imageBuffer->getUnmultipliedImageData(IntRect(IntPoint(), imageRect.size())); unsigned pixelArrayLength = pixelArray->length(); unsigned pixelArrayOffset = 3; // Each pixel is four bytes: RGBA. uint8_t alphaPixelThreshold = threshold * 255; int minBufferY = std::max(0, marginRect.y() - imageRect.y()); int maxBufferY = std::min(imageRect.height(), marginRect.maxY() - imageRect.y()); if (static_cast<unsigned>(imageRect.width() * imageRect.height() * 4) == pixelArrayLength) { for (int y = minBufferY; y < maxBufferY; ++y) { int startX = -1; for (int x = 0; x < imageRect.width(); ++x, pixelArrayOffset += 4) { uint8_t alpha = pixelArray->item(pixelArrayOffset); bool alphaAboveThreshold = alpha > alphaPixelThreshold; if (startX == -1 && alphaAboveThreshold) { startX = x; } else if (startX != -1 && (!alphaAboveThreshold || x == imageRect.width() - 1)) { // We're creating "end-point exclusive" intervals here. The value of an interval's x1 is // the first index of an above-threshold pixel for y, and the value of x2 is 1+ the index // of the last above-threshold pixel. int endX = alphaAboveThreshold ? x + 1 : x; intervals->intervalAt(y + imageRect.y()).unite(IntShapeInterval(startX + imageRect.x(), endX + imageRect.x())); startX = -1; } } } } } auto rasterShape = std::make_unique<RasterShape>(WTF::move(intervals), marginRect.size()); rasterShape->m_writingMode = writingMode; rasterShape->m_margin = margin; return WTF::move(rasterShape); }
static void paintDebugBorders(GraphicsContext& context, LayoutRect borderRect, const LayoutPoint& paintOffset) { borderRect.moveBy(paintOffset); IntRect snappedRect = snappedIntRect(borderRect); if (snappedRect.isEmpty()) return; GraphicsContextStateSaver stateSaver(context); context.setStrokeColor(Color(0, 255, 0)); context.setFillColor(Color::transparent); context.drawRect(snappedRect); }
void RenderProgress::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const { RenderBox::computeLogicalHeight(logicalHeight, logicalTop, computedValues); LayoutRect frame = frameRect(); if (isHorizontalWritingMode()) frame.setHeight(computedValues.m_extent); else frame.setWidth(computedValues.m_extent); IntSize frameSize = theme().progressBarRectForBounds(*this, snappedIntRect(frame)).size(); computedValues.m_extent = isHorizontalWritingMode() ? frameSize.height() : frameSize.width(); }
std::unique_ptr<ImageBuffer> snapshotNode(Frame& frame, Node& node) { if (!node.renderer()) return nullptr; ScopedFramePaintingState state(frame, &node); frame.view()->setBaseBackgroundColor(Color::transparent); frame.view()->setNodeToDraw(&node); LayoutRect topLevelRect; return snapshotFrameRect(frame, snappedIntRect(node.renderer()->paintingRootRect(topLevelRect))); }
LayoutRect RenderSVGRoot::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const { if (style().visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent()) return LayoutRect(); FloatRect contentRepaintRect = m_localToBorderBoxTransform.mapRect(repaintRectInLocalCoordinates()); contentRepaintRect.intersect(snappedIntRect(borderBoxRect())); LayoutRect repaintRect = enclosingLayoutRect(contentRepaintRect); if (m_hasBoxDecorations || hasRenderOverflow()) repaintRect.unite(unionRect(localSelectionRect(false), visualOverflowRect())); return RenderReplaced::computeRectForRepaint(enclosingIntRect(repaintRect), repaintContainer); }
void RenderWidget::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (!shouldPaint(paintInfo, paintOffset)) return; LayoutPoint adjustedPaintOffset = paintOffset + location(); if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection)) paintBoxDecorations(paintInfo, adjustedPaintOffset); if (paintInfo.phase == PaintPhaseMask) { paintMask(paintInfo, adjustedPaintOffset); return; } if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && hasOutline()) paintOutline(paintInfo, LayoutRect(adjustedPaintOffset, size())); if (paintInfo.phase != PaintPhaseForeground) return; if (style().hasBorderRadius()) { LayoutRect borderRect = LayoutRect(adjustedPaintOffset, size()); if (borderRect.isEmpty()) return; // Push a clip if we have a border radius, since we want to round the foreground content that gets painted. paintInfo.context().save(); FloatRoundedRect roundedInnerRect = FloatRoundedRect(style().getRoundedInnerBorderFor(borderRect, paddingTop() + borderTop(), paddingBottom() + borderBottom(), paddingLeft() + borderLeft(), paddingRight() + borderRight(), true, true)); clipRoundedInnerRect(paintInfo.context(), borderRect, roundedInnerRect); } if (m_widget) paintContents(paintInfo, paintOffset); if (style().hasBorderRadius()) paintInfo.context().restore(); // Paint a partially transparent wash over selected widgets. if (isSelected() && !document().printing()) { // FIXME: selectionRect() is in absolute, not painting coordinates. paintInfo.context().fillRect(snappedIntRect(selectionRect()), selectionBackgroundColor(), style().colorSpace()); } if (hasLayer() && layer()->canResize()) layer()->paintResizer(paintInfo.context(), roundedIntPoint(adjustedPaintOffset), paintInfo.rect); }
void RenderFrameSet::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (paintInfo.phase != PaintPhaseForeground) return; RenderObject* child = firstChild(); if (!child) return; LayoutPoint adjustedPaintOffset = paintOffset + location(); size_t rows = m_rows.m_sizes.size(); size_t cols = m_cols.m_sizes.size(); LayoutUnit borderThickness = frameSetElement().border(); LayoutUnit yPos = 0; for (size_t r = 0; r < rows; r++) { LayoutUnit xPos = 0; for (size_t c = 0; c < cols; c++) { downcast<RenderElement>(*child).paint(paintInfo, adjustedPaintOffset); xPos += m_cols.m_sizes[c]; if (borderThickness && m_cols.m_allowBorder[c + 1]) { paintColumnBorder(paintInfo, snappedIntRect(LayoutRect(adjustedPaintOffset.x() + xPos, adjustedPaintOffset.y() + yPos, borderThickness, height()))); xPos += borderThickness; } child = child->nextSibling(); if (!child) return; } yPos += m_rows.m_sizes[r]; if (borderThickness && m_rows.m_allowBorder[r + 1]) { paintRowBorder(paintInfo, snappedIntRect(LayoutRect(adjustedPaintOffset.x(), adjustedPaintOffset.y() + yPos, width(), borderThickness))); yPos += borderThickness; } } }
FloatRect RenderSVGRoot::computeFloatRectForRepaint(const FloatRect& repaintRect, const RenderLayerModelObject* repaintContainer, bool fixed) const { // Apply our local transforms (except for x/y translation), then our shadow, // and then call RenderBox's method to handle all the normal CSS Box model bits FloatRect adjustedRect = m_localToBorderBoxTransform.mapRect(repaintRect); const SVGRenderStyle& svgStyle = style().svgStyle(); if (const ShadowData* shadow = svgStyle.shadow()) shadow->adjustRectForShadow(adjustedRect); // Apply initial viewport clip if (shouldApplyViewportClip()) adjustedRect.intersect(snappedIntRect(borderBoxRect())); if (m_hasBoxDecorations || hasRenderOverflow()) { // The selectionRect can project outside of the overflowRect, so take their union // for repainting to avoid selection painting glitches. LayoutRect decoratedRepaintRect = unionRect(localSelectionRect(false), visualOverflowRect()); adjustedRect.unite(decoratedRepaintRect); } return RenderReplaced::computeRectForRepaint(enclosingIntRect(adjustedRect), repaintContainer, {fixed, false}); }
void RenderScrollbarPart::paintIntoRect(GraphicsContext* graphicsContext, const LayoutPoint& paintOffset, const LayoutRect& rect) { // Make sure our dimensions match the rect. setLocation(rect.location() - toLayoutSize(paintOffset)); setWidth(rect.width()); setHeight(rect.height()); if (graphicsContext->paintingDisabled() || !style().opacity()) return; // We don't use RenderLayers for scrollbar parts, so we need to handle opacity here. // Opacity for ScrollbarBGPart is handled by RenderScrollbarTheme::willPaintScrollbar(). bool needsTransparencyLayer = m_part != ScrollbarBGPart && style().opacity() < 1; if (needsTransparencyLayer) { graphicsContext->save(); graphicsContext->clip(rect); graphicsContext->beginTransparencyLayer(style().opacity()); } // Now do the paint. PaintInfo paintInfo(graphicsContext, snappedIntRect(rect), PaintPhaseBlockBackground, PaintBehaviorNormal); paint(paintInfo, paintOffset); paintInfo.phase = PaintPhaseChildBlockBackgrounds; paint(paintInfo, paintOffset); paintInfo.phase = PaintPhaseFloat; paint(paintInfo, paintOffset); paintInfo.phase = PaintPhaseForeground; paint(paintInfo, paintOffset); paintInfo.phase = PaintPhaseOutline; paint(paintInfo, paintOffset); if (needsTransparencyLayer) { graphicsContext->endTransparencyLayer(); graphicsContext->restore(); } }
void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { // An empty viewport disables rendering. if (pixelSnappedBorderBoxRect().isEmpty()) return; // Don't paint, if the context explicitly disabled it. if (paintInfo.context->paintingDisabled()) return; // SVG outlines are painted during PaintPhaseForeground. if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) return; // An empty viewBox also disables rendering. // (http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute) if (svgSVGElement().hasEmptyViewBox()) return; Page* page = frame().page(); // Don't paint if we don't have kids, except if we have filters we should paint those. if (!firstChild()) { auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this); if (!resources || !resources->filter()) { if (page && paintInfo.phase == PaintPhaseForeground) page->addRelevantUnpaintedObject(this, visualOverflowRect()); return; } } if (page && paintInfo.phase == PaintPhaseForeground) page->addRelevantRepaintedObject(this, visualOverflowRect()); // Make a copy of the PaintInfo because applyTransform will modify the damage rect. PaintInfo childPaintInfo(paintInfo); childPaintInfo.context->save(); // Apply initial viewport clip if (shouldApplyViewportClip()) childPaintInfo.context->clip(snappedIntRect(overflowClipRect(paintOffset, currentRenderNamedFlowFragment()))); // Convert from container offsets (html renderers) to a relative transform (svg renderers). // Transform from our paint container's coordinate system to our local coords. IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset); childPaintInfo.applyTransform(AffineTransform::translation(adjustedPaintOffset.x(), adjustedPaintOffset.y()) * localToBorderBoxTransform()); // SVGRenderingContext must be destroyed before we restore the childPaintInfo.context, because a filter may have // changed the context and it is only reverted when the SVGRenderingContext destructor finishes applying the filter. { SVGRenderingContext renderingContext; bool continueRendering = true; if (childPaintInfo.phase == PaintPhaseForeground) { renderingContext.prepareToRenderSVGContent(*this, childPaintInfo); continueRendering = renderingContext.isRenderingPrepared(); } if (continueRendering) { childPaintInfo.updateSubtreePaintRootForChildren(this); for (auto& child : childrenOfType<RenderElement>(*this)) child.paint(childPaintInfo, location()); } } childPaintInfo.context->restore(); }
void RenderReplaced::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (!shouldPaint(paintInfo, paintOffset)) return; #ifndef NDEBUG SetLayoutNeededForbiddenScope scope(this); #endif LayoutPoint adjustedPaintOffset = paintOffset + location(); if (hasVisibleBoxDecorations() && paintInfo.phase == PaintPhaseForeground) paintBoxDecorations(paintInfo, adjustedPaintOffset); if (paintInfo.phase == PaintPhaseMask) { paintMask(paintInfo, adjustedPaintOffset); return; } LayoutRect paintRect = LayoutRect(adjustedPaintOffset, size()); if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style().outlineWidth()) paintOutline(paintInfo, paintRect); if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection && !canHaveChildren()) return; if (!paintInfo.shouldPaintWithinRoot(*this)) return; bool drawSelectionTint = shouldDrawSelectionTint(); if (paintInfo.phase == PaintPhaseSelection) { if (selectionState() == SelectionNone) return; drawSelectionTint = false; } bool completelyClippedOut = false; if (style().hasBorderRadius()) { LayoutRect borderRect = LayoutRect(adjustedPaintOffset, size()); if (borderRect.isEmpty()) completelyClippedOut = true; else { // Push a clip if we have a border radius, since we want to round the foreground content that gets painted. paintInfo.context().save(); FloatRoundedRect roundedInnerRect = FloatRoundedRect(style().getRoundedInnerBorderFor(paintRect, paddingTop() + borderTop(), paddingBottom() + borderBottom(), paddingLeft() + borderLeft(), paddingRight() + borderRight(), true, true)); clipRoundedInnerRect(paintInfo.context(), paintRect, roundedInnerRect); } } if (!completelyClippedOut) { paintReplaced(paintInfo, adjustedPaintOffset); if (style().hasBorderRadius()) paintInfo.context().restore(); } // The selection tint never gets clipped by border-radius rounding, since we want it to run right up to the edges of // surrounding content. if (drawSelectionTint) { LayoutRect selectionPaintingRect = localSelectionRect(); selectionPaintingRect.moveBy(adjustedPaintOffset); paintInfo.context().fillRect(snappedIntRect(selectionPaintingRect), selectionBackgroundColor()); } }
TextStream& operator<<(TextStream& ts, const LayoutRect& r) { // FIXME: These should be printed as floats. Keeping them ints for consistency with previous test expectations. return ts << snappedIntRect(r); }
void RenderTextControl::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject*) { if (!size().isEmpty()) rects.append(snappedIntRect(additionalOffset, size())); }
WebRenderObject::WebRenderObject(RenderObject* renderer, bool shouldIncludeDescendants) { m_name = renderer->renderName(); m_textLength = 0; if (Node* node = renderer->node()) { if (is<Element>(*node)) { Element& element = downcast<Element>(*node); m_elementTagName = element.tagName(); m_elementID = element.getIdAttribute(); if (element.isStyledElement() && element.hasClass()) { Vector<RefPtr<API::Object>> classNames; classNames.reserveInitialCapacity(element.classNames().size()); for (size_t i = 0, size = element.classNames().size(); i < size; ++i) classNames.append(API::String::create(element.classNames()[i])); m_elementClassNames = API::Array::create(WTFMove(classNames)); } } if (node->isTextNode()) { String value = node->nodeValue(); m_textLength = value.length(); const int maxSnippetLength = 40; if (value.length() > maxSnippetLength) m_textSnippet = value.substring(0, maxSnippetLength); else m_textSnippet = value; } } // FIXME: broken with transforms m_absolutePosition = flooredIntPoint(renderer->localToAbsolute()); if (is<RenderBox>(*renderer)) m_frameRect = snappedIntRect(downcast<RenderBox>(*renderer).frameRect()); else if (is<RenderText>(*renderer)) { m_frameRect = downcast<RenderText>(*renderer).linesBoundingBox(); m_frameRect.setLocation(downcast<RenderText>(*renderer).firstRunLocation()); } else if (is<RenderInline>(*renderer)) m_frameRect = IntRect(downcast<RenderInline>(*renderer).borderBoundingBox()); if (!shouldIncludeDescendants) return; Vector<RefPtr<API::Object>> children; for (RenderObject* coreChild = renderer->firstChildSlow(); coreChild; coreChild = coreChild->nextSibling()) { RefPtr<WebRenderObject> child = adoptRef(new WebRenderObject(coreChild, shouldIncludeDescendants)); children.append(WTFMove(child)); } if (is<RenderWidget>(*renderer)) { if (Widget* widget = downcast<RenderWidget>(*renderer).widget()) { if (is<FrameView>(*widget)) { FrameView& frameView = downcast<FrameView>(*widget); if (RenderView* coreContentRenderer = frameView.frame().contentRenderer()) { RefPtr<WebRenderObject> contentRenderer = adoptRef(new WebRenderObject(coreContentRenderer, shouldIncludeDescendants)); children.append(WTFMove(contentRenderer)); } } } } m_children = API::Array::create(WTFMove(children)); }
bool RenderTheme::paint(const RenderBox& box, ControlStates& controlStates, const PaintInfo& paintInfo, const LayoutRect& rect) { // If painting is disabled, but we aren't updating control tints, then just bail. // If we are updating control tints, just schedule a repaint if the theme supports tinting // for that control. if (paintInfo.context().updatingControlTints()) { if (controlSupportsTints(box)) box.repaint(); return false; } if (paintInfo.context().paintingDisabled()) return false; ControlPart part = box.style().appearance(); IntRect integralSnappedRect = snappedIntRect(rect); float deviceScaleFactor = box.document().deviceScaleFactor(); FloatRect devicePixelSnappedRect = snapRectToDevicePixels(rect, deviceScaleFactor); #if USE(NEW_THEME) float pageScaleFactor = box.document().page() ? box.document().page()->pageScaleFactor() : 1.0f; switch (part) { case CheckboxPart: case RadioPart: case PushButtonPart: case SquareButtonPart: case DefaultButtonPart: case ButtonPart: case InnerSpinButtonPart: updateControlStatesForRenderer(box, controlStates); m_theme->paint(part, controlStates, paintInfo.context(), devicePixelSnappedRect, box.style().effectiveZoom(), &box.view().frameView(), deviceScaleFactor, pageScaleFactor); return false; default: break; } #else UNUSED_PARAM(controlStates); #endif // Call the appropriate paint method based off the appearance value. switch (part) { #if !USE(NEW_THEME) case CheckboxPart: return paintCheckbox(box, paintInfo, integralSnappedRect); case RadioPart: return paintRadio(box, paintInfo, integralSnappedRect); case PushButtonPart: case SquareButtonPart: case DefaultButtonPart: case ButtonPart: return paintButton(box, paintInfo, integralSnappedRect); case InnerSpinButtonPart: return paintInnerSpinButton(box, paintInfo, integralSnappedRect); #endif case MenulistPart: return paintMenuList(box, paintInfo, devicePixelSnappedRect); #if ENABLE(METER_ELEMENT) case MeterPart: case RelevancyLevelIndicatorPart: case ContinuousCapacityLevelIndicatorPart: case DiscreteCapacityLevelIndicatorPart: case RatingLevelIndicatorPart: return paintMeter(box, paintInfo, integralSnappedRect); #endif case ProgressBarPart: return paintProgressBar(box, paintInfo, integralSnappedRect); case SliderHorizontalPart: case SliderVerticalPart: return paintSliderTrack(box, paintInfo, integralSnappedRect); case SliderThumbHorizontalPart: case SliderThumbVerticalPart: return paintSliderThumb(box, paintInfo, integralSnappedRect); case MediaEnterFullscreenButtonPart: case MediaExitFullscreenButtonPart: return paintMediaFullscreenButton(box, paintInfo, integralSnappedRect); case MediaPlayButtonPart: return paintMediaPlayButton(box, paintInfo, integralSnappedRect); case MediaOverlayPlayButtonPart: return paintMediaOverlayPlayButton(box, paintInfo, integralSnappedRect); case MediaMuteButtonPart: return paintMediaMuteButton(box, paintInfo, integralSnappedRect); case MediaSeekBackButtonPart: return paintMediaSeekBackButton(box, paintInfo, integralSnappedRect); case MediaSeekForwardButtonPart: return paintMediaSeekForwardButton(box, paintInfo, integralSnappedRect); case MediaRewindButtonPart: return paintMediaRewindButton(box, paintInfo, integralSnappedRect); case MediaReturnToRealtimeButtonPart: return paintMediaReturnToRealtimeButton(box, paintInfo, integralSnappedRect); case MediaToggleClosedCaptionsButtonPart: return paintMediaToggleClosedCaptionsButton(box, paintInfo, integralSnappedRect); case MediaSliderPart: return paintMediaSliderTrack(box, paintInfo, integralSnappedRect); case MediaSliderThumbPart: return paintMediaSliderThumb(box, paintInfo, integralSnappedRect); case MediaVolumeSliderMuteButtonPart: return paintMediaMuteButton(box, paintInfo, integralSnappedRect); case MediaVolumeSliderContainerPart: return paintMediaVolumeSliderContainer(box, paintInfo, integralSnappedRect); case MediaVolumeSliderPart: return paintMediaVolumeSliderTrack(box, paintInfo, integralSnappedRect); case MediaVolumeSliderThumbPart: return paintMediaVolumeSliderThumb(box, paintInfo, integralSnappedRect); case MediaFullScreenVolumeSliderPart: return paintMediaFullScreenVolumeSliderTrack(box, paintInfo, integralSnappedRect); case MediaFullScreenVolumeSliderThumbPart: return paintMediaFullScreenVolumeSliderThumb(box, paintInfo, integralSnappedRect); case MediaTimeRemainingPart: return paintMediaTimeRemaining(box, paintInfo, integralSnappedRect); case MediaCurrentTimePart: return paintMediaCurrentTime(box, paintInfo, integralSnappedRect); case MediaControlsBackgroundPart: return paintMediaControlsBackground(box, paintInfo, integralSnappedRect); case MenulistButtonPart: case TextFieldPart: case TextAreaPart: case ListboxPart: return true; case SearchFieldPart: return paintSearchField(box, paintInfo, integralSnappedRect); case SearchFieldCancelButtonPart: return paintSearchFieldCancelButton(box, paintInfo, integralSnappedRect); case SearchFieldDecorationPart: return paintSearchFieldDecorationPart(box, paintInfo, integralSnappedRect); case SearchFieldResultsDecorationPart: return paintSearchFieldResultsDecorationPart(box, paintInfo, integralSnappedRect); case SearchFieldResultsButtonPart: return paintSearchFieldResultsButton(box, paintInfo, integralSnappedRect); case SnapshottedPluginOverlayPart: return paintSnapshottedPluginOverlay(box, paintInfo, integralSnappedRect); #if ENABLE(SERVICE_CONTROLS) case ImageControlsButtonPart: return paintImageControlsButton(box, paintInfo, integralSnappedRect); #endif case CapsLockIndicatorPart: return paintCapsLockIndicator(box, paintInfo, integralSnappedRect); #if ENABLE(ATTACHMENT_ELEMENT) case AttachmentPart: return paintAttachment(box, paintInfo, integralSnappedRect); #endif default: break; } return true; // We don't support the appearance, so let the normal background/border paint. }
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 = snappedIntRect(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 (is<RenderFrameSet>(*child)) downcast<RenderFrameSet>(*child).layout(); else downcast<RenderFrame>(*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 = snappedIntRect(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 (is<RenderFrameSet>(*child)) downcast<RenderFrameSet>(*child).layout(); else downcast<RenderFrame>(*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(); } }