void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (style().visibility() != VISIBLE) return; // Push a clip. GraphicsContextStateSaver stateSaver(*paintInfo.context, false); if (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseChildBlockBackgrounds) { IntRect clipRect = enclosingIntRect(LayoutRect(paintOffset.x() + borderLeft(), paintOffset.y() + borderTop(), width() - borderLeft() - borderRight(), height() - borderBottom() - borderTop() + buttonShadowHeight)); if (clipRect.isEmpty()) return; stateSaver.save(); paintInfo.context->clip(clipRect); } if (paintInfo.phase == PaintPhaseForeground) { const String& displayedFilename = fileTextValue(); const Font& font = style().font(); TextRun textRun = constructTextRun(this, font, displayedFilename, style(), TextRun::AllowTrailingExpansion, RespectDirection | RespectDirectionOverride); textRun.disableRoundingHacks(); #if PLATFORM(IOS) int iconHeight = nodeHeight(uploadButton()); int iconWidth = iconHeight; #endif // Determine where the filename should be placed LayoutUnit contentLeft = paintOffset.x() + borderLeft() + paddingLeft(); HTMLInputElement* button = uploadButton(); if (!button) return; LayoutUnit buttonWidth = nodeWidth(button); LayoutUnit buttonAndIconWidth = buttonWidth + afterButtonSpacing + (inputElement().icon() ? iconWidth + iconFilenameSpacing : 0); LayoutUnit textX; if (style().isLeftToRightDirection()) textX = contentLeft + buttonAndIconWidth; else textX = contentLeft + contentWidth() - buttonAndIconWidth - font.width(textRun); LayoutUnit textY = 0; // We want to match the button's baseline // FIXME: Make this work with transforms. if (RenderButton* buttonRenderer = toRenderButton(button->renderer())) textY = paintOffset.y() + borderTop() + paddingTop() + buttonRenderer->baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine); else textY = baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine); paintInfo.context->setFillColor(style().visitedDependentColor(CSSPropertyColor), style().colorSpace()); // Draw the filename paintInfo.context->drawBidiText(font, textRun, IntPoint(roundToInt(textX), roundToInt(textY))); if (inputElement().icon()) { // Determine where the icon should be placed LayoutUnit iconY = paintOffset.y() + borderTop() + paddingTop() + (contentHeight() - iconHeight) / 2; LayoutUnit iconX; if (style().isLeftToRightDirection()) iconX = contentLeft + buttonWidth + afterButtonSpacing; else iconX = contentLeft + contentWidth() - buttonWidth - afterButtonSpacing - iconWidth; #if PLATFORM(IOS) if (RenderButton* buttonRenderer = toRenderButton(button->renderer())) { // Draw the file icon and decorations. IntRect iconRect(iconX, iconY, iconWidth, iconHeight); RenderTheme::FileUploadDecorations decorationsType = inputElement().files()->length() == 1 ? RenderTheme::SingleFile : RenderTheme::MultipleFiles; theme().paintFileUploadIconDecorations(*this, *buttonRenderer, paintInfo, iconRect, inputElement().icon(), decorationsType); } #else // Draw the file icon inputElement().icon()->paint(paintInfo.context, IntRect(roundToInt(iconX), roundToInt(iconY), iconWidth, iconHeight)); #endif } } // Paint the children. RenderBlockFlow::paintObject(paintInfo, paintOffset); }
// addFocusRingRects is called from paintOutline and needs to be in the same coordinates as the paintOuline call void RenderSVGContainer::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&, const RenderLayerModelObject*) { IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRectInLocalCoordinates())); if (!paintRectInParent.isEmpty()) rects.append(paintRectInParent); }
void invalidateRect(const IntRect& paintRect) override { if (!paintRect.isEmpty()) m_popup->widgetClient()->didInvalidateRect(paintRect); }
void RenderReplaced::paint(PaintInfo& paintInfo, int tx, int ty) { if (!shouldPaint(paintInfo, tx, ty)) return; tx += x(); ty += y(); if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection)) paintBoxDecorations(paintInfo, tx, ty); if (paintInfo.phase == PaintPhaseMask) { paintMask(paintInfo, tx, ty); return; } if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth()) paintOutline(paintInfo.context, tx, ty, width(), height()); if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection) return; if (!paintInfo.shouldPaintWithinRoot(this)) return; bool drawSelectionTint = selectionState() != SelectionNone && !document()->printing(); if (paintInfo.phase == PaintPhaseSelection) { if (selectionState() == SelectionNone) return; drawSelectionTint = false; } bool completelyClippedOut = false; if (style()->hasBorderRadius()) { IntRect borderRect = IntRect(tx, ty, width(), height()); 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(); IntSize topLeft, topRight, bottomLeft, bottomRight; style()->getBorderRadiiForRect(borderRect, topLeft, topRight, bottomLeft, bottomRight); paintInfo.context->addRoundedRectClip(borderRect, topLeft, topRight, bottomLeft, bottomRight); } } if (!completelyClippedOut) { paintReplaced(paintInfo, tx, ty); 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) { IntRect selectionPaintingRect = localSelectionRect(); selectionPaintingRect.move(tx, ty); paintInfo.context->fillRect(selectionPaintingRect, selectionBackgroundColor(), style()->colorSpace()); } }
void RotationViewportAnchor::setAnchor() { RootFrameViewport* rootFrameViewport = m_rootFrameView->getRootFrameViewport(); DCHECK(rootFrameViewport); IntRect outerViewRect = layoutViewport().visibleContentRect(IncludeScrollbars); IntRect innerViewRect = rootFrameViewport->visibleContentRect(); m_oldPageScaleFactor = m_visualViewport->scale(); m_oldMinimumPageScaleFactor = m_pageScaleConstraintsSet.finalConstraints().minimumScale; // Save the absolute location in case we won't find the anchor node, we'll // fall back to that. m_visualViewportInDocument = FloatPoint(rootFrameViewport->visibleContentRect().location()); m_anchorNode.clear(); m_anchorNodeBounds = LayoutRect(); m_anchorInNodeCoords = FloatSize(); m_normalizedVisualViewportOffset = FloatSize(); if (innerViewRect.isEmpty()) return; // Preserve origins at the absolute screen origin if (innerViewRect.location() == IntPoint::zero()) return; // Inner rectangle should be within the outer one. DCHECK(outerViewRect.contains(innerViewRect)); // Outer rectangle is used as a scale, we need positive width and height. DCHECK(!outerViewRect.isEmpty()); m_normalizedVisualViewportOffset = FloatSize(innerViewRect.location() - outerViewRect.location()); // Normalize by the size of the outer rect m_normalizedVisualViewportOffset.scale(1.0 / outerViewRect.width(), 1.0 / outerViewRect.height()); FloatPoint anchorOffset(innerViewRect.size()); anchorOffset.scale(m_anchorInInnerViewCoords.width(), m_anchorInInnerViewCoords.height()); const FloatPoint anchorPointInContents = m_rootFrameView->rootFrameToContents( m_visualViewport->viewportToRootFrame(anchorOffset)); Node* node = findNonEmptyAnchorNode(flooredIntPoint(anchorPointInContents), innerViewRect, m_rootFrameView->frame().eventHandler()); if (!node) return; m_anchorNode = node; m_anchorNodeBounds = node->boundingBox(); m_anchorInNodeCoords = anchorPointInContents - FloatPoint(m_anchorNodeBounds.location()); m_anchorInNodeCoords.scale(1.f / m_anchorNodeBounds.width(), 1.f / m_anchorNodeBounds.height()); }
void CoordinatedGraphicsLayer::tiledBackingStorePaint(GraphicsContext* context, const IntRect& rect) { if (rect.isEmpty()) return; paintGraphicsLayerContents(*context, rect); }
void FEComposite::platformApplySoftware() { FilterEffect* in = inputEffect(0); FilterEffect* in2 = inputEffect(1); if (m_type == FECOMPOSITE_OPERATOR_ARITHMETIC) { Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult(); if (!dstPixelArray) return; IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); RefPtr<Uint8ClampedArray> srcPixelArray = in->asPremultipliedImage(effectADrawingRect); IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect()); in2->copyPremultipliedImage(dstPixelArray, effectBDrawingRect); platformArithmeticSoftware(srcPixelArray.get(), dstPixelArray, m_k1, m_k2, m_k3, m_k4); return; } ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; GraphicsContext* filterContext = resultImage->context(); ImageBuffer* imageBuffer = in->asImageBuffer(); ImageBuffer* imageBuffer2 = in2->asImageBuffer(); ASSERT(imageBuffer); ASSERT(imageBuffer2); switch (m_type) { case FECOMPOSITE_OPERATOR_OVER: filterContext->drawImageBuffer(imageBuffer2, ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect())); filterContext->drawImageBuffer(imageBuffer, ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect())); break; case FECOMPOSITE_OPERATOR_IN: { // Applies only to the intersected region. IntRect destinationRect = in->absolutePaintRect(); destinationRect.intersect(in2->absolutePaintRect()); destinationRect.intersect(absolutePaintRect()); if (destinationRect.isEmpty()) break; IntPoint destinationPoint(destinationRect.x() - absolutePaintRect().x(), destinationRect.y() - absolutePaintRect().y()); IntRect sourceRect(IntPoint(destinationRect.x() - in->absolutePaintRect().x(), destinationRect.y() - in->absolutePaintRect().y()), destinationRect.size()); IntRect source2Rect(IntPoint(destinationRect.x() - in2->absolutePaintRect().x(), destinationRect.y() - in2->absolutePaintRect().y()), destinationRect.size()); filterContext->drawImageBuffer(imageBuffer2, ColorSpaceDeviceRGB, destinationPoint, source2Rect); filterContext->drawImageBuffer(imageBuffer, ColorSpaceDeviceRGB, destinationPoint, sourceRect, CompositeSourceIn); break; } case FECOMPOSITE_OPERATOR_OUT: filterContext->drawImageBuffer(imageBuffer, ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect())); filterContext->drawImageBuffer(imageBuffer2, ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()), IntRect(IntPoint(), imageBuffer2->logicalSize()), CompositeDestinationOut); break; case FECOMPOSITE_OPERATOR_ATOP: filterContext->drawImageBuffer(imageBuffer2, ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect())); filterContext->drawImageBuffer(imageBuffer, ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()), IntRect(IntPoint(), imageBuffer->logicalSize()), CompositeSourceAtop); break; case FECOMPOSITE_OPERATOR_XOR: filterContext->drawImageBuffer(imageBuffer2, ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect())); filterContext->drawImageBuffer(imageBuffer, ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()), IntRect(IntPoint(), imageBuffer->logicalSize()), CompositeXOR); break; default: break; } }
void TiledBackingStore::createTiles() { // Guard here as as these can change before the timer fires. if (isBackingStoreUpdatesSuspended()) return; // Update our backing store geometry. const IntRect previousRect = m_rect; m_rect = mapFromContents(m_client->tiledBackingStoreContentsRect()); const IntRect visibleRect = this->visibleRect(); m_visibleRect = visibleRect; if (visibleRect.isEmpty()) return; IntRect keepRect; IntRect coverRect; computeCoverAndKeepRect(visibleRect, coverRect, keepRect); setKeepRect(keepRect); // Resize tiles at the edge in case the contents size has changed, but only do so // after having dropped tiles outside the keep rect. bool didResizeTiles = false; if (previousRect != m_rect) didResizeTiles = resizeEdgeTiles(); // Search for the tile position closest to the viewport center that does not yet contain a tile. // Which position is considered the closest depends on the tileDistance function. double shortestDistance = std::numeric_limits<double>::infinity(); Vector<Tile::Coordinate> tilesToCreate; unsigned requiredTileCount = 0; // Cover areas (in tiles) with minimum distance from the visible rect. If the visible rect is // not covered already it will be covered first in one go, due to the distance being 0 for tiles // inside the visible rect. Tile::Coordinate topLeft = tileCoordinateForPoint(coverRect.location()); Tile::Coordinate bottomRight = tileCoordinateForPoint(innerBottomRight(coverRect)); for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) { for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) { Tile::Coordinate currentCoordinate(xCoordinate, yCoordinate); if (tileAt(currentCoordinate)) continue; ++requiredTileCount; double distance = tileDistance(visibleRect, currentCoordinate); if (distance > shortestDistance) continue; if (distance < shortestDistance) { tilesToCreate.clear(); shortestDistance = distance; } tilesToCreate.append(currentCoordinate); } } // Now construct the tile(s) within the shortest distance. unsigned tilesToCreateCount = tilesToCreate.size(); for (unsigned n = 0; n < tilesToCreateCount; ++n) { Tile::Coordinate coordinate = tilesToCreate[n]; setTile(coordinate, m_backend->createTile(this, coordinate)); } requiredTileCount -= tilesToCreateCount; // Paint the content of the newly created tiles or resized tiles. if (tilesToCreateCount || didResizeTiles) updateTileBuffers(); // Re-call createTiles on a timer to cover the visible area with the newest shortest distance. if (requiredTileCount) m_backingStoreUpdateTimer.startOneShot(m_tileCreationDelay); }
bool IntRect::intersects(const IntRect& other) const { // Checking emptiness handles negative widths as well as zero. return !isEmpty() && !other.isEmpty() && x() < other.maxX() && other.x() < maxX() && y() < other.maxY() && other.y() < maxY(); }
// addFocusRingRects is called from paintOutline and needs to be in the same coordinates as the paintOuline call void RenderSVGContainer::addFocusRingRects(Vector<IntRect>& rects, int, int) { IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRectInLocalCoordinates())); if (!paintRectInParent.isEmpty()) rects.append(paintRectInParent); }