зеркало из https://github.com/mozilla/pjs.git
b=333177, update canvas internal interfaces, optimize canvas, and fix some implementation bugs; r=stuart
This commit is contained in:
Родитель
4ffeb9e81d
Коммит
224933de70
|
@ -40,32 +40,40 @@
|
|||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "imgIContainer.h"
|
||||
|
||||
// {8fd94ec9-d4e0-409b-af8f-828c7d7648f5}
|
||||
// {C234660C-BD06-493e-8583-939A5A158B37}
|
||||
#define NS_ICANVASELEMENT_IID \
|
||||
{ 0x8fd94ec9, 0xd4e0, 0x409b, { 0xaf, 0x8f, 0x82, 0x8c, 0x7d, 0x76, 0x48, 0xf5 } }
|
||||
{ 0xc234660c, 0xbd06, 0x493e, { 0x85, 0x83, 0x93, 0x9a, 0x5a, 0x15, 0x8b, 0x37 } }
|
||||
|
||||
class nsIRenderingContext;
|
||||
|
||||
struct _cairo_surface;
|
||||
|
||||
class nsICanvasElement : public nsISupports {
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICANVASELEMENT_IID)
|
||||
|
||||
/**
|
||||
* Ask the Canvas Element to return the current image container that
|
||||
* the frame should render.
|
||||
*/
|
||||
NS_IMETHOD GetCanvasImageContainer (imgIContainer **aImageContainer) = 0;
|
||||
|
||||
/**
|
||||
* Ask the canvas Element to return the primary frame, if any
|
||||
*/
|
||||
NS_IMETHOD GetPrimaryCanvasFrame (nsIFrame **aFrame) = 0;
|
||||
|
||||
/**
|
||||
* Ask the canvas element to notify the rendering context to update
|
||||
* the image frame, in preparation for rendering
|
||||
* Get the size in pixels of this canvas element
|
||||
*/
|
||||
NS_IMETHOD UpdateImageFrame () = 0;
|
||||
NS_IMETHOD GetSize (PRUint32 *width, PRUint32 *height) = 0;
|
||||
|
||||
/*
|
||||
* Ask the canvas element to tell the contexts to render themselves
|
||||
* into the given nsIRenderingContext at the origin.
|
||||
*/
|
||||
NS_IMETHOD RenderContexts (nsIRenderingContext *rc) = 0;
|
||||
|
||||
/*
|
||||
* Ask the canvas element to tell the contexts to render themselves
|
||||
* into to given cairo_surface_t.
|
||||
*/
|
||||
NS_IMETHOD RenderContextsToSurface (struct _cairo_surface *surf) = 0;
|
||||
|
||||
/**
|
||||
* Determine whether the canvas is write-only.
|
||||
|
|
|
@ -39,14 +39,16 @@
|
|||
#define nsICanvasRenderingContextInternal_h___
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "gfxIImageFrame.h"
|
||||
#include "nsICanvasElement.h"
|
||||
#include "nsIInputStream.h"
|
||||
|
||||
// {0be74436-51a3-4be3-8357-ede741750080}
|
||||
// {05150761-22A3-4e8d-A03E-EC53CB731C70}
|
||||
#define NS_ICANVASRENDERINGCONTEXTINTERNAL_IID \
|
||||
{ 0x0be74436, 0x51a3, 0x4be3, { 0x83, 0x57, 0xed, 0xe7, 0x41, 0x75, 0x00, 0x80 } }
|
||||
{ 0x5150761, 0x22a3, 0x4e8d, { 0xa0, 0x3e, 0xec, 0x53, 0xcb, 0x73, 0x1c, 0x70 } }
|
||||
|
||||
class nsIRenderingContext;
|
||||
|
||||
struct _cairo_surface;
|
||||
|
||||
class nsICanvasRenderingContextInternal : public nsISupports {
|
||||
public:
|
||||
|
@ -56,8 +58,15 @@ public:
|
|||
// with nsnull when the element is going away.
|
||||
NS_IMETHOD SetCanvasElement(nsICanvasElement* aParentCanvas) = 0;
|
||||
|
||||
// Will be called whenever the target image frame changes
|
||||
NS_IMETHOD SetTargetImageFrame(gfxIImageFrame* aImageFrame) = 0;
|
||||
// Sets the dimensions of the canvas, in pixels. Called
|
||||
// whenever the size of the element changes.
|
||||
NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height) = 0;
|
||||
|
||||
// Render the canvas at the origin of the given nsIRenderingContext
|
||||
NS_IMETHOD Render(nsIRenderingContext *rc) = 0;
|
||||
|
||||
// Render the canvas at the origin of the given cairo surface
|
||||
NS_IMETHOD RenderToSurface(struct _cairo_surface *surf) = 0;
|
||||
|
||||
// Gives you a stream containing the image represented by this context.
|
||||
// The format is given in aMimeTime, for example "image/png".
|
||||
|
@ -68,10 +77,6 @@ public:
|
|||
NS_IMETHOD GetInputStream(const nsACString& aMimeType,
|
||||
const nsAString& aEncoderOptions,
|
||||
nsIInputStream **aStream) = 0;
|
||||
|
||||
// Will be called whenever the element needs to be redrawn,
|
||||
// e.g. due to a Redraw on the frame.
|
||||
NS_IMETHOD UpdateImageFrame() = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasRenderingContextInternal,
|
||||
|
|
|
@ -77,6 +77,10 @@ REQUIRES = \
|
|||
libpixman \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(MOZ_ENABLE_CAIRO_GFX),1)
|
||||
REQUIRES += thebes
|
||||
endif
|
||||
|
||||
# XXX some platforms can't handle building
|
||||
# an empty .a/lib. Remove this dummy.cpp
|
||||
# whenever w have a rendering context
|
||||
|
@ -94,6 +98,6 @@ FORCE_STATIC_LIB = 1
|
|||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
CXXFLAGS += $(MOZ_CAIRO_CFLAGS)
|
||||
CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(TK_CFLAGS)
|
||||
|
||||
DEFINES += -D_IMPL_NS_LAYOUT
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -50,9 +50,7 @@
|
|||
#include "prmem.h"
|
||||
|
||||
#include "nsICanvasElement.h"
|
||||
|
||||
#include "gfxIImageFrame.h"
|
||||
#include "imgIContainer.h"
|
||||
#include "nsIRenderingContext.h"
|
||||
|
||||
#include "nsICanvasRenderingContextInternal.h"
|
||||
|
||||
|
@ -83,9 +81,10 @@ public:
|
|||
NS_DECL_NSIDOMHTMLCANVASELEMENT
|
||||
|
||||
// nsICanvasElement
|
||||
NS_IMETHOD GetCanvasImageContainer(imgIContainer **aImageContainer);
|
||||
NS_IMETHOD GetPrimaryCanvasFrame(nsIFrame **aFrame);
|
||||
NS_IMETHOD UpdateImageFrame();
|
||||
NS_IMETHOD GetSize(PRUint32 *width, PRUint32 *height);
|
||||
NS_IMETHOD RenderContexts(nsIRenderingContext *ctx);
|
||||
NS_IMETHOD RenderContextsToSurface(struct _cairo_surface *surf);
|
||||
virtual PRBool IsWriteOnly();
|
||||
virtual void SetWriteOnly();
|
||||
|
||||
|
@ -109,14 +108,10 @@ public:
|
|||
PRBool aNotify);
|
||||
protected:
|
||||
nsIntSize GetWidthHeight();
|
||||
nsresult UpdateImageContainer(PRBool forceCreate);
|
||||
nsresult UpdateContext();
|
||||
|
||||
nsString mCurrentContextId;
|
||||
nsCOMPtr<nsICanvasRenderingContextInternal> mCurrentContext;
|
||||
|
||||
nsCOMPtr<imgIContainer> mImageContainer;
|
||||
nsCOMPtr<gfxIImageFrame> mImageFrame;
|
||||
|
||||
public:
|
||||
// Record whether this canvas should be write-only or not.
|
||||
|
@ -196,7 +191,7 @@ nsHTMLCanvasElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||
if (NS_SUCCEEDED(rv) && mCurrentContext &&
|
||||
(aName == nsHTMLAtoms::width || aName == nsHTMLAtoms::height))
|
||||
{
|
||||
rv = UpdateImageContainer(PR_FALSE);
|
||||
rv = UpdateContext();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -400,7 +395,7 @@ nsHTMLCanvasElement::GetContext(const nsAString& aContextId,
|
|||
rv = mCurrentContext->SetCanvasElement(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = UpdateImageContainer(PR_TRUE);
|
||||
rv = UpdateContext();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mCurrentContextId.Assign(aContextId);
|
||||
|
@ -413,84 +408,53 @@ nsHTMLCanvasElement::GetContext(const nsAString& aContextId,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLCanvasElement::UpdateImageContainer(PRBool forceCreate)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// don't create if we don't already have one,
|
||||
// and no frame or context has asked for one.
|
||||
if (!forceCreate && !mImageFrame)
|
||||
return NS_OK;
|
||||
|
||||
nsIntSize sz = GetWidthHeight();
|
||||
PRInt32 w = 0, h = 0;
|
||||
|
||||
if (mImageFrame) {
|
||||
mImageFrame->GetWidth(&w);
|
||||
mImageFrame->GetHeight(&h);
|
||||
}
|
||||
|
||||
if (sz.width != w || sz.height != h) {
|
||||
mImageContainer = do_CreateInstance("@mozilla.org/image/container;1");
|
||||
mImageContainer->Init(sz.width, sz.height, nsnull);
|
||||
|
||||
mImageFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
|
||||
if (!mImageFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
#if defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS) || defined(MOZ_WIDGET_PHOTON)
|
||||
rv = mImageFrame->Init(0, 0, sz.width, sz.height, gfxIFormats::BGR_A8, 24);
|
||||
#else
|
||||
rv = mImageFrame->Init(0, 0, sz.width, sz.height, gfxIFormats::RGB_A8, 24);
|
||||
#endif
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mImageContainer->AppendFrame(mImageFrame);
|
||||
}
|
||||
|
||||
return UpdateContext();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLCanvasElement::UpdateContext()
|
||||
{
|
||||
if (mCurrentContext)
|
||||
return mCurrentContext->SetTargetImageFrame(mImageFrame);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLCanvasElement::GetCanvasImageContainer(imgIContainer **aImageContainer)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (!mImageContainer) {
|
||||
rv = UpdateImageContainer(PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsresult rv = NS_OK;
|
||||
if (mCurrentContext) {
|
||||
nsIntSize sz = GetWidthHeight();
|
||||
rv = mCurrentContext->SetDimensions(sz.width, sz.height);
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(*aImageContainer = mImageContainer);
|
||||
return NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLCanvasElement::GetPrimaryCanvasFrame(nsIFrame **aFrame)
|
||||
{
|
||||
*aFrame = GetPrimaryFrame(PR_FALSE);
|
||||
*aFrame = GetPrimaryFrame(PR_TRUE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLCanvasElement::UpdateImageFrame()
|
||||
nsHTMLCanvasElement::GetSize(PRUint32 *width, PRUint32 *height)
|
||||
{
|
||||
if (mCurrentContext)
|
||||
return mCurrentContext->UpdateImageFrame();
|
||||
nsIntSize sz = GetWidthHeight();
|
||||
*width = sz.width;
|
||||
*height = sz.height;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLCanvasElement::RenderContexts(nsIRenderingContext *rc)
|
||||
{
|
||||
if (!mCurrentContext)
|
||||
return NS_OK;
|
||||
|
||||
return mCurrentContext->Render(rc);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLCanvasElement::RenderContextsToSurface(struct _cairo_surface *surf)
|
||||
{
|
||||
if (!mCurrentContext)
|
||||
return NS_OK;
|
||||
|
||||
return mCurrentContext->RenderToSurface(surf);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsHTMLCanvasElement::IsWriteOnly()
|
||||
{
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "nsIVariant.idl"
|
||||
|
||||
interface nsIDOMWindow;
|
||||
interface nsIDOMHTMLElement;
|
||||
interface nsIDOMHTMLImageElement;
|
||||
interface nsIDOMHTMLCanvasElement;
|
||||
|
||||
|
@ -53,7 +54,7 @@ interface nsIDOMCanvasPattern : nsISupports
|
|||
{
|
||||
};
|
||||
|
||||
[scriptable, uuid(15487cf4-292b-49aa-bc36-17d9099f77a7)]
|
||||
[scriptable, uuid(ab27f42d-e1e1-4ef6-9c83-059a81da479b)]
|
||||
interface nsIDOMCanvasRenderingContext2D : nsISupports
|
||||
{
|
||||
// back-reference to the canvas element for which
|
||||
|
@ -79,8 +80,8 @@ interface nsIDOMCanvasRenderingContext2D : nsISupports
|
|||
|
||||
nsIDOMCanvasGradient createLinearGradient (in float x0, in float y0, in float x1, in float y1);
|
||||
nsIDOMCanvasGradient createRadialGradient(in float x0, in float y0, in float r0, in float x1, in float y1, in float r1);
|
||||
nsIDOMCanvasPattern createPattern(in nsIDOMHTMLImageElement image, in DOMString repetition);
|
||||
|
||||
//nsIDOMCanvasPattern createPattern(in nsIDOMHTMLImageElement image, in DOMString repetition);
|
||||
nsIDOMCanvasPattern createPattern(in nsIDOMHTMLElement image, in DOMString repetition);
|
||||
attribute float lineWidth; /* default 1 */
|
||||
attribute DOMString lineCap; /* "butt", "round", "square" (default) */
|
||||
attribute DOMString lineJoin; /* "round", "bevel", "miter" (default) */
|
||||
|
|
|
@ -47,6 +47,8 @@
|
|||
#include "nsICanvasElement.h"
|
||||
#include "nsDisplayList.h"
|
||||
|
||||
#include "nsTransform2D.h"
|
||||
|
||||
nsIFrame*
|
||||
NS_NewHTMLCanvasFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
||||
{
|
||||
|
@ -84,20 +86,13 @@ nsHTMLCanvasFrame::Reflow(nsPresContext* aPresContext,
|
|||
nsCOMPtr<nsICanvasElement> canvas(do_QueryInterface(GetContent()));
|
||||
NS_ENSURE_TRUE(canvas, NS_ERROR_FAILURE);
|
||||
|
||||
nsresult rv = canvas->GetCanvasImageContainer(getter_AddRefs(mImageContainer));
|
||||
PRUint32 w, h;
|
||||
nsresult rv = canvas->GetSize (&w, &h);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
float p2t = GetPresContext()->PixelsToTwips();
|
||||
|
||||
if (mImageContainer) {
|
||||
PRInt32 w, h;
|
||||
mImageContainer->GetWidth(&w);
|
||||
mImageContainer->GetHeight(&h);
|
||||
|
||||
mCanvasSize.SizeTo(NSIntPixelsToTwips(w, p2t), NSIntPixelsToTwips(h, p2t));
|
||||
} else {
|
||||
mCanvasSize.SizeTo(0, 0);
|
||||
}
|
||||
mCanvasSize.SizeTo(NSIntPixelsToTwips(w, p2t), NSIntPixelsToTwips(h, p2t));
|
||||
|
||||
if (aReflowState.mComputedWidth == NS_INTRINSICSIZE)
|
||||
aMetrics.width = mCanvasSize.width;
|
||||
|
@ -167,10 +162,39 @@ nsHTMLCanvasFrame::PaintCanvas(nsIRenderingContext& aRenderingContext,
|
|||
const nsRect& aDirtyRect, nsPoint aPt)
|
||||
{
|
||||
nsRect inner = GetInnerArea() + aPt;
|
||||
nsRect src(0, 0, mCanvasSize.width, mCanvasSize.height);
|
||||
|
||||
// XXX this should just draw the dirty area
|
||||
aRenderingContext.DrawImage(mImageContainer, src, inner);
|
||||
nsCOMPtr<nsICanvasElement> canvas(do_QueryInterface(GetContent()));
|
||||
if (!canvas)
|
||||
return;
|
||||
|
||||
float t2p = GetPresContext()->TwipsToPixels();
|
||||
float p2t = GetPresContext()->PixelsToTwips();
|
||||
|
||||
// XXXvlad clip to aDirtyRect!
|
||||
|
||||
if (inner.width != mCanvasSize.width ||
|
||||
inner.height != mCanvasSize.height)
|
||||
{
|
||||
float sx = inner.width / (float) mCanvasSize.width;
|
||||
float sy = inner.height / (float) mCanvasSize.height;
|
||||
|
||||
aRenderingContext.PushState();
|
||||
aRenderingContext.Translate(inner.x, inner.y);
|
||||
aRenderingContext.Scale(sx, sy);
|
||||
|
||||
canvas->RenderContexts(&aRenderingContext);
|
||||
|
||||
aRenderingContext.PopState();
|
||||
} else {
|
||||
//nsIRenderingContext::AutoPushTranslation(&aRenderingContext, px, py);
|
||||
|
||||
aRenderingContext.PushState();
|
||||
aRenderingContext.Translate(inner.x, inner.y);
|
||||
|
||||
canvas->RenderContexts(&aRenderingContext);
|
||||
|
||||
aRenderingContext.PopState();
|
||||
}
|
||||
}
|
||||
|
||||
static void PaintCanvas(nsIFrame* aFrame, nsIRenderingContext* aCtx,
|
||||
|
@ -187,27 +211,12 @@ nsHTMLCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
if (!IsVisibleForPainting(aBuilder))
|
||||
return NS_OK;
|
||||
|
||||
// REVIEW: We don't need any special logic here for deciding which layer
|
||||
// to put the background in ... it goes in aLists.BorderBackground() and
|
||||
// then if we have a block parent, it will put our background in the right
|
||||
// place.
|
||||
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// REVIEW: Checking mRect.IsEmpty() makes no sense to me, so I removed it.
|
||||
// It can't have been protecting us against bad situations with zero-size
|
||||
// images since adding a border would make the rect non-empty.
|
||||
|
||||
// make sure that the rendering context has updated the
|
||||
// image frame
|
||||
nsCOMPtr<nsICanvasElement> canvas(do_QueryInterface(GetContent()));
|
||||
NS_ENSURE_TRUE(canvas, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_SUCCESS(canvas->UpdateImageFrame(), NS_ERROR_FAILURE);
|
||||
|
||||
if (mImageContainer) {
|
||||
rv = aLists.Content()->AppendNewToTop(new (aBuilder)
|
||||
nsDisplayGeneric(this, ::PaintCanvas, "Canvas"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
rv = aLists.Content()->AppendNewToTop(new (aBuilder)
|
||||
nsDisplayGeneric(this, ::PaintCanvas, "Canvas"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return DisplaySelectionOverlay(aBuilder, aLists,
|
||||
nsISelectionDisplay::DISPLAY_IMAGES);
|
||||
|
|
|
@ -46,9 +46,6 @@
|
|||
#include "nsPresContext.h"
|
||||
#include "nsIIOService.h"
|
||||
|
||||
#include "gfxIImageFrame.h"
|
||||
#include "imgIContainer.h"
|
||||
|
||||
nsIFrame* NS_NewHTMLCanvasFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
|
||||
|
||||
class nsHTMLCanvasFrame : public nsSplittableFrame
|
||||
|
@ -92,8 +89,6 @@ protected:
|
|||
|
||||
nscoord GetContinuationOffset(nscoord* aWidth = 0) const;
|
||||
|
||||
nsCOMPtr<imgIContainer> mImageContainer;
|
||||
|
||||
nsMargin mBorderPadding;
|
||||
nsSize mCanvasSize;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче