зеркало из https://github.com/mozilla/pjs.git
adding support for toDataURL and toDataURLAs on canvas. bug 245684. patches from Brett Wilson <brettw@gmail.com>. r=me, sr=vlad
This commit is contained in:
Родитель
a80cc79252
Коммит
3ce096343b
|
@ -42,6 +42,7 @@
|
|||
#include "nsPresContext.h"
|
||||
#include "gfxIImageFrame.h"
|
||||
#include "nsICanvasElement.h"
|
||||
#include "nsIInputStream.h"
|
||||
|
||||
// {0be74436-51a3-4be3-8357-ede741750080}
|
||||
#define NS_ICANVASRENDERINGCONTEXTINTERNAL_IID \
|
||||
|
@ -58,6 +59,16 @@ public:
|
|||
// Will be called whenever the target image frame changes
|
||||
NS_IMETHOD SetTargetImageFrame(gfxIImageFrame* aImageFrame) = 0;
|
||||
|
||||
// Gives you a stream containing the image represented by this context.
|
||||
// The format is given in aMimeTime, for example "image/png".
|
||||
//
|
||||
// If the image format does not support transparency or aIncludeTransparency
|
||||
// is false, alpha will be discarded and the result will be the image
|
||||
// composited on black.
|
||||
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;
|
||||
|
|
|
@ -77,6 +77,7 @@
|
|||
#include "nsIDOMWindow.h"
|
||||
|
||||
#include "cairo.h"
|
||||
#include "imgIEncoder.h"
|
||||
|
||||
static NS_DEFINE_IID(kBlenderCID, NS_BLENDER_CID);
|
||||
|
||||
|
@ -198,6 +199,9 @@ public:
|
|||
// nsICanvasRenderingContextInternal
|
||||
NS_IMETHOD SetCanvasElement(nsICanvasElement* aParentCanvas);
|
||||
NS_IMETHOD SetTargetImageFrame(gfxIImageFrame* aImageFrame);
|
||||
NS_IMETHOD GetInputStream(const nsACString& aMimeType,
|
||||
const nsAString& aEncoderOptions,
|
||||
nsIInputStream **aStream);
|
||||
NS_IMETHOD UpdateImageFrame();
|
||||
|
||||
// nsISupports interface
|
||||
|
@ -537,6 +541,26 @@ nsCanvasRenderingContext2D::SetTargetImageFrame(gfxIImageFrame* aImageFrame)
|
|||
|
||||
return ClearRect (0, 0, mWidth, mHeight);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetInputStream(const nsACString& aMimeType,
|
||||
const nsAString& aEncoderOptions,
|
||||
nsIInputStream **aStream)
|
||||
{
|
||||
nsCString conid(NS_LITERAL_CSTRING("@mozilla.org/image/encoder;2?type="));
|
||||
conid += aMimeType;
|
||||
|
||||
nsCOMPtr<imgIEncoder> encoder = do_CreateInstance(conid.get());
|
||||
if (!encoder)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
encoder->InitFromData(mSurfaceData,
|
||||
mWidth * mHeight * 4, mWidth, mHeight, mWidth * 4,
|
||||
imgIEncoder::INPUT_FORMAT_HOSTARGB,
|
||||
aEncoderOptions);
|
||||
|
||||
return CallQueryInterface(encoder, aStream);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::UpdateImageFrame()
|
||||
|
|
|
@ -45,6 +45,9 @@
|
|||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsNodeInfoManager.h"
|
||||
#include "plbase64.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "prmem.h"
|
||||
|
||||
#include "nsICanvasElement.h"
|
||||
|
||||
|
@ -251,6 +254,91 @@ nsHTMLCanvasElement::ParseAttribute(nsIAtom* aAttribute,
|
|||
return nsGenericHTMLElement::ParseAttribute(aAttribute, aValue, aResult);
|
||||
}
|
||||
|
||||
|
||||
// nsHTMLCanvasElement::toDataURL
|
||||
//
|
||||
// This is the version in the spec, it returns a PNG with transparency
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLCanvasElement::ToDataURL(nsAString& aDataURL)
|
||||
{
|
||||
return ToDataURLAs(NS_LITERAL_STRING("image/png"), EmptyString(),
|
||||
aDataURL);
|
||||
}
|
||||
|
||||
|
||||
// nsHTMLCanvasElement::toDataURLAs
|
||||
//
|
||||
// http://www.mozilla.org/quality/networking/docs/aboutdata.html
|
||||
//
|
||||
// Get the data
|
||||
// encode it as PNG
|
||||
// base64 encode it
|
||||
NS_IMETHODIMP
|
||||
nsHTMLCanvasElement::ToDataURLAs(const nsAString& aMimeType,
|
||||
const nsAString& aEncoderOptions,
|
||||
nsAString& aDataURL)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// We get an input stream from the context. If more than one context type
|
||||
// is supported in the future, this will have to be changed to do the right
|
||||
// thing. For now, just assume that the 2D context has all the goods.
|
||||
nsCOMPtr<nsICanvasRenderingContextInternal> context;
|
||||
rv = GetContext(NS_LITERAL_STRING("2d"), getter_AddRefs(context));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// get image bytes
|
||||
nsCOMPtr<nsIInputStream> imgStream;
|
||||
NS_ConvertUTF16toUTF8 aMimeType8(aMimeType);
|
||||
rv = context->GetInputStream(aMimeType8, aEncoderOptions,
|
||||
getter_AddRefs(imgStream));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Generally, there will be only one chunk of data, and it will be available
|
||||
// for us to read right away, so optimize this case.
|
||||
PRUint32 bufSize;
|
||||
rv = imgStream->Available(&bufSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// ...leave a little extra room so we can call read again and make sure we
|
||||
// got everything. 16 bytes for better padding (maybe)
|
||||
bufSize += 16;
|
||||
PRUint32 imgSize = 0;
|
||||
char* imgData = (char*)PR_Malloc(bufSize);
|
||||
if (! imgData)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
PRUint32 numReadThisTime = 0;
|
||||
while ((rv = imgStream->Read(&imgData[imgSize], bufSize - imgSize,
|
||||
&numReadThisTime)) == NS_OK && numReadThisTime > 0) {
|
||||
imgSize += numReadThisTime;
|
||||
if (imgSize == bufSize) {
|
||||
// need a bigger buffer, just double
|
||||
bufSize *= 2;
|
||||
char* newImgData = (char*)PR_Realloc(imgData, bufSize);
|
||||
if (! newImgData) {
|
||||
PR_Free(imgData);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
imgData = newImgData;
|
||||
}
|
||||
}
|
||||
|
||||
// base 64, result will be NULL terminated
|
||||
char* encodedImg = PL_Base64Encode(imgData, imgSize, nsnull);
|
||||
PR_Free(imgData);
|
||||
if (!encodedImg) // not sure why this would fail
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// build data URL string
|
||||
aDataURL = NS_LITERAL_STRING("data:") + aMimeType +
|
||||
NS_LITERAL_STRING(";base64,") + NS_ConvertUTF8toUTF16(encodedImg);
|
||||
|
||||
PR_Free(encodedImg);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLCanvasElement::GetContext(const nsAString& aContextId,
|
||||
nsISupports **aContext)
|
||||
|
|
|
@ -49,12 +49,21 @@
|
|||
|
||||
// XXX This should inherit from nsIDOMHTMLImageElement instead,
|
||||
// and implement that interface as well.
|
||||
[scriptable, uuid(332dd7d0-97e2-44a0-af5b-1c3bafb0b1f2)]
|
||||
[scriptable, uuid(d0090186-a2b1-4591-9160-e1f044c69da0)]
|
||||
interface nsIDOMHTMLCanvasElement : nsIDOMHTMLElement
|
||||
{
|
||||
attribute long width;
|
||||
attribute long height;
|
||||
|
||||
DOMString toDataURL();
|
||||
|
||||
// This version lets you specify different image types and pass parameters
|
||||
// to the encoder. For example toDataURLAs("image/png", "transparency=none")
|
||||
// gives you a PNG with the alpha channel discarded. See the encoder for
|
||||
// the options string that it supports. Separate multiple options with
|
||||
// semicolons.
|
||||
DOMString toDataURLAs(in DOMString mimeType, in DOMString encoderOptions);
|
||||
|
||||
nsISupports getContext(in DOMString contextId);
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче