Bug 962786 - Convert nsDragService to use Moz2D. r=roc

This commit is contained in:
Matt Woodrow 2014-01-29 13:10:33 +13:00
parent c1c1d9edfb
commit 0d06c40a64
11 changed files with 141 additions and 117 deletions

View File

@ -103,9 +103,13 @@ class Touch;
class ShadowRoot;
} // namespace dom
namespace layers{
namespace layers {
class LayerManager;
} // namespace layers
namespace gfx {
class SourceSurface;
} // namespace gfx
} // namespace mozilla
// Flags to pass to SetCapturingContent
@ -128,11 +132,10 @@ typedef struct CapturingContentInfo {
nsIContent* mContent;
} CapturingContentInfo;
// db8d5e1e-6392-4ec1-9a29-18ee2ec0889b
//bccc1c01-5123-4f49-9572-c0bf506b6418
#define NS_IPRESSHELL_IID \
{ 0xdb8d5e1e, 0x6392, 0x4ec1, \
{0x9a, 0x29, 0x18, 0xee, 0x2e, 0xc0, 0x88, 0x9b}}
{ 0xbccc1c01, 0x5123, 0x4f49, \
{0x95, 0x72, 0xc0, 0xbf, 0x50, 0x6b, 0x64, 0x18}}
// debug VerifyReflow flags
#define VERIFY_REFLOW_ON 0x01
@ -178,6 +181,7 @@ class nsIPresShell : public nsIPresShell_base
{
protected:
typedef mozilla::layers::LayerManager LayerManager;
typedef mozilla::gfx::SourceSurface SourceSurface;
enum eRenderFlag {
STATE_IGNORING_VIEWPORT_SCROLLING = 0x1,
@ -1031,10 +1035,11 @@ public:
* edge of the presshell area. The aPoint, aScreenRect and aSurface
* arguments function in a similar manner as RenderSelection.
*/
virtual already_AddRefed<gfxASurface> RenderNode(nsIDOMNode* aNode,
nsIntRegion* aRegion,
nsIntPoint& aPoint,
nsIntRect* aScreenRect) = 0;
virtual mozilla::TemporaryRef<SourceSurface>
RenderNode(nsIDOMNode* aNode,
nsIntRegion* aRegion,
nsIntPoint& aPoint,
nsIntRect* aScreenRect) = 0;
/**
* Renders a selection to a surface and returns it. This method is primarily
@ -1051,9 +1056,10 @@ public:
* the original. When scaling does not occur, the mouse point isn't used
* as the position can be determined from the displayed frames.
*/
virtual already_AddRefed<gfxASurface> RenderSelection(nsISelection* aSelection,
nsIntPoint& aPoint,
nsIntRect* aScreenRect) = 0;
virtual mozilla::TemporaryRef<SourceSurface>
RenderSelection(nsISelection* aSelection,
nsIntPoint& aPoint,
nsIntRect* aScreenRect) = 0;
void AddWeakFrameInternal(nsWeakFrame* aWeakFrame);
virtual void AddWeakFrameExternal(nsWeakFrame* aWeakFrame);

View File

@ -165,6 +165,7 @@
#include "nsIDOMHTMLElement.h"
#include "nsIDragSession.h"
#include "nsIFrameInlines.h"
#include "mozilla/gfx/2D.h"
#ifdef ANDROID
#include "nsIDocShellTreeOwner.h"
@ -177,6 +178,7 @@ using namespace mozilla;
using namespace mozilla::css;
using namespace mozilla::dom;
using namespace mozilla::layers;
using namespace mozilla::gfx;
CapturingContentInfo nsIPresShell::gCaptureInfo =
{ false /* mAllowed */, false /* mPointerLock */, false /* mRetargetToElement */,
@ -4809,7 +4811,7 @@ PresShell::CreateRangePaintInfo(nsIDOMRange* aRange,
return info;
}
already_AddRefed<gfxASurface>
TemporaryRef<SourceSurface>
PresShell::PaintRangePaintInfo(nsTArray<nsAutoPtr<RangePaintInfo> >* aItems,
nsISelection* aSelection,
nsIntRegion* aRegion,
@ -4878,8 +4880,14 @@ PresShell::PaintRangePaintInfo(nsTArray<nsAutoPtr<RangePaintInfo> >* aItems,
context.Rectangle(gfxRect(0, 0, pixelArea.width, pixelArea.height));
context.Fill();
RefPtr<DrawTarget> dt =
gfxPlatform::GetPlatform()->
CreateDrawTargetForSurface(surface, gfx::IntSize(pixelArea.width, pixelArea.height));
nsRefPtr<gfxContext> ctx = new gfxContext(dt);
nsRefPtr<nsRenderingContext> rc = new nsRenderingContext();
rc->Init(deviceContext, surface);
rc->Init(deviceContext, ctx);
if (aRegion) {
// Convert aRegion from CSS pixels to dev pixels
@ -4927,10 +4935,10 @@ PresShell::PaintRangePaintInfo(nsTArray<nsAutoPtr<RangePaintInfo> >* aItems,
// restore the old selection display state
frameSelection->SetDisplaySelection(oldDisplaySelection);
return surface.forget();
return dt->Snapshot();
}
already_AddRefed<gfxASurface>
TemporaryRef<SourceSurface>
PresShell::RenderNode(nsIDOMNode* aNode,
nsIntRegion* aRegion,
nsIntPoint& aPoint,
@ -4976,7 +4984,7 @@ PresShell::RenderNode(nsIDOMNode* aNode,
aScreenRect);
}
already_AddRefed<gfxASurface>
TemporaryRef<SourceSurface>
PresShell::RenderSelection(nsISelection* aSelection,
nsIntPoint& aPoint,
nsIntRect* aScreenRect)

View File

@ -162,14 +162,16 @@ public:
nscolor aBackgroundColor,
gfxContext* aThebesContext) MOZ_OVERRIDE;
virtual already_AddRefed<gfxASurface> RenderNode(nsIDOMNode* aNode,
nsIntRegion* aRegion,
nsIntPoint& aPoint,
nsIntRect* aScreenRect) MOZ_OVERRIDE;
virtual mozilla::TemporaryRef<SourceSurface>
RenderNode(nsIDOMNode* aNode,
nsIntRegion* aRegion,
nsIntPoint& aPoint,
nsIntRect* aScreenRect) MOZ_OVERRIDE;
virtual already_AddRefed<gfxASurface> RenderSelection(nsISelection* aSelection,
nsIntPoint& aPoint,
nsIntRect* aScreenRect) MOZ_OVERRIDE;
virtual mozilla::TemporaryRef<SourceSurface>
RenderSelection(nsISelection* aSelection,
nsIntPoint& aPoint,
nsIntRect* aScreenRect) MOZ_OVERRIDE;
virtual already_AddRefed<nsPIDOMWindow> GetRootWindow() MOZ_OVERRIDE;
@ -502,7 +504,7 @@ protected:
* aScreenRect - [out] set to the area of the screen the painted area should
* be displayed at
*/
already_AddRefed<gfxASurface>
mozilla::TemporaryRef<SourceSurface>
PaintRangePaintInfo(nsTArray<nsAutoPtr<RangePaintInfo> >* aItems,
nsISelection* aSelection,
nsIntRegion* aRegion,

View File

@ -30,6 +30,11 @@
#include "gfxASurface.h"
#include "gfxContext.h"
#include "nsCocoaUtils.h"
#include "mozilla/gfx/2D.h"
#include "gfxPlatform.h"
using namespace mozilla;
using namespace mozilla::gfx;
#ifdef PR_LOGGING
extern PRLogModuleInfo* sCocoaLog;
@ -141,12 +146,12 @@ nsDragService::ConstructDragImage(nsIDOMNode* aDOMNode,
CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(gLastDragView);
nsRefPtr<gfxASurface> surface;
RefPtr<SourceSurface> surface;
nsPresContext* pc;
nsresult rv = DrawDrag(aDOMNode, aRegion,
NSToIntRound(screenPoint.x),
NSToIntRound(screenPoint.y),
aDragRect, getter_AddRefs(surface), &pc);
aDragRect, &surface, &pc);
if (!aDragRect->width || !aDragRect->height) {
// just use some suitable defaults
int32_t size = nsCocoaUtils::CocoaPointsToDevPixels(20, scaleFactor);
@ -166,13 +171,15 @@ nsDragService::ConstructDragImage(nsIDOMNode* aDOMNode,
if (!imgSurface)
return nil;
nsRefPtr<gfxContext> context = new gfxContext(imgSurface);
if (!context)
RefPtr<DrawTarget> dt =
gfxPlatform::GetPlatform()->
CreateDrawTargetForSurface(imgSurface, IntSize(width, height));
if (!dt)
return nil;
context->SetOperator(gfxContext::OPERATOR_SOURCE);
context->SetSource(surface);
context->Paint();
dt->FillRect(gfx::Rect(0, 0, width, height),
SurfacePattern(surface, ExtendMode::CLAMP),
DrawOptions(1.0f, CompositionOp::OP_SOURCE));
uint32_t* imageData = (uint32_t*)imgSurface->Data();
int32_t stride = imgSurface->Stride();

View File

@ -36,6 +36,11 @@
#include "nsViewManager.h"
#include "nsIFrame.h"
#include "nsGtkUtils.h"
#include "mozilla/gfx/2D.h"
#include "gfxPlatform.h"
using namespace mozilla;
using namespace mozilla::gfx;
// This sets how opaque the drag image is
#define DRAG_IMAGE_ALPHA_LEVEL 0.5
@ -390,11 +395,11 @@ nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode,
}
bool
nsDragService::SetAlphaPixmap(gfxASurface *aSurface,
GdkDragContext *aContext,
int32_t aXOffset,
int32_t aYOffset,
const nsIntRect& dragRect)
nsDragService::SetAlphaPixmap(SourceSurface *aSurface,
GdkDragContext *aContext,
int32_t aXOffset,
int32_t aYOffset,
const nsIntRect& dragRect)
{
#if (MOZ_WIDGET_GTK == 2)
GdkScreen* screen = gtk_widget_get_screen(mHiddenWidget);
@ -422,16 +427,21 @@ nsDragService::SetAlphaPixmap(gfxASurface *aSurface,
if (!xPixmapSurface)
return false;
nsRefPtr<gfxContext> xPixmapCtx = new gfxContext(xPixmapSurface);
RefPtr<DrawTarget> dt =
gfxPlatform::GetPlatform()->
CreateDrawTargetForSurface(xPixmapSurface, IntSize(dragRect.width, dragRect.height));
if (!dt)
return false;
// Clear it...
xPixmapCtx->SetOperator(gfxContext::OPERATOR_CLEAR);
xPixmapCtx->Paint();
dt->ClearRect(Rect(0, 0, dragRect.width, dragRect.height));
// ...and paint the drag image with translucency
xPixmapCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
xPixmapCtx->SetSource(aSurface);
xPixmapCtx->Paint(DRAG_IMAGE_ALPHA_LEVEL);
dt->DrawSurface(aSurface,
Rect(0, 0, dragRect.width, dragRect.height),
Rect(0, 0, dragRect.width, dragRect.height),
DrawSurfaceOptions(),
DrawOptions(DRAG_IMAGE_ALPHA_LEVEL, CompositionOp::OP_SOURCE));
// The drag transaction addrefs the pixmap, so we can just unref it from us here
gtk_drag_set_icon_pixmap(aContext, alphaColormap, pixmap, nullptr,
@ -1565,9 +1575,9 @@ void nsDragService::SetDragIcon(GdkDragContext* aContext)
nsIntRect dragRect;
nsPresContext* pc;
nsRefPtr<gfxASurface> surface;
RefPtr<SourceSurface> surface;
DrawDrag(mSourceNode, mSourceRegion, mScreenX, mScreenY,
&dragRect, getter_AddRefs(surface), &pc);
&dragRect, &surface, &pc);
if (!pc)
return;
@ -1597,7 +1607,7 @@ void nsDragService::SetDragIcon(GdkDragContext* aContext)
else if (surface) {
if (!SetAlphaPixmap(surface, aContext, offsetX, offsetY, dragRect)) {
GdkPixbuf* dragPixbuf =
nsImageToPixbuf::SurfaceToPixbuf(surface, dragRect.width, dragRect.height);
nsImageToPixbuf::SourceSurfaceToPixbuf(surface, dragRect.width, dragrect.height);
if (dragPixbuf) {
gtk_drag_set_icon_pixbuf(aContext, dragPixbuf, offsetX, offsetY);
g_object_unref(dragPixbuf);

View File

@ -14,6 +14,12 @@
class nsWindow;
namespace mozilla {
namespace gfx {
class SourceSurface;
}
}
#ifndef HAVE_NSGOBJECTREFTRAITS
#define HAVE_NSGOBJECTREFTRAITS
template <class T>
@ -183,11 +189,11 @@ private:
// attempts to create a semi-transparent drag image. Returns TRUE if
// successful, FALSE if not
bool SetAlphaPixmap(gfxASurface *aPixbuf,
GdkDragContext *aContext,
int32_t aXOffset,
int32_t aYOffset,
const nsIntRect &dragRect);
bool SetAlphaPixmap(SourceSurface *aPixbuf,
GdkDragContext *aContext,
int32_t aXOffset,
int32_t aYOffset,
const nsIntRect &dragRect);
gboolean Schedule(DragTask aTask, nsWindow *aWindow,
GdkDragContext *aDragContext,

View File

@ -129,37 +129,3 @@ nsImageToPixbuf::SourceSurfaceToPixbuf(SourceSurface* aSurface,
return pixbuf;
}
GdkPixbuf*
nsImageToPixbuf::SurfaceToPixbuf(gfxASurface* aSurface, int32_t aWidth, int32_t aHeight)
{
if (aSurface->CairoStatus()) {
NS_ERROR("invalid surface");
return nullptr;
}
nsRefPtr<gfxImageSurface> imgSurface;
if (aSurface->GetType() == gfxSurfaceType::Image) {
imgSurface = static_cast<gfxImageSurface*>
(static_cast<gfxASurface*>(aSurface));
} else {
imgSurface = new gfxImageSurface(gfxIntSize(aWidth, aHeight),
gfxImageFormat::ARGB32);
if (!imgSurface)
return nullptr;
nsRefPtr<gfxContext> context = new gfxContext(imgSurface);
if (!context)
return nullptr;
context->SetOperator(gfxContext::OPERATOR_SOURCE);
context->SetSource(aSurface);
context->Paint();
}
RefPtr<SourceSurface> surface =
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr,
imgSurface);
return SourceSurfaceToPixbuf(surface, aWidth, aHeight);
}

View File

@ -33,8 +33,6 @@ class nsImageToPixbuf MOZ_FINAL : public nsIImageToPixbuf {
* released as needed by the caller using g_object_unref.
*/
static GdkPixbuf* ImageToPixbuf(imgIContainer * aImage);
static GdkPixbuf* SurfaceToPixbuf(gfxASurface* aSurface,
int32_t aWidth, int32_t aHeight);
static GdkPixbuf* SourceSurfaceToPixbuf(SourceSurface* aSurface,
int32_t aWidth,
int32_t aHeight);

View File

@ -40,6 +40,10 @@
#include "nsRect.h"
#include "nsMathUtils.h"
#include "gfxWindowsPlatform.h"
#include "mozilla/gfx/2D.h"
using namespace mozilla;
using namespace mozilla::gfx;
//-------------------------------------------------------------------------
//
@ -75,11 +79,11 @@ nsDragService::CreateDragImage(nsIDOMNode *aDOMNode,
// Prepare the drag image
nsIntRect dragRect;
nsRefPtr<gfxASurface> surface;
RefPtr<SourceSurface> surface;
nsPresContext* pc;
DrawDrag(aDOMNode, aRegion,
mScreenX, mScreenY,
&dragRect, getter_AddRefs(surface), &pc);
&dragRect, &surface, &pc);
if (!surface)
return false;
@ -90,19 +94,27 @@ nsDragService::CreateDragImage(nsIDOMNode *aDOMNode,
psdi->crColorKey = CLR_NONE;
RefPtr<DataSourceSurface> data = surface->GetDataSurface();
DataSourceSurface::MappedSurface map;
if (!data->Map(DataSourceSurface::READ, &map)) {
return false;
}
nsRefPtr<gfxImageSurface> imgSurface = new gfxImageSurface(
gfxIntSize(bmWidth, bmHeight),
gfxImageFormat::ARGB32);
if (!imgSurface)
return false;
nsRefPtr<gfxContext> context = new gfxContext(imgSurface);
if (!context)
RefPtr<DrawTarget> dt =
gfxPlatform::GetPlatform()->
CreateDrawTargetForSurface(imgSurface, IntSize(bmWidth, bmHeight));
if (!dt)
return false;
context->SetOperator(gfxContext::OPERATOR_SOURCE);
context->SetSource(surface);
context->Paint();
dt->FillRect(Rect(0, 0, bmWidth, bmHeight),
SurfacePattern(surface, ExtendMode::CLAMP),
DrawOptions(1.0f, CompositionOp::OP_SOURCE));
BITMAPV5HEADER bmih;
memset((void*)&bmih, 0, sizeof(BITMAPV5HEADER));
@ -144,6 +156,8 @@ nsDragService::CreateDragImage(nsIDOMNode *aDOMNode,
DeleteDC(hdcSrc);
}
data->Unmap();
return psdi->hbmpDragImage != nullptr;
}

View File

@ -34,12 +34,14 @@
#include "nsMenuPopupFrame.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/Preferences.h"
#include "mozilla/gfx/2D.h"
#include "gfxContext.h"
#include "gfxPlatform.h"
#include <algorithm>
using namespace mozilla;
using namespace mozilla::gfx;
#define DRAGIMAGES_PREF "nglayout.enable_drag_images"
@ -426,7 +428,7 @@ nsBaseDragService::DrawDrag(nsIDOMNode* aDOMNode,
nsIScriptableRegion* aRegion,
int32_t aScreenX, int32_t aScreenY,
nsIntRect* aScreenDragRect,
gfxASurface** aSurface,
RefPtr<SourceSurface>* aSurface,
nsPresContext** aPresContext)
{
*aSurface = nullptr;
@ -497,9 +499,7 @@ nsBaseDragService::DrawDrag(nsIDOMNode* aDOMNode,
// draw the image for selections
if (mSelection) {
nsIntPoint pnt(aScreenDragRect->x, aScreenDragRect->y);
nsRefPtr<gfxASurface> surface = presShell->RenderSelection(mSelection, pnt, aScreenDragRect);
*aSurface = surface;
NS_IF_ADDREF(*aSurface);
*aSurface = presShell->RenderSelection(mSelection, pnt, aScreenDragRect);
return NS_OK;
}
@ -532,7 +532,6 @@ nsBaseDragService::DrawDrag(nsIDOMNode* aDOMNode,
}
}
nsRefPtr<gfxASurface> surface;
if (!mDragPopup) {
// otherwise, just draw the node
nsIntRegion clipRegion;
@ -541,8 +540,8 @@ nsBaseDragService::DrawDrag(nsIDOMNode* aDOMNode,
}
nsIntPoint pnt(aScreenDragRect->x, aScreenDragRect->y);
surface = presShell->RenderNode(dragNode, aRegion ? &clipRegion : nullptr,
pnt, aScreenDragRect);
*aSurface = presShell->RenderNode(dragNode, aRegion ? &clipRegion : nullptr,
pnt, aScreenDragRect);
}
// if an image was specified, reposition the drag rectangle to
@ -552,9 +551,6 @@ nsBaseDragService::DrawDrag(nsIDOMNode* aDOMNode,
aScreenDragRect->y = sy - mImageY;
}
*aSurface = surface;
NS_IF_ADDREF(*aSurface);
return NS_OK;
}
@ -564,7 +560,7 @@ nsBaseDragService::DrawDragForImage(nsPresContext* aPresContext,
nsICanvasElementExternal* aCanvas,
int32_t aScreenX, int32_t aScreenY,
nsIntRect* aScreenDragRect,
gfxASurface** aSurface)
RefPtr<SourceSurface>* aSurface)
{
nsCOMPtr<imgIContainer> imgContainer;
if (aImageLoader) {
@ -620,19 +616,19 @@ nsBaseDragService::DrawDragForImage(nsPresContext* aPresContext,
aScreenDragRect->height = destSize.height;
}
nsRefPtr<gfxASurface> surface =
gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(destSize.width, destSize.height),
gfxContentType::COLOR_ALPHA);
if (!surface)
RefPtr<DrawTarget> dt =
gfxPlatform::GetPlatform()->
CreateOffscreenContentDrawTarget(IntSize(destSize.width, destSize.height),
SurfaceFormat::B8G8R8A8);
if (!dt)
return NS_ERROR_FAILURE;
nsRefPtr<gfxContext> ctx = new gfxContext(surface);
nsRefPtr<gfxContext> ctx = new gfxContext(dt);
if (!ctx)
return NS_ERROR_FAILURE;
*aSurface = surface;
NS_ADDREF(*aSurface);
nsresult result = NS_OK;
if (aImageLoader) {
gfxRect outRect(0, 0, destSize.width, destSize.height);
gfxMatrix scale =
@ -641,10 +637,12 @@ nsBaseDragService::DrawDragForImage(nsPresContext* aPresContext,
imgContainer->Draw(ctx, GraphicsFilter::FILTER_GOOD, scale, outRect, imgSize,
destSize, nullptr, imgIContainer::FRAME_CURRENT,
imgIContainer::FLAG_SYNC_DECODE);
return NS_OK;
} else {
return aCanvas->RenderContextsExternal(ctx, GraphicsFilter::FILTER_GOOD);
result = aCanvas->RenderContextsExternal(ctx, GraphicsFilter::FILTER_GOOD);
}
*aSurface = dt->Snapshot();
return result;
}
void

View File

@ -13,6 +13,7 @@
#include "nsIDOMDataTransfer.h"
#include "nsCOMPtr.h"
#include "nsPoint.h"
#include "mozilla/RefPtr.h"
#include "gfxImageSurface.h"
@ -26,6 +27,12 @@ class nsPresContext;
class nsIImageLoadingContent;
class nsICanvasElementExternal;
namespace mozilla {
namespace gfx {
class SourceSurface;
}
}
/**
* XP DragService wrapper base class
*/
@ -35,6 +42,8 @@ class nsBaseDragService : public nsIDragService,
{
public:
typedef mozilla::gfx::SourceSurface SourceSurface;
nsBaseDragService();
virtual ~nsBaseDragService();
@ -77,7 +86,7 @@ protected:
nsIScriptableRegion* aRegion,
int32_t aScreenX, int32_t aScreenY,
nsIntRect* aScreenDragRect,
gfxASurface** aSurface,
mozilla::RefPtr<SourceSurface>* aSurface,
nsPresContext **aPresContext);
/**
@ -89,7 +98,7 @@ protected:
nsICanvasElementExternal* aCanvas,
int32_t aScreenX, int32_t aScreenY,
nsIntRect* aScreenDragRect,
gfxASurface** aSurface);
mozilla::RefPtr<SourceSurface>* aSurface);
/**
* Convert aScreenX and aScreenY from CSS pixels into unscaled device pixels.