Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc

--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
This commit is contained in:
Joe Drew 2009-07-20 18:50:15 -07:00
parent a6e367551a
commit 2aa59235f2
98 changed files with 2290 additions and 3404 deletions

View file

@ -115,9 +115,9 @@ nsHTMLImageAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
imageRequest->GetImage(getter_AddRefs(imgContainer));
if (imgContainer) {
PRUint32 numFrames;
imgContainer->GetNumFrames(&numFrames);
if (numFrames > 1)
PRBool animated;
imgContainer->GetAnimated(&animated);
if (animated)
*aState |= nsIAccessibleStates::STATE_ANIMATED;
}

View file

@ -91,4 +91,12 @@ EXTRA_DSO_LDOPTS += \
$(NULL)
endif
ifndef MOZ_ENABLE_LIBXUL
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
# Doesn't work, couldn't figure out why
#EXTRA_DSO_LIBS += thebes
EXTRA_DSO_LDOPTS += $(LIBXUL_DIST)/lib/$(LIB_PREFIX)thebes.$(LIB_SUFFIX)
endif
endif
include $(topsrcdir)/config/rules.mk

View file

@ -47,7 +47,6 @@
#include "nsIGConfService.h"
#include "nsIGnomeVFSService.h"
#include "nsIStringBundle.h"
#include "gfxIImageFrame.h"
#include "nsIOutputStream.h"
#include "nsIProcess.h"
#include "nsNetUtil.h"
@ -55,7 +54,6 @@
#include "nsIImageLoadingContent.h"
#include "imgIRequest.h"
#include "imgIContainer.h"
#include "nsIImage.h"
#include "prprf.h"
#ifdef MOZ_WIDGET_GTK2
#include "nsIImageToPixbuf.h"
@ -349,12 +347,8 @@ nsGNOMEShellService::SetShouldCheckDefaultBrowser(PRBool aShouldCheck)
}
static nsresult
WriteImage(const nsCString& aPath, gfxIImageFrame* aImage)
WriteImage(const nsCString& aPath, imgIContainer* aImage)
{
nsCOMPtr<nsIImage> img(do_GetInterface(aImage));
if (!img)
return NS_ERROR_NOT_AVAILABLE;
#ifndef MOZ_WIDGET_GTK2
return NS_ERROR_NOT_AVAILABLE;
#else
@ -363,7 +357,7 @@ WriteImage(const nsCString& aPath, gfxIImageFrame* aImage)
if (!imgToPixbuf)
return NS_ERROR_NOT_AVAILABLE;
GdkPixbuf* pixbuf = imgToPixbuf->ConvertImageToPixbuf(img);
GdkPixbuf* pixbuf = imgToPixbuf->ConvertImageToPixbuf(aImage);
if (!pixbuf)
return NS_ERROR_NOT_AVAILABLE;
@ -379,8 +373,6 @@ nsGNOMEShellService::SetDesktopBackground(nsIDOMElement* aElement,
PRInt32 aPosition)
{
nsresult rv;
nsCOMPtr<gfxIImageFrame> gfxFrame;
nsCOMPtr<nsIImageLoadingContent> imageContent = do_QueryInterface(aElement, &rv);
if (!imageContent) return rv;
@ -393,12 +385,6 @@ nsGNOMEShellService::SetDesktopBackground(nsIDOMElement* aElement,
rv = request->GetImage(getter_AddRefs(container));
if (!container) return rv;
// get the current frame, which holds the image data
container->GetCurrentFrame(getter_AddRefs(gfxFrame));
if (!gfxFrame)
return NS_ERROR_FAILURE;
// Write the background file to the home directory.
nsCAutoString filePath(PR_GetEnv("HOME"));
@ -423,7 +409,7 @@ nsGNOMEShellService::SetDesktopBackground(nsIDOMElement* aElement,
filePath.Append("_wallpaper.png");
// write the image to a file in the home dir
rv = WriteImage(filePath, gfxFrame);
rv = WriteImage(filePath, container);
// if the file was written successfully, set it as the system wallpaper
nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);

View file

@ -41,7 +41,6 @@
*
* ***** END LICENSE BLOCK ***** */
#include "gfxIImageFrame.h"
#include "imgIContainer.h"
#include "imgIRequest.h"
#include "nsIDOMDocument.h"
@ -519,23 +518,18 @@ nsWindowsShellService::SetShouldCheckDefaultBrowser(PRBool aShouldCheck)
}
static nsresult
WriteBitmap(nsIFile* aFile, gfxIImageFrame* aImage)
WriteBitmap(nsIFile* aFile, imgIContainer* aImage)
{
PRInt32 width, height;
aImage->GetWidth(&width);
aImage->GetHeight(&height);
nsRefPtr<gfxImageSurface> image;
nsresult rv = aImage->CopyCurrentFrame(getter_AddRefs(image));
NS_ENSURE_SUCCESS(rv, rv);
PRUint8* bits;
PRUint32 length;
aImage->LockImageData();
aImage->GetImageData(&bits, &length);
if (!bits) {
aImage->UnlockImageData();
return NS_ERROR_FAILURE;
}
PRInt32 width = image->Width();
PRInt32 height = image->Height();
PRUint32 bpr;
aImage->GetImageBytesPerRow(&bpr);
PRUint8* bits = image->Data();
PRUint32 length = image->GetDataSize();
PRUint32 bpr = PRUint32(image->Stride());
PRInt32 bitCount = bpr/width;
// initialize these bitmap structs which we will later
@ -562,7 +556,7 @@ WriteBitmap(nsIFile* aFile, gfxIImageFrame* aImage)
// get a file output stream
nsCOMPtr<nsIOutputStream> stream;
nsresult rv = NS_NewLocalFileOutputStream(getter_AddRefs(stream), aFile);
rv = NS_NewLocalFileOutputStream(getter_AddRefs(stream), aFile);
NS_ENSURE_SUCCESS(rv, rv);
// write the bitmap headers and rgb pixel data to the file
@ -592,7 +586,6 @@ WriteBitmap(nsIFile* aFile, gfxIImageFrame* aImage)
stream->Close();
}
aImage->UnlockImageData();
return rv;
}
@ -602,8 +595,7 @@ nsWindowsShellService::SetDesktopBackground(nsIDOMElement* aElement,
{
nsresult rv;
nsCOMPtr<gfxIImageFrame> gfxFrame;
nsCOMPtr<imgIContainer> container;
nsCOMPtr<nsIDOMHTMLImageElement> imgElement(do_QueryInterface(aElement));
if (!imgElement) {
// XXX write background loading stuff!
@ -620,18 +612,11 @@ nsWindowsShellService::SetDesktopBackground(nsIDOMElement* aElement,
getter_AddRefs(request));
if (!request)
return rv;
nsCOMPtr<imgIContainer> container;
rv = request->GetImage(getter_AddRefs(container));
if (!container)
return NS_ERROR_FAILURE;
// get the current frame, which holds the image data
container->GetCurrentFrame(getter_AddRefs(gfxFrame));
}
if (!gfxFrame)
return NS_ERROR_FAILURE;
// get the file name from localized strings
nsCOMPtr<nsIStringBundleService>
bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
@ -664,7 +649,7 @@ nsWindowsShellService::SetDesktopBackground(nsIDOMElement* aElement,
NS_ENSURE_SUCCESS(rv, rv);
// write the bitmap to a file in the profile directory
rv = WriteBitmap(file, gfxFrame);
rv = WriteBitmap(file, container);
// if the file was written successfully, set it as the system wallpaper
if (NS_SUCCEEDED(rv)) {

View file

@ -78,12 +78,12 @@ class nsIThreadJSContextStack;
class nsIParserService;
class nsIIOService;
class nsIURI;
class imgIContainer;
class imgIDecoderObserver;
class imgIRequest;
class imgILoader;
class imgICache;
class nsIPrefBranch;
class nsIImage;
class nsIImageLoadingContent;
class nsIDOMHTMLFormElement;
class nsIDOMDocument;
@ -654,13 +654,13 @@ public:
static PRBool IsImageInCache(nsIURI* aURI);
/**
* Method to get an nsIImage from an image loading content
* Method to get an imgIContainer from an image loading content
*
* @param aContent The image loading content. Must not be null.
* @param aRequest The image request [out]
* @return the nsIImage corresponding to the first frame of the image
* @return the imgIContainer corresponding to the first frame of the image
*/
static already_AddRefed<nsIImage> GetImageFromContent(nsIImageLoadingContent* aContent, imgIRequest **aRequest = nsnull);
static already_AddRefed<imgIContainer> GetImageFromContent(nsIImageLoadingContent* aContent, imgIRequest **aRequest = nsnull);
/**
* Method that decides whether a content node is draggable

View file

@ -80,7 +80,6 @@
#include "nsINameSpaceManager.h"
#include "nsUnicharUtils.h"
#include "nsIURL.h"
#include "nsIImage.h"
#include "nsIDocument.h"
#include "nsIScriptSecurityManager.h"
#include "nsIPrincipal.h"
@ -93,6 +92,7 @@
#include "nsEscape.h"
#include "nsContentUtils.h"
#include "nsIMIMEService.h"
#include "imgIContainer.h"
#include "imgIRequest.h"
#include "nsContentCID.h"
#include "nsDOMDataTransfer.h"
@ -171,7 +171,7 @@ private:
nsString mInfoString;
PRBool mIsAnchor;
nsCOMPtr<nsIImage> mImage;
nsCOMPtr<imgIContainer> mImage;
};
@ -972,7 +972,7 @@ nsTransferableFactory::Produce(nsDOMDataTransfer* aDataTransfer,
nsCOMPtr<imgIRequest> imgRequest;
// grab the image data, and its request.
nsCOMPtr<nsIImage> img =
nsCOMPtr<imgIContainer> img =
nsContentUtils::GetImageFromContent(image,
getter_AddRefs(imgRequest));

View file

@ -53,7 +53,6 @@ class nsIDOMDocument;
class nsIDOMDragEvent;
class nsISelection;
class nsITransferable;
class nsIImage;
class nsIPresShell;
class nsPresContext;
class nsIContent;

View file

@ -98,8 +98,6 @@
#include "imgIRequest.h"
#include "imgIContainer.h"
#include "imgILoader.h"
#include "nsIImage.h"
#include "gfxIImageFrame.h"
#include "nsIImageLoadingContent.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
@ -2446,7 +2444,7 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
}
// static
already_AddRefed<nsIImage>
already_AddRefed<imgIContainer>
nsContentUtils::GetImageFromContent(nsIImageLoadingContent* aContent,
imgIRequest **aRequest)
{
@ -2470,26 +2468,11 @@ nsContentUtils::GetImageFromContent(nsIImageLoadingContent* aContent,
return nsnull;
}
nsCOMPtr<gfxIImageFrame> imgFrame;
imgContainer->GetFrameAt(0, getter_AddRefs(imgFrame));
if (!imgFrame) {
return nsnull;
}
nsCOMPtr<nsIInterfaceRequestor> ir = do_QueryInterface(imgFrame);
if (!ir) {
return nsnull;
}
if (aRequest) {
imgRequest.swap(*aRequest);
}
nsIImage* image = nsnull;
CallGetInterface(ir.get(), &image);
return image;
return imgContainer.forget();
}
// static

View file

@ -49,6 +49,7 @@
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsIDOMRange.h"
#include "imgIContainer.h"
#include "nsIDocShell.h"
#include "nsIContentViewerEdit.h"
@ -65,7 +66,6 @@
// image copy stuff
#include "nsIImageLoadingContent.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIImage.h"
#include "nsContentUtils.h"
#include "nsContentCID.h"
@ -463,7 +463,7 @@ nsCopySupport::ImageCopy(nsIImageLoadingContent* aImageElement,
if (aCopyFlags & nsIContentViewerEdit::COPY_IMAGE_DATA) {
// get the image data from the element
nsCOMPtr<nsIImage> image =
nsCOMPtr<imgIContainer> image =
nsContentUtils::GetImageFromContent(aImageElement);
NS_ENSURE_TRUE(image, NS_ERROR_FAILURE);

View file

@ -55,7 +55,6 @@
#include "nsIURI.h"
#include "nsILoadGroup.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "imgILoader.h"
#include "nsThreadUtils.h"
#include "nsNetUtil.h"
@ -158,10 +157,9 @@ nsImageLoadingContent::~nsImageLoadingContent()
*/
NS_IMETHODIMP
nsImageLoadingContent::FrameChanged(imgIContainer* aContainer,
gfxIImageFrame* aFrame,
nsIntRect* aDirtyRect)
{
LOOP_OVER_OBSERVERS(FrameChanged(aContainer, aFrame, aDirtyRect));
LOOP_OVER_OBSERVERS(FrameChanged(aContainer, aDirtyRect));
return NS_OK;
}
@ -196,7 +194,7 @@ nsImageLoadingContent::OnStartContainer(imgIRequest* aRequest,
NS_IMETHODIMP
nsImageLoadingContent::OnStartFrame(imgIRequest* aRequest,
gfxIImageFrame* aFrame)
PRUint32 aFrame)
{
LOOP_OVER_OBSERVERS(OnStartFrame(aRequest, aFrame));
return NS_OK;
@ -204,16 +202,16 @@ nsImageLoadingContent::OnStartFrame(imgIRequest* aRequest,
NS_IMETHODIMP
nsImageLoadingContent::OnDataAvailable(imgIRequest* aRequest,
gfxIImageFrame* aFrame,
PRBool aCurrentFrame,
const nsIntRect* aRect)
{
LOOP_OVER_OBSERVERS(OnDataAvailable(aRequest, aFrame, aRect));
LOOP_OVER_OBSERVERS(OnDataAvailable(aRequest, aCurrentFrame, aRect));
return NS_OK;
}
NS_IMETHODIMP
nsImageLoadingContent::OnStopFrame(imgIRequest* aRequest,
gfxIImageFrame* aFrame)
PRUint32 aFrame)
{
LOOP_OVER_OBSERVERS(OnStopFrame(aRequest, aFrame));
return NS_OK;

View file

@ -58,14 +58,14 @@ nsStubImageDecoderObserver::OnStartContainer(imgIRequest *aRequest,
NS_IMETHODIMP
nsStubImageDecoderObserver::OnStartFrame(imgIRequest *aRequest,
gfxIImageFrame *aFrame)
PRUint32 aFrame)
{
return NS_OK;
}
NS_IMETHODIMP
nsStubImageDecoderObserver::OnDataAvailable(imgIRequest *aRequest,
gfxIImageFrame *aFrame,
PRBool aCurrentFrame,
const nsIntRect * aRect)
{
return NS_OK;
@ -73,7 +73,7 @@ nsStubImageDecoderObserver::OnDataAvailable(imgIRequest *aRequest,
NS_IMETHODIMP
nsStubImageDecoderObserver::OnStopFrame(imgIRequest *aRequest,
gfxIImageFrame *aFrame)
PRUint32 aFrame)
{
return NS_OK;
}
@ -102,7 +102,6 @@ nsStubImageDecoderObserver::OnStopRequest(imgIRequest *aRequest,
NS_IMETHODIMP
nsStubImageDecoderObserver::FrameChanged(imgIContainer *aContainer,
gfxIImageFrame *aFrame,
nsIntRect * aDirtyRect)
{
return NS_OK;

View file

@ -61,8 +61,6 @@
#include "nsIDOMSVGURIReference.h"
#include "nsImageLoadingContent.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "nsIImage.h"
#include "nsNetUtil.h"
#include "nsSVGPreserveAspectRatio.h"
#include "nsIInterfaceRequestorUtils.h"
@ -5191,8 +5189,7 @@ public:
NS_IMETHOD OnStopDecode(imgIRequest *aRequest, nsresult status,
const PRUnichar *statusArg);
// imgIContainerObserver
NS_IMETHOD FrameChanged(imgIContainer *aContainer, gfxIImageFrame *newframe,
nsIntRect *dirtyRect);
NS_IMETHOD FrameChanged(imgIContainer *aContainer, nsIntRect *dirtyRect);
// imgIContainerObserver
NS_IMETHOD OnStartContainer(imgIRequest *aRequest,
imgIContainer *aContainer);
@ -5378,31 +5375,27 @@ nsSVGFEImageElement::Filter(nsSVGFilterInstance *instance,
if (currentRequest)
currentRequest->GetImage(getter_AddRefs(imageContainer));
nsCOMPtr<gfxIImageFrame> currentFrame;
nsRefPtr<gfxASurface> currentFrame;
if (imageContainer)
imageContainer->GetCurrentFrame(getter_AddRefs(currentFrame));
nsRefPtr<gfxPattern> thebesPattern = nsnull;
if (currentFrame) {
nsCOMPtr<nsIImage> img(do_GetInterface(currentFrame));
img->GetPattern(getter_AddRefs(thebesPattern));
}
// We need to wrap the surface in a pattern to have somewhere to set the
// graphics filter.
nsRefPtr<gfxPattern> thebesPattern;
if (currentFrame)
thebesPattern = new gfxPattern(currentFrame);
if (thebesPattern) {
thebesPattern->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(frame));
PRInt32 x, y, nativeWidth, nativeHeight;
currentFrame->GetX(&x);
currentFrame->GetY(&y);
currentFrame->GetWidth(&nativeWidth);
currentFrame->GetHeight(&nativeHeight);
PRInt32 nativeWidth, nativeHeight;
imageContainer->GetWidth(&nativeWidth);
imageContainer->GetHeight(&nativeHeight);
nsCOMPtr<nsIDOMSVGMatrix> trans;
const gfxRect& filterSubregion = aTarget->mFilterPrimitiveSubregion;
trans = nsSVGUtils::GetViewBoxTransform(filterSubregion.Width(), filterSubregion.Height(),
x, y,
nativeWidth, nativeHeight,
0, 0, nativeWidth, nativeHeight,
mPreserveAspectRatio);
nsCOMPtr<nsIDOMSVGMatrix> xy, fini;
NS_NewSVGMatrix(getter_AddRefs(xy), 1, 0, 0, 1, filterSubregion.X(), filterSubregion.Y());
@ -5457,11 +5450,10 @@ nsSVGFEImageElement::OnStopDecode(imgIRequest *aRequest,
NS_IMETHODIMP
nsSVGFEImageElement::FrameChanged(imgIContainer *aContainer,
gfxIImageFrame *newframe,
nsIntRect *dirtyRect)
{
nsresult rv =
nsImageLoadingContent::FrameChanged(aContainer, newframe, dirtyRect);
nsImageLoadingContent::FrameChanged(aContainer, dirtyRect);
Invalidate();
return rv;
}

View file

@ -85,7 +85,6 @@
#include "nsPresContext.h"
#include "nsIParser.h"
#include "nsParserCIID.h"
#include "nsIImage.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsLinebreakConverter.h"

View file

@ -93,7 +93,6 @@
#include "nsIDOMDocumentFragment.h"
#include "nsIPresShell.h"
#include "nsPresContext.h"
#include "nsIImage.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "SetDocTitleTxn.h"

View file

@ -50,7 +50,6 @@ XPIDLSRCS = \
nsIFontEnumerator.idl \
nsIScriptableRegion.idl \
gfxIFormats.idl \
gfxIImageFrame.idl \
gfxidltypes.idl \
$(NULL)

View file

@ -1,168 +0,0 @@
/** -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
* Chris Saari <saari@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "gfxidltypes.idl"
#include "gfxIFormats.idl"
%{C++
#include "nsRect.h"
%}
native nsRectRef(nsIntRect &);
/**
* gfxIImageFrame interface
*
* All x, y, width, height values are in pixels.
*
* @author Tim Rowley <tor@cs.brown.edu>
* @author Stuart Parmenter <pavlov@netscape.com>
* @version 0.1
*/
[scriptable, uuid(9c37930b-cadd-453c-89e1-9ed456715b9c)]
interface gfxIImageFrame : nsISupports
{
/**
* Create a new \a aWidth x \a aHeight sized image.
*
* @param aX The x-offset from the origin of the gfxIImageContainer parent.
* @param aY The y-offset from the origin of the gfxIImageContainer parent.
* @param aWidth The width of the image to create.
* @param aHeight The height of the image to create.
* @param aFormat the width of the image to create.
*
* @note The data in a new image is uninitialized.
*/
void init(in PRInt32 aX,
in PRInt32 aY,
in PRInt32 aWidth,
in PRInt32 aHeight,
in gfx_format aFormat,
in gfx_depth aDepth);
/**
* TRUE by default. When set to FALSE, you will no longer be able to make any modifications
* to the data of the image. Any attempts will fail.
*/
attribute boolean mutable;
/**
* The x-offset of the image.
*/
readonly attribute PRInt32 x;
/**
* The y-offset of the image.
*/
readonly attribute PRInt32 y;
/**
* The width of the image.
*/
readonly attribute PRInt32 width;
/**
* The height of the image.
*/
readonly attribute PRInt32 height;
/**
* The rectangle this frame ocupies.
* @param rect this is really an out parameter.
*/
[noscript] void getRect(in nsRectRef rect);
/**
* The image data format the image was created with.
* @see gfxIFormats
*/
readonly attribute gfx_format format;
/**
* returns whether the image requires the background to be painted
*/
readonly attribute boolean needsBackground;
/* data accessors */
readonly attribute unsigned long imageBytesPerRow;
/**
* returns the number of bytes allocated for the image
*/
readonly attribute unsigned long imageDataLength;
// XXX do we copy here? lets not...
void getImageData([array, size_is(length)] out PRUint8 bits, out unsigned long length);
/**
* Get Palette data pointer
*/
void getPaletteData([array, size_is(length)] out gfx_color palette, out unsigned long length);
/**
* Lock image pixels before addressing the data directly
*/
void lockImageData();
/**
* Unlock image pixels
*/
void unlockImageData();
/* GIF Specific methods. These should be in a different class or interface. */
/**
* Represents the number of milliseconds until the next frame should be displayed.
* @note -1 means that this frame should be displayed forever.
*/
attribute long timeout;
/* frame disposal method, used only by GIFs. Should probably subclass image frame
* and image container for GIFs special needs, but for simplicity it is here for the
* moment
*/
attribute long frameDisposalMethod;
/* PNG specific methods */
attribute long blendMethod;
};

View file

@ -60,7 +60,6 @@ EXPORTS = \
nsIRenderingContext.h \
nsIFontMetrics.h \
nsIDeviceContext.h \
nsIImage.h \
nsGfxCIID.h \
nsIRegion.h \
nsITheme.h \

View file

@ -1,307 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsIImage_h___
#define nsIImage_h___
#include "nsISupports.h"
#include "nsMargin.h"
#include "nsRect.h"
#include "gfxPattern.h"
class gfxASurface;
struct gfxMatrix;
struct gfxRect;
class gfxContext;
class nsIDeviceContext;
struct nsColorMap
{
//I lifted this from the image lib. The difference is that
//this uses nscolor instead of NI_RGB. Multiple color pollution
//is a bad thing. MMP
PRInt32 NumColors; // Number of colors in the colormap.
// A negative value can be used to denote a
// possibly non-unique set.
//nscolor *Map; // Colormap colors.
PRUint8 *Index; // NULL, if map is in index order, otherwise
// specifies the indices of the map entries. */
};
typedef enum {
nsMaskRequirements_kNoMask,
nsMaskRequirements_kNeeds1Bit,
nsMaskRequirements_kNeeds8Bit
} nsMaskRequirements;
#define nsImageUpdateFlags_kColorMapChanged 0x1
#define nsImageUpdateFlags_kBitsChanged 0x2
// IID for the nsIImage interface
// 0358ce68-b076-43b0-8f5c-36ed4592822c
#define NS_IIMAGE_IID \
{ 0x358ce68, 0xb076, 0x43b0, \
{ 0x8f, 0x5c, 0x36, 0xed, 0x45, 0x92, 0x82, 0x2c } }
// Interface to Images
class nsIImage : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IIMAGE_IID)
/**
* Build and initialize the nsIImage
* @param aWidth The width in pixels of the desired pixelmap
* @param aHeight The height in pixels of the desired pixelmap
* @param aDepth The number of bits per pixel for the pixelmap
* @param aMaskRequirements A flag indicating if a alpha mask should be allocated
*/
virtual nsresult Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequirements aMaskRequirements) = 0;
/**
* Get the number of bytes per pixel for this image
* @update - dwc 2/3/99
* @return - the number of bytes per pixel
*/
virtual PRInt32 GetBytesPix() = 0;
/**
* Get whether rows are organized top to bottom, or bottom to top
* @update - syd 3/29/99
* @return PR_TRUE if top to bottom, else PR_FALSE
*/
virtual PRBool GetIsRowOrderTopToBottom() = 0;
/**
* Get the width for the pixelmap
* @update - dwc 2/1/99
* @return The width in pixels for the pixelmap
*/
virtual PRInt32 GetWidth() = 0;
/**
* Get the height for the pixelmap
* @update - dwc 2/1/99
* @return The height in pixels for the pixelmap
*/
virtual PRInt32 GetHeight() = 0;
/**
* Get a pointer to the bits for the pixelmap, only if it is not optimized
* @update - dwc 2/1/99
* @return address of the DIB pixel array
*/
virtual PRUint8 * GetBits() = 0;
/**
* Get the number of bytes needed to get to the next scanline for the pixelmap
* @update - dwc 2/1/99
* @return The number of bytes in each scanline
*/
virtual PRInt32 GetLineStride() = 0;
/**
* Get whether this image has an alpha mask. Preferable to testing
* if GetAlphaBits() is non-null.
* @update - sfraser 10/19/99
* @return PR_TRUE if the image has an alpha mask, PR_FALSE otherwise
*/
virtual PRBool GetHasAlphaMask() = 0;
/**
* Get a pointer to the bits for the alpha mask
* @update - dwc 2/1/99
* @return address of the alpha mask pixel array
*/
virtual PRUint8 * GetAlphaBits() = 0;
/**
* Get the number of bytes per scanline for the alpha mask
* @update - dwc 2/1/99
* @return The number of bytes in each scanline
*/
virtual PRInt32 GetAlphaLineStride() = 0;
/**
* Update the nsIImage color table
* @update - dougt 9/9/08
* @param aFlags Used to pass in parameters for the update
* @param aUpdateRect The rectangle to update
* @return success code. failure means stop decoding
*/
virtual nsresult ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsIntRect *aUpdateRect) = 0;
/**
* Get whether this image's region is completely filled with data.
* @return PR_TRUE if image is complete, PR_FALSE if image is not yet
* complete or broken
*/
virtual PRBool GetIsImageComplete() = 0;
/**
* Converted this pixelmap to an optimized pixelmap for the device
* @update - dwc 2/1/99
* @param aContext The device to optimize for
* @return the result of the operation, if NS_OK, then the pixelmap is optimized
*/
virtual nsresult Optimize(nsIDeviceContext* aContext) = 0;
/**
* Get the colormap for the nsIImage
* @update - dwc 2/1/99
* @return if non null, the colormap for the pixelmap,otherwise the image is not color mapped
*/
virtual nsColorMap * GetColorMap() = 0;
/**
* BitBlit the nsIImage to a device, the source and dest can be scaled.
* @param aContext the destination
* @param aFilter the filter for the image
* @param aUserSpaceToImageSpace the transform that maps user-space
* coordinates to coordinates in (tiled, post-padding) image pixels
* @param aFill the area to fill with tiled images
* @param aPadding the padding to be added to this image before tiling,
* in image pixels
* @param aSubimage the subimage in padded+tiled image space that we're
* extracting the contents from. Pixels outside this rectangle must not
* be sampled.
*
* So this is supposed to
* -- add aPadding transparent pixels around the image
* -- use that image to tile the plane
* -- replace everything outside the aSubimage region with the nearest
* border pixel of that region (like EXTEND_PAD)
* -- fill aFill with the image, using aImageSpaceToDeviceSpace as the
* image-space-to-device-space transform
*/
virtual void Draw(gfxContext* aContext,
gfxPattern::GraphicsFilter aFilter,
const gfxMatrix& aUserSpaceToImageSpace,
const gfxRect& aFill,
const nsIntMargin& aPadding,
const nsIntRect& aSubimage) = 0;
/**
* Get the alpha depth for the image mask
* @update - lordpixel 2001/05/16
* @return the alpha mask depth for the image, ie, 0, 1 or 8
*/
virtual PRInt8 GetAlphaDepth() = 0;
/**
* Return information about the bits for this structure
* @update - dwc 2/1/99
* @return a bitmap info structure for the Device Dependent Bits
*/
virtual void* GetBitInfo() = 0;
/**
* LockImagePixels
* Lock the image pixels so that we can access them directly,
* with safety. May be a noop on some platforms.
*
* If you want to be able to call GetSurface(), wrap the call in
* LockImagePixels()/UnlockImagePixels(). This also allows you to write to
* the surface returned by GetSurface().
*
* aMaskPixels = PR_TRUE for the mask, PR_FALSE for the image
*
* Must be balanced by a call to UnlockImagePixels().
*
* @update - sfraser 10/18/99
* @return error result
*/
NS_IMETHOD LockImagePixels(PRBool aMaskPixels) = 0;
/**
* UnlockImagePixels
* Unlock the image pixels. May be a noop on some platforms.
*
* Should balance an earlier call to LockImagePixels().
*
* aMaskPixels = PR_TRUE for the mask, PR_FALSE for the image
*
* @update - sfraser 10/18/99
* @return error result
*/
NS_IMETHOD UnlockImagePixels(PRBool aMaskPixels) = 0;
/**
* GetSurface
* Return the Thebes gfxASurface in aSurface, if there is one. Should be
* wrapped by LockImagePixels()/UnlockImagePixels().
*
* aSurface will be AddRef'd (as with most getters), so
* getter_AddRefs should be used.
*/
NS_IMETHOD GetSurface(gfxASurface **aSurface) = 0;
/**
* GetSurface
* Return the Thebes gfxPattern in aPattern. It is always possible to get a
* gfxPattern (unlike the gfxASurface from GetSurface()).
*
* aPattern will be AddRef'd (as with most getters), so
* getter_AddRefs should be used.
*/
NS_IMETHOD GetPattern(gfxPattern **aPattern) = 0;
/**
* SetHasNoAlpha
*
* Hint to the image that all the pixels are fully opaque, even if
* the original format requested a 1-bit or 8-bit alpha mask
*/
virtual void SetHasNoAlpha() = 0;
/**
* Extract a rectangular region of the nsIImage and return it as a new
* nsIImage.
* @param aSubimage the region to extract
* @param aResult the extracted image
*/
NS_IMETHOD Extract(const nsIntRect& aSubimage,
nsIImage** aResult NS_OUTPARAM) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIImage, NS_IIMAGE_IID)
#endif

View file

@ -59,7 +59,7 @@ REQUIRES = xpcom \
xpconnect \
$(NULL)
DIRS = shared thebes
DIRS = thebes
ifdef MOZ_ENABLE_POSTSCRIPT
DIRS += psshared

View file

@ -1,67 +0,0 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 2001
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = gfx
LIBRARY_NAME = gfxshared_s
FORCE_STATIC_LIB=1
EXPORT_LIBRARY=1
LIBXUL_LIBRARY = 1
REQUIRES= \
xpcom \
string \
imglib2 \
widget \
thebes \
$(NULL)
CPPSRCS = \
gfxImageFrame.cpp \
$(NULL)
LOCAL_INCLUDES = -I$(srcdir)/.. \
$(NULL)
include $(topsrcdir)/config/rules.mk

View file

@ -1,428 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "gfxImageFrame.h"
#include "nsIServiceManager.h"
#include <limits.h>
#include "prmem.h"
NS_IMPL_ISUPPORTS2(gfxImageFrame, gfxIImageFrame, nsIInterfaceRequestor)
gfxImageFrame::gfxImageFrame() :
mImageData(nsnull),
mTimeout(100),
mDisposalMethod(0), /* imgIContainer::kDisposeNotSpecified */
mBlendMethod(1), /* imgIContainer::kBlendOver */
mInitialized(PR_FALSE),
mMutable(PR_TRUE)
{
/* member initializers and constructor code */
}
gfxImageFrame::~gfxImageFrame()
{
/* destructor code */
PR_FREEIF(mImageData);
mInitialized = PR_FALSE;
}
/* void init (in PRInt32 aX, in PRInt32 aY, in PRInt32 aWidth, in PRInt32 aHeight, in gfx_format aFormat); */
NS_IMETHODIMP gfxImageFrame::Init(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, gfx_format aFormat,gfx_depth aDepth)
{
if (mInitialized)
return NS_ERROR_FAILURE;
// assert for properties that should be verified by decoders, warn for properties related to bad content
if (aWidth <= 0 || aHeight <= 0) {
NS_ASSERTION(0, "error - negative image size\n");
return NS_ERROR_FAILURE;
}
/* check to make sure we don't overflow a 32-bit */
PRInt32 tmp = aWidth * aHeight;
if (tmp / aHeight != aWidth) {
NS_WARNING("width or height too large");
return NS_ERROR_FAILURE;
}
tmp = tmp * 4;
if (tmp / 4 != aWidth * aHeight) {
NS_WARNING("width or height too large");
return NS_ERROR_FAILURE;
}
/* reject over-wide or over-tall images */
const PRInt32 k64KLimit = 0x0000FFFF;
if ( aWidth > k64KLimit || aHeight > k64KLimit ){
NS_WARNING("image too big");
return NS_ERROR_FAILURE;
}
#if defined(XP_MACOSX)
// CoreGraphics is limited to images < 32K in *height*, so clamp all surfaces on the Mac to that height
if (aHeight > SHRT_MAX) {
NS_WARNING("image too big");
return NS_ERROR_FAILURE;
}
#endif
mOffset.MoveTo(aX, aY);
mSize.SizeTo(aWidth, aHeight);
mFormat = aFormat;
mDepth = aDepth;
PRBool needImage = PR_TRUE;
nsMaskRequirements maskReq;
switch (aFormat) {
case gfxIFormats::BGR:
case gfxIFormats::RGB:
maskReq = nsMaskRequirements_kNoMask;
break;
case gfxIFormats::BGRA:
case gfxIFormats::RGBA:
maskReq = nsMaskRequirements_kNeeds8Bit;
break;
case gfxIFormats::BGR_A1:
case gfxIFormats::RGB_A1:
maskReq = nsMaskRequirements_kNeeds1Bit;
break;
case gfxIFormats::BGR_A8:
case gfxIFormats::RGB_A8:
maskReq = nsMaskRequirements_kNeeds8Bit;
break;
case gfxIFormats::PAL:
case gfxIFormats::PAL_A1:
needImage = PR_FALSE;
break;
default:
NS_ERROR("unsupported gfx_format\n");
return NS_ERROR_FAILURE;
}
if (needImage) {
if (aDepth != 24) {
NS_ERROR("This Depth is not supported");
return NS_ERROR_FAILURE;
}
nsresult rv;
mImage = do_CreateInstance("@mozilla.org/gfx/image;1", &rv);
NS_ASSERTION(mImage, "creation of image failed");
if (NS_FAILED(rv)) return rv;
rv = mImage->Init(aWidth, aHeight, aDepth, maskReq);
NS_ENSURE_SUCCESS(rv, rv);
} else {
if ((aDepth < 1) || (aDepth > 8)) {
NS_ERROR("This Depth is not supported\n");
return NS_ERROR_FAILURE;
}
mImageData = (PRUint8*)PR_MALLOC(PaletteDataLength() + ImageDataLength());
NS_ENSURE_TRUE(mImageData, NS_ERROR_OUT_OF_MEMORY);
}
mInitialized = PR_TRUE;
return NS_OK;
}
/* attribute boolean mutable */
NS_IMETHODIMP gfxImageFrame::GetMutable(PRBool *aMutable)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
NS_ASSERTION(mInitialized, "gfxImageFrame::GetMutable called on non-inited gfxImageFrame");
*aMutable = mMutable;
return NS_OK;
}
NS_IMETHODIMP gfxImageFrame::SetMutable(PRBool aMutable)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
mMutable = aMutable;
if (!aMutable && mImage)
mImage->Optimize(nsnull);
return NS_OK;
}
/* readonly attribute PRInt32 x; */
NS_IMETHODIMP gfxImageFrame::GetX(PRInt32 *aX)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
*aX = mOffset.x;
return NS_OK;
}
/* readonly attribute PRInt32 y; */
NS_IMETHODIMP gfxImageFrame::GetY(PRInt32 *aY)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
*aY = mOffset.y;
return NS_OK;
}
/* readonly attribute PRInt32 width; */
NS_IMETHODIMP gfxImageFrame::GetWidth(PRInt32 *aWidth)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
*aWidth = mSize.width;
return NS_OK;
}
/* readonly attribute PRInt32 height; */
NS_IMETHODIMP gfxImageFrame::GetHeight(PRInt32 *aHeight)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
*aHeight = mSize.height;
return NS_OK;
}
/* void getRect(in nsRectRef rect); */
NS_IMETHODIMP gfxImageFrame::GetRect(nsIntRect &aRect)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
aRect.SetRect(mOffset.x, mOffset.y, mSize.width, mSize.height);
return NS_OK;
}
/* readonly attribute gfx_format format; */
NS_IMETHODIMP gfxImageFrame::GetFormat(gfx_format *aFormat)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
*aFormat = mFormat;
return NS_OK;
}
/* readonly attribute boolean needsBackground; */
NS_IMETHODIMP gfxImageFrame::GetNeedsBackground(PRBool *aNeedsBackground)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
*aNeedsBackground = (mFormat != gfxIFormats::RGB &&
mFormat != gfxIFormats::PAL &&
mFormat != gfxIFormats::BGR) ||
!mImage->GetIsImageComplete();
return NS_OK;
}
/* readonly attribute unsigned long imageBytesPerRow; */
NS_IMETHODIMP gfxImageFrame::GetImageBytesPerRow(PRUint32 *aBytesPerRow)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
*aBytesPerRow = mImage ? mImage->GetLineStride(): mSize.width;
return NS_OK;
}
/* readonly attribute unsigned long imageDataLength; */
NS_IMETHODIMP gfxImageFrame::GetImageDataLength(PRUint32 *aBitsLength)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
*aBitsLength = ImageDataLength();
return NS_OK;
}
/* void getImageData([array, size_is(length)] out PRUint8 bits, out unsigned long length); */
NS_IMETHODIMP gfxImageFrame::GetImageData(PRUint8 **aData, PRUint32 *length)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
NS_ASSERTION(mMutable, "trying to get data on an immutable frame");
*aData = mImage ? mImage->GetBits() : (mImageData + PaletteDataLength());
*length = ImageDataLength();
return NS_OK;
}
/* void getPaletteData ([array, size_is (length)] out PRUint32 palette, out unsigned long length); */
NS_IMETHODIMP gfxImageFrame::GetPaletteData(gfx_color **aPalette, PRUint32 *length)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
if (!mImageData)
return NS_ERROR_FAILURE;
*aPalette = (gfx_color*)mImageData;
*length = PaletteDataLength();
return NS_OK;
}
/* void lockImageData (); */
NS_IMETHODIMP gfxImageFrame::LockImageData()
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
if (!mImage)
return NS_OK;
return mImage->LockImagePixels(PR_FALSE);
}
/* void unlockImageData (); */
NS_IMETHODIMP gfxImageFrame::UnlockImageData()
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
if (!mImage)
return NS_OK;
return mImage->UnlockImagePixels(PR_FALSE);
}
/* attribute long timeout; */
NS_IMETHODIMP gfxImageFrame::GetTimeout(PRInt32 *aTimeout)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
// Ensure a minimal time between updates so we don't throttle the UI thread.
// consider 0 == unspecified and make it fast but not too fast. See bug
// 125137, bug 139677, and bug 207059. The behavior of recent IE and Opera
// versions seems to be:
// IE 6/Win:
// 10 - 50ms go 100ms
// >50ms go correct speed
// Opera 7 final/Win:
// 10ms goes 100ms
// >10ms go correct speed
// It seems that there are broken tools out there that set a 0ms or 10ms
// timeout when they really want a "default" one. So munge values in that
// range.
if (mTimeout >= 0 && mTimeout <= 10)
*aTimeout = 100;
else
*aTimeout = mTimeout;
return NS_OK;
}
NS_IMETHODIMP gfxImageFrame::SetTimeout(PRInt32 aTimeout)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
mTimeout = aTimeout;
return NS_OK;
}
/* attribute long frameDisposalMethod; */
NS_IMETHODIMP gfxImageFrame::GetFrameDisposalMethod(PRInt32 *aFrameDisposalMethod)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
*aFrameDisposalMethod = mDisposalMethod;
return NS_OK;
}
NS_IMETHODIMP gfxImageFrame::SetFrameDisposalMethod(PRInt32 aFrameDisposalMethod)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
mDisposalMethod = aFrameDisposalMethod;
return NS_OK;
}
/* attribute long blendMethod; */
NS_IMETHODIMP gfxImageFrame::GetBlendMethod(PRInt32 *aBlendMethod)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
*aBlendMethod = mBlendMethod;
return NS_OK;
}
NS_IMETHODIMP gfxImageFrame::SetBlendMethod(PRInt32 aBlendMethod)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
mBlendMethod = (PRInt8)aBlendMethod;
return NS_OK;
}
NS_IMETHODIMP gfxImageFrame::GetInterface(const nsIID & aIID, void * *result)
{
if (!mInitialized)
return NS_ERROR_NOT_INITIALIZED;
NS_ENSURE_ARG_POINTER(result);
if (NS_SUCCEEDED(QueryInterface(aIID, result)))
return NS_OK;
if (mImage && aIID.Equals(NS_GET_IID(nsIImage)))
return mImage->QueryInterface(aIID, result);
return NS_NOINTERFACE;
}

View file

@ -1,94 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2000-2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "gfxIImageFrame.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIImage.h"
#include "nsPoint.h"
#include "nsSize.h"
#include "nsCOMPtr.h"
#define GFX_IMAGEFRAME_CID \
{ /* aa699204-1dd1-11b2-84a9-a280c268e4fb */ \
0xaa699204, \
0x1dd1, \
0x11b2, \
{0x84, 0xa9, 0xa2, 0x80, 0xc2, 0x68, 0xe4, 0xfb} \
}
class gfxImageFrame : public gfxIImageFrame,
public nsIInterfaceRequestor
{
public:
NS_DECL_ISUPPORTS
NS_DECL_GFXIIMAGEFRAME
NS_DECL_NSIINTERFACEREQUESTOR
gfxImageFrame();
virtual ~gfxImageFrame();
protected:
nsIntSize mSize;
private:
PRUint32 PaletteDataLength() const {
return ((1 << mDepth) * sizeof(gfx_color));
}
PRUint32 ImageDataLength() const {
return (mImage ? mImage->GetLineStride() : mSize.width) * mSize.height;
}
nsCOMPtr<nsIImage> mImage;
PRUint8* mImageData;
PRInt32 mTimeout; // -1 means display forever
nsIntPoint mOffset;
PRInt32 mDisposalMethod;
gfx_format mFormat;
gfx_depth mDepth;
PRInt8 mBlendMethod;
PRPackedBool mInitialized;
PRPackedBool mMutable;
};

View file

@ -72,7 +72,6 @@ endif
CPPSRCS = \
nsThebesDeviceContext.cpp \
nsThebesImage.cpp \
nsThebesRegion.cpp \
nsThebesGfxFactory.cpp \
nsThebesRenderingContext.cpp \
@ -128,7 +127,6 @@ LOCAL_INCLUDES = \
$(NULL)
EXTRA_DSO_LDOPTS += \
../shared/$(LIB_PREFIX)gfxshared_s.$(LIB_SUFFIX) \
$(LIBS_DIR) \
$(EXTRA_DSO_LIBS) \
$(DEPTH)/modules/libutil/src/$(LIB_PREFIX)mozutil_s.$(LIB_SUFFIX) \

View file

@ -42,21 +42,17 @@
#include "nsGfxCIID.h"
#include "nsScriptableRegion.h"
#include "gfxImageFrame.h"
#include "nsThebesDeviceContext.h"
#include "nsThebesRenderingContext.h"
#include "nsThebesImage.h"
#include "nsThebesRegion.h"
#include "nsThebesFontMetrics.h"
#include "nsThebesFontEnumerator.h"
#include "gfxPlatform.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsThebesFontMetrics)
NS_GENERIC_FACTORY_CONSTRUCTOR(gfxImageFrame)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsThebesDeviceContext)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsThebesRenderingContext)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsThebesImage)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsThebesRegion)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsThebesFontEnumerator)
@ -119,10 +115,6 @@ static const nsModuleComponentInfo components[] =
NS_RENDERING_CONTEXT_CID,
"@mozilla.org/gfx/renderingcontext;1",
nsThebesRenderingContextConstructor },
{ "Thebes nsImage",
NS_IMAGE_CID,
"@mozilla.org/gfx/image;1",
nsThebesImageConstructor },
{ "Thebes Region",
NS_REGION_CID,
"@mozilla.org/gfx/region/nsThebes;1",
@ -131,10 +123,6 @@ static const nsModuleComponentInfo components[] =
NS_SCRIPTABLE_REGION_CID,
"@mozilla.org/gfx/region;1",
nsScriptableRegionConstructor },
{ "image frame",
GFX_IMAGEFRAME_CID,
"@mozilla.org/gfx/image/frame;2",
gfxImageFrameConstructor },
};
static nsresult

View file

@ -1,857 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is thebes gfx
*
* The Initial Developer of the Original Code is
* mozilla.org.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsThebesImage.h"
#include "nsThebesRenderingContext.h"
#include "gfxContext.h"
#include "gfxPattern.h"
#include "gfxPlatform.h"
#include "prenv.h"
static PRBool gDisableOptimize = PR_FALSE;
/*XXX get CAIRO_HAS_DDRAW_SURFACE */
#include "cairo.h"
#ifdef CAIRO_HAS_DDRAW_SURFACE
#include "gfxDDrawSurface.h"
#endif
#if defined(XP_WIN) || defined(WINCE)
#include "gfxWindowsPlatform.h"
#endif
#if defined(XP_WIN) && !defined(WINCE)
/* Whether to use the windows surface; only for desktop win32 */
#define USE_WIN_SURFACE 1
static PRUint32 gTotalDDBs = 0;
static PRUint32 gTotalDDBSize = 0;
// only use up a maximum of 64MB in DDBs
#define kMaxDDBSize (64*1024*1024)
// and don't let anything in that's bigger than 4MB
#define kMaxSingleDDBSize (4*1024*1024)
#endif
NS_IMPL_ISUPPORTS1(nsThebesImage, nsIImage)
nsThebesImage::nsThebesImage()
: mFormat(gfxImageSurface::ImageFormatRGB24),
mWidth(0),
mHeight(0),
mDecoded(0,0,0,0),
mImageComplete(PR_FALSE),
mSinglePixel(PR_FALSE),
mFormatChanged(PR_FALSE),
mNeverUseDeviceSurface(PR_FALSE),
mSinglePixelColor(0),
mAlphaDepth(0)
{
static PRBool hasCheckedOptimize = PR_FALSE;
if (!hasCheckedOptimize) {
if (PR_GetEnv("MOZ_DISABLE_IMAGE_OPTIMIZE")) {
gDisableOptimize = PR_TRUE;
}
hasCheckedOptimize = PR_TRUE;
}
#ifdef USE_WIN_SURFACE
mIsDDBSurface = PR_FALSE;
#endif
}
nsresult
nsThebesImage::Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequirements aMaskRequirements)
{
mWidth = aWidth;
mHeight = aHeight;
// Reject over-wide or over-tall images.
if (!AllowedImageSize(aWidth, aHeight))
return NS_ERROR_FAILURE;
// Check to see if we are running OOM
nsCOMPtr<nsIMemory> mem;
NS_GetMemoryManager(getter_AddRefs(mem));
if (!mem)
return NS_ERROR_UNEXPECTED;
PRBool lowMemory;
mem->IsLowMemory(&lowMemory);
if (lowMemory)
return NS_ERROR_OUT_OF_MEMORY;
gfxImageSurface::gfxImageFormat format;
switch(aMaskRequirements)
{
case nsMaskRequirements_kNeeds1Bit:
format = gfxImageSurface::ImageFormatARGB32;
mAlphaDepth = 1;
break;
case nsMaskRequirements_kNeeds8Bit:
format = gfxImageSurface::ImageFormatARGB32;
mAlphaDepth = 8;
break;
default:
format = gfxImageSurface::ImageFormatRGB24;
mAlphaDepth = 0;
break;
}
mFormat = format;
// For Windows, we must create the device surface first (if we're
// going to) so that the image surface can wrap it. Can't be done
// the other way around.
#ifdef USE_WIN_SURFACE
if (!mNeverUseDeviceSurface && !ShouldUseImageSurfaces()) {
mWinSurface = new gfxWindowsSurface(gfxIntSize(mWidth, mHeight), format);
if (mWinSurface && mWinSurface->CairoStatus() == 0) {
// no error
mImageSurface = mWinSurface->GetImageSurface();
} else {
mWinSurface = nsnull;
}
}
#endif
// For other platforms we create the image surface first and then
// possibly wrap it in a device surface. This branch is also used
// on Windows if we're not using device surfaces or if we couldn't
// create one.
if (!mImageSurface)
mImageSurface = new gfxImageSurface(gfxIntSize(mWidth, mHeight), format);
if (!mImageSurface || mImageSurface->CairoStatus()) {
mImageSurface = nsnull;
// guess
return NS_ERROR_OUT_OF_MEMORY;
}
#ifdef XP_MACOSX
if (!mNeverUseDeviceSurface && !ShouldUseImageSurfaces()) {
mQuartzSurface = new gfxQuartzImageSurface(mImageSurface);
}
#endif
mStride = mImageSurface->Stride();
return NS_OK;
}
nsThebesImage::~nsThebesImage()
{
#ifdef USE_WIN_SURFACE
if (mIsDDBSurface) {
gTotalDDBs--;
gTotalDDBSize -= mWidth*mHeight*4;
}
#endif
}
PRInt32
nsThebesImage::GetBytesPix()
{
return 4;
}
PRBool
nsThebesImage::GetIsRowOrderTopToBottom()
{
return PR_TRUE;
}
PRInt32
nsThebesImage::GetWidth()
{
return mWidth;
}
PRInt32
nsThebesImage::GetHeight()
{
return mHeight;
}
PRUint8 *
nsThebesImage::GetBits()
{
if (mImageSurface)
return mImageSurface->Data();
return nsnull;
}
PRInt32
nsThebesImage::GetLineStride()
{
return mStride;
}
PRBool
nsThebesImage::GetHasAlphaMask()
{
return mAlphaDepth > 0;
}
PRUint8 *
nsThebesImage::GetAlphaBits()
{
return nsnull;
}
PRInt32
nsThebesImage::GetAlphaLineStride()
{
return (mAlphaDepth > 0) ? mStride : 0;
}
nsresult
nsThebesImage::ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsIntRect *aUpdateRect)
{
// Check to see if we are running OOM
nsCOMPtr<nsIMemory> mem;
NS_GetMemoryManager(getter_AddRefs(mem));
if (!mem)
return NS_ERROR_UNEXPECTED;
PRBool lowMemory;
mem->IsLowMemory(&lowMemory);
if (lowMemory)
return NS_ERROR_OUT_OF_MEMORY;
mDecoded.UnionRect(mDecoded, *aUpdateRect);
// clamp to bounds, in case someone sends a bogus
// updateRect (I'm looking at you, gif decoder)
nsIntRect boundsRect(0, 0, mWidth, mHeight);
mDecoded.IntersectRect(mDecoded, boundsRect);
#ifdef XP_MACOSX
if (mQuartzSurface)
mQuartzSurface->Flush();
#endif
return NS_OK;
}
PRBool
nsThebesImage::GetIsImageComplete()
{
if (!mImageComplete)
mImageComplete = (mDecoded == nsIntRect(0, 0, mWidth, mHeight));
return mImageComplete;
}
nsresult
nsThebesImage::Optimize(nsIDeviceContext* aContext)
{
if (gDisableOptimize)
return NS_OK;
if (mOptSurface || mSinglePixel)
return NS_OK;
/* Figure out if the entire image is a constant color */
// this should always be true
if (mStride == mWidth * 4) {
PRUint32 *imgData = (PRUint32*) mImageSurface->Data();
PRUint32 firstPixel = * (PRUint32*) imgData;
PRUint32 pixelCount = mWidth * mHeight + 1;
while (--pixelCount && *imgData++ == firstPixel)
;
if (pixelCount == 0) {
// all pixels were the same
if (mFormat == gfxImageSurface::ImageFormatARGB32 ||
mFormat == gfxImageSurface::ImageFormatRGB24)
{
mSinglePixelColor = gfxRGBA
(firstPixel,
(mFormat == gfxImageSurface::ImageFormatRGB24 ?
gfxRGBA::PACKED_XRGB :
gfxRGBA::PACKED_ARGB_PREMULTIPLIED));
mSinglePixel = PR_TRUE;
// blow away the older surfaces, to release data
mImageSurface = nsnull;
mOptSurface = nsnull;
#ifdef USE_WIN_SURFACE
mWinSurface = nsnull;
#endif
#ifdef XP_MACOSX
mQuartzSurface = nsnull;
#endif
return NS_OK;
}
}
// if it's not RGB24/ARGB32, don't optimize, but we never hit this at the moment
}
// if we're being forced to use image surfaces due to
// resource constraints, don't try to optimize beyond same-pixel.
if (mNeverUseDeviceSurface || ShouldUseImageSurfaces())
return NS_OK;
mOptSurface = nsnull;
#ifdef USE_WIN_SURFACE
// we need to special-case windows here, because windows has
// a distinction between DIB and DDB and we want to use DDBs as much
// as we can.
if (mWinSurface) {
// Don't do DDBs for large images; see bug 359147
// Note that we bother with DDBs at all because they are much faster
// on some systems; on others there isn't much of a speed difference
// between DIBs and DDBs.
//
// Originally this just limited to 1024x1024; but that still
// had us hitting overall total memory usage limits (which was
// around 220MB on my intel shared memory system with 2GB RAM
// and 16-128mb in use by the video card, so I can't make
// heads or tails out of this limit).
//
// So instead, we clamp the max size to 64MB (this limit shuld
// be made dynamic based on.. something.. as soon a we figure
// out that something) and also limit each individual image to
// be less than 4MB to keep very large images out of DDBs.
// assume (almost -- we don't quadword-align) worst-case size
PRUint32 ddbSize = mWidth * mHeight * 4;
if (ddbSize <= kMaxSingleDDBSize &&
ddbSize + gTotalDDBSize <= kMaxDDBSize)
{
nsRefPtr<gfxWindowsSurface> wsurf = mWinSurface->OptimizeToDDB(nsnull, gfxIntSize(mWidth, mHeight), mFormat);
if (wsurf) {
gTotalDDBs++;
gTotalDDBSize += ddbSize;
mIsDDBSurface = PR_TRUE;
mOptSurface = wsurf;
}
}
if (!mOptSurface && !mFormatChanged) {
// just use the DIB if the format has not changed
mOptSurface = mWinSurface;
}
}
#endif
#ifdef XP_MACOSX
if (mQuartzSurface) {
mQuartzSurface->Flush();
mOptSurface = mQuartzSurface;
}
#endif
if (mOptSurface == nsnull)
mOptSurface = gfxPlatform::GetPlatform()->OptimizeImage(mImageSurface, mFormat);
if (mOptSurface) {
mImageSurface = nsnull;
#ifdef USE_WIN_SURFACE
mWinSurface = nsnull;
#endif
#ifdef XP_MACOSX
mQuartzSurface = nsnull;
#endif
}
return NS_OK;
}
nsColorMap *
nsThebesImage::GetColorMap()
{
return NULL;
}
PRInt8
nsThebesImage::GetAlphaDepth()
{
return mAlphaDepth;
}
void *
nsThebesImage::GetBitInfo()
{
return NULL;
}
NS_IMETHODIMP
nsThebesImage::LockImagePixels(PRBool aMaskPixels)
{
if (aMaskPixels)
return NS_ERROR_NOT_IMPLEMENTED;
if ((mOptSurface || mSinglePixel) && !mImageSurface) {
// Recover the pixels
mImageSurface = new gfxImageSurface(gfxIntSize(mWidth, mHeight),
gfxImageSurface::ImageFormatARGB32);
if (!mImageSurface || mImageSurface->CairoStatus())
return NS_ERROR_OUT_OF_MEMORY;
gfxContext context(mImageSurface);
context.SetOperator(gfxContext::OPERATOR_SOURCE);
if (mSinglePixel)
context.SetDeviceColor(mSinglePixelColor);
else
context.SetSource(mOptSurface);
context.Paint();
#ifdef USE_WIN_SURFACE
mWinSurface = nsnull;
#endif
#ifdef XP_MACOSX
mQuartzSurface = nsnull;
#endif
}
return NS_OK;
}
NS_IMETHODIMP
nsThebesImage::UnlockImagePixels(PRBool aMaskPixels)
{
if (aMaskPixels)
return NS_ERROR_NOT_IMPLEMENTED;
mOptSurface = nsnull;
#ifdef XP_MACOSX
if (mQuartzSurface)
mQuartzSurface->Flush();
#endif
return NS_OK;
}
static PRBool
IsSafeImageTransformComponent(gfxFloat aValue)
{
return aValue >= -32768 && aValue <= 32767;
}
void
nsThebesImage::Draw(gfxContext* aContext,
gfxPattern::GraphicsFilter aFilter,
const gfxMatrix& aUserSpaceToImageSpace,
const gfxRect& aFill,
const nsIntMargin& aPadding,
const nsIntRect& aSubimage)
{
NS_ASSERTION(!aFill.IsEmpty(), "zero dest size --- fix caller");
NS_ASSERTION(!aSubimage.IsEmpty(), "zero source size --- fix caller");
PRBool doPadding = aPadding != nsIntMargin(0,0,0,0);
PRBool doPartialDecode = !GetIsImageComplete();
gfxContext::GraphicsOperator op = aContext->CurrentOperator();
if (mSinglePixel && !doPadding && !doPartialDecode) {
// Single-color fast path
// if a == 0, it's a noop
if (mSinglePixelColor.a == 0.0)
return;
if (op == gfxContext::OPERATOR_OVER && mSinglePixelColor.a == 1.0)
aContext->SetOperator(gfxContext::OPERATOR_SOURCE);
aContext->SetDeviceColor(mSinglePixelColor);
aContext->NewPath();
aContext->Rectangle(aFill);
aContext->Fill();
aContext->SetOperator(op);
aContext->SetDeviceColor(gfxRGBA(0,0,0,0));
return;
}
gfxMatrix userSpaceToImageSpace = aUserSpaceToImageSpace;
gfxRect sourceRect = userSpaceToImageSpace.Transform(aFill);
gfxRect imageRect(0, 0, mWidth + aPadding.LeftRight(), mHeight + aPadding.TopBottom());
gfxRect subimage(aSubimage.x, aSubimage.y, aSubimage.width, aSubimage.height);
gfxRect fill = aFill;
nsRefPtr<gfxASurface> surface;
gfxImageSurface::gfxImageFormat format;
NS_ASSERTION(!sourceRect.Intersect(subimage).IsEmpty(),
"We must be allowed to sample *some* source pixels!");
PRBool doTile = !imageRect.Contains(sourceRect);
if (doPadding || doPartialDecode) {
gfxRect available = gfxRect(mDecoded.x, mDecoded.y, mDecoded.width, mDecoded.height) +
gfxPoint(aPadding.left, aPadding.top);
if (!doTile && !mSinglePixel) {
// Not tiling, and we have a surface, so we can account for
// padding and/or a partial decode just by twiddling parameters.
// First, update our user-space fill rect.
sourceRect = sourceRect.Intersect(available);
gfxMatrix imageSpaceToUserSpace = userSpaceToImageSpace;
imageSpaceToUserSpace.Invert();
fill = imageSpaceToUserSpace.Transform(sourceRect);
surface = ThebesSurface();
format = mFormat;
subimage = subimage.Intersect(available) - gfxPoint(aPadding.left, aPadding.top);
userSpaceToImageSpace.Multiply(
gfxMatrix().Translate(-gfxPoint(aPadding.left, aPadding.top)));
sourceRect = sourceRect - gfxPoint(aPadding.left, aPadding.top);
imageRect = gfxRect(0, 0, mWidth, mHeight);
} else {
// Create a temporary surface
gfxIntSize size(PRInt32(imageRect.Width()),
PRInt32(imageRect.Height()));
// Give this surface an alpha channel because there are
// transparent pixels in the padding or undecoded area
format = gfxASurface::ImageFormatARGB32;
surface = gfxPlatform::GetPlatform()->CreateOffscreenSurface(size,
format);
if (!surface || surface->CairoStatus() != 0)
return;
// Fill 'available' with whatever we've got
gfxContext tmpCtx(surface);
tmpCtx.SetOperator(gfxContext::OPERATOR_SOURCE);
if (mSinglePixel) {
tmpCtx.SetDeviceColor(mSinglePixelColor);
} else {
tmpCtx.SetSource(ThebesSurface(), gfxPoint(aPadding.left, aPadding.top));
}
tmpCtx.Rectangle(available);
tmpCtx.Fill();
}
} else {
NS_ASSERTION(!mSinglePixel, "This should already have been handled");
surface = ThebesSurface();
format = mFormat;
}
// At this point, we've taken care of mSinglePixel images, images with
// aPadding, and partially-decoded images.
if (!AllowedImageSize(fill.size.width + 1, fill.size.height + 1)) {
NS_WARNING("Destination area too large, bailing out");
return;
}
// Compute device-space-to-image-space transform. We need to sanity-
// check it to work around a pixman bug :-(
// XXX should we only do this for certain surface types?
gfxFloat deviceX, deviceY;
nsRefPtr<gfxASurface> currentTarget =
aContext->CurrentSurface(&deviceX, &deviceY);
gfxMatrix currentMatrix = aContext->CurrentMatrix();
gfxMatrix deviceToUser = currentMatrix;
deviceToUser.Invert();
deviceToUser.Translate(-gfxPoint(-deviceX, -deviceY));
gfxMatrix deviceToImage = deviceToUser;
deviceToImage.Multiply(userSpaceToImageSpace);
PRBool pushedGroup = PR_FALSE;
if (currentTarget->GetType() != gfxASurface::SurfaceTypeQuartz) {
// BEGIN working around cairo/pixman bug (bug 364968)
// Quartz's limits for matrix are much larger than pixman
// Our device-space-to-image-space transform may not be acceptable to pixman.
if (!IsSafeImageTransformComponent(deviceToImage.xx) ||
!IsSafeImageTransformComponent(deviceToImage.xy) ||
!IsSafeImageTransformComponent(deviceToImage.yx) ||
!IsSafeImageTransformComponent(deviceToImage.yy)) {
NS_WARNING("Scaling up too much, bailing out");
return;
}
if (!IsSafeImageTransformComponent(deviceToImage.x0) ||
!IsSafeImageTransformComponent(deviceToImage.y0)) {
// We'll push a group, which will hopefully reduce our transform's
// translation so it's in bounds
aContext->Save();
// Clip the rounded-out-to-device-pixels bounds of the
// transformed fill area. This is the area for the group we
// want to push.
aContext->IdentityMatrix();
gfxRect bounds = currentMatrix.TransformBounds(fill);
bounds.RoundOut();
aContext->Clip(bounds);
aContext->SetMatrix(currentMatrix);
aContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
aContext->SetOperator(gfxContext::OPERATOR_OVER);
pushedGroup = PR_TRUE;
}
// END working around cairo/pixman bug (bug 364968)
}
nsRefPtr<gfxPattern> pattern = new gfxPattern(surface);
pattern->SetMatrix(userSpaceToImageSpace);
// OK now, the hard part left is to account for the subimage sampling
// restriction. If all the transforms involved are just integer
// translations, then we assume no resampling will occur so there's
// nothing to do.
// XXX if only we had source-clipping in cairo!
if (!currentMatrix.HasNonIntegerTranslation() &&
!userSpaceToImageSpace.HasNonIntegerTranslation()) {
if (doTile) {
pattern->SetExtend(gfxPattern::EXTEND_REPEAT);
}
} else {
if (doTile || !subimage.Contains(imageRect)) {
// EXTEND_PAD won't help us here; we have to create a temporary
// surface to hold the subimage of pixels we're allowed to
// sample
gfxRect userSpaceClipExtents = aContext->GetClipExtents();
// This isn't optimal --- if aContext has a rotation then
// GetClipExtents will have to do a bounding-box computation,
// and TransformBounds might too, so we could get a better
// result if we computed image space clip extents in one go
// --- but it doesn't really matter and this is easier to
// understand.
gfxRect imageSpaceClipExtents =
userSpaceToImageSpace.TransformBounds(userSpaceClipExtents);
// Inflate by one pixel because bilinear filtering will sample
// at most one pixel beyond the computed image pixel coordinate.
imageSpaceClipExtents.Outset(1.0);
gfxRect needed =
imageSpaceClipExtents.Intersect(sourceRect).Intersect(subimage);
needed.RoundOut();
// if 'needed' is empty, nothing will be drawn since aFill
// must be entirely outside the clip region, so it doesn't
// matter what we do here, but we should avoid trying to
// create a zero-size surface.
if (!needed.IsEmpty()) {
gfxIntSize size(PRInt32(needed.Width()), PRInt32(needed.Height()));
nsRefPtr<gfxASurface> temp =
gfxPlatform::GetPlatform()->CreateOffscreenSurface(size, format);
if (temp && temp->CairoStatus() == 0) {
gfxContext tmpCtx(temp);
tmpCtx.SetOperator(gfxContext::OPERATOR_SOURCE);
nsRefPtr<gfxPattern> tmpPattern = new gfxPattern(surface);
if (tmpPattern) {
tmpPattern->SetExtend(gfxPattern::EXTEND_REPEAT);
tmpPattern->SetMatrix(gfxMatrix().Translate(needed.pos));
tmpCtx.SetPattern(tmpPattern);
tmpCtx.Paint();
tmpPattern = new gfxPattern(temp);
if (tmpPattern) {
pattern.swap(tmpPattern);
pattern->SetMatrix(
gfxMatrix(userSpaceToImageSpace).Multiply(gfxMatrix().Translate(-needed.pos)));
}
}
}
}
}
// In theory we can handle this using cairo's EXTEND_PAD,
// but implementation limitations mean we have to consult
// the surface type.
switch (currentTarget->GetType()) {
case gfxASurface::SurfaceTypeXlib:
case gfxASurface::SurfaceTypeXcb: {
// See bug 324698. This is a workaround for EXTEND_PAD not being
// implemented correctly on linux in the X server.
//
// Set the filter to CAIRO_FILTER_FAST --- otherwise,
// pixman's sampling will sample transparency for the outside edges and we'll
// get blurry edges. CAIRO_EXTEND_PAD would also work here, if
// available
//
// But don't do this for simple downscales because it's horrible.
// Downscaling means that device-space coordinates are
// scaled *up* to find the image pixel coordinates.
//
// deviceToImage is slightly stale because up above we may
// have adjusted the pattern's matrix ... but the adjustment
// is only a translation so the scale factors in deviceToImage
// are still valid.
PRBool isDownscale =
deviceToImage.xx >= 1.0 && deviceToImage.yy >= 1.0 &&
deviceToImage.xy == 0.0 && deviceToImage.yx == 0.0;
if (!isDownscale) {
pattern->SetFilter(gfxPattern::FILTER_FAST);
}
break;
}
case gfxASurface::SurfaceTypeQuartz:
case gfxASurface::SurfaceTypeQuartzImage:
// Don't set EXTEND_PAD, Mac seems to be OK. Really?
pattern->SetFilter(aFilter);
break;
default:
// turn on EXTEND_PAD.
// This is what we really want for all surface types, if the
// implementation was universally good.
pattern->SetExtend(gfxPattern::EXTEND_PAD);
pattern->SetFilter(aFilter);
break;
}
}
if ((op == gfxContext::OPERATOR_OVER || pushedGroup) &&
format == gfxASurface::ImageFormatRGB24) {
aContext->SetOperator(gfxContext::OPERATOR_SOURCE);
}
// Phew! Now we can actually draw this image
aContext->NewPath();
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
pattern->SetFilter(gfxPattern::FILTER_FAST);
#endif
aContext->SetPattern(pattern);
aContext->Rectangle(fill);
aContext->Fill();
aContext->SetOperator(op);
if (pushedGroup) {
aContext->PopGroupToSource();
aContext->Paint();
aContext->Restore();
}
}
nsresult
nsThebesImage::Extract(const nsIntRect& aRegion,
nsIImage** aResult)
{
nsRefPtr<nsThebesImage> subImage(new nsThebesImage());
if (!subImage)
return NS_ERROR_OUT_OF_MEMORY;
// The scaling problems described in bug 468496 are especially
// likely to be visible for the sub-image, as at present the only
// user is the border-image code and border-images tend to get
// stretched a lot. At the same time, the performance concerns
// that prevent us from just using Cairo's fallback scaler when
// accelerated graphics won't cut it are less relevant to such
// images, since they also tend to be small. Thus, we forcibly
// disable the use of anything other than a client-side image
// surface for the sub-image; this ensures that the correct
// (albeit slower) Cairo fallback scaler will be used.
subImage->mNeverUseDeviceSurface = PR_TRUE;
// ->Init() is just going to convert this back, bleah.
nsMaskRequirements maskReq;
switch (mAlphaDepth) {
case 0: maskReq = nsMaskRequirements_kNoMask; break;
case 1: maskReq = nsMaskRequirements_kNeeds1Bit; break;
case 8: maskReq = nsMaskRequirements_kNeeds8Bit; break;
default:
NS_NOTREACHED("impossible alpha depth");
maskReq = nsMaskRequirements_kNeeds8Bit; // safe
}
nsresult rv = subImage->Init(aRegion.width, aRegion.height,
8 /* ignored */, maskReq);
NS_ENSURE_SUCCESS(rv, rv);
{ // scope to destroy ctx
gfxContext ctx(subImage->ThebesSurface());
ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
if (mSinglePixel) {
ctx.SetDeviceColor(mSinglePixelColor);
} else {
// SetSource() places point (0,0) of its first argument at
// the coordinages given by its second argument. We want
// (x,y) of the image to be (0,0) of source space, so we
// put (0,0) of the image at (-x,-y).
ctx.SetSource(this->ThebesSurface(),
gfxPoint(-aRegion.x, -aRegion.y));
}
ctx.Rectangle(gfxRect(0, 0, aRegion.width, aRegion.height));
ctx.Fill();
}
nsIntRect filled(0, 0, aRegion.width, aRegion.height);
subImage->ImageUpdated(nsnull, nsImageUpdateFlags_kBitsChanged, &filled);
subImage->Optimize(nsnull);
NS_ADDREF(*aResult = subImage);
return NS_OK;
}
PRBool
nsThebesImage::ShouldUseImageSurfaces()
{
#if defined(WINCE)
// There is no test on windows mobile to check for Gui resources.
// Allocate, until we run out of memory.
gfxWindowsPlatform::RenderMode rmode = gfxWindowsPlatform::GetPlatform()->GetRenderMode();
return rmode != gfxWindowsPlatform::RENDER_DDRAW &&
rmode != gfxWindowsPlatform::RENDER_DDRAW_GL;
#elif defined(USE_WIN_SURFACE)
static const DWORD kGDIObjectsHighWaterMark = 7000;
// at 7000 GDI objects, stop allocating normal images to make sure
// we never hit the 10k hard limit.
// GetCurrentProcess() just returns (HANDLE)-1, it's inlined afaik
DWORD count = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
if (count == 0 ||
count > kGDIObjectsHighWaterMark)
{
// either something's broken (count == 0),
// or we hit our high water mark; disable
// image allocations for a bit.
return PR_TRUE;
}
#endif
return PR_FALSE;
}
// A hint from the image decoders that this image has no alpha, even
// though we created is ARGB32. This changes our format to RGB24,
// which in turn will cause us to Optimize() to RGB24. Has no effect
// after Optimize() is called, though in all cases it will be just a
// performance win -- the pixels are still correct and have the A byte
// set to 0xff.
void
nsThebesImage::SetHasNoAlpha()
{
if (mFormat == gfxASurface::ImageFormatARGB32) {
mFormat = gfxASurface::ImageFormatRGB24;
mFormatChanged = PR_TRUE;
mAlphaDepth = 0;
}
}

View file

@ -1,187 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is thebes gfx
*
* The Initial Developer of the Original Code is
* mozilla.org.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _NSTHEBESIMAGE_H_
#define _NSTHEBESIMAGE_H_
#include "nsIImage.h"
#include "gfxColor.h"
#include "gfxASurface.h"
#include "gfxImageSurface.h"
#include "gfxPattern.h"
#if defined(XP_WIN)
#include "gfxWindowsSurface.h"
#elif defined(XP_MACOSX)
#include "gfxQuartzImageSurface.h"
#endif
class nsThebesImage : public nsIImage
{
public:
nsThebesImage();
~nsThebesImage();
NS_DECL_ISUPPORTS
virtual nsresult Init(PRInt32 aWidth, PRInt32 aHeight,
PRInt32 aDepth, nsMaskRequirements aMaskRequirements);
virtual PRInt32 GetBytesPix();
virtual PRBool GetIsRowOrderTopToBottom();
virtual PRInt32 GetWidth();
virtual PRInt32 GetHeight();
virtual PRUint8 *GetBits();
virtual PRInt32 GetLineStride();
virtual PRBool GetHasAlphaMask();
virtual PRUint8 *GetAlphaBits();
virtual PRInt32 GetAlphaLineStride();
virtual PRBool GetIsImageComplete();
virtual nsresult ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsIntRect *aUpdateRect);
virtual nsresult Optimize(nsIDeviceContext* aContext);
virtual nsColorMap *GetColorMap();
virtual void Draw(gfxContext* aContext,
gfxPattern::GraphicsFilter aFilter,
const gfxMatrix& aUserSpaceToImageSpace,
const gfxRect& aFill,
const nsIntMargin& aPadding,
const nsIntRect& aSubimage);
virtual PRInt8 GetAlphaDepth();
virtual void* GetBitInfo();
NS_IMETHOD LockImagePixels(PRBool aMaskPixels);
NS_IMETHOD UnlockImagePixels(PRBool aMaskPixels);
NS_IMETHOD GetSurface(gfxASurface **aSurface) {
*aSurface = ThebesSurface();
NS_ADDREF(*aSurface);
return NS_OK;
}
NS_IMETHOD GetPattern(gfxPattern **aPattern) {
if (mSinglePixel)
*aPattern = new gfxPattern(mSinglePixelColor);
else
*aPattern = new gfxPattern(ThebesSurface());
NS_ADDREF(*aPattern);
return NS_OK;
}
gfxASurface* ThebesSurface() {
if (mOptSurface)
return mOptSurface;
#if defined(XP_WIN) && !defined(WINCE)
if (mWinSurface)
return mWinSurface;
#elif defined(XP_MACOSX)
if (mQuartzSurface)
return mQuartzSurface;
#endif
return mImageSurface;
}
void SetHasNoAlpha();
NS_IMETHOD Extract(const nsIntRect& aSubimage,
nsIImage** aResult NS_OUTPARAM);
protected:
static PRBool AllowedImageSize(PRInt32 aWidth, PRInt32 aHeight) {
NS_ASSERTION(aWidth > 0, "invalid image width");
NS_ASSERTION(aHeight > 0, "invalid image height");
// reject over-wide or over-tall images
const PRInt32 k64KLimit = 0x0000FFFF;
if (NS_UNLIKELY(aWidth > k64KLimit || aHeight > k64KLimit )) {
NS_WARNING("image too big");
return PR_FALSE;
}
// protect against division by zero - this really shouldn't happen
// if our consumers were well behaved, but they aren't (bug 368427)
if (NS_UNLIKELY(aHeight == 0)) {
return PR_FALSE;
}
// check to make sure we don't overflow a 32-bit
PRInt32 tmp = aWidth * aHeight;
if (NS_UNLIKELY(tmp / aHeight != aWidth)) {
NS_WARNING("width or height too large");
return PR_FALSE;
}
tmp = tmp * 4;
if (NS_UNLIKELY(tmp / 4 != aWidth * aHeight)) {
NS_WARNING("width or height too large");
return PR_FALSE;
}
return PR_TRUE;
}
gfxImageSurface::gfxImageFormat mFormat;
PRInt32 mWidth;
PRInt32 mHeight;
PRInt32 mStride;
nsIntRect mDecoded;
PRPackedBool mImageComplete;
PRPackedBool mSinglePixel;
PRPackedBool mFormatChanged;
PRPackedBool mNeverUseDeviceSurface;
#if defined(XP_WIN) && !defined(WINCE)
PRPackedBool mIsDDBSurface;
#endif
gfxRGBA mSinglePixelColor;
nsRefPtr<gfxImageSurface> mImageSurface;
nsRefPtr<gfxASurface> mOptSurface;
#if defined(XP_WIN) && !defined(WINCE)
nsRefPtr<gfxWindowsSurface> mWinSurface;
#elif defined(XP_MACOSX)
nsRefPtr<gfxQuartzImageSurface> mQuartzSurface;
#endif
PRUint8 mAlphaDepth;
// this function should return true if
// we should (temporarily) not allocate any
// platform native surfaces and instead use
// image surfaces for everything.
static PRBool ShouldUseImageSurfaces();
};
#endif /* _NSTHEBESIMAGE_H_ */

View file

@ -46,12 +46,7 @@
#include "nsIInterfaceRequestorUtils.h"
#include "nsGfxCIID.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "nsIImage.h"
#include "nsThebesRegion.h"
#include "nsThebesImage.h"
#include <stdlib.h>
#include <sys/types.h>

View file

@ -54,8 +54,6 @@
#include "nsIThebesFontMetrics.h"
#include "gfxContext.h"
class nsIImage;
class nsThebesRenderingContext : public nsIRenderingContext
{
public:

View file

@ -46,7 +46,6 @@
#include "nsStyleConsts.h"
#include "nsPresContext.h"
#include "nsIImage.h"
#include "nsIFrame.h"
#include "nsPoint.h"
#include "nsRect.h"
@ -63,7 +62,6 @@
#include "nsIScrollableFrame.h"
#include "imgIRequest.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "nsCSSRendering.h"
#include "nsCSSColorUtils.h"
#include "nsITheme.h"
@ -321,7 +319,7 @@ static void DrawBorderImage(nsPresContext* aPresContext,
static void DrawBorderImageComponent(nsIRenderingContext& aRenderingContext,
nsIFrame* aForFrame,
nsIImage* aImage,
imgIContainer* aImage,
const nsRect& aDirtyRect,
const nsRect& aFill,
const nsIntRect& aSrc,
@ -1687,27 +1685,9 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
drawBackgroundColor) {
nsCOMPtr<imgIContainer> image;
bottomImage->GetImage(getter_AddRefs(image));
// If the image is completely opaque, we may not need to paint
// the background color.
nsCOMPtr<gfxIImageFrame> gfxImgFrame;
image->GetCurrentFrame(getter_AddRefs(gfxImgFrame));
if (gfxImgFrame) {
gfxImgFrame->GetNeedsBackground(&drawBackgroundColor);
if (!drawBackgroundColor) {
// If the current frame is smaller than its container, we
// need to paint the background color even if the frame
// itself is opaque.
nsIntSize iSize;
image->GetWidth(&iSize.width);
image->GetHeight(&iSize.height);
nsIntRect iframeRect;
gfxImgFrame->GetRect(iframeRect);
if (iSize.width != iframeRect.width ||
iSize.height != iframeRect.height) {
drawBackgroundColor = PR_TRUE;
}
}
}
PRBool isOpaque;
if (NS_SUCCEEDED(image->GetCurrentFrameIsOpaque(&isOpaque)) && isOpaque)
drawBackgroundColor = PR_FALSE;
}
// The background color is rendered over the entire dirty area,
@ -1938,18 +1918,6 @@ DrawBorderImage(nsPresContext* aPresContext,
imgContainer->GetWidth(&imageSize.width);
imgContainer->GetHeight(&imageSize.height);
nsCOMPtr<gfxIImageFrame> imgFrame;
imgContainer->GetCurrentFrame(getter_AddRefs(imgFrame));
nsIntRect innerRect;
imgFrame->GetRect(innerRect);
nsCOMPtr<nsIImage> img(do_GetInterface(imgFrame));
// The inner rectangle should precisely enclose the image pixels for
// this frame.
NS_ASSERTION(innerRect.width == img->GetWidth(), "img inner width off");
NS_ASSERTION(innerRect.height == img->GetHeight(), "img inner height off");
// Convert percentages and clamp values to the image size.
nsIntMargin split;
NS_FOR_CSS_SIDES(s) {
@ -1983,7 +1951,7 @@ DrawBorderImage(nsPresContext* aPresContext,
// These helper tables recharacterize the 'split' and 'border' margins
// in a more convenient form: they are the x/y/width/height coords
// required for various bands of the border, and they have been transformed
// to be relative to the innerRect (for 'split') or the page (for 'border').
// to be relative to the image (for 'split') or the page (for 'border').
enum {
LEFT, MIDDLE, RIGHT,
TOP = LEFT, BOTTOM = RIGHT
@ -2010,14 +1978,14 @@ DrawBorderImage(nsPresContext* aPresContext,
};
const PRInt32 splitX[3] = {
-innerRect.x + 0,
-innerRect.x + split.left,
-innerRect.x + imageSize.width - split.right,
0,
split.left,
imageSize.width - split.right,
};
const PRInt32 splitY[3] = {
-innerRect.y + 0,
-innerRect.y + split.top,
-innerRect.y + imageSize.height - split.bottom,
0,
split.top,
imageSize.height - split.bottom,
};
const PRInt32 splitWidth[3] = {
split.left,
@ -2108,7 +2076,7 @@ DrawBorderImage(nsPresContext* aPresContext,
}
DrawBorderImageComponent(aRenderingContext, aForFrame,
img, aDirtyRect,
imgContainer, aDirtyRect,
destArea, subArea,
fillStyleH, fillStyleV, unitSize);
}
@ -2118,7 +2086,7 @@ DrawBorderImage(nsPresContext* aPresContext,
static void
DrawBorderImageComponent(nsIRenderingContext& aRenderingContext,
nsIFrame* aForFrame,
nsIImage* aImage,
imgIContainer* aImage,
const nsRect& aDirtyRect,
const nsRect& aFill,
const nsIntRect& aSrc,
@ -2129,8 +2097,8 @@ DrawBorderImageComponent(nsIRenderingContext& aRenderingContext,
if (aFill.IsEmpty() || aSrc.IsEmpty())
return;
nsCOMPtr<nsIImage> subImage;
if (NS_FAILED(aImage->Extract(aSrc, getter_AddRefs(subImage))))
nsCOMPtr<imgIContainer> subImage;
if (NS_FAILED(aImage->ExtractCurrentFrame(aSrc, getter_AddRefs(subImage))))
return;
gfxPattern::GraphicsFilter graphicsFilter =

View file

@ -39,7 +39,6 @@
#include "nsStyleConsts.h"
#include "nsPresContext.h"
#include "nsIImage.h"
#include "nsIFrame.h"
#include "nsPoint.h"
#include "nsRect.h"
@ -56,7 +55,6 @@
#include "nsIScrollableFrame.h"
#include "imgIRequest.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "nsCSSRendering.h"
#include "nsCSSColorUtils.h"
#include "nsITheme.h"

View file

@ -58,9 +58,7 @@
#endif
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIImage.h"
nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
PRBool aIsForEvents, PRBool aBuildCaret)
@ -555,18 +553,12 @@ nsDisplayBackground::IsOpaque(nsDisplayListBuilder* aBuilder) {
nsCOMPtr<imgIContainer> container;
bottomLayer.mImage->GetImage(getter_AddRefs(container));
if (container) {
PRUint32 nframes;
container->GetNumFrames(&nframes);
if (nframes == 1) {
nsCOMPtr<gfxIImageFrame> imgFrame;
container->GetCurrentFrame(getter_AddRefs(imgFrame));
if (imgFrame) {
nsCOMPtr<nsIImage> img(do_GetInterface(imgFrame));
PRBool hasMask = img->GetHasAlphaMask();
return !hasMask;
}
PRBool animated;
container->GetAnimated(&animated);
if (!animated) {
PRBool isOpaque;
if (NS_SUCCEEDED(container->GetCurrentFrameIsOpaque(&isOpaque)))
return isOpaque;
}
}
}

View file

@ -154,7 +154,7 @@ NS_IMETHODIMP nsImageLoader::OnStartContainer(imgIRequest *aRequest,
}
NS_IMETHODIMP nsImageLoader::OnStopFrame(imgIRequest *aRequest,
gfxIImageFrame *aFrame)
PRUint32 aFrame)
{
if (!mFrame)
return NS_ERROR_FAILURE;
@ -182,7 +182,6 @@ NS_IMETHODIMP nsImageLoader::OnStopFrame(imgIRequest *aRequest,
}
NS_IMETHODIMP nsImageLoader::FrameChanged(imgIContainer *aContainer,
gfxIImageFrame *newframe,
nsIntRect *dirtyRect)
{
if (!mFrame)

View file

@ -70,7 +70,7 @@ public:
// imgIDecoderObserver (override nsStubImageDecoderObserver)
NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
NS_IMETHOD OnStopFrame(imgIRequest *aRequest, gfxIImageFrame *aFrame);
NS_IMETHOD OnStopFrame(imgIRequest *aRequest, PRUint32 aFrame);
// Do not override OnDataAvailable since background images are not
// displayed incrementally; they are displayed after the entire image
// has been loaded.
@ -78,8 +78,7 @@ public:
// incrementally in nsImageFrame.cpp.
// imgIContainerObserver (override nsStubImageDecoderObserver)
NS_IMETHOD FrameChanged(imgIContainer *aContainer, gfxIImageFrame *newframe,
nsIntRect *dirtyRect);
NS_IMETHOD FrameChanged(imgIContainer *aContainer, nsIntRect *dirtyRect);
void Destroy();

View file

@ -61,12 +61,10 @@
#include "nsFrameManager.h"
#include "nsBlockFrame.h"
#include "nsBidiPresUtils.h"
#include "gfxIImageFrame.h"
#include "imgIContainer.h"
#include "gfxRect.h"
#include "gfxContext.h"
#include "gfxFont.h"
#include "nsIImage.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsCSSRendering.h"
#include "nsContentUtils.h"
@ -2732,14 +2730,13 @@ MapToFloatUserPixels(const gfxSize& aSize,
static nsresult
DrawImageInternal(nsIRenderingContext* aRenderingContext,
nsIImage* aImage,
imgIContainer* aImage,
gfxPattern::GraphicsFilter aGraphicsFilter,
const nsRect& aDest,
const nsRect& aFill,
const nsPoint& aAnchor,
const nsRect& aDirty,
const nsIntSize& aImageSize,
const nsIntRect& aInnerRect)
const nsIntSize& aImageSize)
{
if (aDest.IsEmpty() || aFill.IsEmpty())
return NS_OK;
@ -2839,22 +2836,18 @@ DrawImageInternal(nsIRenderingContext* aRenderingContext,
if (finalFillRect.IsEmpty())
return NS_OK;
nsIntMargin padding(aInnerRect.x, aInnerRect.y,
imageSize.width - aInnerRect.XMost(),
imageSize.height - aInnerRect.YMost());
aImage->Draw(ctx, aGraphicsFilter, transform, finalFillRect, padding, intSubimage);
aImage->Draw(ctx, aGraphicsFilter, transform, finalFillRect, intSubimage);
return NS_OK;
}
/* Workhorse for DrawSingleUnscaledImage. */
static nsresult
DrawSingleUnscaledImageInternal(nsIRenderingContext* aRenderingContext,
nsIImage* aImage,
imgIContainer* aImage,
const nsPoint& aDest,
const nsRect& aDirty,
const nsRect* aSourceArea,
const nsIntSize& aImageSize,
const nsIntRect& aInnerRect)
const nsIntSize& aImageSize)
{
if (aImageSize.width == 0 || aImageSize.height == 0)
return NS_OK;
@ -2877,19 +2870,18 @@ DrawSingleUnscaledImageInternal(nsIRenderingContext* aRenderingContext,
// translation but we don't want to actually tile the image.
fill.IntersectRect(fill, dest);
return DrawImageInternal(aRenderingContext, aImage, gfxPattern::FILTER_NEAREST,
dest, fill, aDest, aDirty, aImageSize, aInnerRect);
dest, fill, aDest, aDirty, aImageSize);
}
/* Workhorse for DrawSingleImage. */
static nsresult
DrawSingleImageInternal(nsIRenderingContext* aRenderingContext,
nsIImage* aImage,
imgIContainer* aImage,
gfxPattern::GraphicsFilter aGraphicsFilter,
const nsRect& aDest,
const nsRect& aDirty,
const nsRect* aSourceArea,
const nsIntSize& aImageSize,
const nsIntRect& aInnerRect)
const nsIntSize& aImageSize)
{
if (aImageSize.width == 0 || aImageSize.height == 0)
return NS_OK;
@ -2911,7 +2903,7 @@ DrawSingleImageInternal(nsIRenderingContext* aRenderingContext,
nsRect fill;
fill.IntersectRect(aDest, dest);
return DrawImageInternal(aRenderingContext, aImage, aGraphicsFilter, dest, fill,
fill.TopLeft(), aDirty, aImageSize, aInnerRect);
fill.TopLeft(), aDirty, aImageSize);
}
/* The exposed Draw*Image functions just do interface conversion and call the
@ -2926,38 +2918,13 @@ nsLayoutUtils::DrawImage(nsIRenderingContext* aRenderingContext,
const nsPoint& aAnchor,
const nsRect& aDirty)
{
nsCOMPtr<gfxIImageFrame> imgFrame;
aImage->GetCurrentFrame(getter_AddRefs(imgFrame));
if (!imgFrame) return NS_ERROR_FAILURE;
nsCOMPtr<nsIImage> img(do_GetInterface(imgFrame));
if (!img) return NS_ERROR_FAILURE;
nsIntRect innerRect;
imgFrame->GetRect(innerRect);
nsIntSize imageSize;
aImage->GetWidth(&imageSize.width);
aImage->GetHeight(&imageSize.height);
return DrawImageInternal(aRenderingContext, img, aGraphicsFilter,
aDest, aFill, aAnchor, aDirty,
imageSize, innerRect);
}
/* static */ nsresult
nsLayoutUtils::DrawImage(nsIRenderingContext* aRenderingContext,
nsIImage* aImage,
gfxPattern::GraphicsFilter aGraphicsFilter,
const nsRect& aDest,
const nsRect& aFill,
const nsPoint& aAnchor,
const nsRect& aDirty)
{
nsIntSize imageSize(aImage->GetWidth(), aImage->GetHeight());
return DrawImageInternal(aRenderingContext, aImage, aGraphicsFilter,
aDest, aFill, aAnchor, aDirty,
imageSize, nsIntRect(nsIntPoint(0,0), imageSize));
imageSize);
}
/* static */ nsresult
@ -2967,23 +2934,13 @@ nsLayoutUtils::DrawSingleUnscaledImage(nsIRenderingContext* aRenderingContext,
const nsRect& aDirty,
const nsRect* aSourceArea)
{
nsCOMPtr<gfxIImageFrame> imgFrame;
aImage->GetCurrentFrame(getter_AddRefs(imgFrame));
if (!imgFrame) return NS_ERROR_FAILURE;
nsCOMPtr<nsIImage> img(do_GetInterface(imgFrame));
if (!img) return NS_ERROR_FAILURE;
nsIntRect innerRect;
imgFrame->GetRect(innerRect);
nsIntSize imageSize;
aImage->GetWidth(&imageSize.width);
aImage->GetHeight(&imageSize.height);
return DrawSingleUnscaledImageInternal(aRenderingContext, img,
return DrawSingleUnscaledImageInternal(aRenderingContext, aImage,
aDest, aDirty, aSourceArea,
imageSize, innerRect);
imageSize);
}
/* static */ nsresult
@ -2994,41 +2951,15 @@ nsLayoutUtils::DrawSingleImage(nsIRenderingContext* aRenderingContext,
const nsRect& aDirty,
const nsRect* aSourceArea)
{
nsCOMPtr<gfxIImageFrame> imgFrame;
aImage->GetCurrentFrame(getter_AddRefs(imgFrame));
if (!imgFrame) return NS_ERROR_FAILURE;
nsCOMPtr<nsIImage> img(do_GetInterface(imgFrame));
if (!img) return NS_ERROR_FAILURE;
nsIntRect innerRect;
imgFrame->GetRect(innerRect);
nsIntSize imageSize;
aImage->GetWidth(&imageSize.width);
aImage->GetHeight(&imageSize.height);
return DrawSingleImageInternal(aRenderingContext, img, aGraphicsFilter,
aDest, aDirty, aSourceArea,
imageSize, innerRect);
}
/* static */ nsresult
nsLayoutUtils::DrawSingleImage(nsIRenderingContext* aRenderingContext,
nsIImage* aImage,
gfxPattern::GraphicsFilter aGraphicsFilter,
const nsRect& aDest,
const nsRect& aDirty,
const nsRect* aSourceArea)
{
nsIntSize imageSize(aImage->GetWidth(), aImage->GetHeight());
return DrawSingleImageInternal(aRenderingContext, aImage, aGraphicsFilter,
aDest, aDirty, aSourceArea,
imageSize,
nsIntRect(nsIntPoint(0, 0), imageSize));
imageSize);
}
/* static */ nsRect
nsLayoutUtils::GetWholeImageDestination(const nsIntSize& aWholeImageSize,
const nsRect& aImageSourceArea,
@ -3386,7 +3317,6 @@ nsLayoutUtils::SurfaceFromElement(nsIDOMElement *aElement,
#endif
// Finally, check if it's a normal image
nsCOMPtr<imgIContainer> imgContainer;
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(aElement);
if (!imageLoader)
@ -3425,34 +3355,28 @@ nsLayoutUtils::SurfaceFromElement(nsIDOMElement *aElement,
return result;
}
nsCOMPtr<imgIContainer> imgContainer;
rv = imgRequest->GetImage(getter_AddRefs(imgContainer));
if (NS_FAILED(rv) || !imgContainer)
return result;
nsCOMPtr<gfxIImageFrame> frame;
rv = imgContainer->GetCurrentFrame(getter_AddRefs(frame));
nsRefPtr<gfxASurface> framesurf;
rv = imgContainer->GetCurrentFrame(getter_AddRefs(framesurf));
if (NS_FAILED(rv))
return result;
nsCOMPtr<nsIImage> img(do_GetInterface(frame));
if (!img)
return result;
PRInt32 imgWidth, imgHeight;
rv = frame->GetWidth(&imgWidth);
rv |= frame->GetHeight(&imgHeight);
rv = imgContainer->GetWidth(&imgWidth);
rv |= imgContainer->GetHeight(&imgHeight);
if (NS_FAILED(rv))
return result;
nsRefPtr<gfxPattern> gfxpattern;
img->GetPattern(getter_AddRefs(gfxpattern));
nsRefPtr<gfxASurface> gfxsurf = gfxpattern->GetSurface();
if (wantImageSurface && gfxsurf->GetType() != gfxASurface::SurfaceTypeImage) {
if (wantImageSurface && framesurf->GetType() != gfxASurface::SurfaceTypeImage) {
forceCopy = PR_TRUE;
}
if (forceCopy || !gfxsurf) {
nsRefPtr<gfxASurface> gfxsurf = framesurf;
if (forceCopy) {
if (wantImageSurface) {
gfxsurf = new gfxImageSurface (gfxIntSize(imgWidth, imgHeight), gfxASurface::ImageFormatARGB32);
} else {
@ -3463,7 +3387,7 @@ nsLayoutUtils::SurfaceFromElement(nsIDOMElement *aElement,
nsRefPtr<gfxContext> ctx = new gfxContext(gfxsurf);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->SetPattern(gfxpattern);
ctx->SetSource(framesurf);
ctx->Paint();
}

View file

@ -862,14 +862,6 @@ public:
const nsPoint& aAnchor,
const nsRect& aDirty);
static nsresult DrawImage(nsIRenderingContext* aRenderingContext,
nsIImage* aImage,
gfxPattern::GraphicsFilter aGraphicsFilter,
const nsRect& aDest,
const nsRect& aFill,
const nsPoint& aAnchor,
const nsRect& aDirty);
/**
* Draw a whole image without scaling or tiling.
*
@ -911,13 +903,6 @@ public:
const nsRect& aDirty,
const nsRect* aSourceArea = nsnull);
static nsresult DrawSingleImage(nsIRenderingContext* aRenderingContext,
nsIImage* aImage,
gfxPattern::GraphicsFilter aGraphicsFilter,
const nsRect& aDest,
const nsRect& aDirty,
const nsRect* aSourceArea = nsnull);
/**
* Given a source area of an image (in appunits) and a destination area
* that we want to map that source area too, computes the area that

View file

@ -84,7 +84,6 @@ class nsIContent;
class nsIFontMetrics;
class nsIFrame;
class nsFrameManager;
class nsIImage;
class nsILinkHandler;
class nsStyleContext;
class nsIAtom;

View file

@ -52,7 +52,6 @@
#include "nsISupports.h"
#include "nsGkAtoms.h"
#include "nsCSSAnonBoxes.h"
#include "nsIImage.h"
#include "nsStyleConsts.h"
#include "nsIComponentManager.h"
#include "nsIDocument.h"

View file

@ -49,7 +49,6 @@
#include "nsGkAtoms.h"
#include "nsIDeviceContext.h"
#include "nsIFontMetrics.h"
#include "nsIImage.h"
#include "nsStyleConsts.h"
#include "nsFormControlFrame.h"
#include "nsGUIEvent.h"

View file

@ -71,13 +71,12 @@ public:
NS_DECL_ISUPPORTS
// imgIDecoderObserver (override nsStubImageDecoderObserver)
NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
NS_IMETHOD OnDataAvailable(imgIRequest *aRequest, gfxIImageFrame *aFrame,
NS_IMETHOD OnDataAvailable(imgIRequest *aRequest, PRBool aCurrentFrame,
const nsIntRect *aRect);
NS_IMETHOD OnStopDecode(imgIRequest *aRequest, nsresult status,
const PRUnichar *statusArg);
// imgIContainerObserver (override nsStubImageDecoderObserver)
NS_IMETHOD FrameChanged(imgIContainer *aContainer, gfxIImageFrame *newframe,
nsIntRect *dirtyRect);
NS_IMETHOD FrameChanged(imgIContainer *aContainer, nsIntRect *dirtyRect);
void SetFrame(nsBulletFrame *frame) { mFrame = frame; }
@ -1458,7 +1457,7 @@ NS_IMETHODIMP nsBulletFrame::OnStartContainer(imgIRequest *aRequest,
}
NS_IMETHODIMP nsBulletFrame::OnDataAvailable(imgIRequest *aRequest,
gfxIImageFrame *aFrame,
PRBool aCurrentFrame,
const nsIntRect *aRect)
{
// The image has changed.
@ -1489,7 +1488,6 @@ NS_IMETHODIMP nsBulletFrame::OnStopDecode(imgIRequest *aRequest,
}
NS_IMETHODIMP nsBulletFrame::FrameChanged(imgIContainer *aContainer,
gfxIImageFrame *aNewFrame,
nsIntRect *aDirtyRect)
{
// Invalidate the entire content area. Maybe it's not optimal but it's simple and
@ -1547,13 +1545,13 @@ NS_IMETHODIMP nsBulletListener::OnStartContainer(imgIRequest *aRequest,
}
NS_IMETHODIMP nsBulletListener::OnDataAvailable(imgIRequest *aRequest,
gfxIImageFrame *aFrame,
PRBool aCurrentFrame,
const nsIntRect *aRect)
{
if (!mFrame)
return NS_ERROR_FAILURE;
return mFrame->OnDataAvailable(aRequest, aFrame, aRect);
return mFrame->OnDataAvailable(aRequest, aCurrentFrame, aRect);
}
NS_IMETHODIMP nsBulletListener::OnStopDecode(imgIRequest *aRequest,
@ -1567,11 +1565,10 @@ NS_IMETHODIMP nsBulletListener::OnStopDecode(imgIRequest *aRequest,
}
NS_IMETHODIMP nsBulletListener::FrameChanged(imgIContainer *aContainer,
gfxIImageFrame *newframe,
nsIntRect *dirtyRect)
{
if (!mFrame)
return NS_ERROR_FAILURE;
return mFrame->FrameChanged(aContainer, newframe, dirtyRect);
return mFrame->FrameChanged(aContainer, dirtyRect);
}

View file

@ -45,7 +45,6 @@
#include "imgIRequest.h"
#include "imgIDecoderObserver.h"
class gfxIImageFrame;
/**
* A simple class that manages the layout and rendering of html bullets.
@ -81,13 +80,12 @@ public:
NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
NS_IMETHOD OnDataAvailable(imgIRequest *aRequest,
gfxIImageFrame *aFrame,
PRBool aCurrentFrame,
const nsIntRect *aRect);
NS_IMETHOD OnStopDecode(imgIRequest *aRequest,
nsresult aStatus,
const PRUnichar *aStatusArg);
NS_IMETHOD FrameChanged(imgIContainer *aContainer,
gfxIImageFrame *aNewframe,
nsIntRect *aDirtyRect);
/* get list item text, without '.' */

View file

@ -109,7 +109,6 @@
#include "nsIServiceManager.h"
#include "imgIContainer.h"
#include "imgIRequest.h"
#include "gfxIImageFrame.h"
#include "nsILookAndFeel.h"
#include "nsLayoutCID.h"
#include "nsWidgetsCID.h" // for NS_LOOKANDFEEL_CID

View file

@ -47,7 +47,6 @@
#include "nsPresContext.h"
#include "nsIRenderingContext.h"
#include "nsIPresShell.h"
#include "nsIImage.h"
#include "nsGkAtoms.h"
#include "nsIDocument.h"
#include "nsINodeInfo.h"
@ -93,7 +92,6 @@
#include "nsCSSFrameConstructor.h"
#include "nsIPrefBranch2.h"
#include "nsIPrefService.h"
#include "gfxIImageFrame.h"
#include "nsIDOMRange.h"
#include "nsIContentPolicy.h"
@ -523,7 +521,7 @@ nsImageFrame::OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage)
nsresult
nsImageFrame::OnDataAvailable(imgIRequest *aRequest,
gfxIImageFrame *aFrame,
PRBool aCurrentFrame,
const nsIntRect *aRect)
{
// XXX do we need to make sure that the reflow from the
@ -555,16 +553,8 @@ nsImageFrame::OnDataAvailable(imgIRequest *aRequest,
// Don't invalidate if the current visible frame isn't the one the data is
// from
nsCOMPtr<imgIContainer> container;
aRequest->GetImage(getter_AddRefs(container));
if (container) {
nsCOMPtr<gfxIImageFrame> currentFrame;
container->GetCurrentFrame(getter_AddRefs(currentFrame));
if (aFrame != currentFrame) {
// just bail
return NS_OK;
}
}
if (!aCurrentFrame)
return NS_OK;
#ifdef DEBUG_decode
printf("Source rect (%d,%d,%d,%d) -> invalidate dest rect (%d,%d,%d,%d)\n",
@ -634,9 +624,7 @@ nsImageFrame::OnStopDecode(imgIRequest *aRequest,
}
nsresult
nsImageFrame::FrameChanged(imgIContainer *aContainer,
gfxIImageFrame *aNewFrame,
nsIntRect *aDirtyRect)
nsImageFrame::FrameChanged(imgIContainer *aContainer, nsIntRect *aDirtyRect)
{
if (!GetStyleVisibility()->IsVisible()) {
return NS_OK;
@ -1833,13 +1821,13 @@ NS_IMETHODIMP nsImageListener::OnStartContainer(imgIRequest *aRequest,
}
NS_IMETHODIMP nsImageListener::OnDataAvailable(imgIRequest *aRequest,
gfxIImageFrame *aFrame,
PRBool aCurrentFrame,
const nsIntRect *aRect)
{
if (!mFrame)
return NS_ERROR_FAILURE;
return mFrame->OnDataAvailable(aRequest, aFrame, aRect);
return mFrame->OnDataAvailable(aRequest, aCurrentFrame, aRect);
}
NS_IMETHODIMP nsImageListener::OnStopDecode(imgIRequest *aRequest,
@ -1853,13 +1841,12 @@ NS_IMETHODIMP nsImageListener::OnStopDecode(imgIRequest *aRequest,
}
NS_IMETHODIMP nsImageListener::FrameChanged(imgIContainer *aContainer,
gfxIImageFrame *newframe,
nsIntRect * dirtyRect)
{
if (!mFrame)
return NS_ERROR_FAILURE;
return mFrame->FrameChanged(aContainer, newframe, dirtyRect);
return mFrame->FrameChanged(aContainer, dirtyRect);
}
static PRBool

View file

@ -73,13 +73,12 @@ public:
NS_DECL_ISUPPORTS
// imgIDecoderObserver (override nsStubImageDecoderObserver)
NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
NS_IMETHOD OnDataAvailable(imgIRequest *aRequest, gfxIImageFrame *aFrame,
NS_IMETHOD OnDataAvailable(imgIRequest *aRequest, PRBool aCurrentFrame,
const nsIntRect *aRect);
NS_IMETHOD OnStopDecode(imgIRequest *aRequest, nsresult status,
const PRUnichar *statusArg);
// imgIContainerObserver (override nsStubImageDecoderObserver)
NS_IMETHOD FrameChanged(imgIContainer *aContainer, gfxIImageFrame *newframe,
nsIntRect * dirtyRect);
NS_IMETHOD FrameChanged(imgIContainer *aContainer, nsIntRect * dirtyRect);
void SetFrame(nsImageFrame *frame) { mFrame = frame; }
@ -218,15 +217,12 @@ protected:
protected:
friend class nsImageListener;
nsresult OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
nsresult OnDataAvailable(imgIRequest *aRequest,
gfxIImageFrame *aFrame,
nsresult OnDataAvailable(imgIRequest *aRequest, PRBool aCurrentFrame,
const nsIntRect *rect);
nsresult OnStopDecode(imgIRequest *aRequest,
nsresult aStatus,
const PRUnichar *aStatusArg);
nsresult FrameChanged(imgIContainer *aContainer,
gfxIImageFrame *aNewframe,
nsIntRect *aDirtyRect);
nsresult FrameChanged(imgIContainer *aContainer, nsIntRect *aDirtyRect);
private:
// random helpers

View file

@ -21,6 +21,6 @@
<rect width="100%" height="100%" fill="lime"/>
<rect width="183" height="183" fill="red"/>
<image width="183" height="183" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAABGdBTUEAALGPC%2FxhBQAAAAxJREFUGFdjYPjPAAACAgEA0dNGRAAAAABJRU5ErkJggg%3D%3D"/>
<image style="image-rendering: -moz-crisp-edges" width="183" height="183" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAABGdBTUEAALGPC%2FxhBQAAAAxJREFUGFdjYPjPAAACAgEA0dNGRAAAAABJRU5ErkJggg%3D%3D"/>
</svg>

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -37,7 +37,6 @@
#include "nsSVGPathGeometryFrame.h"
#include "nsIDOMSVGMatrix.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "nsStubImageDecoderObserver.h"
#include "nsImageLoadingContent.h"
#include "nsIDOMSVGImageElement.h"
@ -47,7 +46,6 @@
#include "nsSVGMatrix.h"
#include "gfxContext.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIImage.h"
class nsSVGImageFrame;
@ -61,8 +59,7 @@ public:
NS_IMETHOD OnStopDecode(imgIRequest *aRequest, nsresult status,
const PRUnichar *statusArg);
// imgIContainerObserver (override nsStubImageDecoderObserver)
NS_IMETHOD FrameChanged(imgIContainer *aContainer, gfxIImageFrame *newframe,
nsRect * dirtyRect);
NS_IMETHOD FrameChanged(imgIContainer *aContainer, nsIntRect * dirtyRect);
// imgIContainerObserver (override nsStubImageDecoderObserver)
NS_IMETHOD OnStartContainer(imgIRequest *aRequest,
imgIContainer *aContainer);
@ -243,16 +240,15 @@ nsSVGImageFrame::PaintSVG(nsSVGRenderState *aContext,
currentRequest->GetImage(getter_AddRefs(mImageContainer));
}
nsCOMPtr<gfxIImageFrame> currentFrame;
nsRefPtr<gfxASurface> currentFrame;
if (mImageContainer)
mImageContainer->GetCurrentFrame(getter_AddRefs(currentFrame));
nsRefPtr<gfxPattern> thebesPattern = nsnull;
if (currentFrame) {
nsCOMPtr<nsIImage> img(do_GetInterface(currentFrame));
img->GetPattern(getter_AddRefs(thebesPattern));
}
// We need to wrap the surface in a pattern to have somewhere to set the
// graphics filter.
nsRefPtr<gfxPattern> thebesPattern;
if (currentFrame)
thebesPattern = new gfxPattern(currentFrame);
if (thebesPattern) {
@ -279,8 +275,8 @@ nsSVGImageFrame::PaintSVG(nsSVGRenderState *aContext,
}
PRInt32 nativeWidth, nativeHeight;
currentFrame->GetWidth(&nativeWidth);
currentFrame->GetHeight(&nativeHeight);
mImageContainer->GetWidth(&nativeWidth);
mImageContainer->GetHeight(&nativeHeight);
nsSVGUtils::CompositePatternMatrix(gfx, thebesPattern, fini, nativeWidth, nativeHeight, opacity);
@ -384,8 +380,7 @@ NS_IMETHODIMP nsSVGImageListener::OnStopDecode(imgIRequest *aRequest,
}
NS_IMETHODIMP nsSVGImageListener::FrameChanged(imgIContainer *aContainer,
gfxIImageFrame *newframe,
nsRect * dirtyRect)
nsIntRect * dirtyRect)
{
if (!mFrame)
return NS_ERROR_FAILURE;

View file

@ -58,7 +58,6 @@
#include "nsPresContext.h"
#include "nsIRenderingContext.h"
#include "nsIPresShell.h"
#include "nsIImage.h"
#include "nsIDocument.h"
#include "nsIHTMLDocument.h"
#include "nsStyleConsts.h"
@ -543,7 +542,6 @@ NS_IMETHODIMP nsImageBoxFrame::OnStopDecode(imgIRequest *request,
}
NS_IMETHODIMP nsImageBoxFrame::FrameChanged(imgIContainer *container,
gfxIImageFrame *newframe,
nsIntRect *dirtyRect)
{
nsBoxLayoutState state(PresContext());
@ -591,12 +589,11 @@ NS_IMETHODIMP nsImageBoxListener::OnStopDecode(imgIRequest *request,
}
NS_IMETHODIMP nsImageBoxListener::FrameChanged(imgIContainer *container,
gfxIImageFrame *newframe,
nsIntRect *dirtyRect)
{
if (!mFrame)
return NS_ERROR_FAILURE;
return mFrame->FrameChanged(container, newframe, dirtyRect);
return mFrame->FrameChanged(container, dirtyRect);
}

View file

@ -59,8 +59,7 @@ public:
NS_IMETHOD OnStopDecode(imgIRequest *request, nsresult status,
const PRUnichar *statusArg);
// imgIContainerObserver (override nsStubImageDecoderObserver)
NS_IMETHOD FrameChanged(imgIContainer *container, gfxIImageFrame *newframe,
nsIntRect *dirtyRect);
NS_IMETHOD FrameChanged(imgIContainer *container, nsIntRect *dirtyRect);
void SetFrame(nsImageBoxFrame *frame) { mFrame = frame; }
@ -121,9 +120,7 @@ public:
NS_IMETHOD OnStopDecode(imgIRequest *request,
nsresult status,
const PRUnichar *statusArg);
NS_IMETHOD FrameChanged(imgIContainer *container,
gfxIImageFrame *newframe,
nsIntRect *dirtyRect);
NS_IMETHOD FrameChanged(imgIContainer *container, nsIntRect *dirtyRect);
virtual ~nsImageBoxFrame();

View file

@ -2173,11 +2173,11 @@ nsTreeBodyFrame::GetImage(PRInt32 aRowIndex, nsTreeColumn* aCol, PRBool aUseCont
imgIRequest *imgReq = entry.request;
imgReq->GetImageStatus(&status);
imgReq->GetImage(aResult); // We hand back the image here. The GetImage call addrefs *aResult.
PRUint32 numFrames = 1;
PRBool animated = PR_FALSE;
if (*aResult)
(*aResult)->GetNumFrames(&numFrames);
(*aResult)->GetAnimated(&animated);
if ((!(status & imgIRequest::STATUS_LOAD_COMPLETE)) || numFrames > 1) {
if ((!(status & imgIRequest::STATUS_LOAD_COMPLETE)) || animated) {
// We either aren't done loading, or we're animating. Add our row as a listener for invalidations.
nsCOMPtr<imgIDecoderObserver> obs;
imgReq->GetDecoderObserver(getter_AddRefs(obs));

View file

@ -64,7 +64,7 @@ NS_IMETHODIMP nsTreeImageListener::OnStartContainer(imgIRequest *aRequest,
}
NS_IMETHODIMP nsTreeImageListener::OnDataAvailable(imgIRequest *aRequest,
gfxIImageFrame *aFrame,
PRBool aCurrentFrame,
const nsIntRect *aRect)
{
Invalidate();
@ -72,7 +72,6 @@ NS_IMETHODIMP nsTreeImageListener::OnDataAvailable(imgIRequest *aRequest,
}
NS_IMETHODIMP nsTreeImageListener::FrameChanged(imgIContainer *aContainer,
gfxIImageFrame *newframe,
nsIntRect *dirtyRect)
{
Invalidate();

View file

@ -72,11 +72,10 @@ public:
NS_DECL_ISUPPORTS
// imgIDecoderObserver (override nsStubImageDecoderObserver)
NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
NS_IMETHOD OnDataAvailable(imgIRequest *aRequest, gfxIImageFrame *aFrame,
NS_IMETHOD OnDataAvailable(imgIRequest *aRequest, PRBool aCurrentFrame,
const nsIntRect *aRect);
// imgIContainerObserver (override nsStubImageDecoderObserver)
NS_IMETHOD FrameChanged(imgIContainer *aContainer, gfxIImageFrame *newframe,
nsIntRect *dirtyRect);
NS_IMETHOD FrameChanged(imgIContainer *aContainer, nsIntRect *dirtyRect);
NS_IMETHOD AddCell(PRInt32 aIndex, nsITreeColumn* aCol);

View file

@ -47,6 +47,7 @@
#define IMG_BUILD_xbm 1
#endif
#include "nsIDeviceContext.h"
#include "nsIGenericFactory.h"
#include "nsIModule.h"
#include "nsICategoryManager.h"
@ -206,7 +207,7 @@ static const nsModuleComponentInfo components[] =
imgLoaderConstructor, },
{ "image container",
NS_IMGCONTAINER_CID,
"@mozilla.org/image/container;1",
"@mozilla.org/image/container;2",
imgContainerConstructor, },
{ "image loader",
NS_IMGLOADER_CID,
@ -313,6 +314,12 @@ static const nsModuleComponentInfo components[] =
static nsresult
imglib_Initialize(nsIModule* aSelf)
{
// Hack: We need the gfx module to be initialized because we use gfxPlatform
// in imgFrame. Request something from the gfx module to ensure that
// everything's set up for us.
nsCOMPtr<nsIDeviceContext> devctx =
do_CreateInstance("@mozilla.org/gfx/devicecontext;1");
imgLoader::InitCache();
return NS_OK;
}

View file

@ -51,7 +51,6 @@
#include "nsIInterfaceRequestorUtils.h"
#include "imgILoad.h"
#include "nsIImage.h"
#include "prlog.h"
@ -89,11 +88,7 @@ NS_IMETHODIMP nsBMPDecoder::Init(imgILoad *aLoad)
mObserver = do_QueryInterface(aLoad);
nsresult rv;
mImage = do_CreateInstance("@mozilla.org/image/container;1", &rv);
if (NS_FAILED(rv))
return rv;
mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2", &rv);
mImage = do_CreateInstance("@mozilla.org/image/container;2", &rv);
if (NS_FAILED(rv))
return rv;
@ -106,13 +101,12 @@ NS_IMETHODIMP nsBMPDecoder::Close()
mImage->DecodingComplete();
if (mObserver) {
mObserver->OnStopFrame(nsnull, mFrame);
mObserver->OnStopFrame(nsnull, 0);
mObserver->OnStopContainer(nsnull, mImage);
mObserver->OnStopDecode(nsnull, NS_OK, nsnull);
mObserver = nsnull;
}
mImage = nsnull;
mFrame = nsnull;
return NS_OK;
}
@ -266,8 +260,10 @@ NS_METHOD nsBMPDecoder::ProcessData(const char* aBuffer, PRUint32 aCount)
NS_ENSURE_SUCCESS(rv, rv);
mOldLine = mCurLine = real_height;
PRUint32 imageLength;
if ((mBIH.compression == BI_RLE8) || (mBIH.compression == BI_RLE4)) {
rv = mFrame->Init(0, 0, mBIH.width, real_height, RLE_GFXFORMAT_ALPHA, 24);
rv = mImage->AppendFrame(0, 0, mBIH.width, real_height, gfxASurface::ImageFormatARGB32,
(PRUint8**)&mImageData, &imageLength);
} else {
// mRow is not used for RLE encoded images
mRow = (PRUint8*)malloc((mBIH.width * mBIH.bpp)/8 + 4);
@ -277,12 +273,10 @@ NS_METHOD nsBMPDecoder::ProcessData(const char* aBuffer, PRUint32 aCount)
if (!mRow) {
return NS_ERROR_OUT_OF_MEMORY;
}
rv = mFrame->Init(0, 0, mBIH.width, real_height, BMP_GFXFORMAT, 24);
rv = mImage->AppendFrame(0, 0, mBIH.width, real_height, gfxASurface::ImageFormatRGB24,
(PRUint8**)&mImageData, &imageLength);
}
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 imageLength;
mFrame->GetImageData((PRUint8**)&mImageData, &imageLength);
if (!mImageData)
return NS_ERROR_FAILURE;
@ -297,9 +291,7 @@ NS_METHOD nsBMPDecoder::ProcessData(const char* aBuffer, PRUint32 aCount)
memset(mImageData, 0, imageLength);
}
rv = mImage->AppendFrame(mFrame);
NS_ENSURE_SUCCESS(rv, rv);
mObserver->OnStartFrame(nsnull, mFrame);
mObserver->OnStartFrame(nsnull, 0);
NS_ENSURE_SUCCESS(rv, rv);
}
PRUint8 bpc; // bytes per color
@ -603,14 +595,11 @@ NS_METHOD nsBMPDecoder::ProcessData(const char* aBuffer, PRUint32 aCount)
nsIntRect r(0, mBIH.height < 0 ? -mBIH.height - mOldLine : mCurLine,
mBIH.width, rows);
// Tell the image that it's data has been updated
nsCOMPtr<nsIImage> img(do_GetInterface(mFrame, &rv));
// Tell the image that its data has been updated
rv = mImage->FrameUpdated(0, r);
NS_ENSURE_SUCCESS(rv, rv);
rv = img->ImageUpdated(nsnull, nsImageUpdateFlags_kBitsChanged, &r);
if (NS_FAILED(rv))
return rv;
mObserver->OnDataAvailable(nsnull, mFrame, &r);
mObserver->OnDataAvailable(nsnull, PR_TRUE, &r);
mOldLine = mCurLine;
}

View file

@ -43,7 +43,6 @@
#include "imgIDecoder.h"
#include "imgIContainer.h"
#include "imgIDecoderObserver.h"
#include "gfxIImageFrame.h"
#include "gfxColor.h"
#define NS_BMPDECODER_CID \
@ -118,9 +117,6 @@ struct bitFields {
#endif
#define USE_RGB
#define BMP_GFXFORMAT gfxIFormats::RGB
#define RLE_GFXFORMAT_ALPHA gfxIFormats::RGB_A1
#define GFXBYTESPERPIXEL 4
// BMPINFOHEADER.compression defines
#define BI_RLE8 1
@ -173,7 +169,6 @@ private:
nsCOMPtr<imgIDecoderObserver> mObserver;
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<gfxIImageFrame> mFrame;
PRUint32 mPos;

View file

@ -51,7 +51,6 @@
#include "imgILoad.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIImage.h"
#include "nsIProperties.h"
#include "nsISupportsPrimitives.h"
@ -93,39 +92,30 @@ NS_IMETHODIMP nsICODecoder::Init(imgILoad *aLoad)
{
mObserver = do_QueryInterface(aLoad);
mImage = do_CreateInstance("@mozilla.org/image/container;1");
mImage = do_CreateInstance("@mozilla.org/image/container;2");
if (!mImage)
return NS_ERROR_OUT_OF_MEMORY;
mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
if (!mFrame)
return NS_ERROR_OUT_OF_MEMORY;
return aLoad->SetImage(mImage);
}
NS_IMETHODIMP nsICODecoder::Close()
{
// Tell the image that it's data has been updated
// This should be a mFrame function, so that we don't have to query for interface...
nsIntRect r(0, 0, mDirEntry.mWidth, mDirEntry.mHeight);
nsCOMPtr<nsIImage> img(do_GetInterface(mFrame));
nsresult rv = NS_OK;
if (img)
rv = img->ImageUpdated(nsnull, nsImageUpdateFlags_kBitsChanged, &r);
nsresult rv = mImage->FrameUpdated(0, r);
mImage->DecodingComplete();
if (mObserver) {
mObserver->OnDataAvailable(nsnull, mFrame, &r);
mObserver->OnStopFrame(nsnull, mFrame);
mObserver->OnStopContainer(nsnull, mImage);
mObserver->OnDataAvailable(nsnull, PR_TRUE, &r);
mObserver->OnStopFrame(nsnull, 0);
mObserver->OnStopContainer(nsnull, 0);
mObserver->OnStopDecode(nsnull, NS_OK, nsnull);
mObserver = nsnull;
}
mImage = nsnull;
mFrame = nsnull;
mPos = 0;
@ -304,15 +294,13 @@ nsresult nsICODecoder::ProcessData(const char* aBuffer, PRUint32 aCount) {
if (!mRow)
return NS_ERROR_OUT_OF_MEMORY;
rv = mFrame->Init(0, 0, mDirEntry.mWidth, mDirEntry.mHeight, GFXFORMATALPHA8, 24);
NS_ENSURE_SUCCESS(rv, rv);
rv = mImage->AppendFrame(mFrame);
NS_ENSURE_SUCCESS(rv, rv);
mObserver->OnStartFrame(nsnull, mFrame);
PRUint32 imageLength;
rv = mImage->AppendFrame(0, 0, mDirEntry.mWidth, mDirEntry.mHeight,
gfxASurface::ImageFormatARGB32, (PRUint8**)&mImageData, &imageLength);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 imageLength;
mFrame->GetImageData((PRUint8**)&mImageData, &imageLength);
mObserver->OnStartFrame(nsnull, 0);
NS_ENSURE_SUCCESS(rv, rv);
}
if (mColors && (mPos >= mImageOffset + BITMAPINFOSIZE) &&

View file

@ -44,20 +44,12 @@
#include "imgIDecoder.h"
#include "imgIContainer.h"
#include "imgIDecoderObserver.h"
#include "gfxIImageFrame.h"
#include "nsBMPDecoder.h"
// {CB3EDE1A-0FA5-4e27-AAFE-0F7801E5A1F1}
#define NS_ICODECODER_CID \
{ 0xcb3ede1a, 0xfa5, 0x4e27, { 0xaa, 0xfe, 0xf, 0x78, 0x1, 0xe5, 0xa1, 0xf1 } }
#if defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS) || defined(MOZ_WIDGET_PHOTON)
#define GFXFORMATALPHA8 gfxIFormats::BGR_A8
#else
#define USE_RGBA1
#define GFXFORMATALPHA8 gfxIFormats::RGB_A8
#endif
struct IconDirEntry
{
PRUint8 mWidth;
@ -103,7 +95,6 @@ private:
private:
nsCOMPtr<imgIDecoderObserver> mObserver;
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<gfxIImageFrame> mFrame;
PRUint32 mPos;
PRUint16 mNumIcons;

View file

@ -74,7 +74,6 @@ mailing address.
#include <stddef.h>
#include "prmem.h"
#include "nsIImage.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsGIFDecoder2.h"
@ -142,7 +141,7 @@ NS_IMETHODIMP nsGIFDecoder2::Init(imgILoad *aLoad)
{
mObserver = do_QueryInterface(aLoad);
mImageContainer = do_CreateInstance("@mozilla.org/image/container;1");
mImageContainer = do_CreateInstance("@mozilla.org/image/container;2");
aLoad->SetImage(mImageContainer);
// Start with the version (GIF89a|GIF87a)
@ -161,8 +160,7 @@ NS_IMETHODIMP nsGIFDecoder2::Init(imgILoad *aLoad)
/* void close (); */
NS_IMETHODIMP nsGIFDecoder2::Close()
{
if (mImageFrame)
EndImageFrame();
EndImageFrame();
EndGIF();
PR_FREEIF(mGIFStruct.local_colormap);
@ -205,8 +203,7 @@ nsGIFDecoder2::FlushImageData(PRUint32 fromRow, PRUint32 rows)
nsIntRect r(0, fromRow, mGIFStruct.width, rows);
// Update image
nsCOMPtr<nsIImage> img(do_GetInterface(mImageFrame));
nsresult rv = img->ImageUpdated(nsnull, nsImageUpdateFlags_kBitsChanged, &r);
nsresult rv = mImageContainer->FrameUpdated(mGIFStruct.images_decoded, r);
if (NS_FAILED(rv)) {
return rv;
}
@ -214,8 +211,10 @@ nsGIFDecoder2::FlushImageData(PRUint32 fromRow, PRUint32 rows)
// Offset to the frame position
// Only notify observer(s) for first frame
if (!mGIFStruct.images_decoded && mObserver) {
PRUint32 imgCurFrame;
mImageContainer->GetCurrentFrameIndex(&imgCurFrame);
r.y += mGIFStruct.y_offset;
mObserver->OnDataAvailable(nsnull, mImageFrame, &r);
mObserver->OnDataAvailable(nsnull, imgCurFrame == PRUint32(mGIFStruct.images_decoded), &r);
}
return NS_OK;
}
@ -251,7 +250,7 @@ nsresult nsGIFDecoder2::ProcessData(unsigned char *data, PRUint32 count, PRUint3
NS_ENSURE_SUCCESS(rv, rv);
// Flushing is only needed for first frame
if (!mGIFStruct.images_decoded && mImageFrame) {
if (!mGIFStruct.images_decoded) {
rv = FlushImageData();
mLastFlushedRow = mCurrentRow;
mLastFlushedPass = mCurrentPass;
@ -324,8 +323,6 @@ void nsGIFDecoder2::EndGIF()
//******************************************************************************
void nsGIFDecoder2::BeginImageFrame(gfx_depth aDepth)
{
mImageFrame = nsnull; // clear out our current frame reference
if (!mGIFStruct.images_decoded) {
// Send a onetime OnDataAvailable (Display Refresh) for the first frame
// if it has a y-axis offset. Otherwise, the area may never be refreshed
@ -333,41 +330,46 @@ void nsGIFDecoder2::BeginImageFrame(gfx_depth aDepth)
if (mGIFStruct.y_offset > 0) {
PRInt32 imgWidth;
mImageContainer->GetWidth(&imgWidth);
PRUint32 imgCurFrame;
mImageContainer->GetCurrentFrameIndex(&imgCurFrame);
nsIntRect r(0, 0, imgWidth, mGIFStruct.y_offset);
mObserver->OnDataAvailable(nsnull, mImageFrame, &r);
mObserver->OnDataAvailable(nsnull, imgCurFrame == PRUint32(mGIFStruct.images_decoded), &r);
}
}
PRUint32 imageDataLength;
nsresult rv;
gfxASurface::gfxImageFormat format;
if (mGIFStruct.is_transparent)
format = gfxASurface::ImageFormatARGB32;
else
format = gfxASurface::ImageFormatRGB24;
// Use correct format, RGB for first frame, PAL for following frames
// and include transparency to allow for optimization of opaque images
gfx_format format;
if (mGIFStruct.images_decoded) {
// Image data is stored with original depth and palette
format = mGIFStruct.is_transparent ? gfxIFormats::PAL_A1 : gfxIFormats::PAL;
rv = mImageContainer->AppendPalettedFrame(mGIFStruct.x_offset, mGIFStruct.y_offset,
mGIFStruct.width, mGIFStruct.height,
format, aDepth, &mImageData, &imageDataLength,
&mColormap, &mColormapSize);
} else {
// Regardless of depth of input, image is decoded into 24bit RGB
format = mGIFStruct.is_transparent ? gfxIFormats::RGB_A1 : gfxIFormats::RGB;
aDepth = 24;
rv = mImageContainer->AppendFrame(mGIFStruct.x_offset, mGIFStruct.y_offset,
mGIFStruct.width, mGIFStruct.height,
format, &mImageData, &imageDataLength);
}
// initialize the frame and append it to the container
mImageFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
if (!mImageFrame || NS_FAILED(mImageFrame->Init(
mGIFStruct.x_offset, mGIFStruct.y_offset,
mGIFStruct.width, mGIFStruct.height, format, aDepth))) {
mImageFrame = 0;
if (NS_FAILED(rv))
return;
}
mImageFrame->SetFrameDisposalMethod(mGIFStruct.disposal_method);
if (!mGIFStruct.images_decoded)
mImageContainer->AppendFrame(mImageFrame);
mImageContainer->SetFrameDisposalMethod(mGIFStruct.images_decoded,
mGIFStruct.disposal_method);
if (mObserver)
mObserver->OnStartFrame(nsnull, mImageFrame);
PRUint32 imageDataLength;
mImageFrame->GetImageData(&mImageData, &imageDataLength);
mObserver->OnStartFrame(nsnull, mGIFStruct.images_decoded);
}
@ -384,20 +386,23 @@ void nsGIFDecoder2::EndImageFrame()
// This will clear the remaining bits of the placeholder. (Bug 37589)
const PRUint32 realFrameHeight = mGIFStruct.height + mGIFStruct.y_offset;
if (realFrameHeight < mGIFStruct.screen_height) {
PRUint32 imgCurFrame;
mImageContainer->GetCurrentFrameIndex(&imgCurFrame);
nsIntRect r(0, realFrameHeight,
mGIFStruct.screen_width,
mGIFStruct.screen_height - realFrameHeight);
mObserver->OnDataAvailable(nsnull, mImageFrame, &r);
mObserver->OnDataAvailable(nsnull, imgCurFrame == PRUint32(mGIFStruct.images_decoded), &r);
}
// This transparency check is only valid for first frame
if (mGIFStruct.is_transparent && !mSawTransparency) {
nsCOMPtr<nsIImage> img(do_GetInterface(mImageFrame));
img->SetHasNoAlpha();
mImageContainer->SetFrameHasNoAlpha(mGIFStruct.images_decoded);
}
}
mCurrentRow = mLastFlushedRow = -1;
mCurrentPass = mLastFlushedPass = 0;
PRUint32 curframe = mGIFStruct.images_decoded;
// Only add frame if we have any rows at all
if (mGIFStruct.rows_remaining != mGIFStruct.height) {
if (mGIFStruct.rows_remaining && mGIFStruct.images_decoded) {
@ -410,18 +415,14 @@ void nsGIFDecoder2::EndImageFrame()
// image data, at least according to the spec, but we delay in setting the
// timeout for the image until here to help ensure that we have the whole
// image frame decoded before we go off and try to display another frame.
mImageFrame->SetTimeout(mGIFStruct.delay_time);
if (mGIFStruct.images_decoded)
mImageContainer->AppendFrame(mImageFrame);
mImageContainer->SetFrameTimeout(mGIFStruct.images_decoded, mGIFStruct.delay_time);
mImageContainer->EndFrameDecode(mGIFStruct.images_decoded);
mGIFStruct.images_decoded++;
mGIFStruct.images_decoded++;
}
if (mObserver)
mObserver->OnStopFrame(nsnull, mImageFrame);
// Release reference to this frame
mImageFrame = nsnull;
mObserver->OnStopFrame(nsnull, curframe);
// Reset the transparent pixel
if (mOldColor) {
@ -497,7 +498,7 @@ PRUint32 nsGIFDecoder2::OutputRow()
if (drow_end > drow_start) {
// irow is the current row filled
for (int r = drow_start; r <= drow_end; r++) {
if (r != mGIFStruct.irow) {
if (r != int(mGIFStruct.irow)) {
memcpy(mImageData + (r * bpr), rowp, bpr);
}
}
@ -1060,7 +1061,7 @@ nsresult nsGIFDecoder2::GifWrite(const PRUint8 *buf, PRUint32 len)
BeginImageFrame(realDepth);
// handle allocation error
if (!mImageFrame) {
if (!mImageData) {
mGIFStruct.state = gif_error;
break;
}
@ -1086,17 +1087,12 @@ nsresult nsGIFDecoder2::GifWrite(const PRUint8 *buf, PRUint32 len)
if (q[8] & 0x80) /* has a local colormap? */
{
mGIFStruct.local_colormap_size = 1 << depth;
PRUint32 paletteSize;
if (mGIFStruct.images_decoded) {
// Copy directly into the palette of current frame,
// by pointing mColormap to that palette.
mImageFrame->GetPaletteData(&mColormap, &paletteSize);
} else {
if (!mGIFStruct.images_decoded) {
// First frame has local colormap, allocate space for it
// as the image frame doesn't have its own palette
paletteSize = sizeof(PRUint32) << realDepth;
mColormapSize = sizeof(PRUint32) << realDepth;
if (!mGIFStruct.local_colormap) {
mGIFStruct.local_colormap = (PRUint32*)PR_MALLOC(paletteSize);
mGIFStruct.local_colormap = (PRUint32*)PR_MALLOC(mColormapSize);
if (!mGIFStruct.local_colormap) {
mGIFStruct.state = gif_oom;
break;
@ -1105,9 +1101,9 @@ nsresult nsGIFDecoder2::GifWrite(const PRUint8 *buf, PRUint32 len)
mColormap = mGIFStruct.local_colormap;
}
const PRUint32 size = 3 << depth;
if (paletteSize > size) {
if (mColormapSize > size) {
// Clear the notfilled part of the colormap
memset(((PRUint8*)mColormap) + size, 0, paletteSize - size);
memset(((PRUint8*)mColormap) + size, 0, mColormapSize - size);
}
if (len < size) {
// Use 'hold' pattern to get the image colormap
@ -1122,12 +1118,11 @@ nsresult nsGIFDecoder2::GifWrite(const PRUint8 *buf, PRUint32 len)
break;
} else {
/* Switch back to the global palette */
mColormap = mGIFStruct.global_colormap;
if (mGIFStruct.images_decoded) {
// Copy global colormap into the palette of current frame
PRUint32 size;
mImageFrame->GetPaletteData(&mColormap, &size);
memcpy(mColormap, mGIFStruct.global_colormap, size);
memcpy(mColormap, mGIFStruct.global_colormap, mColormapSize);
} else {
mColormap = mGIFStruct.global_colormap;
}
}
GETN(1, gif_lzw_start);

View file

@ -44,7 +44,6 @@
#include "imgIDecoder.h"
#include "imgIContainer.h"
#include "imgIDecoderObserver.h"
#include "gfxIImageFrame.h"
#include "GIF2.h"
@ -88,13 +87,13 @@ private:
inline int ClearCode() const { return 1 << mGIFStruct.datasize; }
nsCOMPtr<imgIContainer> mImageContainer;
nsCOMPtr<gfxIImageFrame> mImageFrame;
nsCOMPtr<imgIDecoderObserver> mObserver; // this is just qi'd from mRequest for speed
PRInt32 mCurrentRow;
PRInt32 mLastFlushedRow;
PRUint8 *mImageData; // Pointer to image data in either Cairo or 8bit format
PRUint32 *mColormap; // Current colormap to be used in Cairo format
PRUint32 mColormapSize;
PRUint32 mOldColor; // The old value of the transparent pixel
PRUint8 mCurrentPass;
PRUint8 mLastFlushedPass;

View file

@ -47,7 +47,6 @@
#include "nsRect.h"
#include "nsComponentManagerUtils.h"
#include "nsIImage.h"
#include "nsIInterfaceRequestorUtils.h"
NS_IMPL_THREADSAFE_ADDREF(nsIconDecoder)
@ -71,14 +70,11 @@ NS_IMETHODIMP nsIconDecoder::Init(imgILoad *aLoad)
{
mObserver = do_QueryInterface(aLoad); // we're holding 2 strong refs to the request.
mImage = do_CreateInstance("@mozilla.org/image/container;1");
mImage = do_CreateInstance("@mozilla.org/image/container;2");
if (!mImage) return NS_ERROR_OUT_OF_MEMORY;
aLoad->SetImage(mImage);
mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
if (!mFrame) return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
@ -88,7 +84,7 @@ NS_IMETHODIMP nsIconDecoder::Close()
if (mObserver)
{
mObserver->OnStopFrame(nsnull, mFrame);
mObserver->OnStopFrame(nsnull, 0);
mObserver->OnStopContainer(nsnull, mImage);
mObserver->OnStopDecode(nsnull, NS_OK, nsnull);
}
@ -120,17 +116,15 @@ NS_IMETHODIMP nsIconDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR
if (mObserver)
mObserver->OnStartContainer(nsnull, mImage);
rv = mFrame->Init(0, 0, w, h, gfxIFormats::BGRA, 24);
PRUint32 imageLen;
PRUint8 *imageData;
rv = mImage->AppendFrame(0, 0, w, h, gfxASurface::ImageFormatARGB32, &imageData, &imageLen);
if (NS_FAILED(rv))
return rv;
mImage->AppendFrame(mFrame);
if (mObserver)
mObserver->OnStartFrame(nsnull, mFrame);
PRUint32 imageLen;
PRUint8 *imageData;
mFrame->GetImageData(&imageData, &imageLen);
mObserver->OnStartFrame(nsnull, 0);
// Ensure that there enough in the inputStream
NS_ENSURE_TRUE(count >= imageLen, NS_ERROR_UNEXPECTED);
@ -142,12 +136,11 @@ NS_IMETHODIMP nsIconDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR
// Notify the image...
nsIntRect r(0, 0, w, h);
nsCOMPtr<nsIImage> img(do_GetInterface(mFrame));
rv = img->ImageUpdated(nsnull, nsImageUpdateFlags_kBitsChanged, &r);
rv = mImage->FrameUpdated(0, r);
if (NS_FAILED(rv))
return rv;
mObserver->OnDataAvailable(nsnull, mFrame, &r);
mObserver->OnDataAvailable(nsnull, PR_TRUE, &r);
return NS_OK;
}

View file

@ -46,7 +46,6 @@
#include "imgIContainer.h"
#include "imgIDecoderObserver.h"
#include "gfxIImageFrame.h"
#define NS_ICONDECODER_CID \
{ /* FFC08380-256C-11d5-9905-001083010E9B */ \
@ -87,7 +86,6 @@ public:
private:
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<gfxIImageFrame> mFrame;
nsCOMPtr<imgIDecoderObserver> mObserver; // this is just qi'd from mRequest for speed
};

View file

@ -48,7 +48,6 @@
#include "nspr.h"
#include "nsCRT.h"
#include "ImageLogging.h"
#include "nsIImage.h"
#include "nsIInterfaceRequestorUtils.h"
#include "gfxColor.h"
@ -101,6 +100,7 @@ nsJPEGDecoder::nsJPEGDecoder()
mState = JPEG_HEADER;
mReading = PR_TRUE;
mError = NS_OK;
mImageData = nsnull;
mBytesToSkip = 0;
memset(&mInfo, 0, sizeof(jpeg_decompress_struct));
@ -187,7 +187,7 @@ NS_IMETHODIMP nsJPEGDecoder::Init(imgILoad *aLoad)
mImageLoad->GetImage(getter_AddRefs(mImage));
if (!mImage) {
mImage = do_CreateInstance("@mozilla.org/image/container;1");
mImage = do_CreateInstance("@mozilla.org/image/container;2");
if (!mImage)
return NS_ERROR_OUT_OF_MEMORY;
@ -473,49 +473,23 @@ nsresult nsJPEGDecoder::ProcessData(const char *data, PRUint32 count, PRUint32 *
mObserver->OnStartContainer(nsnull, mImage);
mImage->GetFrameAt(0, getter_AddRefs(mFrame));
if (mFrame) {
PRInt32 width, height;
mFrame->GetWidth(&width);
mFrame->GetHeight(&height);
if ((width != (PRInt32)mInfo.image_width) ||
(height != (PRInt32)mInfo.image_height)) {
// Can't reuse frame, create a new one with correct size
mFrame = nsnull;
}
}
if (!mFrame) {
mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
if (!mFrame) {
mState = JPEG_ERROR;
PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
("} (could not create image frame)"));
return NS_ERROR_OUT_OF_MEMORY;
}
gfx_format format = gfxIFormats::RGB;
#if defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS)
format = gfxIFormats::BGR;
#endif
if (NS_FAILED(mFrame->Init(0, 0, mInfo.image_width, mInfo.image_height, format, 24))) {
mState = JPEG_ERROR;
PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
("} (could not initialize image frame)"));
return NS_ERROR_OUT_OF_MEMORY;
}
mImage->AppendFrame(mFrame);
// Use EnsureCleanFrame so we don't create a new frame if we're being
// reused for e.g. multipart/x-replace
PRUint32 imagelength;
if (NS_FAILED(mImage->EnsureCleanFrame(0, 0, 0, mInfo.image_width, mInfo.image_height,
gfxASurface::ImageFormatRGB24,
&mImageData, &imagelength))) {
mState = JPEG_ERROR;
PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
(" JPEGDecoderAccounting: nsJPEGDecoder::ProcessData -- created image frame with %ux%u pixels",
mInfo.image_width, mInfo.image_height));
("} (could not initialize image frame)"));
return NS_ERROR_OUT_OF_MEMORY;
}
mObserver->OnStartFrame(nsnull, mFrame);
PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
(" JPEGDecoderAccounting: nsJPEGDecoder::ProcessData -- created image frame with %ux%u pixels",
mInfo.image_width, mInfo.image_height));
mObserver->OnStartFrame(nsnull, 0);
mState = JPEG_START_DECOMPRESS;
}
@ -699,16 +673,9 @@ nsJPEGDecoder::OutputScanlines(PRBool* suspend)
const PRUint32 top = mInfo.output_scanline;
nsresult rv = NS_OK;
mFrame->LockImageData();
// we're thebes. we can write stuff directly to the data
PRUint8 *imageData;
PRUint32 imageDataLength;
mFrame->GetImageData(&imageData, &imageDataLength);
while ((mInfo.output_scanline < mInfo.output_height)) {
/* Use the Cairo image buffer as scanline buffer */
PRUint32 *imageRow = ((PRUint32*)imageData) +
PRUint32 *imageRow = ((PRUint32*)mImageData) +
(mInfo.output_scanline * mInfo.output_width);
if (mInfo.cconvert->color_convert == ycc_rgb_convert_argb) {
@ -791,13 +758,10 @@ nsJPEGDecoder::OutputScanlines(PRBool* suspend)
if (top != mInfo.output_scanline) {
nsIntRect r(0, top, mInfo.output_width, mInfo.output_scanline-top);
nsCOMPtr<nsIImage> img(do_GetInterface(mFrame));
rv = img->ImageUpdated(nsnull, nsImageUpdateFlags_kBitsChanged, &r);
mObserver->OnDataAvailable(nsnull, mFrame, &r);
rv = mImage->FrameUpdated(0, r);
mObserver->OnDataAvailable(nsnull, PR_TRUE, &r);
}
mFrame->UnlockImageData();
return rv;
}
@ -1013,15 +977,16 @@ term_source (j_decompress_ptr jd)
nsJPEGDecoder *decoder = (nsJPEGDecoder *)(jd->client_data);
if (decoder->mObserver) {
decoder->mObserver->OnStopFrame(nsnull, decoder->mFrame);
decoder->mObserver->OnStopFrame(nsnull, 0);
decoder->mObserver->OnStopContainer(nsnull, decoder->mImage);
decoder->mObserver->OnStopDecode(nsnull, NS_OK, nsnull);
}
PRBool isMutable = PR_FALSE;
PRBool multipart = PR_FALSE;
if (decoder->mImageLoad)
decoder->mImageLoad->GetIsMultiPartChannel(&isMutable);
decoder->mFrame->SetMutable(isMutable);
decoder->mImageLoad->GetIsMultiPartChannel(&multipart);
if (!multipart)
decoder->mImage->DecodingComplete();
}

View file

@ -45,7 +45,6 @@
#include "nsCOMPtr.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "imgIDecoderObserver.h"
#include "imgILoad.h"
#include "nsIInputStream.h"
@ -99,9 +98,9 @@ protected:
public:
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<imgILoad> mImageLoad;
nsCOMPtr<gfxIImageFrame> mFrame;
nsCOMPtr<imgIDecoderObserver> mObserver;
PRUint8 *mImageData;
struct jpeg_decompress_struct mInfo;
struct jpeg_source_mgr mSourceMgr;

View file

@ -48,7 +48,6 @@
#include "nsIInputStream.h"
#include "imgIContainerObserver.h"
#include "nsIImage.h"
#include "nsIInterfaceRequestorUtils.h"
#include "gfxColor.h"
@ -99,25 +98,29 @@ nsPNGDecoder::~nsPNGDecoder()
// CreateFrame() is used for both simple and animated images
void nsPNGDecoder::CreateFrame(png_uint_32 x_offset, png_uint_32 y_offset,
PRInt32 width, PRInt32 height, gfx_format format)
PRInt32 width, PRInt32 height,
gfxASurface::gfxImageFormat format)
{
mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
if (!mFrame)
longjmp(mPNG->jmpbuf, 5); // NS_ERROR_OUT_OF_MEMORY
nsresult rv = mFrame->Init(x_offset, y_offset, width, height, format, 24);
PRUint32 imageDataLength;
nsresult rv = mImage->AppendFrame(x_offset, y_offset, width, height, format,
&mImageData, &imageDataLength);
if (NS_FAILED(rv))
longjmp(mPNG->jmpbuf, 5); // NS_ERROR_OUT_OF_MEMORY
mFrameRect.x = x_offset;
mFrameRect.y = y_offset;
mFrameRect.width = width;
mFrameRect.height = height;
if (png_get_valid(mPNG, mInfo, PNG_INFO_acTL))
SetAnimFrameInfo();
mImage->AppendFrame(mFrame);
if (mObserver)
mObserver->OnStartFrame(nsnull, mFrame);
PRUint32 numFrames = 0;
mImage->GetNumFrames(&numFrames);
if (mObserver)
mObserver->OnStartFrame(nsnull, numFrames - 1);
PR_LOG(gPNGDecoderAccountingLog, PR_LOG_DEBUG,
("PNGDecoderAccounting: nsPNGDecoder::CreateFrame -- created image frame with %dx%d pixels in container %p",
width, height,
@ -141,7 +144,7 @@ void nsPNGDecoder::SetAnimFrameInfo()
blend_op = png_get_next_frame_blend_op(mPNG, mInfo);
if (delay_num == 0) {
timeout = 0; // gfxImageFrame::SetTimeout() will set to a minimum
timeout = 0; // SetFrameTimeout() will set to a minimum
} else {
if (delay_den == 0)
delay_den = 100; // so says the APNG spec
@ -151,54 +154,49 @@ void nsPNGDecoder::SetAnimFrameInfo()
timeout = static_cast<PRInt32>
(static_cast<PRFloat64>(delay_num) * 1000 / delay_den);
}
mFrame->SetTimeout(timeout);
PRUint32 numFrames = 0;
mImage->GetNumFrames(&numFrames);
mImage->SetFrameTimeout(numFrames - 1, timeout);
if (dispose_op == PNG_DISPOSE_OP_PREVIOUS)
mFrame->SetFrameDisposalMethod(imgIContainer::kDisposeRestorePrevious);
mImage->SetFrameDisposalMethod(numFrames - 1, imgIContainer::kDisposeRestorePrevious);
else if (dispose_op == PNG_DISPOSE_OP_BACKGROUND)
mFrame->SetFrameDisposalMethod(imgIContainer::kDisposeClear);
mImage->SetFrameDisposalMethod(numFrames - 1, imgIContainer::kDisposeClear);
else
mFrame->SetFrameDisposalMethod(imgIContainer::kDisposeKeep);
mImage->SetFrameDisposalMethod(numFrames - 1, imgIContainer::kDisposeKeep);
if (blend_op == PNG_BLEND_OP_SOURCE)
mFrame->SetBlendMethod(imgIContainer::kBlendSource);
/*else // 'over' is the default for a gfxImageFrame
mFrame->SetBlendMethod(imgIContainer::kBlendOver); */
mImage->SetFrameBlendMethod(numFrames - 1, imgIContainer::kBlendSource);
/*else // 'over' is the default
mImage->SetFrameBlendMethod(numFrames - 1, imgIContainer::kBlendOver); */
}
// set timeout and frame disposal method for the current frame
void nsPNGDecoder::EndImageFrame()
{
if (mFrameHasNoAlpha) {
nsCOMPtr<nsIImage> img(do_GetInterface(mFrame));
img->SetHasNoAlpha();
}
// First tell the container that this frame is complete
PRInt32 timeout = 100;
PRUint32 numFrames = 0;
mFrame->GetTimeout(&timeout);
mImage->GetNumFrames(&numFrames);
// We can't use mPNG->num_frames_read as it may be one ahead.
if (numFrames > 1) {
// Tell the image renderer that the frame is complete
PRInt32 width, height;
mFrame->GetWidth(&width);
mFrame->GetHeight(&height);
if (mFrameHasNoAlpha)
mImage->SetFrameHasNoAlpha(numFrames - 1);
nsIntRect r(0, 0, width, height);
nsCOMPtr<nsIImage> img(do_GetInterface(mFrame));
if (NS_FAILED(img->ImageUpdated(nsnull, nsImageUpdateFlags_kBitsChanged, &r))) {
if (NS_FAILED(mImage->FrameUpdated(numFrames - 1, mFrameRect))) {
mError = PR_TRUE;
// allow the call out to the observers.
}
mObserver->OnDataAvailable(nsnull, mFrame, &r);
PRUint32 curFrame;
mImage->GetCurrentFrameIndex(&curFrame);
mObserver->OnDataAvailable(nsnull, curFrame == numFrames - 1, &mFrameRect);
}
mImage->EndFrameDecode(numFrames);
mImage->EndFrameDecode(numFrames - 1);
if (mObserver)
mObserver->OnStopFrame(nsnull, mFrame);
mObserver->OnStopFrame(nsnull, numFrames - 1);
}
@ -265,7 +263,7 @@ NS_IMETHODIMP nsPNGDecoder::Init(imgILoad *aLoad)
*/
mImageLoad->GetImage(getter_AddRefs(mImage));
if (!mImage) {
mImage = do_CreateInstance("@mozilla.org/image/container;1");
mImage = do_CreateInstance("@mozilla.org/image/container;2");
if (!mImage)
return NS_ERROR_OUT_OF_MEMORY;
@ -556,12 +554,11 @@ info_callback(png_structp png_ptr, png_infop info_ptr)
decoder->mInProfile = PNGGetColorProfile(png_ptr, info_ptr,
color_type, &inType, &pIntent);
/* If we're not mandating an intent, use the one from the image. */
if (intent == -1)
if (intent == PRUint32(-1))
intent = pIntent;
}
if (decoder->mInProfile && gfxPlatform::GetCMSOutputProfile()) {
qcms_data_type outType;
PRUint32 dwFlags = 0;
if (color_type & PNG_COLOR_MASK_ALPHA || num_trans)
outType = QCMS_DATA_RGBA_8;
@ -631,22 +628,17 @@ info_callback(png_structp png_ptr, png_infop info_ptr)
if (containerWidth == 0 && containerHeight == 0) {
// the image hasn't been inited yet
decoder->mImage->Init(width, height, decoder->mObserver);
} else if (containerWidth != width || containerHeight != height) {
} else if (containerWidth != PRInt32(width) || containerHeight != PRInt32(height)) {
longjmp(decoder->mPNG->jmpbuf, 5); // NS_ERROR_UNEXPECTED
}
if (decoder->mObserver)
decoder->mObserver->OnStartContainer(nsnull, decoder->mImage);
if (channels == 1 || channels == 3) {
decoder->format = gfxIFormats::RGB;
} else if (channels == 2 || channels == 4) {
if (alpha_bits == 8) {
decoder->format = gfxIFormats::RGB_A8;
} else if (alpha_bits == 1) {
decoder->format = gfxIFormats::RGB_A1;
}
}
if (channels == 1 || channels == 3)
decoder->format = gfxASurface::ImageFormatRGB24;
else if (channels == 2 || channels == 4)
decoder->format = gfxASurface::ImageFormatARGB32;
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL))
png_set_progressive_frame_fn(png_ptr, frame_info_callback, NULL);
@ -674,9 +666,6 @@ info_callback(png_structp png_ptr, png_infop info_ptr)
}
}
if (png_get_first_frame_is_hidden(png_ptr, info_ptr))
decoder->mFrame = nsnull;
/* Reject any ancillary chunk after IDAT with a bad CRC (bug #397593).
* It would be better to show the default frame (if one has already been
* successfully decoded) before bailing, but it's simpler to just bail
@ -725,9 +714,8 @@ row_callback(png_structp png_ptr, png_bytep new_row,
return;
if (new_row) {
PRInt32 width;
decoder->mFrame->GetWidth(&width);
PRUint32 iwidth = width;
PRInt32 width = decoder->mFrameRect.width;
PRUint32 iwidth = decoder->mFrameRect.width;
png_bytep line = new_row;
if (decoder->interlacebuf) {
@ -735,11 +723,8 @@ row_callback(png_structp png_ptr, png_bytep new_row,
png_progressive_combine_row(png_ptr, line, new_row);
}
// we're thebes. we can write stuff directly to the data
PRUint8 *imageData;
PRUint32 imageDataLength, bpr = width * sizeof(PRUint32);
decoder->mFrame->GetImageData(&imageData, &imageDataLength);
PRUint32 *cptr32 = (PRUint32*)(imageData + (row_num*bpr));
PRUint32 bpr = width * sizeof(PRUint32);
PRUint32 *cptr32 = (PRUint32*)(decoder->mImageData + (row_num*bpr));
PRBool rowHasNoAlpha = PR_TRUE;
if (decoder->mTransform) {
@ -758,7 +743,7 @@ row_callback(png_structp png_ptr, png_bytep new_row,
}
switch (decoder->format) {
case gfxIFormats::RGB:
case gfxASurface::ImageFormatRGB24:
{
// counter for while() loops below
PRUint32 idx = iwidth;
@ -785,17 +770,7 @@ row_callback(png_structp png_ptr, png_bytep new_row,
}
}
break;
case gfxIFormats::RGB_A1:
{
for (PRUint32 x=iwidth; x>0; --x) {
*cptr32++ = GFX_PACKED_PIXEL(line[3]?0xFF:0x00, line[0], line[1], line[2]);
if (line[3] == 0)
rowHasNoAlpha = PR_FALSE;
line += 4;
}
}
break;
case gfxIFormats::RGB_A8:
case gfxASurface::ImageFormatARGB32:
{
for (PRUint32 x=width; x>0; --x) {
*cptr32++ = GFX_PACKED_PIXEL(line[3], line[0], line[1], line[2]);
@ -805,6 +780,10 @@ row_callback(png_structp png_ptr, png_bytep new_row,
}
}
break;
default:
NS_ERROR("Unknown PNG format!");
NS_ABORT();
break;
}
if (!rowHasNoAlpha)
@ -815,12 +794,13 @@ row_callback(png_structp png_ptr, png_bytep new_row,
if (numFrames <= 1) {
// Only do incremental image display for the first frame
nsIntRect r(0, row_num, width, 1);
nsCOMPtr<nsIImage> img(do_GetInterface(decoder->mFrame));
if (NS_FAILED(img->ImageUpdated(nsnull, nsImageUpdateFlags_kBitsChanged, &r))) {
if (NS_FAILED(decoder->mImage->FrameUpdated(numFrames - 1, r))) {
decoder->mError = PR_TRUE; /* bail */
return;
}
decoder->mObserver->OnDataAvailable(nsnull, decoder->mFrame, &r);
PRUint32 curFrame;
decoder->mImage->GetCurrentFrameIndex(&curFrame);
decoder->mObserver->OnDataAvailable(nsnull, curFrame == numFrames - 1, &r);
}
}
}

View file

@ -44,9 +44,8 @@
#include "imgIContainer.h"
#include "imgIDecoderObserver.h"
#include "gfxIImageFrame.h"
#include "imgILoad.h"
#include "gfxASurface.h"
#include "nsCOMPtr.h"
@ -72,25 +71,27 @@ public:
virtual ~nsPNGDecoder();
void CreateFrame(png_uint_32 x_offset, png_uint_32 y_offset,
PRInt32 width, PRInt32 height, gfx_format format);
PRInt32 width, PRInt32 height,
gfxASurface::gfxImageFormat format);
void SetAnimFrameInfo();
void EndImageFrame();
public:
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<gfxIImageFrame> mFrame;
nsCOMPtr<imgILoad> mImageLoad;
nsCOMPtr<imgIDecoderObserver> mObserver; // this is just qi'd from mRequest for speed
png_structp mPNG;
png_infop mInfo;
nsIntRect mFrameRect;
PRUint8 *mCMSLine;
PRUint8 *interlacebuf;
PRUint8 *mImageData;
qcms_profile *mInProfile;
qcms_transform *mTransform;
gfx_format format;
gfxASurface::gfxImageFormat format;
PRUint8 mChannels;
PRPackedBool mError;
PRPackedBool mFrameHasNoAlpha;

View file

@ -47,7 +47,6 @@
#include "nsIInputStream.h"
#include "nsIComponentManager.h"
#include "nsIImage.h"
#include "nsIInterfaceRequestorUtils.h"
#include "imgILoad.h"
@ -56,7 +55,6 @@
#include "nsISupportsPrimitives.h"
#include "gfxColor.h"
#include "nsIImage.h"
#include "nsIInterfaceRequestorUtils.h"
// Static colormap
@ -82,11 +80,7 @@ NS_IMETHODIMP nsXBMDecoder::Init(imgILoad *aLoad)
nsresult rv;
mObserver = do_QueryInterface(aLoad);
mImage = do_CreateInstance("@mozilla.org/image/container;1", &rv);
if (NS_FAILED(rv))
return rv;
mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2", &rv);
mImage = do_CreateInstance("@mozilla.org/image/container;2", &rv);
if (NS_FAILED(rv))
return rv;
@ -106,7 +100,6 @@ NS_IMETHODIMP nsXBMDecoder::Close()
mObserver->OnStopDecode(nsnull, NS_OK, nsnull);
mObserver = nsnull;
mImage = nsnull;
mFrame = nsnull;
mImageData = nsnull;
return NS_OK;
@ -198,7 +191,9 @@ nsresult nsXBMDecoder::ProcessData(const char* aData, PRUint32 aCount) {
mImage->Init(mWidth, mHeight, mObserver);
mObserver->OnStartContainer(nsnull, mImage);
nsresult rv = mFrame->Init(0, 0, mWidth, mHeight, gfxIFormats::RGB_A1, 24);
PRUint32 imageLen;
nsresult rv = mImage->AppendFrame(0, 0, mWidth, mHeight, gfxASurface::ImageFormatARGB32,
(PRUint8**)&mImageData, &imageLen);
if (NS_FAILED(rv))
return rv;
@ -218,11 +213,7 @@ nsresult nsXBMDecoder::ProcessData(const char* aData, PRUint32 aCount) {
}
}
mImage->AppendFrame(mFrame);
mObserver->OnStartFrame(nsnull, mFrame);
PRUint32 imageLen;
mFrame->GetImageData((PRUint8**)&mImageData, &imageLen);
mObserver->OnStartFrame(nsnull, 0);
mState = RECV_SEEK;
@ -240,7 +231,6 @@ nsresult nsXBMDecoder::ProcessData(const char* aData, PRUint32 aCount) {
}
}
if (mState == RECV_DATA) {
nsCOMPtr<nsIImage> img = do_GetInterface(mFrame);
PRUint32 *ar = mImageData + mCurRow * mWidth + mCurCol;
do {
@ -279,17 +269,17 @@ nsresult nsXBMDecoder::ProcessData(const char* aData, PRUint32 aCount) {
mCurCol += numPixels;
if (mCurCol == mWidth || mState == RECV_DONE) {
nsIntRect r(0, mCurRow, mWidth, 1);
nsresult rv = img->ImageUpdated(nsnull, nsImageUpdateFlags_kBitsChanged, &r);
nsresult rv = mImage->FrameUpdated(0, r);
if (NS_FAILED(rv)) {
return rv;
}
mObserver->OnDataAvailable(nsnull, mFrame, &r);
mObserver->OnDataAvailable(nsnull, PR_TRUE, &r);
mCurRow++;
if (mCurRow == mHeight) {
mState = RECV_DONE;
return mObserver->OnStopFrame(nsnull, mFrame);
return mObserver->OnStopFrame(nsnull, 0);
}
mCurCol = 0;
}

View file

@ -44,7 +44,6 @@
#include "imgIDecoder.h"
#include "imgIContainer.h"
#include "imgIDecoderObserver.h"
#include "gfxIImageFrame.h"
#define NS_XBMDECODER_CID \
{ /* {dbfd145d-3298-4f3c-902f-2c5e1a1494ce} */ \
@ -72,7 +71,6 @@ private:
nsCOMPtr<imgIDecoderObserver> mObserver;
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<gfxIImageFrame> mFrame;
PRUint32 mCurRow;
PRUint32 mCurCol;

View file

@ -23,6 +23,7 @@
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
* Federico Mena-Quintero <federico@novell.com>
* Joe Drew <joe@drew.ca>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -39,22 +40,113 @@
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "gfxidltypes.idl"
#include "gfxIFormats.idl"
interface gfxIImageFrame;
interface imgIContainerObserver;
%{C++
#include "gfxImageSurface.h"
#include "gfxContext.h"
#include "gfxMatrix.h"
#include "gfxRect.h"
#include "gfxPattern.h"
#include "gfxASurface.h"
#include "nsRect.h"
%}
[ptr] native gfxImageSurface(gfxImageSurface);
[ptr] native gfxASurface(gfxASurface);
native gfxImageFormat(gfxASurface::gfxImageFormat);
[ptr] native gfxContext(gfxContext);
[ref] native gfxMatrix(gfxMatrix);
[ref] native gfxRect(gfxRect);
native gfxGraphicsFilter(gfxPattern::GraphicsFilter);
[ref] native nsIntRect(nsIntRect);
/**
* gfxIImageContainer interface
* imgIContainer is the interface that represents an image. It allows
* access to frames as Thebes surfaces, and permits users to extract subregions
* as other imgIContainers. It also allows drawing of images on to Thebes
* contexts.
*
* @author Stuart Parmenter <pavlov@netscape.com>
* @version 0.2
* @see "gfx2"
* Internally, imgIContainer also manages animation of images.
*/
[scriptable, uuid(a4e9df32-f5d7-479f-9082-70e1fead23d5)]
[scriptable, uuid(1bcf7a25-1356-47a8-bf80-e284989ea38f)]
interface imgIContainer : nsISupports
{
/**
* The width of the container rectangle.
*/
readonly attribute PRInt32 width;
/**
* The height of the container rectangle.
*/
readonly attribute PRInt32 height;
/**
* Whether this image is animated.
*/
readonly attribute boolean animated;
/**
* Whether the current frame is opaque; that is, needs the background painted
* behind it.
*/
readonly attribute boolean currentFrameIsOpaque;
/**
* Get a surface for the current frame. This may be a platform-native,
* optimized frame, so you cannot inspect its pixel data.
*/
[noscript] readonly attribute gfxASurface currentFrame;
/**
* Create and return a new copy of the current frame that you can write to
* and otherwise inspect the pixels of.
*/
[noscript] gfxImageSurface copyCurrentFrame();
/**
* Create a new imgContainer that contains only a single frame, which itself
* contains a subregion of the current frame.
*
* @param aRect the area of the current frame to be duplicated in the
* returned imgContainer's frame.
*/
[noscript] imgIContainer extractCurrentFrame([const] in nsIntRect aRect);
/**
* Draw the current frame on to the context specified.
*
* @param aContext The Thebex context to draw the image to.
* @param aFilter The filter to be used if we're scaling the image.
* @param aUserSpaceToImageSpace The transformation from user space (e.g.,
* appunits) to image space.
* @param aFill The area in the context to draw pixels to. Image will be
* automatically tiled as necessary.
* @param @aSubimage The area of the image, in pixels, that we are allowed to
* sample from.
*/
[noscript] void draw(in gfxContext aContext, in gfxGraphicsFilter aFilter,
in gfxMatrix aUserSpaceToImageSpace, in gfxRect aFill,
in nsIntRect aSubimage);
/************ Internal libpr0n use only below here. *****************/
/**
* Create a new \a aWidth x \a aHeight sized image container.
*
* @param aWidth The width of the container in which all the
* frames will fit.
* @param aHeight The height of the container in which all the
* frames will fit.
* @param aObserver Observer to send animation notifications to.
*/
void init(in PRInt32 aWidth,
in PRInt32 aHeight,
in imgIContainerObserver aObserver);
/**
* "Disposal" method indicates how the image should be handled before the
* subsequent image is displayed.
@ -78,42 +170,6 @@ interface imgIContainer : nsISupports
const long kBlendOver = 1; // The frame should be composited onto the output buffer
// based on its alpha, using a simple OVER operation
/**
* Create a new \a aWidth x \a aHeight sized image container.
*
* @param aWidth The width of the container in which all the
* gfxIImageFrame children will fit.
* @param aHeight The height of the container in which all the
* gfxIImageFrame children will fit.
* @param aObserver Observer to send animation notifications to.
*/
void init(in PRInt32 aWidth,
in PRInt32 aHeight,
in imgIContainerObserver aObserver);
/* this should probably be on the device context (or equiv) */
readonly attribute gfx_format preferredAlphaChannelFormat;
/**
* The width of the container rectangle.
*/
readonly attribute PRInt32 width;
/**
* The height of the container rectangle.
*/
readonly attribute PRInt32 height;
/**
* Get the current frame that would be drawn if the image was to be drawn now
*/
readonly attribute gfxIImageFrame currentFrame;
readonly attribute unsigned long numFrames;
/**
* Animation mode Constants
* 0 = normal
@ -126,13 +182,54 @@ interface imgIContainer : nsISupports
attribute unsigned short animationMode;
gfxIImageFrame getFrameAt(in unsigned long index);
/**
* The rectangle defining the location and size of the currently displayed frame.
* Should be an attribute, but can't be because of reference/pointer
* conflicts with native types in xpidl.
*/
[noscript] void getCurrentFrameRect(in nsIntRect aFrameRect);
/**
* Adds \a item to the end of the list of frames.
* @param item frame to add.
* The index of the current frame that would be drawn if the image was to be
* drawn now.
*/
void appendFrame(in gfxIImageFrame item);
readonly attribute unsigned long currentFrameIndex;
/**
* The total number of frames in this image.
*/
readonly attribute unsigned long numFrames;
/**
* Get the size, in bytes, of a particular frame's image data.
*/
unsigned long getFrameImageDataLength(in unsigned long framenumber);
void getFrameColormap(in unsigned long framenumber,
[array, size_is(paletteLength)] out PRUint32 paletteData,
out unsigned long paletteLength);
void setFrameDisposalMethod(in unsigned long framenumber, in PRInt32 aDisposalMethod);
void setFrameBlendMethod(in unsigned long framenumber, in PRInt32 aBlendMethod);
void setFrameTimeout(in unsigned long framenumber, in PRInt32 aTimeout);
void setFrameHasNoAlpha(in unsigned long framenumber);
/**
* Create or re-use a frame at index aFrameNum. It is an error to call this with aFrameNum not in the range [0, numFrames].
*/
[noscript] void ensureCleanFrame(in unsigned long aFramenum, in PRInt32 aX, in PRInt32 aY, in PRInt32 aWidth, in PRInt32 aHeight, in gfxImageFormat aFormat,
[array, size_is(imageLength)] out PRUint8 imageData, out unsigned long imageLength);
/**
* Adds to the end of the list of frames.
*/
[noscript] void appendFrame(in PRInt32 aX, in PRInt32 aY, in PRInt32 aWidth, in PRInt32 aHeight, in gfxImageFormat aFormat,
[array, size_is(imageLength)] out PRUint8 imageData, out unsigned long imageLength);
[noscript] void appendPalettedFrame(in PRInt32 aX, in PRInt32 aY, in PRInt32 aWidth, in PRInt32 aHeight, in gfxImageFormat aFormat, in PRUint8 aPaletteDepth,
[array, size_is(imageLength)] out PRUint8 imageData, out unsigned long imageLength,
[array, size_is(paletteLength)] out PRUint32 paletteData, out unsigned long paletteLength);
[noscript] void frameUpdated(in unsigned long framenum, in nsIntRect aNewRect);
/* notification when the current frame is done decoding */
void endFrameDecode(in unsigned long framenumber);

View file

@ -46,18 +46,14 @@
interface imgIContainer;
interface gfxIImageFrame;
/**
* imgIContainerObserver interface
*
* @author Stuart Parmenter <pavlov@netscape.com>
* @version 0.1
*/
[scriptable, uuid(53102f15-0f53-4939-957e-aea353ad2700)]
[scriptable, uuid(e214c295-4b8e-4aa9-9907-45289e57295b)]
interface imgIContainerObserver : nsISupports
{
[noscript] void frameChanged(in imgIContainer aContainer,
in gfxIImageFrame aFrame,
in nsIntRect aDirtyRect);
[noscript] void frameChanged(in imgIContainer aContainer, in nsIntRect aDirtyRect);
};

View file

@ -41,7 +41,6 @@
interface imgIRequest;
interface imgIContainer;
interface gfxIImageFrame;
%{C++
#include "nsRect.h"
@ -59,7 +58,7 @@ interface gfxIImageFrame;
* @version 0.1
* @see imagelib2
*/
[scriptable, uuid(876f14ee-f27c-41cd-b6fb-9efda3ebc7b5)]
[scriptable, uuid(1dfc9189-6421-4281-83b2-d9c1c9ba4d1b)]
interface imgIDecoderObserver : imgIContainerObserver
{
/**
@ -85,17 +84,17 @@ interface imgIDecoderObserver : imgIContainerObserver
/**
* called when each frame is created
*/
void onStartFrame(in imgIRequest aRequest, in gfxIImageFrame aFrame);
void onStartFrame(in imgIRequest aRequest, in unsigned long aFrame);
/**
* called when some part of the frame has new data in it
*/
[noscript] void onDataAvailable(in imgIRequest aRequest, in gfxIImageFrame aFrame, [const] in nsIntRect aRect);
[noscript] void onDataAvailable(in imgIRequest aRequest, in boolean aCurrentFrame, [const] in nsIntRect aRect);
/**
* called when a frame is finished decoding
*/
void onStopFrame(in imgIRequest aRequest, in gfxIImageFrame aFrame);
void onStopFrame(in imgIRequest aRequest, in unsigned long aFrame);
/**
* probably not needed. called right before onStopDecode

View file

@ -59,10 +59,12 @@ REQUIRES = xpcom \
xpconnect \
js \
uriloader \
qcms \
$(NULL)
CPPSRCS = \
imgContainer.cpp \
imgFrame.cpp \
imgLoader.cpp \
imgRequest.cpp \
imgRequestProxy.cpp \
@ -70,3 +72,7 @@ CPPSRCS = \
include $(topsrcdir)/config/rules.mk
# Because imgFrame.cpp includes "cairo.h"
CXXFLAGS += $(MOZ_CAIRO_CFLAGS)

File diff suppressed because it is too large Load diff

View file

@ -55,18 +55,18 @@
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "nsIProperties.h"
#include "nsITimer.h"
#include "nsWeakReference.h"
#include "nsTArray.h"
#include "imgFrame.h"
#define NS_IMGCONTAINER_CID \
{ /* 27f0682c-ff64-4dd2-ae7a-668e59f2fd38 */ \
0x27f0682c, \
0xff64, \
0x4dd2, \
{0xae, 0x7a, 0x66, 0x8e, 0x59, 0xf2, 0xfd, 0x38} \
{ /* c76ff2c1-9bf6-418a-b143-3340c00112f7 */ \
0x376ff2c1, \
0x9bf6, \
0x418a, \
{0xb1, 0x43, 0x33, 0x40, 0xc0, 0x01, 0x12, 0xf7} \
}
/**
@ -167,14 +167,14 @@ private:
* lastCompositedFrameIndex to -1. Code assume that if
* lastCompositedFrameIndex >= 0 then compositingFrame exists.
*/
nsCOMPtr<gfxIImageFrame> compositingFrame;
nsAutoPtr<imgFrame> compositingFrame;
/** the previous composited frame, for DISPOSE_RESTORE_PREVIOUS
*
* The Previous Frame (all frames composited up to the current) needs to be
* stored in cases where the image specifies it wants the last frame back
* when it's done with the current frame.
*/
nsCOMPtr<gfxIImageFrame> compositingPrevFrame;
nsAutoPtr<imgFrame> compositingPrevFrame;
//! Timer to animate multiframed images
nsCOMPtr<nsITimer> timer;
@ -195,7 +195,9 @@ private:
}
};
gfxIImageFrame* GetCurrentFrameNoRef();
imgFrame* GetImgFrame(PRUint32 framenum);
imgFrame* GetCurrentImgFrame();
PRInt32 GetCurrentImgFrameIndex() const;
inline Anim* ensureAnimExists() {
if (!mAnim)
@ -212,76 +214,53 @@ private:
* @param aNextFrame Frame we need to incorperate/display
* @param aNextFrameIndex Position of aNextFrame in mFrames list
*/
nsresult DoComposite(gfxIImageFrame** aFrameToUse, nsIntRect* aDirtyRect,
gfxIImageFrame* aPrevFrame,
gfxIImageFrame* aNextFrame,
nsresult DoComposite(imgFrame** aFrameToUse, nsIntRect* aDirtyRect,
imgFrame* aPrevFrame,
imgFrame* aNextFrame,
PRInt32 aNextFrameIndex);
/**
* Combine aOverlayFrame's mask into aCompositingFrame's mask.
*
* This takes the mask information from the passed in aOverlayFrame and
* inserts that information into the aCompositingFrame's mask at the proper
* offsets. It does *not* rebuild the entire mask.
*
* @param aCompositingFrame Target frame
* @param aOverlayFrame This frame's mask is being copied
*/
void BuildCompositeMask(gfxIImageFrame* aCompositingFrame,
gfxIImageFrame* aOverlayFrame);
/** Sets an area of the frame's mask.
*
* @param aFrame Target Frame
* @param aVisible Turn on (PR_TRUE) or off (PR_FALSE) visibility
*
* @note Invisible area of frame's image will need to be set to 0
*/
void SetMaskVisibility(gfxIImageFrame *aFrame, PRBool aVisible);
//! @overload
void SetMaskVisibility(gfxIImageFrame *aFrame,
PRInt32 aX, PRInt32 aY,
PRInt32 aWidth, PRInt32 aHeight,
PRBool aVisible);
//! @overload
void SetMaskVisibility(gfxIImageFrame *aFrame,
nsIntRect &aRect, PRBool aVisible) {
SetMaskVisibility(aFrame, aRect.x, aRect.y,
aRect.width, aRect.height, aVisible);
}
/** Clears an area of <aFrame> with transparent black.
*
* @param aFrame Target Frame
*
* @note Does also clears the transparancy mask
*/
static void ClearFrame(gfxIImageFrame* aFrame);
static void ClearFrame(imgFrame* aFrame);
//! @overload
static void ClearFrame(gfxIImageFrame* aFrame, nsIntRect &aRect);
static void ClearFrame(imgFrame* aFrame, nsIntRect &aRect);
//! Copy one gfxIImageFrame's image and mask into another
static PRBool CopyFrameImage(gfxIImageFrame *aSrcFrame,
gfxIImageFrame *aDstFrame);
//! Copy one frames's image and mask into another
static PRBool CopyFrameImage(imgFrame *aSrcFrame,
imgFrame *aDstFrame);
/** Draws one gfxIImageFrame's image to into another,
/** Draws one frames's image to into another,
* at the position specified by aRect
*
* @param aSrcFrame Frame providing the source image
* @param aDstFrame Frame where the image is drawn into
* @param aRect The position and size to draw the image
*/
static nsresult DrawFrameTo(gfxIImageFrame *aSrcFrame,
gfxIImageFrame *aDstFrame,
static nsresult DrawFrameTo(imgFrame *aSrcFrame,
imgFrame *aDstFrame,
nsIntRect& aRect);
nsresult InternalAddFrameHelper(PRUint32 framenum, imgFrame *frame,
PRUint8 **imageData, PRUint32 *imageLength,
PRUint32 **paletteData, PRUint32 *paletteLength);
nsresult InternalAddFrame(PRUint32 framenum, PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight,
gfxASurface::gfxImageFormat aFormat, PRUint8 aPaletteDepth,
PRUint8 **imageData, PRUint32 *imageLength,
PRUint32 **paletteData, PRUint32 *paletteLength);
private: // data
nsIntSize mSize;
//! All the <gfxIImageFrame>s of the PNG
//! All the frames of the image
// *** IMPORTANT: if you use mFrames in a method, call RestoreDiscardedData() first to ensure
// that the frames actually exist (they may have been discarded to save memory).
nsCOMArray<gfxIImageFrame> mFrames;
nsTArray<imgFrame *> mFrames;
int mNumFrames; /* stored separately from mFrames.Count() to support discarded images */
nsCOMPtr<nsIProperties> mProperties;

View file

@ -0,0 +1,922 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Joe Drew <joe@drew.ca> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "imgFrame.h"
#include <limits.h>
#include "prmem.h"
#include "prenv.h"
#include "gfxPlatform.h"
static PRBool gDisableOptimize = PR_FALSE;
/*XXX get CAIRO_HAS_DDRAW_SURFACE */
#include "cairo.h"
#ifdef CAIRO_HAS_DDRAW_SURFACE
#include "gfxDDrawSurface.h"
#endif
#if defined(XP_WIN) || defined(WINCE)
#include "gfxWindowsPlatform.h"
#endif
#if defined(XP_WIN) && !defined(WINCE)
/* Whether to use the windows surface; only for desktop win32 */
#define USE_WIN_SURFACE 1
static PRUint32 gTotalDDBs = 0;
static PRUint32 gTotalDDBSize = 0;
// only use up a maximum of 64MB in DDBs
#define kMaxDDBSize (64*1024*1024)
// and don't let anything in that's bigger than 4MB
#define kMaxSingleDDBSize (4*1024*1024)
#endif
// Returns true if an image of aWidth x aHeight is allowed and legal.
static PRBool AllowedImageSize(PRInt32 aWidth, PRInt32 aHeight)
{
NS_ASSERTION(aWidth > 0, "invalid image width");
NS_ASSERTION(aHeight > 0, "invalid image height");
// reject over-wide or over-tall images
const PRInt32 k64KLimit = 0x0000FFFF;
if (NS_UNLIKELY(aWidth > k64KLimit || aHeight > k64KLimit )) {
NS_WARNING("image too big");
return PR_FALSE;
}
// protect against division by zero - this really shouldn't happen
// if our consumers were well behaved, but they aren't (bug 368427)
if (NS_UNLIKELY(aHeight == 0)) {
return PR_FALSE;
}
// check to make sure we don't overflow a 32-bit
PRInt32 tmp = aWidth * aHeight;
if (NS_UNLIKELY(tmp / aHeight != aWidth)) {
NS_WARNING("width or height too large");
return PR_FALSE;
}
tmp = tmp * 4;
if (NS_UNLIKELY(tmp / 4 != aWidth * aHeight)) {
NS_WARNING("width or height too large");
return PR_FALSE;
}
#if defined(XP_MACOSX)
// CoreGraphics is limited to images < 32K in *height*, so clamp all surfaces on the Mac to that height
if (NS_UNLIKELY(aHeight > SHRT_MAX)) {
NS_WARNING("image too big");
return PR_FALSE;
}
#endif
return PR_TRUE;
}
// Returns whether we should, at this time, use image surfaces instead of
// optimized platform-specific surfaces.
static PRBool ShouldUseImageSurfaces()
{
#if defined(WINCE)
// There is no test on windows mobile to check for Gui resources.
// Allocate, until we run out of memory.
gfxWindowsPlatform::RenderMode rmode = gfxWindowsPlatform::GetPlatform()->GetRenderMode();
return rmode != gfxWindowsPlatform::RENDER_DDRAW &&
rmode != gfxWindowsPlatform::RENDER_DDRAW_GL;
#elif defined(USE_WIN_SURFACE)
static const DWORD kGDIObjectsHighWaterMark = 7000;
// at 7000 GDI objects, stop allocating normal images to make sure
// we never hit the 10k hard limit.
// GetCurrentProcess() just returns (HANDLE)-1, it's inlined afaik
DWORD count = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
if (count == 0 ||
count > kGDIObjectsHighWaterMark)
{
// either something's broken (count == 0),
// or we hit our high water mark; disable
// image allocations for a bit.
return PR_TRUE;
}
#endif
return PR_FALSE;
}
imgFrame::imgFrame() :
mDecoded(0, 0, 0, 0),
mPalettedImageData(nsnull),
mSinglePixelColor(0),
mTimeout(100),
mDisposalMethod(0), /* imgIContainer::kDisposeNotSpecified */
mBlendMethod(1), /* imgIContainer::kBlendOver */
mSinglePixel(PR_FALSE),
mNeverUseDeviceSurface(PR_FALSE),
mFormatChanged(PR_FALSE)
#ifdef USE_WIN_SURFACE
, mIsDDBSurface(PR_FALSE)
#endif
{
static PRBool hasCheckedOptimize = PR_FALSE;
if (!hasCheckedOptimize) {
if (PR_GetEnv("MOZ_DISABLE_IMAGE_OPTIMIZE")) {
gDisableOptimize = PR_TRUE;
}
hasCheckedOptimize = PR_TRUE;
}
}
imgFrame::~imgFrame()
{
PR_FREEIF(mPalettedImageData);
#ifdef USE_WIN_SURFACE
if (mIsDDBSurface) {
gTotalDDBs--;
gTotalDDBSize -= mSize.width * mSize.height * 4;
}
#endif
}
nsresult imgFrame::Init(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight,
gfxASurface::gfxImageFormat aFormat, PRInt8 aPaletteDepth /* = 0 */)
{
// assert for properties that should be verified by decoders, warn for properties related to bad content
if (!AllowedImageSize(aWidth, aHeight))
return NS_ERROR_FAILURE;
// Check to see if we are running OOM
nsCOMPtr<nsIMemory> mem;
NS_GetMemoryManager(getter_AddRefs(mem));
if (!mem)
return NS_ERROR_UNEXPECTED;
PRBool lowMemory;
mem->IsLowMemory(&lowMemory);
if (lowMemory)
return NS_ERROR_OUT_OF_MEMORY;
mOffset.MoveTo(aX, aY);
mSize.SizeTo(aWidth, aHeight);
mFormat = aFormat;
mPaletteDepth = aPaletteDepth;
if (aPaletteDepth != 0) {
// We're creating for a paletted image.
if (aPaletteDepth > 8) {
NS_ERROR("This Depth is not supported\n");
return NS_ERROR_FAILURE;
}
mPalettedImageData = (PRUint8*)PR_MALLOC(PaletteDataLength() + GetImageDataLength());
NS_ENSURE_TRUE(mPalettedImageData, NS_ERROR_OUT_OF_MEMORY);
} else {
// For Windows, we must create the device surface first (if we're
// going to) so that the image surface can wrap it. Can't be done
// the other way around.
#ifdef USE_WIN_SURFACE
if (!mNeverUseDeviceSurface && !ShouldUseImageSurfaces()) {
mWinSurface = new gfxWindowsSurface(gfxIntSize(mSize.width, mSize.height), mFormat);
if (mWinSurface && mWinSurface->CairoStatus() == 0) {
// no error
mImageSurface = mWinSurface->GetImageSurface();
} else {
mWinSurface = nsnull;
}
}
#endif
// For other platforms we create the image surface first and then
// possibly wrap it in a device surface. This branch is also used
// on Windows if we're not using device surfaces or if we couldn't
// create one.
if (!mImageSurface)
mImageSurface = new gfxImageSurface(gfxIntSize(mSize.width, mSize.height), mFormat);
if (!mImageSurface || mImageSurface->CairoStatus()) {
mImageSurface = nsnull;
// guess
return NS_ERROR_OUT_OF_MEMORY;
}
#ifdef XP_MACOSX
if (!mNeverUseDeviceSurface && !ShouldUseImageSurfaces()) {
mQuartzSurface = new gfxQuartzImageSurface(mImageSurface);
}
#endif
}
return NS_OK;
}
nsresult imgFrame::Optimize()
{
if (gDisableOptimize)
return NS_OK;
if (mPalettedImageData || mOptSurface || mSinglePixel)
return NS_OK;
/* Figure out if the entire image is a constant color */
// this should always be true
if (mImageSurface->Stride() == mSize.width * 4) {
PRUint32 *imgData = (PRUint32*) mImageSurface->Data();
PRUint32 firstPixel = * (PRUint32*) imgData;
PRUint32 pixelCount = mSize.width * mSize.height + 1;
while (--pixelCount && *imgData++ == firstPixel)
;
if (pixelCount == 0) {
// all pixels were the same
if (mFormat == gfxASurface::ImageFormatARGB32 ||
mFormat == gfxASurface::ImageFormatRGB24)
{
mSinglePixelColor = gfxRGBA
(firstPixel,
(mFormat == gfxImageSurface::ImageFormatRGB24 ?
gfxRGBA::PACKED_XRGB :
gfxRGBA::PACKED_ARGB_PREMULTIPLIED));
mSinglePixel = PR_TRUE;
// blow away the older surfaces (if they exist), to release their memory
mImageSurface = nsnull;
mOptSurface = nsnull;
#ifdef USE_WIN_SURFACE
mWinSurface = nsnull;
#endif
#ifdef XP_MACOSX
mQuartzSurface = nsnull;
#endif
return NS_OK;
}
}
// if it's not RGB24/ARGB32, don't optimize, but we never hit this at the moment
}
// if we're being forced to use image surfaces due to
// resource constraints, don't try to optimize beyond same-pixel.
if (mNeverUseDeviceSurface || ShouldUseImageSurfaces())
return NS_OK;
mOptSurface = nsnull;
#ifdef USE_WIN_SURFACE
// we need to special-case windows here, because windows has
// a distinction between DIB and DDB and we want to use DDBs as much
// as we can.
if (mWinSurface) {
// Don't do DDBs for large images; see bug 359147
// Note that we bother with DDBs at all because they are much faster
// on some systems; on others there isn't much of a speed difference
// between DIBs and DDBs.
//
// Originally this just limited to 1024x1024; but that still
// had us hitting overall total memory usage limits (which was
// around 220MB on my intel shared memory system with 2GB RAM
// and 16-128mb in use by the video card, so I can't make
// heads or tails out of this limit).
//
// So instead, we clamp the max size to 64MB (this limit shuld
// be made dynamic based on.. something.. as soon a we figure
// out that something) and also limit each individual image to
// be less than 4MB to keep very large images out of DDBs.
// assume (almost -- we don't quadword-align) worst-case size
PRUint32 ddbSize = mSize.width * mSize.height * 4;
if (ddbSize <= kMaxSingleDDBSize &&
ddbSize + gTotalDDBSize <= kMaxDDBSize)
{
nsRefPtr<gfxWindowsSurface> wsurf = mWinSurface->OptimizeToDDB(nsnull, gfxIntSize(mSize.width, mSize.height), mFormat);
if (wsurf) {
gTotalDDBs++;
gTotalDDBSize += ddbSize;
mIsDDBSurface = PR_TRUE;
mOptSurface = wsurf;
}
}
if (!mOptSurface && !mFormatChanged) {
// just use the DIB if the format has not changed
mOptSurface = mWinSurface;
}
}
#endif
#ifdef XP_MACOSX
if (mQuartzSurface) {
mQuartzSurface->Flush();
mOptSurface = mQuartzSurface;
}
#endif
if (mOptSurface == nsnull)
mOptSurface = gfxPlatform::GetPlatform()->OptimizeImage(mImageSurface, mFormat);
if (mOptSurface) {
mImageSurface = nsnull;
#ifdef USE_WIN_SURFACE
mWinSurface = nsnull;
#endif
#ifdef XP_MACOSX
mQuartzSurface = nsnull;
#endif
}
return NS_OK;
}
static PRBool
IsSafeImageTransformComponent(gfxFloat aValue)
{
return aValue >= -32768 && aValue <= 32767;
}
void imgFrame::Draw(gfxContext *aContext, gfxPattern::GraphicsFilter aFilter,
const gfxMatrix &aUserSpaceToImageSpace, const gfxRect& aFill,
const nsIntMargin &aPadding, const nsIntRect &aSubimage)
{
NS_ASSERTION(!aFill.IsEmpty(), "zero dest size --- fix caller");
NS_ASSERTION(!aSubimage.IsEmpty(), "zero source size --- fix caller");
NS_ASSERTION(!mPalettedImageData, "Directly drawing a paletted image!");
PRBool doPadding = aPadding != nsIntMargin(0,0,0,0);
PRBool doPartialDecode = !ImageComplete();
gfxContext::GraphicsOperator op = aContext->CurrentOperator();
if (mSinglePixel && !doPadding && ImageComplete()) {
// Single-color fast path
// if a == 0, it's a noop
if (mSinglePixelColor.a == 0.0)
return;
if (op == gfxContext::OPERATOR_OVER && mSinglePixelColor.a == 1.0)
aContext->SetOperator(gfxContext::OPERATOR_SOURCE);
aContext->SetDeviceColor(mSinglePixelColor);
aContext->NewPath();
aContext->Rectangle(aFill);
aContext->Fill();
aContext->SetOperator(op);
aContext->SetDeviceColor(gfxRGBA(0,0,0,0));
return;
}
gfxMatrix userSpaceToImageSpace = aUserSpaceToImageSpace;
gfxRect sourceRect = userSpaceToImageSpace.Transform(aFill);
gfxRect imageRect(0, 0, mSize.width + aPadding.LeftRight(), mSize.height + aPadding.TopBottom());
gfxRect subimage(aSubimage.x, aSubimage.y, aSubimage.width, aSubimage.height);
gfxRect fill = aFill;
nsRefPtr<gfxASurface> surface;
gfxImageSurface::gfxImageFormat format;
NS_ASSERTION(!sourceRect.Intersect(subimage).IsEmpty(),
"We must be allowed to sample *some* source pixels!");
PRBool doTile = !imageRect.Contains(sourceRect);
if (doPadding || doPartialDecode) {
gfxRect available = gfxRect(mDecoded.x, mDecoded.y, mDecoded.width, mDecoded.height) +
gfxPoint(aPadding.left, aPadding.top);
if (!doTile && !mSinglePixel) {
// Not tiling, and we have a surface, so we can account for
// padding and/or a partial decode just by twiddling parameters.
// First, update our user-space fill rect.
sourceRect = sourceRect.Intersect(available);
gfxMatrix imageSpaceToUserSpace = userSpaceToImageSpace;
imageSpaceToUserSpace.Invert();
fill = imageSpaceToUserSpace.Transform(sourceRect);
surface = ThebesSurface();
format = mFormat;
subimage = subimage.Intersect(available) - gfxPoint(aPadding.left, aPadding.top);
userSpaceToImageSpace.Multiply(gfxMatrix().Translate(-gfxPoint(aPadding.left, aPadding.top)));
sourceRect = sourceRect - gfxPoint(aPadding.left, aPadding.top);
imageRect = gfxRect(0, 0, mSize.width, mSize.height);
} else {
// Create a temporary surface
gfxIntSize size(PRInt32(imageRect.Width()), PRInt32(imageRect.Height()));
// Give this surface an alpha channel because there are
// transparent pixels in the padding or undecoded area
format = gfxASurface::ImageFormatARGB32;
surface = gfxPlatform::GetPlatform()->CreateOffscreenSurface(size, format);
if (!surface || surface->CairoStatus() != 0)
return;
// Fill 'available' with whatever we've got
gfxContext tmpCtx(surface);
tmpCtx.SetOperator(gfxContext::OPERATOR_SOURCE);
if (mSinglePixel) {
tmpCtx.SetDeviceColor(mSinglePixelColor);
} else {
tmpCtx.SetSource(ThebesSurface(), gfxPoint(aPadding.left, aPadding.top));
}
tmpCtx.Rectangle(available);
tmpCtx.Fill();
}
} else {
NS_ASSERTION(!mSinglePixel, "This should already have been handled");
surface = ThebesSurface();
format = mFormat;
}
// At this point, we've taken care of mSinglePixel images, images with
// aPadding, and partially-decoded images.
if (!AllowedImageSize(fill.size.width + 1, fill.size.height + 1)) {
NS_WARNING("Destination area too large, bailing out");
return;
}
// Compute device-space-to-image-space transform. We need to sanity-
// check it to work around a pixman bug :-(
// XXX should we only do this for certain surface types?
gfxFloat deviceX, deviceY;
nsRefPtr<gfxASurface> currentTarget =
aContext->CurrentSurface(&deviceX, &deviceY);
gfxMatrix currentMatrix = aContext->CurrentMatrix();
gfxMatrix deviceToUser = currentMatrix;
deviceToUser.Invert();
deviceToUser.Translate(-gfxPoint(-deviceX, -deviceY));
gfxMatrix deviceToImage = deviceToUser;
deviceToImage.Multiply(userSpaceToImageSpace);
PRBool pushedGroup = PR_FALSE;
if (currentTarget->GetType() != gfxASurface::SurfaceTypeQuartz) {
// BEGIN working around cairo/pixman bug (bug 364968)
// Quartz's limits for matrix are much larger than pixman
// Our device-space-to-image-space transform may not be acceptable to pixman.
if (!IsSafeImageTransformComponent(deviceToImage.xx) ||
!IsSafeImageTransformComponent(deviceToImage.xy) ||
!IsSafeImageTransformComponent(deviceToImage.yx) ||
!IsSafeImageTransformComponent(deviceToImage.yy)) {
NS_WARNING("Scaling up too much, bailing out");
return;
}
if (!IsSafeImageTransformComponent(deviceToImage.x0) ||
!IsSafeImageTransformComponent(deviceToImage.y0)) {
// We'll push a group, which will hopefully reduce our transform's
// translation so it's in bounds
aContext->Save();
// Clip the rounded-out-to-device-pixels bounds of the
// transformed fill area. This is the area for the group we
// want to push.
aContext->IdentityMatrix();
gfxRect bounds = currentMatrix.TransformBounds(fill);
bounds.RoundOut();
aContext->Clip(bounds);
aContext->SetMatrix(currentMatrix);
aContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
aContext->SetOperator(gfxContext::OPERATOR_OVER);
pushedGroup = PR_TRUE;
}
// END working around cairo/pixman bug (bug 364968)
}
nsRefPtr<gfxPattern> pattern = new gfxPattern(surface);
pattern->SetMatrix(userSpaceToImageSpace);
// OK now, the hard part left is to account for the subimage sampling
// restriction. If all the transforms involved are just integer
// translations, then we assume no resampling will occur so there's
// nothing to do.
// XXX if only we had source-clipping in cairo!
if (!currentMatrix.HasNonIntegerTranslation() &&
!userSpaceToImageSpace.HasNonIntegerTranslation()) {
if (doTile) {
pattern->SetExtend(gfxPattern::EXTEND_REPEAT);
}
} else {
if (doTile || !subimage.Contains(imageRect)) {
// EXTEND_PAD won't help us here; we have to create a temporary
// surface to hold the subimage of pixels we're allowed to
// sample
gfxRect userSpaceClipExtents = aContext->GetClipExtents();
// This isn't optimal --- if aContext has a rotation then GetClipExtents
// will have to do a bounding-box computation, and TransformBounds might
// too, so we could get a better result if we computed image space clip
// extents in one go --- but it doesn't really matter and this is easier
// to understand.
gfxRect imageSpaceClipExtents = userSpaceToImageSpace.TransformBounds(userSpaceClipExtents);
// Inflate by one pixel because bilinear filtering will sample at most
// one pixel beyond the computed image pixel coordinate.
imageSpaceClipExtents.Outset(1.0);
gfxRect needed = imageSpaceClipExtents.Intersect(sourceRect).Intersect(subimage);
needed.RoundOut();
// if 'needed' is empty, nothing will be drawn since aFill
// must be entirely outside the clip region, so it doesn't
// matter what we do here, but we should avoid trying to
// create a zero-size surface.
if (!needed.IsEmpty()) {
gfxIntSize size(PRInt32(needed.Width()), PRInt32(needed.Height()));
nsRefPtr<gfxASurface> temp =
gfxPlatform::GetPlatform()->CreateOffscreenSurface(size, format);
if (temp && temp->CairoStatus() == 0) {
gfxContext tmpCtx(temp);
tmpCtx.SetOperator(gfxContext::OPERATOR_SOURCE);
nsRefPtr<gfxPattern> tmpPattern = new gfxPattern(surface);
if (tmpPattern) {
tmpPattern->SetExtend(gfxPattern::EXTEND_REPEAT);
tmpPattern->SetMatrix(gfxMatrix().Translate(needed.pos));
tmpCtx.SetPattern(tmpPattern);
tmpCtx.Paint();
tmpPattern = new gfxPattern(temp);
if (tmpPattern) {
pattern.swap(tmpPattern);
pattern->SetMatrix(
gfxMatrix(userSpaceToImageSpace).Multiply(gfxMatrix().Translate(-needed.pos)));
}
}
}
}
}
// In theory we can handle this using cairo's EXTEND_PAD,
// but implementation limitations mean we have to consult
// the surface type.
switch (currentTarget->GetType()) {
case gfxASurface::SurfaceTypeXlib:
case gfxASurface::SurfaceTypeXcb:
{
// See bug 324698. This is a workaround for EXTEND_PAD not being
// implemented correctly on linux in the X server.
//
// Set the filter to CAIRO_FILTER_FAST --- otherwise,
// pixman's sampling will sample transparency for the outside edges and we'll
// get blurry edges. CAIRO_EXTEND_PAD would also work here, if
// available
//
// But don't do this for simple downscales because it's horrible.
// Downscaling means that device-space coordinates are
// scaled *up* to find the image pixel coordinates.
//
// deviceToImage is slightly stale because up above we may
// have adjusted the pattern's matrix ... but the adjustment
// is only a translation so the scale factors in deviceToImage
// are still valid.
PRBool isDownscale =
deviceToImage.xx >= 1.0 && deviceToImage.yy >= 1.0 &&
deviceToImage.xy == 0.0 && deviceToImage.yx == 0.0;
if (!isDownscale) {
pattern->SetFilter(gfxPattern::FILTER_FAST);
}
break;
}
case gfxASurface::SurfaceTypeQuartz:
case gfxASurface::SurfaceTypeQuartzImage:
// Don't set EXTEND_PAD, Mac seems to be OK. Really?
pattern->SetFilter(aFilter);
break;
default:
// turn on EXTEND_PAD.
// This is what we really want for all surface types, if the
// implementation was universally good.
pattern->SetExtend(gfxPattern::EXTEND_PAD);
pattern->SetFilter(aFilter);
break;
}
}
if ((op == gfxContext::OPERATOR_OVER || pushedGroup) &&
format == gfxASurface::ImageFormatRGB24) {
aContext->SetOperator(gfxContext::OPERATOR_SOURCE);
}
// Phew! Now we can actually draw this image
aContext->NewPath();
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
pattern->SetFilter(gfxPattern::FILTER_FAST);
#endif
aContext->SetPattern(pattern);
aContext->Rectangle(fill);
aContext->Fill();
aContext->SetOperator(op);
if (pushedGroup) {
aContext->PopGroupToSource();
aContext->Paint();
aContext->Restore();
}
}
nsresult imgFrame::Extract(const nsIntRect& aRegion, imgFrame** aResult)
{
nsAutoPtr<imgFrame> subImage(new imgFrame());
if (!subImage)
return NS_ERROR_OUT_OF_MEMORY;
// The scaling problems described in bug 468496 are especially
// likely to be visible for the sub-image, as at present the only
// user is the border-image code and border-images tend to get
// stretched a lot. At the same time, the performance concerns
// that prevent us from just using Cairo's fallback scaler when
// accelerated graphics won't cut it are less relevant to such
// images, since they also tend to be small. Thus, we forcibly
// disable the use of anything other than a client-side image
// surface for the sub-image; this ensures that the correct
// (albeit slower) Cairo fallback scaler will be used.
subImage->mNeverUseDeviceSurface = PR_TRUE;
nsresult rv = subImage->Init(0, 0, aRegion.width, aRegion.height,
mFormat, mPaletteDepth);
NS_ENSURE_SUCCESS(rv, rv);
// scope to destroy ctx
{
gfxContext ctx(subImage->ThebesSurface());
ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
if (mSinglePixel) {
ctx.SetDeviceColor(mSinglePixelColor);
} else {
// SetSource() places point (0,0) of its first argument at
// the coordinages given by its second argument. We want
// (x,y) of the image to be (0,0) of source space, so we
// put (0,0) of the image at (-x,-y).
ctx.SetSource(this->ThebesSurface(), gfxPoint(-aRegion.x, -aRegion.y));
}
ctx.Rectangle(gfxRect(0, 0, aRegion.width, aRegion.height));
ctx.Fill();
}
nsIntRect filled(0, 0, aRegion.width, aRegion.height);
rv = subImage->ImageUpdated(filled);
NS_ENSURE_SUCCESS(rv, rv);
subImage->Optimize();
*aResult = subImage.forget();
return NS_OK;
}
nsresult imgFrame::ImageUpdated(const nsIntRect &aUpdateRect)
{
// Check to see if we are running OOM
nsCOMPtr<nsIMemory> mem;
NS_GetMemoryManager(getter_AddRefs(mem));
if (!mem)
return NS_ERROR_UNEXPECTED;
PRBool lowMemory;
mem->IsLowMemory(&lowMemory);
if (lowMemory)
return NS_ERROR_OUT_OF_MEMORY;
mDecoded.UnionRect(mDecoded, aUpdateRect);
// clamp to bounds, in case someone sends a bogus updateRect (I'm looking at
// you, gif decoder)
nsIntRect boundsRect(0, 0, mSize.width, mSize.height);
mDecoded.IntersectRect(mDecoded, boundsRect);
#ifdef XP_MACOSX
if (mQuartzSurface)
mQuartzSurface->Flush();
#endif
return NS_OK;
}
PRInt32 imgFrame::GetX() const
{
return mOffset.x;
}
PRInt32 imgFrame::GetY() const
{
return mOffset.y;
}
PRInt32 imgFrame::GetWidth() const
{
return mSize.width;
}
PRInt32 imgFrame::GetHeight() const
{
return mSize.height;
}
nsIntRect imgFrame::GetRect() const
{
return nsIntRect(mOffset, mSize);
}
gfxASurface::gfxImageFormat imgFrame::GetFormat() const
{
return mFormat;
}
PRBool imgFrame::GetNeedsBackground() const
{
// We need a background painted if we have alpha or we're incomplete.
return (mFormat == gfxASurface::ImageFormatARGB32 || !ImageComplete());
}
PRUint32 imgFrame::GetImageBytesPerRow() const
{
if (mImageSurface)
return mImageSurface->Stride();
else
return mSize.width;
}
PRUint32 imgFrame::GetImageDataLength() const
{
if (mImageSurface)
return mImageSurface->Stride() * mSize.height;
else
return mSize.width * mSize.height;
}
void imgFrame::GetImageData(PRUint8 **aData, PRUint32 *length) const
{
if (mImageSurface)
*aData = mImageSurface->Data();
else if (mPalettedImageData)
*aData = mPalettedImageData + PaletteDataLength();
else
*aData = nsnull;
*length = GetImageDataLength();
}
PRBool imgFrame::GetIsPaletted() const
{
return mPalettedImageData != nsnull;
}
PRBool imgFrame::GetHasAlpha() const
{
return mFormat != gfxASurface::ImageFormatARGB32;
}
void imgFrame::GetPaletteData(PRUint32 **aPalette, PRUint32 *length) const
{
if (!mPalettedImageData) {
*aPalette = nsnull;
*length = 0;
} else {
*aPalette = (PRUint32 *) mPalettedImageData;
*length = PaletteDataLength();
}
}
nsresult imgFrame::LockImageData()
{
if (mPalettedImageData)
return NS_OK;
if ((mOptSurface || mSinglePixel) && !mImageSurface) {
// Recover the pixels
mImageSurface = new gfxImageSurface(gfxIntSize(mSize.width, mSize.height),
gfxImageSurface::ImageFormatARGB32);
if (!mImageSurface || mImageSurface->CairoStatus())
return NS_ERROR_OUT_OF_MEMORY;
gfxContext context(mImageSurface);
context.SetOperator(gfxContext::OPERATOR_SOURCE);
if (mSinglePixel)
context.SetDeviceColor(mSinglePixelColor);
else
context.SetSource(mOptSurface);
context.Paint();
mOptSurface = nsnull;
#ifdef USE_WIN_SURFACE
mWinSurface = nsnull;
#endif
#ifdef XP_MACOSX
mQuartzSurface = nsnull;
#endif
}
return NS_OK;
}
nsresult imgFrame::UnlockImageData()
{
if (mPalettedImageData)
return NS_OK;
#ifdef XP_MACOSX
if (mQuartzSurface)
mQuartzSurface->Flush();
#endif
return NS_OK;
}
PRInt32 imgFrame::GetTimeout() const
{
// Ensure a minimal time between updates so we don't throttle the UI thread.
// consider 0 == unspecified and make it fast but not too fast. See bug
// 125137, bug 139677, and bug 207059. The behavior of recent IE and Opera
// versions seems to be:
// IE 6/Win:
// 10 - 50ms go 100ms
// >50ms go correct speed
// Opera 7 final/Win:
// 10ms goes 100ms
// >10ms go correct speed
// It seems that there are broken tools out there that set a 0ms or 10ms
// timeout when they really want a "default" one. So munge values in that
// range.
if (mTimeout >= 0 && mTimeout <= 10)
return 100;
else
return mTimeout;
}
void imgFrame::SetTimeout(PRInt32 aTimeout)
{
mTimeout = aTimeout;
}
PRInt32 imgFrame::GetFrameDisposalMethod() const
{
return mDisposalMethod;
}
void imgFrame::SetFrameDisposalMethod(PRInt32 aFrameDisposalMethod)
{
mDisposalMethod = aFrameDisposalMethod;
}
PRInt32 imgFrame::GetBlendMethod() const
{
return mBlendMethod;
}
void imgFrame::SetBlendMethod(PRInt32 aBlendMethod)
{
mBlendMethod = (PRInt8)aBlendMethod;
}
PRBool imgFrame::ImageComplete() const
{
return mDecoded == nsIntRect(0, 0, mSize.width, mSize.height);
}
// A hint from the image decoders that this image has no alpha, even
// though we created is ARGB32. This changes our format to RGB24,
// which in turn will cause us to Optimize() to RGB24. Has no effect
// after Optimize() is called, though in all cases it will be just a
// performance win -- the pixels are still correct and have the A byte
// set to 0xff.
void imgFrame::SetHasNoAlpha()
{
if (mFormat == gfxASurface::ImageFormatARGB32) {
mFormat = gfxASurface::ImageFormatRGB24;
mFormatChanged = PR_TRUE;
}
}

View file

@ -0,0 +1,178 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Joe Drew <joe@drew.ca> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef imgFrame_h
#define imgFrame_h
#include "nsRect.h"
#include "nsPoint.h"
#include "nsSize.h"
#include "gfxTypes.h"
#include "nsID.h"
#include "gfxIFormats.h"
#include "gfxContext.h"
#include "gfxPattern.h"
#include "gfxImageSurface.h"
#if defined(XP_WIN)
#include "gfxWindowsSurface.h"
#elif defined(XP_MACOSX)
#include "gfxQuartzImageSurface.h"
#endif
#include "nsAutoPtr.h"
class imgFrame
{
public:
imgFrame();
~imgFrame();
nsresult Init(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, gfxASurface::gfxImageFormat aFormat, PRInt8 aPaletteDepth = 0);
nsresult Optimize();
void Draw(gfxContext *aContext, gfxPattern::GraphicsFilter aFilter,
const gfxMatrix &aUserSpaceToImageSpace, const gfxRect& aFill,
const nsIntMargin &aPadding, const nsIntRect &aSubimage);
nsresult Extract(const nsIntRect& aRegion, imgFrame** aResult);
nsresult ImageUpdated(const nsIntRect &aUpdateRect);
PRInt32 GetX() const;
PRInt32 GetY() const;
PRInt32 GetWidth() const;
PRInt32 GetHeight() const;
nsIntRect GetRect() const;
gfxASurface::gfxImageFormat GetFormat() const;
PRBool GetNeedsBackground() const;
PRUint32 GetImageBytesPerRow() const;
PRUint32 GetImageDataLength() const;
PRBool GetIsPaletted() const;
PRBool GetHasAlpha() const;
void GetImageData(PRUint8 **aData, PRUint32 *length) const;
void GetPaletteData(PRUint32 **aPalette, PRUint32 *length) const;
PRInt32 GetTimeout() const;
void SetTimeout(PRInt32 aTimeout);
PRInt32 GetFrameDisposalMethod() const;
void SetFrameDisposalMethod(PRInt32 aFrameDisposalMethod);
PRInt32 GetBlendMethod() const;
void SetBlendMethod(PRInt32 aBlendMethod);
PRBool ImageComplete() const;
void SetHasNoAlpha();
nsresult LockImageData();
nsresult UnlockImageData();
nsresult GetSurface(gfxASurface **aSurface) const
{
*aSurface = ThebesSurface();
NS_IF_ADDREF(*aSurface);
return NS_OK;
}
nsresult GetPattern(gfxPattern **aPattern) const
{
if (mSinglePixel)
*aPattern = new gfxPattern(mSinglePixelColor);
else
*aPattern = new gfxPattern(ThebesSurface());
NS_ADDREF(*aPattern);
return NS_OK;
}
gfxASurface* ThebesSurface() const
{
if (mOptSurface)
return mOptSurface;
#if defined(XP_WIN) && !defined(WINCE)
if (mWinSurface)
return mWinSurface;
#elif defined(XP_MACOSX)
if (mQuartzSurface)
return mQuartzSurface;
#endif
return mImageSurface;
}
private: // methods
PRUint32 PaletteDataLength() const {
return ((1 << mPaletteDepth) * sizeof(PRUint32));
}
private: // data
nsRefPtr<gfxImageSurface> mImageSurface;
nsRefPtr<gfxASurface> mOptSurface;
#if defined(XP_WIN) && !defined(WINCE)
nsRefPtr<gfxWindowsSurface> mWinSurface;
#elif defined(XP_MACOSX)
nsRefPtr<gfxQuartzImageSurface> mQuartzSurface;
#endif
nsIntSize mSize;
nsIntPoint mOffset;
nsIntRect mDecoded;
// The palette and image data for images that are paletted, since Cairo
// doesn't support these images.
// The paletted data comes first, then the image data itself.
// Total length is PaletteDataLength() + GetImageDataLength().
PRUint8* mPalettedImageData;
gfxRGBA mSinglePixelColor;
PRInt32 mTimeout; // -1 means display forever
PRInt32 mDisposalMethod;
gfxASurface::gfxImageFormat mFormat;
PRInt8 mPaletteDepth;
PRInt8 mBlendMethod;
PRPackedBool mSinglePixel;
PRPackedBool mNeverUseDeviceSurface;
PRPackedBool mFormatChanged;
#ifdef XP_WIN
PRPackedBool mIsDDBSurface;
#endif
};
#endif /* imgFrame_h */

View file

@ -46,8 +46,6 @@
#include "ImageErrors.h"
#include "ImageLogging.h"
#include "gfxIImageFrame.h"
#include "netCore.h"
#include "nsIChannel.h"
@ -269,24 +267,19 @@ nsresult imgRequest::NotifyProxyListener(imgRequestProxy *proxy)
mImage->GetNumFrames(&nframes);
if (nframes > 0) {
nsCOMPtr<gfxIImageFrame> frame;
// get the current frame or only frame
mImage->GetCurrentFrame(getter_AddRefs(frame));
NS_ENSURE_TRUE(frame, NS_ERROR_OUT_OF_MEMORY);
// OnStartFrame
PRUint32 frame;
mImage->GetCurrentFrameIndex(&frame);
proxy->OnStartFrame(frame);
if (!(mState & onStopContainer)) {
// OnDataAvailable
nsIntRect r;
frame->GetRect(r); // XXX we should only send the currently decoded rectangle here.
mImage->GetCurrentFrameRect(r); // XXX we should only send the currently decoded rectangle here.
proxy->OnDataAvailable(frame, &r);
} else {
// OnDataAvailable
nsIntRect r;
frame->GetRect(r); // We're done loading this image, send the the whole rect
mImage->GetCurrentFrameRect(r); // We're done loading this image, send the the whole rect
proxy->OnDataAvailable(frame, &r);
// OnStopFrame
@ -511,16 +504,15 @@ NS_IMETHODIMP imgRequest::GetIsMultiPartChannel(PRBool *aIsMultiPartChannel)
/** imgIContainerObserver methods **/
/* [noscript] void frameChanged (in imgIContainer container, in gfxIImageFrame newframe, in nsIntRect dirtyRect); */
/* [noscript] void frameChanged (in imgIContainer container, in nsIntRect dirtyRect); */
NS_IMETHODIMP imgRequest::FrameChanged(imgIContainer *container,
gfxIImageFrame *newframe,
nsIntRect * dirtyRect)
{
LOG_SCOPE(gImgLog, "imgRequest::FrameChanged");
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
while (iter.HasMore()) {
iter.GetNext()->FrameChanged(container, newframe, dirtyRect);
iter.GetNext()->FrameChanged(container, dirtyRect);
}
return NS_OK;
@ -577,9 +569,9 @@ NS_IMETHODIMP imgRequest::OnStartContainer(imgIRequest *request, imgIContainer *
return NS_OK;
}
/* void onStartFrame (in imgIRequest request, in gfxIImageFrame frame); */
/* void onStartFrame (in imgIRequest request, in unsigned long frame); */
NS_IMETHODIMP imgRequest::OnStartFrame(imgIRequest *request,
gfxIImageFrame *frame)
PRUint32 frame)
{
LOG_SCOPE(gImgLog, "imgRequest::OnStartFrame");
@ -591,28 +583,25 @@ NS_IMETHODIMP imgRequest::OnStartFrame(imgIRequest *request,
return NS_OK;
}
/* [noscript] void onDataAvailable (in imgIRequest request, in gfxIImageFrame frame, [const] in nsIntRect rect); */
/* [noscript] void onDataAvailable (in imgIRequest request, in boolean aCurrentFrame, [const] in nsIntRect rect); */
NS_IMETHODIMP imgRequest::OnDataAvailable(imgIRequest *request,
gfxIImageFrame *frame,
PRBool aCurrentFrame,
const nsIntRect * rect)
{
LOG_SCOPE(gImgLog, "imgRequest::OnDataAvailable");
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
while (iter.HasMore()) {
iter.GetNext()->OnDataAvailable(frame, rect);
iter.GetNext()->OnDataAvailable(aCurrentFrame, rect);
}
return NS_OK;
}
/* void onStopFrame (in imgIRequest request, in gfxIImageFrame frame); */
/* void onStopFrame (in imgIRequest request, in unsigned long frame); */
NS_IMETHODIMP imgRequest::OnStopFrame(imgIRequest *request,
gfxIImageFrame *frame)
PRUint32 frame)
{
NS_ASSERTION(frame, "imgRequest::OnStopFrame called with NULL frame");
if (!frame) return NS_ERROR_UNEXPECTED;
LOG_SCOPE(gImgLog, "imgRequest::OnStopFrame");
mImageStatus |= imgIRequest::STATUS_FRAME_COMPLETE;
@ -621,7 +610,8 @@ NS_IMETHODIMP imgRequest::OnStopFrame(imgIRequest *request,
PRUint32 cacheSize = mCacheEntry->GetDataSize();
PRUint32 imageSize = 0;
frame->GetImageDataLength(&imageSize);
if (mImage)
mImage->GetFrameImageDataLength(frame, &imageSize);
mCacheEntry->SetDataSize(cacheSize + imageSize);

View file

@ -425,14 +425,14 @@ NS_IMETHODIMP imgRequestProxy::GetHasTransferredData(PRBool* hasData)
/** imgIContainerObserver methods **/
void imgRequestProxy::FrameChanged(imgIContainer *container, gfxIImageFrame *newframe, nsIntRect * dirtyRect)
void imgRequestProxy::FrameChanged(imgIContainer *container, nsIntRect * dirtyRect)
{
LOG_FUNC(gImgLog, "imgRequestProxy::FrameChanged");
if (mListener && !mCanceled) {
// Hold a ref to the listener while we call it, just in case.
nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener);
mListener->FrameChanged(container, newframe, dirtyRect);
mListener->FrameChanged(container, dirtyRect);
}
}
@ -460,7 +460,7 @@ void imgRequestProxy::OnStartContainer(imgIContainer *image)
}
}
void imgRequestProxy::OnStartFrame(gfxIImageFrame *frame)
void imgRequestProxy::OnStartFrame(PRUint32 frame)
{
LOG_FUNC(gImgLog, "imgRequestProxy::OnStartFrame");
@ -471,18 +471,18 @@ void imgRequestProxy::OnStartFrame(gfxIImageFrame *frame)
}
}
void imgRequestProxy::OnDataAvailable(gfxIImageFrame *frame, const nsIntRect * rect)
void imgRequestProxy::OnDataAvailable(PRBool aCurrentFrame, const nsIntRect * rect)
{
LOG_FUNC(gImgLog, "imgRequestProxy::OnDataAvailable");
if (mListener && !mCanceled) {
// Hold a ref to the listener while we call it, just in case.
nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener);
mListener->OnDataAvailable(this, frame, rect);
mListener->OnDataAvailable(this, aCurrentFrame, rect);
}
}
void imgRequestProxy::OnStopFrame(gfxIImageFrame *frame)
void imgRequestProxy::OnStopFrame(PRUint32 frame)
{
LOG_FUNC(gImgLog, "imgRequestProxy::OnStopFrame");

View file

@ -111,14 +111,14 @@ protected:
/* non-virtual imgIDecoderObserver methods */
void OnStartDecode ();
void OnStartContainer(imgIContainer *aContainer);
void OnStartFrame (gfxIImageFrame *aFrame);
void OnDataAvailable (gfxIImageFrame *aFrame, const nsIntRect * aRect);
void OnStopFrame (gfxIImageFrame *aFrame);
void OnStartFrame (PRUint32 aFrame);
void OnDataAvailable (PRBool aCurrentFrame, const nsIntRect * aRect);
void OnStopFrame (PRUint32 aFrame);
void OnStopContainer (imgIContainer *aContainer);
void OnStopDecode (nsresult status, const PRUnichar *statusArg);
/* non-virtual imgIContainerObserver methods */
void FrameChanged(imgIContainer *aContainer, gfxIImageFrame *aFrame, nsIntRect * aDirtyRect);
void FrameChanged(imgIContainer *aContainer, nsIntRect * aDirtyRect);
/* non-virtual nsIRequestObserver (plus some) methods */
void OnStartRequest(nsIRequest *request, nsISupports *ctxt);

View file

@ -46,9 +46,6 @@
#include "imgIEncoder.h"
#include "imgIDecoderObserver.h"
#include "imgIContainerObserver.h"
#include "nsIImage.h"
#include "gfxIImageFrame.h"
#include "gfxImageSurface.h"
#include "gfxContext.h"
#include "nsStringStream.h"
#include "nsComponentManagerUtils.h"
@ -129,22 +126,21 @@ HelperLoader::OnStartContainer(imgIRequest *aRequest, imgIContainer
/* Implement imgIDecoderObserver::onStartFrame() */
NS_IMETHODIMP
HelperLoader::OnStartFrame(imgIRequest *aRequest, gfxIImageFrame *aFrame)
HelperLoader::OnStartFrame(imgIRequest *aRequest, PRUint32 aFrame)
{
return NS_OK;
}
/* Implement imgIDecoderObserver::onDataAvailable() */
NS_IMETHODIMP
HelperLoader::OnDataAvailable(imgIRequest *aRequest, gfxIImageFrame
*aFrame, const nsIntRect * aRect)
HelperLoader::OnDataAvailable(imgIRequest *aRequest, PRBool aCurrentFrame, const nsIntRect * aRect)
{
return NS_OK;
}
/* Implement imgIDecoderObserver::onStopFrame() */
NS_IMETHODIMP
HelperLoader::OnStopFrame(imgIRequest *aRequest, gfxIImageFrame *aFrame)
HelperLoader::OnStopFrame(imgIRequest *aRequest, PRUint32 aFrame)
{
return NS_OK;
}
@ -174,8 +170,7 @@ HelperLoader::OnStopRequest(imgIRequest *aRequest, PRBool aIsLastPart)
/* implement imgIContainerObserver::frameChanged() */
NS_IMETHODIMP
HelperLoader::FrameChanged(imgIContainer *aContainer,
gfxIImageFrame *aFrame, nsIntRect * aDirtyRect)
HelperLoader::FrameChanged(imgIContainer *aContainer, nsIntRect * aDirtyRect)
{
return NS_OK;
}
@ -230,7 +225,6 @@ NS_IMETHODIMP imgTools::DecodeImageData(nsIInputStream* aInStr,
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 written;
NS_ENSURE_SUCCESS(rv, rv);
rv = decoder->WriteFrom(aInStr, length, &written);
NS_ENSURE_SUCCESS(rv, rv);
if (written != length)
@ -285,19 +279,16 @@ NS_IMETHODIMP imgTools::EncodeScaledImage(imgIContainer *aContainer,
return NS_IMAGELIB_ERROR_NO_ENCODER;
// Use frame 0 from the image container.
nsCOMPtr<gfxIImageFrame> frame;
rv = aContainer->GetFrameAt(0, getter_AddRefs(frame));
nsRefPtr<gfxImageSurface> frame;
rv = aContainer->CopyCurrentFrame(getter_AddRefs(frame));
NS_ENSURE_SUCCESS(rv, rv);
if (!frame)
return NS_ERROR_NOT_AVAILABLE;
PRInt32 w,h;
frame->GetWidth(&w);
frame->GetHeight(&h);
PRInt32 w = frame->Width(), h = frame->Height();
if (!w || !h)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIImage> img(do_GetInterface(frame));
nsRefPtr<gfxImageSurface> dest;
if (!doScaling) {
@ -305,23 +296,16 @@ NS_IMETHODIMP imgTools::EncodeScaledImage(imgIContainer *aContainer,
aScaledWidth = w;
aScaledHeight = h;
img->LockImagePixels(PR_FALSE);
bitmapData = img->GetBits();
if (!bitmapData) {
img->UnlockImagePixels(PR_FALSE);
bitmapData = frame->Data();
if (!bitmapData)
return NS_ERROR_FAILURE;
}
frame->GetImageBytesPerRow(&strideSize);
strideSize = frame->Stride();
bitmapDataLength = aScaledHeight * strideSize;
} else {
// Prepare to draw a scaled version of the image to a temporary surface...
// Get the source image surface
nsRefPtr<gfxPattern> gfxpat;
img->GetPattern(getter_AddRefs(gfxpat));
// Create a temporary image surface
dest = new gfxImageSurface(gfxIntSize(aScaledWidth, aScaledHeight),
gfxASurface::ImageFormatARGB32);
@ -337,7 +321,7 @@ NS_IMETHODIMP imgTools::EncodeScaledImage(imgIContainer *aContainer,
// Paint a scaled image
ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
ctx.SetPattern(gfxpat);
ctx.SetSource(frame);
ctx.Paint();
bitmapData = dest->Data();
@ -349,8 +333,6 @@ NS_IMETHODIMP imgTools::EncodeScaledImage(imgIContainer *aContainer,
rv = encoder->InitFromData(bitmapData, bitmapDataLength,
aScaledWidth, aScaledHeight, strideSize,
imgIEncoder::INPUT_FORMAT_HOSTARGB, EmptyString());
if (!doScaling)
img->UnlockImagePixels(PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);

View file

@ -383,19 +383,23 @@ imgFile = do_get_file(imgName);
istream = getFileInputStream(imgFile);
do_check_eq(istream.available(), 17759);
// You'd think the decoder would fail, but it doesn't. The decoders use
// stream->ReadSegments with a callback, and buffered streams ignore errors
// from the callback. :-( See bug 413595.
outParam = { value: null };
imgTools.decodeImageData(istream, inMimeType, outParam);
container = outParam.value;
try {
istream = imgTools.encodeImage(container, "image/png");
outParam = { value: null };
imgTools.decodeImageData(istream, inMimeType, outParam);
container = outParam.value;
// We should never hit this - decodeImageData throws an assertion because the
// image decoded doesn't have enough frames.
try {
istream = imgTools.encodeImage(container, "image/png");
} catch (e) {
err = e;
}
} catch (e) {
err = e;
err = e;
}
checkExpectedError(/NS_ERROR_NOT_AVAILABLE/, err);
checkExpectedError(/NS_ERROR_ILLEGAL_VALUE/, err);
/* ========== end ========== */

View file

@ -95,7 +95,6 @@ STATIC_LIBS += \
xpcom_core \
ucvutil_s \
gkgfx \
gfxshared_s \
$(NULL)
#ifndef MOZ_EMBEDDING_LEVEL_DEFAULT

View file

@ -36,10 +36,9 @@
* ***** END LICENSE BLOCK ***** */
#include "nsAlertsIconListener.h"
#include "imgIContainer.h"
#include "imgILoader.h"
#include "imgIRequest.h"
#include "gfxIImageFrame.h"
#include "nsIImage.h"
#include "nsNetUtil.h"
#include "nsIImageToPixbuf.h"
#include "nsIStringBundle.h"
@ -106,7 +105,7 @@ nsAlertsIconListener::OnStartContainer(imgIRequest* aRequest,
NS_IMETHODIMP
nsAlertsIconListener::OnStartFrame(imgIRequest* aRequest,
gfxIImageFrame* aFrame)
PRUint32 aFrame)
{
return NS_OK;
}
@ -114,7 +113,7 @@ nsAlertsIconListener::OnStartFrame(imgIRequest* aRequest,
NS_IMETHODIMP
nsAlertsIconListener::OnDataAvailable(imgIRequest* aRequest,
gfxIImageFrame* aFrame,
PRBool aCurrentFrame,
const nsIntRect* aRect)
{
return NS_OK;
@ -138,7 +137,6 @@ nsAlertsIconListener::OnStopDecode(imgIRequest* aRequest,
NS_IMETHODIMP
nsAlertsIconListener::FrameChanged(imgIContainer* aContainer,
gfxIImageFrame* aFrame,
nsIntRect* aDirtyRect)
{
return NS_OK;
@ -165,7 +163,7 @@ nsAlertsIconListener::OnStopRequest(imgIRequest* aRequest,
NS_IMETHODIMP
nsAlertsIconListener::OnStopFrame(imgIRequest* aRequest,
gfxIImageFrame* aFrame)
PRUint32 aFrame)
{
if (aRequest != mIconRequest)
return NS_ERROR_FAILURE;
@ -173,12 +171,8 @@ nsAlertsIconListener::OnStopFrame(imgIRequest* aRequest,
if (mLoadedFrame)
return NS_OK; // only use one frame
nsCOMPtr<gfxIImageFrame> frame = aFrame;
nsCOMPtr<nsIImage> image = do_GetInterface(frame);
if (!image)
return NS_ERROR_FAILURE;
nsresult rv = image->LockImagePixels(PR_FALSE);
nsCOMPtr<imgIContainer> image;
nsresult rv = aRequest->GetImage(getter_AddRefs(image));
if (NS_FAILED(rv))
return rv;
@ -189,10 +183,6 @@ nsAlertsIconListener::OnStopFrame(imgIRequest* aRequest,
if (!imagePixbuf)
return NS_ERROR_FAILURE;
rv = image->UnlockImagePixels(PR_FALSE);
if (NS_FAILED(rv))
return rv;
ShowAlert(imagePixbuf);
g_object_unref(imagePixbuf);

View file

@ -94,9 +94,6 @@ JS_Init
<atoms>
NS_NewPermanentAtom
<images>
gfxImageFrame::Init
<images>
gif_write

View file

@ -43,13 +43,13 @@
#include "nsXPIDLString.h"
#include "nsPrimitiveHelpers.h"
#include "nsMemory.h"
#include "nsIImage.h"
#include "nsILocalFile.h"
#include "nsStringStream.h"
#include "nsDragService.h"
#include "nsEscape.h"
#include "nsPrintfCString.h"
#include "nsObjCExceptions.h"
#include "imgIContainer.h"
// Screenshots use the (undocumented) png pasteboard type.
#define IMAGE_PASTEBOARD_TYPES NSTIFFPboardType, @"Apple PNG pasteboard type", nil
@ -425,18 +425,19 @@ nsClipboard::PasteboardDictFromTransferable(nsITransferable* aTransferable)
nsCOMPtr<nsISupports> primitiveData;
ptrPrimitive->GetData(getter_AddRefs(primitiveData));
nsCOMPtr<nsIImage> image(do_QueryInterface(primitiveData));
nsCOMPtr<imgIContainer> image(do_QueryInterface(primitiveData));
if (!image) {
NS_WARNING("Image isn't an nsIImage in transferable");
NS_WARNING("Image isn't an imgIContainer in transferable");
continue;
}
if (NS_FAILED(image->LockImagePixels(PR_FALSE)))
nsRefPtr<gfxImageSurface> currentFrame;
if (NS_FAILED(image->CopyCurrentFrame(getter_AddRefs(currentFrame))))
continue;
PRInt32 height = image->GetHeight();
PRInt32 stride = image->GetLineStride();
PRInt32 width = image->GetWidth();
PRInt32 height = currentFrame->Height();
PRInt32 stride = currentFrame->Stride();
PRInt32 width = currentFrame->Width();
if ((stride % 4 != 0) || (height < 1) || (width < 1))
continue;
@ -444,7 +445,7 @@ nsClipboard::PasteboardDictFromTransferable(nsITransferable* aTransferable)
// the alpha ordering and endianness of the machine so we don't have to
// touch the bits ourselves.
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL,
image->GetBits(),
currentFrame->Data(),
stride * height,
NULL);
CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
@ -475,7 +476,7 @@ nsClipboard::PasteboardDictFromTransferable(nsITransferable* aTransferable)
if (destRef)
CFRelease(destRef);
if (NS_FAILED(image->UnlockImagePixels(PR_FALSE)) || !successfullyConverted) {
if (!successfullyConverted) {
if (tiffData)
CFRelease(tiffData);
continue;

View file

@ -50,7 +50,6 @@
#include "nsIDOMNode.h"
#include "nsRect.h"
#include "nsPoint.h"
#include "nsIImage.h"
#include "nsICharsetConverterManager.h"
#include "nsIIOService.h"
#include "nsNetUtil.h"

View file

@ -59,9 +59,9 @@
#include "nsNetUtil.h"
#include "imgILoader.h"
#include "imgIRequest.h"
#include "gfxIImageFrame.h"
#include "nsIImage.h"
#include "nsMenuItemX.h"
#include "gfxImageSurface.h"
#include "imgIContainer.h"
static const PRUint32 kIconWidth = 16;
static const PRUint32 kIconHeight = 16;
@ -280,9 +280,8 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconURI)
//
NS_IMETHODIMP
nsMenuItemIconX::FrameChanged(imgIContainer* aContainer,
gfxIImageFrame* aFrame,
nsIntRect* aDirtyRect)
nsMenuItemIconX::FrameChanged(imgIContainer* aContainer,
nsIntRect* aDirtyRect)
{
return NS_OK;
}
@ -305,32 +304,33 @@ nsMenuItemIconX::OnStartDecode(imgIRequest* aRequest)
NS_IMETHODIMP
nsMenuItemIconX::OnStartContainer(imgIRequest* aRequest,
imgIContainer* aContainer)
imgIContainer* aContainer)
{
return NS_OK;
}
NS_IMETHODIMP
nsMenuItemIconX::OnStartFrame(imgIRequest* aRequest, gfxIImageFrame* aFrame)
nsMenuItemIconX::OnStartFrame(imgIRequest* aRequest, PRUint32 aFrame)
{
return NS_OK;
}
NS_IMETHODIMP
nsMenuItemIconX::OnDataAvailable(imgIRequest* aRequest,
gfxIImageFrame* aFrame,
const nsIntRect* aRect)
PRBool aCurrentFrame,
const nsIntRect* aRect)
{
return NS_OK;
}
NS_IMETHODIMP
nsMenuItemIconX::OnStopFrame(imgIRequest* aRequest,
gfxIImageFrame* aFrame)
PRUint32 aFrame)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (aRequest != mIconRequest) return NS_ERROR_FAILURE;
if (aRequest != mIconRequest)
return NS_ERROR_FAILURE;
// Only support one frame.
if (mLoadedIcon)
@ -338,22 +338,22 @@ nsMenuItemIconX::OnStopFrame(imgIRequest* aRequest,
if (!mNativeMenuItem) return NS_ERROR_FAILURE;
nsCOMPtr<gfxIImageFrame> frame = aFrame;
nsCOMPtr<nsIImage> image = do_GetInterface(frame);
if (!image) return NS_ERROR_FAILURE;
nsCOMPtr<imgIContainer> imageContainer;
aRequest->GetImage(getter_AddRefs(imageContainer));
if (!imageContainer)
return NS_ERROR_FAILURE;
nsresult rv = image->LockImagePixels(PR_FALSE);
if (NS_FAILED(rv))
return rv;
nsRefPtr<gfxImageSurface> image;
imageContainer->CopyCurrentFrame(getter_AddRefs(image));
PRInt32 height = image->GetHeight();
PRInt32 stride = image->GetLineStride();
PRInt32 width = image->GetWidth();
PRInt32 height = image->Height();
PRInt32 stride = image->Stride();
PRInt32 width = image->Width();
PRUint32 imageLength = ((stride * height) / 4);
if ((stride % 4 != 0) || (height < 1) || (width < 1))
return NS_ERROR_FAILURE;
PRUint32* imageData = (PRUint32*)image->GetBits();
PRUint32* imageData = (PRUint32*)image->Data();
PRUint32* reorderedData = (PRUint32*)malloc(height * stride);
if (!reorderedData)
@ -378,12 +378,6 @@ nsMenuItemIconX::OnStopFrame(imgIRequest* aRequest,
NULL, true, kCGRenderingIntentDefault);
::CGDataProviderRelease(provider);
rv = image->UnlockImagePixels(PR_FALSE);
if (NS_FAILED(rv)) {
::CGColorSpaceRelease(colorSpace);
return rv;
}
// The image may not be the right size for a menu icon (16x16).
// Create a new CGImage for the menu item.
PRUint8* bitmap = (PRUint8*)malloc(kIconBytes);

View file

@ -44,10 +44,11 @@
#include "nsPrimitiveHelpers.h"
#include "nsICharsetConverterManager.h"
#include "nsIServiceManager.h"
#include "nsIImage.h"
#include "nsImageToPixbuf.h"
#include "nsStringStream.h"
#include "imgIContainer.h"
#include <gtk/gtk.h>
// For manipulation of the X event queue
@ -239,22 +240,17 @@ nsClipboard::SetData(nsITransferable *aTransferable,
nsCOMPtr<nsISupports> primitiveData;
ptrPrimitive->GetData(getter_AddRefs(primitiveData));
nsCOMPtr<nsIImage> image(do_QueryInterface(primitiveData));
nsCOMPtr<imgIContainer> image(do_QueryInterface(primitiveData));
if (!image) // Not getting an image for an image mime type!?
continue;
if (NS_FAILED(image->LockImagePixels(PR_FALSE)))
continue;
GdkPixbuf* pixbuf = nsImageToPixbuf::ImageToPixbuf(image);
if (!pixbuf) {
image->UnlockImagePixels(PR_FALSE);
if (!pixbuf)
continue;
}
GtkClipboard *aClipboard = gtk_clipboard_get(GetSelectionAtom(aWhichClipboard));
gtk_clipboard_set_image(aClipboard, pixbuf);
g_object_unref(pixbuf);
image->UnlockImagePixels(PR_FALSE);
continue;
}

View file

@ -44,17 +44,17 @@
{ 0xdfa4ac93, 0x83f2, 0x4ab8, \
{ 0x9b, 0x2a, 0x0f, 0xf7, 0x02, 0x2a, 0xeb, 0xe2 } }
class nsIImage;
class imgIContainer;
typedef struct _GdkPixbuf GdkPixbuf;
/**
* An interface that allows converting an nsIImage to a GdkPixbuf*.
* An interface that allows converting the current frame of an imgIContainer to a GdkPixbuf*.
*/
class nsIImageToPixbuf : public nsISupports {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NSIIMAGETOPIXBUF_IID)
NS_IMETHOD_(GdkPixbuf*) ConvertImageToPixbuf(nsIImage* aImage) = 0;
NS_IMETHOD_(GdkPixbuf*) ConvertImageToPixbuf(imgIContainer* aImage) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIImageToPixbuf, NSIIMAGETOPIXBUF_IID)

View file

@ -41,7 +41,7 @@
#include "gfxImageSurface.h"
#include "gfxContext.h"
#include "nsIImage.h"
#include "imgIContainer.h"
#include "nsAutoPtr.h"
@ -60,21 +60,18 @@ unpremultiply (unsigned char color,
}
NS_IMETHODIMP_(GdkPixbuf*)
nsImageToPixbuf::ConvertImageToPixbuf(nsIImage* aImage)
nsImageToPixbuf::ConvertImageToPixbuf(imgIContainer* aImage)
{
return ImageToPixbuf(aImage);
}
GdkPixbuf*
nsImageToPixbuf::ImageToPixbuf(nsIImage* aImage)
nsImageToPixbuf::ImageToPixbuf(imgIContainer* aImage)
{
PRInt32 width = aImage->GetWidth(),
height = aImage->GetHeight();
nsRefPtr<gfxImageSurface> frame;
aImage->CopyCurrentFrame(getter_AddRefs(frame));
nsRefPtr<gfxPattern> pattern;
aImage->GetPattern(getter_AddRefs(pattern));
return PatternToPixbuf(pattern, width, height);
return ImgSurfaceToPixbuf(frame, frame->Width(), frame->Height());
}
GdkPixbuf*
@ -158,39 +155,3 @@ nsImageToPixbuf::SurfaceToPixbuf(gfxASurface* aSurface, PRInt32 aWidth, PRInt32
return ImgSurfaceToPixbuf(imgSurface, aWidth, aHeight);
}
GdkPixbuf*
nsImageToPixbuf::PatternToPixbuf(gfxPattern* aPattern, PRInt32 aWidth, PRInt32 aHeight)
{
if (aPattern->CairoStatus()) {
NS_ERROR("invalid pattern");
return nsnull;
}
nsRefPtr<gfxImageSurface> imgSurface;
if (aPattern->GetType() == gfxPattern::PATTERN_SURFACE) {
nsRefPtr<gfxASurface> surface = aPattern->GetSurface();
if (surface->GetType() == gfxASurface::SurfaceTypeImage) {
imgSurface = static_cast<gfxImageSurface*>
(static_cast<gfxASurface*>(surface.get()));
}
}
if (!imgSurface) {
imgSurface = new gfxImageSurface(gfxIntSize(aWidth, aHeight),
gfxImageSurface::ImageFormatARGB32);
if (!imgSurface)
return nsnull;
nsRefPtr<gfxContext> context = new gfxContext(imgSurface);
if (!context)
return nsnull;
context->SetOperator(gfxContext::OPERATOR_SOURCE);
context->SetPattern(aPattern);
context->Paint();
}
return ImgSurfaceToPixbuf(imgSurface, aWidth, aHeight);
}

View file

@ -47,15 +47,13 @@ class gfxImageSurface;
class nsImageToPixbuf : public nsIImageToPixbuf {
public:
NS_DECL_ISUPPORTS
NS_IMETHOD_(GdkPixbuf*) ConvertImageToPixbuf(nsIImage* aImage);
NS_IMETHOD_(GdkPixbuf*) ConvertImageToPixbuf(imgIContainer* aImage);
// Friendlier version of ConvertImageToPixbuf for callers inside of
// widget
static GdkPixbuf* ImageToPixbuf(nsIImage* aImage);
static GdkPixbuf* ImageToPixbuf(imgIContainer * aImage);
static GdkPixbuf* SurfaceToPixbuf(gfxASurface* aSurface,
PRInt32 aWidth, PRInt32 aHeight);
static GdkPixbuf* PatternToPixbuf(gfxPattern* aPattern,
PRInt32 aWidth, PRInt32 aHeight);
private:
static GdkPixbuf* ImgSurfaceToPixbuf(gfxImageSurface* aImgSurface,
PRInt32 aWidth, PRInt32 aHeight);

View file

@ -104,9 +104,7 @@ static const char sAccessibilityKey [] = "config.use_system_prefs.accessibility"
/* SetCursor(imgIContainer*) */
#include <gdk/gdk.h>
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "nsGfxCIID.h"
#include "nsIImage.h"
#include "nsImageToPixbuf.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsAutoPtr.h"
@ -1572,17 +1570,8 @@ nsWindow::SetCursor(imgIContainer* aCursor,
}
mCursor = nsCursor(-1);
// Get first image frame
nsCOMPtr<gfxIImageFrame> frame;
aCursor->GetFrameAt(0, getter_AddRefs(frame));
if (!frame)
return NS_ERROR_NOT_AVAILABLE;
nsCOMPtr<nsIImage> img(do_GetInterface(frame));
if (!img)
return NS_ERROR_NOT_AVAILABLE;
GdkPixbuf* pixbuf = nsImageToPixbuf::ImageToPixbuf(img);
// Get the image's current frame
GdkPixbuf* pixbuf = nsImageToPixbuf::ImageToPixbuf(aCursor);
if (!pixbuf)
return NS_ERROR_NOT_AVAILABLE;

View file

@ -78,7 +78,6 @@
#include "nsOS2Uni.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include <stdlib.h>
#include <ctype.h>
@ -1711,39 +1710,19 @@ NS_IMETHODIMP nsWindow::SetCursor(imgIContainer* aCursor,
return NS_OK;
}
nsCOMPtr<gfxIImageFrame> frame;
aCursor->GetFrameAt(0, getter_AddRefs(frame));
nsRefPtr<gfxImageFrame> frame;
aCursor->CopyCurrentFrame(getter_AddRefs(frame));
if (!frame)
return NS_ERROR_NOT_AVAILABLE;
// if the image is ridiculously large, exit because
// it will be unrecognizable when shrunk to 32x32
PRInt32 width, height;
frame->GetWidth(&width);
frame->GetHeight(&height);
PRInt32 width = frame->Width();
PRInt32 height = frame->Height();
if (width > 128 || height > 128)
return NS_ERROR_FAILURE;
gfx_format format;
nsresult rv = frame->GetFormat(&format);
if (NS_FAILED(rv))
return rv;
// only 24-bit images with 0, 1, or 8-bit alpha data are supported.
// These are all the formats used in Cairo, and all map to the RGB24 resp. ARGB32 Cairo formats.
if (format != gfxIFormats::BGR_A1 && format != gfxIFormats::RGB_A1 &&
format != gfxIFormats::BGR_A8 && format != gfxIFormats::RGB_A8 &&
format != gfxIFormats::BGR && format != gfxIFormats::RGB)
return NS_ERROR_UNEXPECTED;
frame->LockImageData();
PRUint32 dataLen;
PRUint8* data;
rv = frame->GetImageData(&data, &dataLen);
if (NS_FAILED(rv)) {
frame->UnlockImageData();
return rv;
}
PRUint8* data = frame->Data();
// create the color bitmap
HBITMAP hBmp = CreateBitmapRGB(data, width, height);
@ -1751,15 +1730,12 @@ NS_IMETHODIMP nsWindow::SetCursor(imgIContainer* aCursor,
return NS_ERROR_FAILURE;
// create a transparency mask from the alpha bytes
HBITMAP hAlpha = CreateTransparencyMask(format, data, width, height);
HBITMAP hAlpha = CreateTransparencyMask(frame->Format(), data, width, height);
if (!hAlpha) {
GpiDeleteBitmap(hBmp);
return NS_ERROR_FAILURE;
}
// Unlock image data after both processing colors and alpha data
frame->UnlockImageData();
POINTERINFO info = {0};
info.fPointer = TRUE;
info.xHotspot = aHotspotX;
@ -1875,7 +1851,7 @@ HBITMAP nsWindow::CreateBitmapRGB(PRUint8* aImageData,
// create a monochrome AND/XOR bitmap from 0, 1, or 8-bit alpha data
HBITMAP nsWindow::CreateTransparencyMask(gfx_format format,
HBITMAP nsWindow::CreateTransparencyMask(gfxASurface::gfxImageFormat format,
PRUint8* aImageData,
PRUint32 aWidth,
PRUint32 aHeight)
@ -1889,36 +1865,29 @@ HBITMAP nsWindow::CreateTransparencyMask(gfx_format format,
if (!mono)
return NULL;
switch (format) {
// gfxIFormats::BGR and case gfxIFormats::RGB are already
// taken care of by initializing XOR and AND masks to zero
if (format == gfxASurface::ImageFormatARGB32) {
// Non-alpha formats are already taken care of by initializing the XOR and
// AND masks to zero
// make the AND mask the inverse of the 8-bit alpha data
case gfxIFormats::BGR_A1:
case gfxIFormats::RGB_A1:
case gfxIFormats::RGB_A8:
case gfxIFormats::BGR_A8: {
PRInt32* pSrc = (PRInt32*)aImageData;
for (PRUint32 row = aHeight; row > 0; --row) {
// Point to the right row in the AND mask
PRUint8* pDst = mono + cbData + abpr * (row - 1);
PRUint8 mask = 0x80;
for (PRUint32 col = aWidth; col > 0; --col) {
// Use sign bit to test for transparency, as alpha byte is highest byte
// Positive means, alpha < 128, so consider as transparent and set the AND mask
if (*pSrc++ >= 0) {
*pDst |= mask;
}
PRInt32* pSrc = (PRInt32*)aImageData;
for (PRUint32 row = aHeight; row > 0; --row) {
// Point to the right row in the AND mask
PRUint8* pDst = mono + cbData + abpr * (row - 1);
PRUint8 mask = 0x80;
for (PRUint32 col = aWidth; col > 0; --col) {
// Use sign bit to test for transparency, as alpha byte is highest byte
// Positive means, alpha < 128, so consider as transparent and set the AND mask
if (*pSrc++ >= 0) {
*pDst |= mask;
}
mask >>= 1;
if (!mask) {
pDst++;
mask = 0x80;
}
mask >>= 1;
if (!mask) {
pDst++;
mask = 0x80;
}
}
break;
}
}

View file

@ -313,9 +313,8 @@ protected:
HBITMAP DataToBitmap(PRUint8* aImageData, PRUint32 aWidth,
PRUint32 aHeight, PRUint32 aDepth);
HBITMAP CreateBitmapRGB(PRUint8* aImageData, PRUint32 aWidth, PRUint32 aHeight);
// 'format' should be 'gfx_format' which is a PRInt32
HBITMAP CreateTransparencyMask(PRInt32 format, PRUint8* aImageData,
PRUint32 aWidth, PRUint32 aHeight);
HBITMAP CreateTransparencyMask(gfxASurface::gfxImageFormat format,
PRUint8* aImageData, PRUint32 aWidth, PRUint32 aHeight);
BOOL NotifyForeignChildWindows(HWND aWnd);
void ScrollChildWindows(PRInt32 aX, PRInt32 aY);

View file

@ -76,9 +76,7 @@
/* SetCursor(imgIContainer*) */
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "nsGfxCIID.h"
#include "nsIImage.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsAutoPtr.h"

View file

@ -70,8 +70,6 @@
#include "nsNetUtil.h"
#include "nsEscape.h"
#include "nsIImage.h"
// oddly, this isn't in the MSVC headers anywhere.
UINT nsClipboard::CF_HTML = ::RegisterClipboardFormatW(L"HTML Format");

View file

@ -51,7 +51,6 @@
#include "IEnumFE.h"
#include "nsPrimitiveHelpers.h"
#include "nsXPIDLString.h"
#include "nsIImage.h"
#include "nsImageClipboard.h"
#include "nsCRT.h"
#include "nsPrintfCString.h"
@ -859,7 +858,7 @@ nsDataObj::GetBitmap ( const nsACString& , FORMATETC&, STGMEDIUM& )
// GetDIB
//
// Someone is asking for a bitmap. The data in the transferable will be a straight
// nsIImage, so just QI it.
// imgIContainer, so just QI it.
//
HRESULT
nsDataObj :: GetDib ( const nsACString& inFlavor, FORMATETC &, STGMEDIUM & aSTG )
@ -869,12 +868,11 @@ nsDataObj :: GetDib ( const nsACString& inFlavor, FORMATETC &, STGMEDIUM & aSTG
PRUint32 len = 0;
nsCOMPtr<nsISupports> genericDataWrapper;
mTransferable->GetTransferData(PromiseFlatCString(inFlavor).get(), getter_AddRefs(genericDataWrapper), &len);
nsCOMPtr<nsIImage> image ( do_QueryInterface(genericDataWrapper) );
nsCOMPtr<imgIContainer> image ( do_QueryInterface(genericDataWrapper) );
if ( !image ) {
// In the 0.9.4 timeframe, I had some embedding clients put the nsIImage directly into the
// transferable. Newer code, however, wraps the nsIImage in a nsISupportsInterfacePointer.
// We should be backwards compatibile with code already out in the field. If we can't find
// the image directly out of the transferable, unwrap the image from its wrapper.
// Check if the image was put in an nsISupportsInterfacePointer wrapper.
// This might not be necessary any more, but could be useful for backwards
// compatibility.
nsCOMPtr<nsISupportsInterfacePointer> ptr(do_QueryInterface(genericDataWrapper));
if ( ptr )
ptr->GetData(getter_AddRefs(image));
@ -1384,13 +1382,12 @@ HRESULT nsDataObj::GetFile(FORMATETC& aFE, STGMEDIUM& aSTG)
nsCOMPtr<nsISupports> genericDataWrapper;
mTransferable->GetTransferData(kNativeImageMime, getter_AddRefs(genericDataWrapper), &len);
nsCOMPtr<nsIImage> image ( do_QueryInterface(genericDataWrapper) );
nsCOMPtr<imgIContainer> image ( do_QueryInterface(genericDataWrapper) );
if (!image) {
// In the 0.9.4 timeframe, I had some embedding clients put the nsIImage directly into the
// transferable. Newer code, however, wraps the nsIImage in a nsISupportsInterfacePointer.
// We should be backwards compatibile with code already out in the field. If we can't find
// the image directly out of the transferable, unwrap the image from its wrapper.
// Check if the image was put in an nsISupportsInterfacePointer wrapper.
// This might not be necessary any more, but could be useful for backwards
// compatibility.
nsCOMPtr<nsISupportsInterfacePointer> ptr(do_QueryInterface(genericDataWrapper));
if (ptr)
ptr->GetData(getter_AddRefs(image));

View file

@ -59,9 +59,9 @@ Any other render format? HTML?
//
// nsImageToClipboard ctor
//
// Given an nsIImage, convert it to a DIB that is ready to go on the win32 clipboard
// Given an imgIContainer, convert it to a DIB that is ready to go on the win32 clipboard
//
nsImageToClipboard :: nsImageToClipboard ( nsIImage* inImage )
nsImageToClipboard :: nsImageToClipboard ( imgIContainer* inImage )
: mImage(inImage)
{
// nothing to do here
@ -143,19 +143,21 @@ nsImageToClipboard::CalcSpanLength(PRUint32 aWidth, PRUint32 aBitCount)
// image.
//
nsresult
nsImageToClipboard::CreateFromImage ( nsIImage* inImage, HANDLE* outBitmap )
nsImageToClipboard::CreateFromImage ( imgIContainer* inImage, HANDLE* outBitmap )
{
nsresult result = NS_OK;
*outBitmap = nsnull;
inImage->LockImagePixels(PR_FALSE);
nsRefPtr<gfxImageSurface> frame;
nsresult rv = inImage->CopyCurrentFrame(getter_AddRefs(frame));
if (NS_FAILED(rv))
return rv;
const PRUint32 imageSize = inImage->GetLineStride() * inImage->GetHeight();
const PRUint32 imageSize = frame->GetDataSize();
const PRInt32 bitmapSize = sizeof(BITMAPINFOHEADER) + imageSize;
HGLOBAL glob = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT, bitmapSize);
if (!glob) {
inImage->UnlockImagePixels(PR_FALSE);
return NS_ERROR_OUT_OF_MEMORY;
}
@ -164,18 +166,21 @@ nsImageToClipboard::CreateFromImage ( nsIImage* inImage, HANDLE* outBitmap )
BITMAPINFOHEADER *header = (BITMAPINFOHEADER*)data;
header->biSize = sizeof(BITMAPINFOHEADER);
header->biWidth = inImage->GetWidth();
header->biHeight = inImage->GetHeight();
header->biWidth = frame->Width();
header->biHeight = frame->Height();
header->biPlanes = 1;
header->biBitCount = inImage->GetBytesPix() * 8;
if (frame->Format() == gfxASurface::ImageFormatARGB32)
header->biBitCount = 32;
else if (frame->Format() == gfxASurface::ImageFormatRGB24)
header->biBitCount = 24;
header->biCompression = BI_RGB;
header->biSizeImage = imageSize;
const PRUint32 bpr = inImage->GetLineStride();
const PRUint32 bpr = frame->Stride();
BYTE *dstBits = (BYTE*)data + sizeof(BITMAPINFOHEADER);
BYTE *srcBits = inImage->GetBits();
BYTE *srcBits = frame->Data();
for (PRInt32 i = 0; i < header->biHeight; ++i) {
PRUint32 srcOffset = imageSize - (bpr * (i + 1));
PRUint32 dstOffset = i * bpr;
@ -186,11 +191,7 @@ nsImageToClipboard::CreateFromImage ( nsIImage* inImage, HANDLE* outBitmap )
*outBitmap = (HANDLE)glob;
inImage->UnlockImagePixels(PR_FALSE);
return NS_OK;
// Wow the old code is broken. I'm not touching it.
// It should probably lock/unlock the same object....
}
nsImageFromClipboard :: nsImageFromClipboard ()

View file

@ -50,20 +50,20 @@ Any other render format? HTML?
#include <windows.h>
#include "nsCOMPtr.h"
#include "nsIImage.h"
#include "imgIContainer.h"
#include "nsIInputStream.h"
//
// nsImageToClipboard
//
// A utility class that takes an nsIImage and does all the bitmap magic
// A utility class that takes an imgIContainer and does all the bitmap magic
// to allow us to put it on the clipboard
//
class nsImageToClipboard
{
public:
nsImageToClipboard ( nsIImage* inImage );
nsImageToClipboard ( imgIContainer* inImage );
~nsImageToClipboard();
// Call to get the actual bits that go on the clipboard. If |nsnull|, the
@ -79,9 +79,9 @@ private:
PRInt32 CalcSpanLength(PRUint32 aWidth, PRUint32 aBitCount);
// Do the work
nsresult CreateFromImage ( nsIImage* inImage, HANDLE* outBitmap );
nsresult CreateFromImage ( imgIContainer* inImage, HANDLE* outBitmap );
nsCOMPtr<nsIImage> mImage; // the image we're working with
nsCOMPtr<imgIContainer> mImage; // the image we're working with
}; // class nsImageToClipboard

View file

@ -119,13 +119,11 @@
#include "nsISupportsPrimitives.h"
#include "nsIDOMNSUIEvent.h"
#include "nsITheme.h"
#include "nsIImage.h"
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsIObserverService.h"
#include "nsIScreenManager.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "nsIFile.h"
#include "nsIRollupListener.h"
#include "nsIMenuRollup.h"
@ -2058,14 +2056,13 @@ NS_IMETHODIMP nsWindow::SetCursor(imgIContainer* aCursor,
}
// Get the image data
nsCOMPtr<gfxIImageFrame> frame;
aCursor->GetFrameAt(0, getter_AddRefs(frame));
nsRefPtr<gfxImageSurface> frame;
aCursor->CopyCurrentFrame(getter_AddRefs(frame));
if (!frame)
return NS_ERROR_NOT_AVAILABLE;
PRInt32 width, height;
frame->GetWidth(&width);
frame->GetHeight(&height);
PRInt32 width = frame->Width();
PRInt32 height = frame->Height();
// Reject cursors greater than 128 pixels in either direction, to prevent
// spoofing.
@ -2074,19 +2071,10 @@ NS_IMETHODIMP nsWindow::SetCursor(imgIContainer* aCursor,
if (width > 128 || height > 128)
return NS_ERROR_NOT_AVAILABLE;
frame->LockImageData();
PRUint32 dataLen;
PRUint8 *data;
nsresult rv = frame->GetImageData(&data, &dataLen);
if (NS_FAILED(rv)) {
frame->UnlockImageData();
return rv;
}
PRUint8 *data = frame->Data();
HBITMAP bmp = DataToBitmap(data, width, -height, 32);
PRUint8* a1data = Data32BitTo1Bit(data, width, height);
frame->UnlockImageData();
if (!a1data) {
return NS_ERROR_FAILURE;
}

View file

@ -62,9 +62,7 @@
#include "nsIDOMDataTransfer.h"
#include "nsIEventStateManager.h"
#include "nsICanvasElement.h"
#include "nsIImage.h"
#include "nsIImageLoadingContent.h"
#include "gfxIImageFrame.h"
#include "imgIContainer.h"
#include "imgIRequest.h"
#include "nsIViewObserver.h"
@ -530,7 +528,7 @@ nsBaseDragService::DrawDragForImage(nsPresContext* aPresContext,
nsIntRect* aScreenDragRect,
gfxASurface** aSurface)
{
nsCOMPtr<nsIImage> img;
nsCOMPtr<imgIContainer> imgContainer;
if (aImageLoader) {
nsCOMPtr<imgIRequest> imgRequest;
nsresult rv = aImageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
@ -539,21 +537,11 @@ nsBaseDragService::DrawDragForImage(nsPresContext* aPresContext,
if (!imgRequest)
return NS_ERROR_NOT_AVAILABLE;
nsCOMPtr<imgIContainer> imgContainer;
rv = imgRequest->GetImage(getter_AddRefs(imgContainer));
NS_ENSURE_SUCCESS(rv, rv);
if (!imgContainer)
return NS_ERROR_NOT_AVAILABLE;
nsCOMPtr<gfxIImageFrame> iframe;
imgContainer->GetCurrentFrame(getter_AddRefs(iframe));
if (!iframe)
return NS_ERROR_FAILURE;
img = do_GetInterface(iframe);
if (!img)
return NS_ERROR_FAILURE;
// use the size of the image as the size of the drag image
imgContainer->GetWidth(&aScreenDragRect->width);
imgContainer->GetHeight(&aScreenDragRect->height);
@ -612,8 +600,8 @@ nsBaseDragService::DrawDragForImage(nsPresContext* aPresContext,
gfxRect outRect(0, 0, destSize.width, destSize.height);
gfxMatrix scale =
gfxMatrix().Scale(srcSize.width/outRect.Width(), srcSize.height/outRect.Height());
img->Draw(ctx, gfxPattern::FILTER_GOOD, scale, outRect, nsIntMargin(0,0,0,0),
nsIntRect(0, 0, srcSize.width, srcSize.height));
nsIntRect imgSize(0, 0, srcSize.width, srcSize.height);
imgContainer->Draw(ctx, gfxPattern::FILTER_GOOD, scale, outRect, imgSize);
return NS_OK;
} else {
return aCanvas->RenderContexts(ctx, gfxPattern::FILTER_GOOD);