void EventTargetNode::dispatchWheelEvent(PlatformWheelEvent& e) { assert(!eventDispatchForbidden()); if (e.delta() == 0) return; FrameView* view = document()->view(); if (!view) return; IntPoint pos = view->viewportToContents(e.pos()); RefPtr<WheelEvent> we = new WheelEvent(e.isHorizontal(), e.delta(), document()->defaultView(), e.globalX(), e.globalY(), pos.x(), pos.y(), e.ctrlKey(), e.altKey(), e.shiftKey(), e.metaKey()); ExceptionCode ec = 0; if (!dispatchEvent(we, ec, true)) e.accept(); }
bool RenderThemeGtk::paintMozillaGtkWidget(GtkThemeWidgetType type, GraphicsContext* context, const IntRect& rect, GtkWidgetState* widgetState, int flags, GtkTextDirection textDirection) { // Painting is disabled so just claim to have succeeded if (context->paintingDisabled()) return false; PlatformRefPtr<GdkDrawable> drawable(context->gdkDrawable()); GdkRectangle paintRect, clipRect; if (drawable) { AffineTransform ctm = context->getCTM(); IntPoint pos = ctm.mapPoint(rect.location()); paintRect = IntRect(pos.x(), pos.y(), rect.width(), rect.height()); // Intersect the cairo rectangle with the target widget region. This will // prevent the theme drawing code from drawing into regions that cairo will // clip anyway. double clipX1, clipX2, clipY1, clipY2; cairo_clip_extents(context->platformContext(), &clipX1, &clipY1, &clipX2, &clipY2); IntPoint clipPos = ctm.mapPoint(IntPoint(clipX1, clipY1)); clipRect.width = clipX2 - clipX1; clipRect.height = clipY2 - clipY1; clipRect.x = clipPos.x(); clipRect.y = clipPos.y(); gdk_rectangle_intersect(&paintRect, &clipRect, &clipRect); } else { // In some situations, like during print previews, this GraphicsContext is not // backed by a GdkDrawable. In those situations, we render onto a pixmap and then // copy the rendered data back to the GraphicsContext via Cairo. drawable = adoptPlatformRef(gdk_pixmap_new(0, rect.width(), rect.height(), gdk_visual_get_depth(gdk_visual_get_system()))); paintRect = clipRect = IntRect(0, 0, rect.width(), rect.height()); } moz_gtk_use_theme_parts(partsForDrawable(drawable.get())); bool success = moz_gtk_widget_paint(type, drawable.get(), &paintRect, &clipRect, widgetState, flags, textDirection) == MOZ_GTK_SUCCESS; // If the drawing was successful and we rendered onto a pixmap, copy the // results back to the original GraphicsContext. if (success && !context->gdkDrawable()) { cairo_t* cairoContext = context->platformContext(); cairo_save(cairoContext); gdk_cairo_set_source_pixmap(cairoContext, drawable.get(), rect.x(), rect.y()); cairo_paint(cairoContext); cairo_restore(cairoContext); } return !success; }
static void updateWebMouseEventFromWebCoreMouseEvent(const MouseRelatedEvent& event, const Widget& widget, const WebCore::RenderObject& renderObject, WebMouseEvent& webEvent) { webEvent.timeStampSeconds = event.timeStamp() / millisPerSecond; webEvent.modifiers = getWebInputModifiers(event); ScrollView* view = widget.parent(); IntPoint windowPoint = view->contentsToWindow(IntPoint(event.absoluteLocation().x(), event.absoluteLocation().y())); webEvent.globalX = event.screenX(); webEvent.globalY = event.screenY(); webEvent.windowX = windowPoint.x(); webEvent.windowY = windowPoint.y(); IntPoint localPoint = convertAbsoluteLocationForRenderObject(event.absoluteLocation(), renderObject); webEvent.x = localPoint.x(); webEvent.y = localPoint.y(); }
IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, const IntPoint& popupInitialCoordinate) { // Reset the max width and height to their default values, they will be recomputed below // if necessary. m_listBox->setMaxHeight(kMaxHeight); m_listBox->setMaxWidth(std::numeric_limits<int>::max()); // Lay everything out to figure out our preferred size, then tell the view's // WidgetClient about it. It should assign us a client. int rtlOffset = layoutAndGetRTLOffset(); bool isRTL = this->isRTL(); int rightOffset = isRTL ? rtlOffset : 0; // Assume m_listBox size is already calculated. IntSize targetSize(m_listBox->width() + kBorderSize * 2, m_listBox->height() + kBorderSize * 2); IntRect widgetRectInScreen; ChromeClientChromium* chromeClient = chromeClientChromium(); if (chromeClient) { // If the popup would extend past the bottom of the screen, open upwards // instead. FloatRect screen = screenAvailableRect(m_frameView.get()); // Use popupInitialCoordinate.x() + rightOffset because RTL position // needs to be considered. widgetRectInScreen = chromeClient->rootViewToScreen(IntRect(popupInitialCoordinate.x() + rightOffset, popupInitialCoordinate.y(), targetSize.width(), targetSize.height())); // If we have multiple screens and the browser rect is in one screen, we have // to clip the window width to the screen width. // When clipping, we also need to set a maximum width for the list box. FloatRect windowRect = chromeClient->windowRect(); bool needToResizeView = false; widgetRectInScreen = layoutAndCalculateWidgetRectInternal(widgetRectInScreen, targetControlHeight, windowRect, screen, isRTL, rtlOffset, m_listBox.get(), needToResizeView); if (needToResizeView) fitToListBox(); } return widgetRectInScreen; }
// FIXME: Change |widget| to const Widget& after RemoteFrames get // RemoteFrameViews. static void updateWebMouseEventFromCoreMouseEvent(const MouseRelatedEvent& event, const Widget* widget, const LayoutObject& layoutObject, WebMouseEvent& webEvent) { webEvent.timeStampSeconds = event.platformTimeStamp(); webEvent.modifiers = event.modifiers(); FrameView* view = widget ? toFrameView(widget->parent()) : 0; // TODO(bokan): If view == nullptr, pointInRootFrame will really be pointInRootContent. IntPoint pointInRootFrame = IntPoint(event.absoluteLocation().x(), event.absoluteLocation().y()); if (view) pointInRootFrame = view->contentsToRootFrame(pointInRootFrame); webEvent.globalX = event.screenX(); webEvent.globalY = event.screenY(); webEvent.windowX = pointInRootFrame.x(); webEvent.windowY = pointInRootFrame.y(); IntPoint localPoint = convertAbsoluteLocationForLayoutObject(event.absoluteLocation(), layoutObject); webEvent.x = localPoint.x(); webEvent.y = localPoint.y(); }
void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem coordinateSystem) { if (!m_context->isAcceleratedContext()) { m_data.putData(source, sourceSize, sourceRect, destPoint, internalSize(), m_context->isAcceleratedContext(), multiplied == Unmultiplied, coordinateSystem == LogicalCoordinateSystem ? m_resolutionScale : 1); return; } #if USE(IOSURFACE_CANVAS_BACKING_STORE) // Make a copy of the source to ensure the bits don't change before being drawn IntSize sourceCopySize(sourceRect.width(), sourceRect.height()); OwnPtr<ImageBuffer> sourceCopy = ImageBuffer::create(sourceCopySize, 1, ColorSpaceDeviceRGB, Unaccelerated); if (!sourceCopy) return; sourceCopy->m_data.putData(source, sourceSize, sourceRect, IntPoint(-sourceRect.x(), -sourceRect.y()), sourceCopy->internalSize(), sourceCopy->context()->isAcceleratedContext(), multiplied == Unmultiplied, 1); // Set up context for using drawImage as a direct bit copy CGContextRef destContext = context()->platformContext(); CGContextSaveGState(destContext); if (coordinateSystem == LogicalCoordinateSystem) CGContextConcatCTM(destContext, AffineTransform(wkGetUserToBaseCTM(destContext)).inverse()); else CGContextConcatCTM(destContext, AffineTransform(CGContextGetCTM(destContext)).inverse()); wkCGContextResetClip(destContext); CGContextSetInterpolationQuality(destContext, kCGInterpolationNone); CGContextSetAlpha(destContext, 1.0); CGContextSetBlendMode(destContext, kCGBlendModeCopy); CGContextSetShadowWithColor(destContext, CGSizeZero, 0, 0); // Draw the image in CG coordinate space IntPoint destPointInCGCoords(destPoint.x() + sourceRect.x(), (coordinateSystem == LogicalCoordinateSystem ? logicalSize() : internalSize()).height() - (destPoint.y() + sourceRect.y()) - sourceRect.height()); IntRect destRectInCGCoords(destPointInCGCoords, sourceCopySize); RetainPtr<CGImageRef> sourceCopyImage(AdoptCF, sourceCopy->copyNativeImage()); CGContextDrawImage(destContext, destRectInCGCoords, sourceCopyImage.get()); CGContextRestoreGState(destContext); #endif }
// Generate a synthetic WebMouseEvent given a TouchEvent (eg. for emulating a mouse // with touch input for plugins that don't support touch input). WebMouseEventBuilder::WebMouseEventBuilder(const Widget* widget, const WebCore::RenderObject* renderObject, const TouchEvent& event) { if (!event.touches()) return; if (event.touches()->length() != 1) { if (event.touches()->length() || event.type() != EventTypeNames::touchend || !event.changedTouches() || event.changedTouches()->length() != 1) return; } const Touch* touch = event.touches()->length() == 1 ? event.touches()->item(0) : event.changedTouches()->item(0); if (touch->identifier()) return; if (event.type() == EventTypeNames::touchstart) type = MouseDown; else if (event.type() == EventTypeNames::touchmove) type = MouseMove; else if (event.type() == EventTypeNames::touchend) type = MouseUp; else return; timeStampSeconds = event.timeStamp() / millisPerSecond; modifiers = getWebInputModifiers(event); // The mouse event co-ordinates should be generated from the co-ordinates of the touch point. ScrollView* view = toScrollView(widget->parent()); IntPoint windowPoint = IntPoint(touch->absoluteLocation().x(), touch->absoluteLocation().y()); if (view) windowPoint = view->contentsToWindow(windowPoint); globalX = touch->screenX(); globalY = touch->screenY(); windowX = windowPoint.x(); windowY = windowPoint.y(); button = WebMouseEvent::ButtonLeft; modifiers |= WebInputEvent::LeftButtonDown; clickCount = (type == MouseDown || type == MouseUp); IntPoint localPoint = convertAbsoluteLocationForRenderObject(touch->absoluteLocation(), *renderObject); x = localPoint.x(); y = localPoint.y(); }
void NetscapePlugin::callSetWindow() { if (wantsPluginRelativeNPWindowCoordinates()) { m_npWindow.x = 0; m_npWindow.y = 0; m_npWindow.clipRect.top = m_clipRect.y(); m_npWindow.clipRect.left = m_clipRect.x(); } else { IntPoint pluginLocationInRootViewCoordinates = convertToRootView(IntPoint()); IntPoint clipRectInRootViewCoordinates = convertToRootView(m_clipRect.location()); m_npWindow.x = pluginLocationInRootViewCoordinates.x(); m_npWindow.y = pluginLocationInRootViewCoordinates.y(); m_npWindow.clipRect.top = clipRectInRootViewCoordinates.y(); m_npWindow.clipRect.left = clipRectInRootViewCoordinates.x(); } m_npWindow.width = m_pluginSize.width(); m_npWindow.height = m_pluginSize.height(); m_npWindow.clipRect.right = m_npWindow.clipRect.left + m_clipRect.width(); m_npWindow.clipRect.bottom = m_npWindow.clipRect.top + m_clipRect.height(); NPP_SetWindow(&m_npWindow); }
FloatPoint::FloatPoint(const IntPoint& p) : m_x(p.x()), m_y(p.y()) { }
// This is only used to draw borders. void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) { if (paintingDisabled()) return; if (strokeStyle() == NoStroke) return; float width = strokeThickness(); FloatPoint p1 = point1; FloatPoint p2 = point2; bool isVerticalLine = (p1.x() == p2.x()); // For odd widths, we add in 0.5 to the appropriate x/y so that the float arithmetic // works out. For example, with a border width of 3, KHTML will pass us (y1+y2)/2, e.g., // (50+53)/2 = 103/2 = 51 when we want 51.5. It is always true that an even width gave // us a perfect position, but an odd width gave us a position that is off by exactly 0.5. if (strokeStyle() == DottedStroke || strokeStyle() == DashedStroke) { if (isVerticalLine) { p1.move(0, width); p2.move(0, -width); } else { p1.move(width, 0); p2.move(-width, 0); } } if (((int)width) % 2) { if (isVerticalLine) { // We're a vertical line. Adjust our x. p1.move(0.5f, 0.0f); p2.move(0.5f, 0.0f); } else { // We're a horizontal line. Adjust our y. p1.move(0.0f, 0.5f); p2.move(0.0f, 0.5f); } } int patWidth = 0; switch (strokeStyle()) { case NoStroke: case SolidStroke: break; case DottedStroke: patWidth = (int)width; break; case DashedStroke: patWidth = 3 * (int)width; break; } CGContextRef context = platformContext(); if (shouldAntialias()) CGContextSetShouldAntialias(context, false); if (patWidth) { CGContextSaveGState(context); // Do a rect fill of our endpoints. This ensures we always have the // appearance of being a border. We then draw the actual dotted/dashed line. setCGFillColor(context, strokeColor(), strokeColorSpace()); // The save/restore make it safe to mutate the fill color here without setting it back to the old color. if (isVerticalLine) { CGContextFillRect(context, FloatRect(p1.x() - width / 2, p1.y() - width, width, width)); CGContextFillRect(context, FloatRect(p2.x() - width / 2, p2.y(), width, width)); } else { CGContextFillRect(context, FloatRect(p1.x() - width, p1.y() - width / 2, width, width)); CGContextFillRect(context, FloatRect(p2.x(), p2.y() - width / 2, width, width)); } // Example: 80 pixels with a width of 30 pixels. // Remainder is 20. The maximum pixels of line we could paint // will be 50 pixels. int distance = (isVerticalLine ? (point2.y() - point1.y()) : (point2.x() - point1.x())) - 2*(int)width; int remainder = distance % patWidth; int coverage = distance - remainder; int numSegments = coverage / patWidth; float patternOffset = 0.0f; // Special case 1px dotted borders for speed. if (patWidth == 1) patternOffset = 1.0f; else { bool evenNumberOfSegments = !(numSegments % 2); if (remainder) evenNumberOfSegments = !evenNumberOfSegments; if (evenNumberOfSegments) { if (remainder) { patternOffset += patWidth - remainder; patternOffset += remainder / 2; } else patternOffset = patWidth / 2; } else { if (remainder) patternOffset = (patWidth - remainder)/2; } } const CGFloat dottedLine[2] = { patWidth, patWidth }; CGContextSetLineDash(context, patternOffset, dottedLine, 2); } CGContextBeginPath(context); CGContextMoveToPoint(context, p1.x(), p1.y()); CGContextAddLineToPoint(context, p2.x(), p2.y()); CGContextStrokePath(context); if (patWidth) CGContextRestoreGState(context); if (shouldAntialias()) CGContextSetShouldAntialias(context, true); }
void RenderMathMLRoot::paint(PaintInfo& info, const LayoutPoint& paintOffset) { RenderMathMLBlock::paint(info, paintOffset); if (info.context->paintingDisabled()) return; IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location() + contentBoxRect().location()); int startX = adjustedPaintOffset.x(); int frontWidth = lroundf(gFrontWidthEms * style()->fontSize()); int overbarWidth = roundToInt(contentLogicalWidth()) + m_overbarLeftPointShift; int baseHeight = roundToInt(contentLogicalHeight()); int rootPad = lroundf(gSpaceAboveEms * style()->fontSize()); adjustedPaintOffset.setY(adjustedPaintOffset.y() - rootPad); float radicalDipLeftPointYPos = (index() ? gRootRadicalDipLeftPointYPos : gSqrtRadicalDipLeftPointYPos) * baseHeight; FloatPoint overbarLeftPoint(startX - m_overbarLeftPointShift, adjustedPaintOffset.y()); FloatPoint bottomPoint(startX - gRadicalBottomPointXFront * frontWidth, adjustedPaintOffset.y() + baseHeight + gRadicalBottomPointLower); FloatPoint dipLeftPoint(startX - gRadicalDipLeftPointXFront * frontWidth, adjustedPaintOffset.y() + radicalDipLeftPointYPos); FloatPoint leftEnd(startX - frontWidth, dipLeftPoint.y() + gRadicalLeftEndYShiftEms * style()->fontSize()); GraphicsContextStateSaver stateSaver(*info.context); info.context->setStrokeThickness(gRadicalLineThicknessEms * style()->fontSize()); info.context->setStrokeStyle(SolidStroke); info.context->setStrokeColor(style()->visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB); info.context->setLineJoin(MiterJoin); info.context->setMiterLimit(style()->fontSize()); Path root; root.moveTo(FloatPoint(overbarLeftPoint.x() + overbarWidth, adjustedPaintOffset.y())); // draw top root.addLineTo(overbarLeftPoint); // draw from top left corner to bottom point of radical root.addLineTo(bottomPoint); // draw from bottom point to top of left part of radical base "dip" root.addLineTo(dipLeftPoint); // draw to end root.addLineTo(leftEnd); info.context->strokePath(root); GraphicsContextStateSaver maskStateSaver(*info.context); // Build a mask to draw the thick part of the root. Path mask; mask.moveTo(overbarLeftPoint); mask.addLineTo(bottomPoint); mask.addLineTo(dipLeftPoint); mask.addLineTo(FloatPoint(2 * dipLeftPoint.x() - leftEnd.x(), 2 * dipLeftPoint.y() - leftEnd.y())); info.context->clip(mask); // Draw the thick part of the root. info.context->setStrokeThickness(gRadicalThickLineThicknessEms * style()->fontSize()); info.context->setLineCap(SquareCap); Path line; line.moveTo(bottomPoint); line.addLineTo(dipLeftPoint); info.context->strokePath(line); }
void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem coordinateSystem) { IntRect scaledSourceRect = backingStoreUnit(sourceRect, coordinateSystem, m_resolutionScale); IntSize scaledSourceSize = backingStoreUnit(sourceSize, coordinateSystem, m_resolutionScale); IntPoint scaledDestPoint = backingStoreUnit(destPoint, coordinateSystem, m_resolutionScale); IntRect logicalSourceRect = logicalUnit(sourceRect, coordinateSystem, m_resolutionScale); IntPoint logicalDestPoint = logicalUnit(destPoint, coordinateSystem, m_resolutionScale); ASSERT(scaledSourceRect.width() > 0); ASSERT(scaledSourceRect.height() > 0); int originx = scaledSourceRect.x(); int destx = scaledDestPoint.x() + scaledSourceRect.x(); int logicalDestx = logicalDestPoint.x() + logicalSourceRect.x(); ASSERT(destx >= 0); ASSERT(destx < m_size.width()); ASSERT(originx >= 0); ASSERT(originx <= scaledSourceRect.maxX()); int endx = scaledDestPoint.x() + scaledSourceRect.maxX(); int logicalEndx = logicalDestPoint.x() + logicalSourceRect.maxX(); ASSERT(endx <= m_size.width()); int numColumns = endx - destx; int logicalNumColumns = logicalEndx - logicalDestx; int originy = scaledSourceRect.y(); int desty = scaledDestPoint.y() + scaledSourceRect.y(); int logicalDesty = logicalDestPoint.y() + logicalSourceRect.y(); ASSERT(desty >= 0); ASSERT(desty < m_size.height()); ASSERT(originy >= 0); ASSERT(originy <= scaledSourceRect.maxY()); int endy = scaledDestPoint.y() + scaledSourceRect.maxY(); int logicalEndy = logicalDestPoint.y() + logicalSourceRect.maxY(); ASSERT(endy <= m_size.height()); int numRows = endy - desty; int logicalNumRows = logicalEndy - logicalDesty; // The size of the derived surface is in BackingStoreCoordinateSystem. // We need to set the device scale for the derived surface from this ImageBuffer. IntRect imageRect(destx, desty, numColumns, numRows); RefPtr<cairo_surface_t> imageSurface = copySurfaceToImageAndAdjustRect(m_data.m_surface.get(), imageRect); cairoSurfaceSetDeviceScale(imageSurface.get(), m_resolutionScale, m_resolutionScale); destx = imageRect.x(); desty = imageRect.y(); unsigned char* pixelData = cairo_image_surface_get_data(imageSurface.get()); unsigned srcBytesPerRow = 4 * scaledSourceSize.width(); int stride = cairo_image_surface_get_stride(imageSurface.get()); unsigned char* srcRows = source->data() + originy * srcBytesPerRow + originx * 4; for (int y = 0; y < numRows; ++y) { unsigned* row = reinterpret_cast_ptr<unsigned*>(pixelData + stride * (y + desty)); for (int x = 0; x < numColumns; x++) { int basex = x * 4; unsigned* pixel = row + x + destx; // Avoid calling Color::premultipliedARGBFromColor() because one // function call per pixel is too expensive. unsigned red = srcRows[basex]; unsigned green = srcRows[basex + 1]; unsigned blue = srcRows[basex + 2]; unsigned alpha = srcRows[basex + 3]; if (multiplied == Unmultiplied) { if (alpha != 255) { red = (red * alpha + 254) / 255; green = (green * alpha + 254) / 255; blue = (blue * alpha + 254) / 255; } } *pixel = (alpha << 24) | red << 16 | green << 8 | blue; } srcRows += srcBytesPerRow; } // This cairo surface operation is done in LogicalCoordinateSystem. cairo_surface_mark_dirty_rectangle(imageSurface.get(), logicalDestx, logicalDesty, logicalNumColumns, logicalNumRows); if (imageSurface != m_data.m_surface.get()) { // This cairo surface operation is done in LogicalCoordinateSystem. copyRectFromOneSurfaceToAnother(imageSurface.get(), m_data.m_surface.get(), IntSize(), IntRect(0, 0, logicalNumColumns, logicalNumRows), IntSize(logicalDestPoint.x() + logicalSourceRect.x(), logicalDestPoint.y() + logicalSourceRect.y()), CAIRO_OPERATOR_SOURCE); } }
void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem) { ASSERT(sourceRect.width() > 0); ASSERT(sourceRect.height() > 0); int originx = sourceRect.x(); int destx = destPoint.x() + sourceRect.x(); ASSERT(destx >= 0); ASSERT(destx < m_size.width()); ASSERT(originx >= 0); ASSERT(originx <= sourceRect.maxX()); int endx = destPoint.x() + sourceRect.maxX(); ASSERT(endx <= m_size.width()); int numColumns = endx - destx; int originy = sourceRect.y(); int desty = destPoint.y() + sourceRect.y(); ASSERT(desty >= 0); ASSERT(desty < m_size.height()); ASSERT(originy >= 0); ASSERT(originy <= sourceRect.maxY()); int endy = destPoint.y() + sourceRect.maxY(); ASSERT(endy <= m_size.height()); int numRows = endy - desty; IntRect imageRect(destx, desty, numColumns, numRows); RefPtr<cairo_surface_t> imageSurface = copySurfaceToImageAndAdjustRect(m_data.m_surface.get(), imageRect); destx = imageRect.x(); desty = imageRect.y(); unsigned char* pixelData = cairo_image_surface_get_data(imageSurface.get()); unsigned srcBytesPerRow = 4 * sourceSize.width(); int stride = cairo_image_surface_get_stride(imageSurface.get()); unsigned char* srcRows = source->data() + originy * srcBytesPerRow + originx * 4; for (int y = 0; y < numRows; ++y) { unsigned* row = reinterpret_cast_ptr<unsigned*>(pixelData + stride * (y + desty)); for (int x = 0; x < numColumns; x++) { int basex = x * 4; unsigned* pixel = row + x + destx; // Avoid calling Color::premultipliedARGBFromColor() because one // function call per pixel is too expensive. unsigned red = srcRows[basex]; unsigned green = srcRows[basex + 1]; unsigned blue = srcRows[basex + 2]; unsigned alpha = srcRows[basex + 3]; if (multiplied == Unmultiplied) { if (alpha != 255) { red = (red * alpha + 254) / 255; green = (green * alpha + 254) / 255; blue = (blue * alpha + 254) / 255; } } *pixel = (alpha << 24) | red << 16 | green << 8 | blue; } srcRows += srcBytesPerRow; } cairo_surface_mark_dirty_rectangle(imageSurface.get(), destx, desty, numColumns, numRows); if (imageSurface != m_data.m_surface.get()) copyRectFromOneSurfaceToAnother(imageSurface.get(), m_data.m_surface.get(), IntSize(), IntRect(0, 0, numColumns, numRows), IntSize(destPoint.x() + sourceRect.x(), destPoint.y() + sourceRect.y()), CAIRO_OPERATOR_SOURCE); }
IntSize IntRect::differenceToPoint(const IntPoint& point) const { int xdistance = distanceToInterval(point.x(), x(), maxX()); int ydistance = distanceToInterval(point.y(), y(), maxY()); return IntSize(xdistance, ydistance); }
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; // 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()) { SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(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 - not affected by overflow handling childPaintInfo.context->clip(pixelSnappedIntRect(overflowClipRect(paintOffset, paintInfo.renderRegion))); // 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 (RenderObject* child = firstChild(); child; child = child->nextSibling()) { // FIXME: Can this ever have RenderText children? if (!child->isRenderElement()) continue; toRenderElement(child)->paint(childPaintInfo, location()); } } } childPaintInfo.context->restore(); }
bool RenderFrameSet::canResizeRow(const IntPoint& p) const { int r = hitTestSplit(m_rows, p.y()); return r != noSplit && !m_rows.m_preventResize[r]; }
IntPoint WebPluginScrollbarImpl::convertFromContainingViewToScrollbar(const IntPoint& parentPoint) const { IntPoint offset(parentPoint.x() - m_scrollbar->x(), parentPoint.y() - m_scrollbar->y()); return m_scrollbar->Widget::convertFromContainingView(offset); }
PlatformGestureEventBuilder::PlatformGestureEventBuilder(Widget* widget, const WebGestureEvent& e) { float scale = widgetInputEventsScaleFactor(widget); IntSize offset = widgetInputEventsOffset(widget); IntPoint pinchViewport = pinchViewportOffset(widget); switch (e.type) { case WebInputEvent::GestureScrollBegin: m_type = PlatformEvent::GestureScrollBegin; break; case WebInputEvent::GestureScrollEnd: m_type = PlatformEvent::GestureScrollEnd; break; case WebInputEvent::GestureFlingStart: m_type = PlatformEvent::GestureFlingStart; break; case WebInputEvent::GestureScrollUpdate: m_type = PlatformEvent::GestureScrollUpdate; m_data.m_scrollUpdate.m_deltaX = e.data.scrollUpdate.deltaX / scale; m_data.m_scrollUpdate.m_deltaY = e.data.scrollUpdate.deltaY / scale; m_data.m_scrollUpdate.m_velocityX = e.data.scrollUpdate.velocityX; m_data.m_scrollUpdate.m_velocityY = e.data.scrollUpdate.velocityY; break; case WebInputEvent::GestureScrollUpdateWithoutPropagation: m_type = PlatformEvent::GestureScrollUpdateWithoutPropagation; m_data.m_scrollUpdate.m_deltaX = e.data.scrollUpdate.deltaX / scale; m_data.m_scrollUpdate.m_deltaY = e.data.scrollUpdate.deltaY / scale; m_data.m_scrollUpdate.m_velocityX = e.data.scrollUpdate.velocityX; m_data.m_scrollUpdate.m_velocityY = e.data.scrollUpdate.velocityY; break; case WebInputEvent::GestureTap: m_type = PlatformEvent::GestureTap; m_area = expandedIntSize(FloatSize(e.data.tap.width / scale, e.data.tap.height / scale)); m_data.m_tap.m_tapCount = e.data.tap.tapCount; break; case WebInputEvent::GestureTapUnconfirmed: m_type = PlatformEvent::GestureTapUnconfirmed; m_area = expandedIntSize(FloatSize(e.data.tap.width / scale, e.data.tap.height / scale)); break; case WebInputEvent::GestureTapDown: m_type = PlatformEvent::GestureTapDown; m_area = expandedIntSize(FloatSize(e.data.tapDown.width / scale, e.data.tapDown.height / scale)); break; case WebInputEvent::GestureShowPress: m_type = PlatformEvent::GestureShowPress; m_area = expandedIntSize(FloatSize(e.data.showPress.width / scale, e.data.showPress.height / scale)); break; case WebInputEvent::GestureTapCancel: m_type = PlatformEvent::GestureTapDownCancel; break; case WebInputEvent::GestureDoubleTap: // DoubleTap gesture is now handled as PlatformEvent::GestureTap with tap_count = 2. So no // need to convert to a Platfrom DoubleTap gesture. But in WebViewImpl::handleGestureEvent // all WebGestureEvent are converted to PlatformGestureEvent, for completeness and not reach // the ASSERT_NOT_REACHED() at the end, convert the DoubleTap to a NoType. m_type = PlatformEvent::NoType; break; case WebInputEvent::GestureTwoFingerTap: m_type = PlatformEvent::GestureTwoFingerTap; m_area = expandedIntSize(FloatSize(e.data.twoFingerTap.firstFingerWidth / scale, e.data.twoFingerTap.firstFingerHeight / scale)); break; case WebInputEvent::GestureLongPress: m_type = PlatformEvent::GestureLongPress; m_area = expandedIntSize(FloatSize(e.data.longPress.width / scale, e.data.longPress.height / scale)); break; case WebInputEvent::GestureLongTap: m_type = PlatformEvent::GestureLongTap; m_area = expandedIntSize(FloatSize(e.data.longPress.width / scale, e.data.longPress.height / scale)); break; case WebInputEvent::GesturePinchBegin: m_type = PlatformEvent::GesturePinchBegin; break; case WebInputEvent::GesturePinchEnd: m_type = PlatformEvent::GesturePinchEnd; break; case WebInputEvent::GesturePinchUpdate: m_type = PlatformEvent::GesturePinchUpdate; m_data.m_pinchUpdate.m_scale = e.data.pinchUpdate.scale; break; default: ASSERT_NOT_REACHED(); } m_position = widget->convertFromContainingWindow( IntPoint((e.x - offset.width()) / scale + pinchViewport.x(), (e.y - offset.height()) / scale + pinchViewport.y())); m_globalPosition = IntPoint(e.globalX, e.globalY); m_timestamp = e.timeStampSeconds; m_modifiers = 0; if (e.modifiers & WebInputEvent::ShiftKey) m_modifiers |= PlatformEvent::ShiftKey; if (e.modifiers & WebInputEvent::ControlKey) m_modifiers |= PlatformEvent::CtrlKey; if (e.modifiers & WebInputEvent::AltKey) m_modifiers |= PlatformEvent::AltKey; if (e.modifiers & WebInputEvent::MetaKey) m_modifiers |= PlatformEvent::MetaKey; }
IntPoint ScrollableArea::clampScrollPosition(const IntPoint& scrollPosition) const { return scrollPosition.shrunkTo(maximumScrollPosition()).expandedTo(minimumScrollPosition()); }
void AccessibilityObject::scrollToGlobalPoint(const IntPoint& globalPoint) const { // Search up the parent chain and create a vector of all scrollable parent objects // and ending with this object itself. Vector<const AccessibilityObject*> objects; AccessibilityObject* parentObject; for (parentObject = this->parentObject(); parentObject; parentObject = parentObject->parentObject()) { if (parentObject->getScrollableAreaIfScrollable()) objects.prepend(parentObject); } objects.append(this); // Start with the outermost scrollable (the main window) and try to scroll the // next innermost object to the given point. int offsetX = 0, offsetY = 0; IntPoint point = globalPoint; size_t levels = objects.size() - 1; for (size_t i = 0; i < levels; i++) { const AccessibilityObject* outer = objects[i]; const AccessibilityObject* inner = objects[i + 1]; ScrollableArea* scrollableArea = outer->getScrollableAreaIfScrollable(); LayoutRect innerRect = inner->isAccessibilityScrollView() ? inner->parentObject()->elementRect() : inner->elementRect(); LayoutRect objectRect = innerRect; IntPoint scrollPosition = scrollableArea->scrollPosition(); // Convert the object rect into local coordinates. objectRect.move(offsetX, offsetY); if (!outer->isAccessibilityScrollView()) objectRect.move(scrollPosition.x(), scrollPosition.y()); int desiredX = computeBestScrollOffset( 0, objectRect.x(), objectRect.maxX(), objectRect.x(), objectRect.maxX(), point.x(), point.x()); int desiredY = computeBestScrollOffset( 0, objectRect.y(), objectRect.maxY(), objectRect.y(), objectRect.maxY(), point.y(), point.y()); outer->scrollTo(IntPoint(desiredX, desiredY)); if (outer->isAccessibilityScrollView() && !inner->isAccessibilityScrollView()) { // If outer object we just scrolled is a scroll view (main window or iframe) but the // inner object is not, keep track of the coordinate transformation to apply to // future nested calculations. scrollPosition = scrollableArea->scrollPosition(); offsetX -= (scrollPosition.x() + point.x()); offsetY -= (scrollPosition.y() + point.y()); point.move(scrollPosition.x() - innerRect.x(), scrollPosition.y() - innerRect.y()); } else if (inner->isAccessibilityScrollView()) { // Otherwise, if the inner object is a scroll view, reset the coordinate transformation. offsetX = 0; offsetY = 0; } } }
AffineTransform RenderSVGRoot::localToRepaintContainerTransform(const IntPoint& parentOriginInContainer) const { AffineTransform parentToContainer(localToParentTransform()); return parentToContainer.translateRight(parentOriginInContainer.x(), parentOriginInContainer.y()); }
void ScrollableAreaPainter::paintOverflowControls( GraphicsContext& context, const IntPoint& paintOffset, const CullRect& cullRect, bool paintingOverlayControls) { // Don't do anything if we have no overflow. if (!getScrollableArea().box().hasOverflowClip()) return; IntPoint adjustedPaintOffset = paintOffset; if (paintingOverlayControls) adjustedPaintOffset = getScrollableArea().cachedOverlayScrollbarOffset(); CullRect adjustedCullRect(cullRect, -adjustedPaintOffset); // Overlay scrollbars paint in a second pass through the layer tree so that // they will paint on top of everything else. If this is the normal painting // pass, paintingOverlayControls will be false, and we should just tell the // root layer that there are overlay scrollbars that need to be painted. That // will cause the second pass through the layer tree to run, and we'll paint // the scrollbars then. In the meantime, cache tx and ty so that the second // pass doesn't need to re-enter the LayoutTree to get it right. if (getScrollableArea().hasOverlayScrollbars() && !paintingOverlayControls) { getScrollableArea().setCachedOverlayScrollbarOffset(paintOffset); // It's not necessary to do the second pass if the scrollbars paint into // layers. if ((getScrollableArea().horizontalScrollbar() && getScrollableArea().layerForHorizontalScrollbar()) || (getScrollableArea().verticalScrollbar() && getScrollableArea().layerForVerticalScrollbar())) return; if (!overflowControlsIntersectRect(adjustedCullRect)) return; LayoutView* layoutView = getScrollableArea().box().view(); PaintLayer* paintingRoot = getScrollableArea().layer()->enclosingLayerWithCompositedLayerMapping( IncludeSelf); if (!paintingRoot) paintingRoot = layoutView->layer(); paintingRoot->setContainsDirtyOverlayScrollbars(true); return; } // This check is required to avoid painting custom CSS scrollbars twice. if (paintingOverlayControls && !getScrollableArea().hasOverlayScrollbars()) return; { Optional<ScopedPaintChunkProperties> scopedTransformProperty; if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { const auto* objectProperties = getScrollableArea().box().paintProperties(); if (objectProperties && objectProperties->scrollbarPaintOffset()) { PaintChunkProperties properties( context.getPaintController().currentPaintChunkProperties()); properties.transform = objectProperties->scrollbarPaintOffset(); scopedTransformProperty.emplace( context.getPaintController(), getScrollableArea().box(), DisplayItem::kScrollOverflowControls, properties); } } if (getScrollableArea().horizontalScrollbar() && !getScrollableArea().layerForHorizontalScrollbar()) { TransformRecorder translateRecorder( context, *getScrollableArea().horizontalScrollbar(), AffineTransform::translation(adjustedPaintOffset.x(), adjustedPaintOffset.y())); getScrollableArea().horizontalScrollbar()->paint(context, adjustedCullRect); } if (getScrollableArea().verticalScrollbar() && !getScrollableArea().layerForVerticalScrollbar()) { TransformRecorder translateRecorder( context, *getScrollableArea().verticalScrollbar(), AffineTransform::translation(adjustedPaintOffset.x(), adjustedPaintOffset.y())); getScrollableArea().verticalScrollbar()->paint(context, adjustedCullRect); } } if (getScrollableArea().layerForScrollCorner()) return; // We fill our scroll corner with white if we have a scrollbar that doesn't // run all the way up to the edge of the box. paintScrollCorner(context, adjustedPaintOffset, cullRect); // Paint our resizer last, since it sits on top of the scroll corner. paintResizer(context, adjustedPaintOffset, cullRect); }
static GRefPtr<GdkCursor> createCustomCursor(Image* image, const IntPoint& hotSpot) { IntPoint effectiveHotSpot = determineHotSpot(image, hotSpot); GRefPtr<GdkPixbuf> pixbuf = adoptGRef(image->getGdkPixbuf()); return adoptGRef(gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pixbuf.get(), effectiveHotSpot.x(), effectiveHotSpot.y())); }
int WebPopupMenuProxyWin::listIndexAtPoint(const IntPoint& point) const { return m_scrollOffset + point.y() / m_itemHeight; }
bool ScrollbarTheme::shouldSnapBackToDragOrigin(const ScrollbarThemeClient* scrollbar, const PlatformMouseEvent& evt) { IntPoint mousePosition = scrollbar->convertFromContainingWindow(evt.position()); mousePosition.move(scrollbar->x(), scrollbar->y()); return Platform::current()->scrollbarBehavior()->shouldSnapBackToDragOrigin(mousePosition, trackRect(scrollbar), scrollbar->orientation() == HorizontalScrollbar); }
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; } RefPtr<HTMLInputElement> input(static_cast<HTMLInputElement*>(shadowHost())); if (input->disabled() || input->readOnly()) { 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->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. RefPtr<Node> protector(this); input->focus(); input->select(); if (renderer()) { if (m_upDownState != Indeterminate) { doStepAction(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->pixelSnappedBorderBoxRect().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(); m_upDownState = Indeterminate; } } if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); }
void InlineBox::paint(PaintInfo& paintInfo, int tx, int ty, int /* lineTop */, int /*lineBottom*/) { if (!paintInfo.shouldPaintWithinRoot(renderer()) || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection)) return; IntPoint childPoint = IntPoint(tx, ty); if (parent()->renderer()->style()->isFlippedBlocksWritingMode()) // Faster than calling containingBlock(). childPoint = renderer()->containingBlock()->flipForWritingMode(toRenderBox(renderer()), childPoint, RenderBox::ParentToChildFlippingAdjustment); // Paint all phases of replaced elements atomically, as though the replaced element established its // own stacking context. (See Appendix E.2, section 6.4 on inline block/table elements in the CSS2.1 // specification.) bool preservePhase = paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip; PaintInfo info(paintInfo); info.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground; renderer()->paint(info, childPoint.x(), childPoint.y()); if (!preservePhase) { info.phase = PaintPhaseChildBlockBackgrounds; renderer()->paint(info, childPoint.x(), childPoint.y()); info.phase = PaintPhaseFloat; renderer()->paint(info, childPoint.x(), childPoint.y()); info.phase = PaintPhaseForeground; renderer()->paint(info, childPoint.x(), childPoint.y()); info.phase = PaintPhaseOutline; renderer()->paint(info, childPoint.x(), childPoint.y()); } }
bool RenderFrameSet::canResizeColumn(const IntPoint& p) const { int c = hitTestSplit(m_cols, p.x()); return c != noSplit && !m_cols.m_preventResize[c]; }
void WebPopupMenuProxyWin::setScrollOffset(const IntPoint& offset) { scrollTo(offset.y()); }