Landing pref based, automatic image resizing.

Disabled by default.
r=jst, sr=jag
This commit is contained in:
varga%netscape.com 2003-01-18 10:17:58 +00:00
Родитель d1688f5365
Коммит ebba8d599c
12 изменённых файлов: 576 добавлений и 304 удалений

Просмотреть файл

@ -1,4 +0,0 @@
#
# This is a list of local files which get copied to the mozilla:dist:idl directory
#
nsIWyciwygChannel.idl

Просмотреть файл

@ -28,8 +28,9 @@ include $(DEPTH)/config/autoconf.mk
MODULE = content
XPIDLSRCS = nsIWyciwygChannel.idl \
$(NULL)
XPIDLSRCS = \
nsIImageDocument.idl \
nsIWyciwygChannel.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -20,9 +20,10 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Morten Nilsen <morten@nilsen.com>
* Christian Biesinger <cbiesinger@web.de>
*
* Morten Nilsen <morten@nilsen.com>
* Christian Biesinger <cbiesinger@web.de>
* Jan Varga <varga@netscape.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"),
@ -37,210 +38,157 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h"
#include "nsRect.h"
#include "nsHTMLDocument.h"
#include "nsIImageDocument.h"
#include "nsGenericHTMLElement.h"
#include "nsIDOMHTMLImageElement.h"
#include "nsIDOMEvent.h"
#include "nsIDOMKeyEvent.h"
#include "nsIDOMEventListener.h"
#include "nsHTMLAtoms.h"
#include "nsIHTMLContent.h"
#include "imgIRequest.h"
#include "imgILoader.h"
#include "imgIContainer.h"
#include "nsIStreamListener.h"
#include "imgIDecoderObserver.h"
#include "nsIURL.h"
#include "nsHTMLValue.h"
#include "nsIHTMLStyleSheet.h"
#include "nsIHTMLCSSStyleSheet.h"
#include "nsIScrollable.h"
#include "nsIPresShell.h"
#include "nsIPresContext.h"
#include "nsIStyleContext.h"
#include "nsIViewManager.h"
#include "nsIChannel.h"
#include "nsINameSpaceManager.h"
#include "nsINodeInfo.h"
// Needed for Localization
#include "nsXPIDLString.h"
#include "nsIStringBundle.h"
// Needed to fetch scrollbar prefs for image documents that are iframes/frameset frames
#include "nsIScrollable.h"
#include "nsWeakReference.h"
#include "nsRect.h"
#include "nsIPrefService.h"
#define NSIMAGEDOCUMENT_PROPERTIES_URI "chrome://communicator/locale/layout/ImageDocument.properties"
static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
// done L10N
// XXX TODO:
// 1. hookup the original stream to the image library directly so that we
// don't have to load the image twice.
// 2. have a synthetic document url that we load that has patterns in it
// that we replace with the image url (so that we can customize the
// the presentation of the image): we could add script code to set the
// width/height to provide scale buttons, we could show the image
// attributes; etc.; should we have a seperate style sheet?
// 3. override the save-as methods so that we don't write out our synthetic
// html
#define AUTOMATIC_IMAGE_RESIZING_PREF "browser.enable_automatic_image_resizing"
class nsImageDocument : public nsHTMLDocument {
class nsImageDocument : public nsHTMLDocument,
public nsIImageDocument,
public nsIStreamListener,
public imgIDecoderObserver,
public nsIDOMEventListener
{
public:
nsImageDocument();
virtual ~nsImageDocument();
NS_IMETHOD StartDocumentLoad(const char* aCommand,
nsIChannel* aChannel,
nsILoadGroup* aLoadGroup,
nsISupports* aContainer,
nsIStreamListener **aDocListener,
PRBool aReset = PR_TRUE,
nsIContentSink* aSink = nsnull);
NS_DECL_ISUPPORTS
// nsIHTMLDocument
nsresult Init();
NS_IMETHOD StartDocumentLoad(const char* aCommand,
nsIChannel* aChannel,
nsILoadGroup* aLoadGroup,
nsISupports* aContainer,
nsIStreamListener** aDocListener,
PRBool aReset = PR_TRUE,
nsIContentSink* aSink = nsnull);
NS_IMETHOD SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject);
nsresult CreateSyntheticDocument();
NS_DECL_NSIIMAGEDOCUMENT
nsresult EndLayout(nsISupports *ctxt,
nsresult status);
nsresult UpdateTitle( void );
void StartLayout();
nsCOMPtr<imgIRequest> mImageRequest;
nscolor mBlack;
nsWeakPtr mContainer;
};
//----------------------------------------------------------------------
class ImageListener : public nsIStreamListener {
public:
ImageListener(nsImageDocument* aDoc);
virtual ~ImageListener();
NS_DECL_ISUPPORTS
// nsIRequestObserver methods:
NS_DECL_NSIREQUESTOBSERVER
// nsIStreamListener methods:
NS_DECL_NSISTREAMLISTENER
nsImageDocument* mDocument;
nsCOMPtr<nsIStreamListener> mNextStream;
NS_DECL_IMGIDECODEROBSERVER
NS_DECL_IMGICONTAINEROBSERVER
// nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
protected:
nsresult CreateSyntheticDocument();
nsresult CheckOverflowing();
nsresult StartLayout();
nsresult UpdateTitle();
nsCOMPtr<nsIStringBundle> mStringBundle;
nsCOMPtr<nsIDOMElement> mImageElement;
nsCOMPtr<imgIRequest> mImageRequest;
nsCOMPtr<nsIStreamListener> mNextStream;
nscoord mVisibleWidth;
nscoord mVisibleHeight;
nscoord mImageWidth;
nscoord mImageHeight;
PRPackedBool mImageResizingEnabled;
PRPackedBool mImageIsOverflowing;
PRPackedBool mImageIsResized;
};
ImageListener::ImageListener(nsImageDocument* aDoc)
{
mDocument = aDoc;
NS_ADDREF(aDoc);
}
ImageListener::~ImageListener()
{
NS_RELEASE(mDocument);
}
NS_IMPL_THREADSAFE_ISUPPORTS1(ImageListener, nsIStreamListener)
NS_IMETHODIMP
ImageListener::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
{
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
if (!channel) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIPresShell> shell;
nsCOMPtr<nsIPresContext> context;
mDocument->GetShellAt(0, getter_AddRefs(shell));
if (shell) {
shell->GetPresContext(getter_AddRefs(context));
}
nsCOMPtr<nsIStreamListener> kungFuDeathGrip(this);
nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1"));
il->LoadImageWithChannel(channel, nsnull, context, getter_AddRefs(mNextStream),
getter_AddRefs(mDocument->mImageRequest));
// XXX
// if we get a cache hit, and we cancel the channel in the above function,
// do we call OnStopRequest before we call StartLayout?
// if so, should LoadImageWithChannel() not call channel->Cancel() ?
mDocument->StartLayout();
if (nsnull == mNextStream) {
return NS_ERROR_FAILURE;
}
return mNextStream->OnStartRequest(request, ctxt);
}
NS_IMETHODIMP
ImageListener::OnStopRequest(nsIRequest* request, nsISupports *ctxt,
nsresult status)
{
if(mDocument){
mDocument->EndLayout(ctxt, status);
}
if (nsnull == mNextStream) {
return NS_ERROR_FAILURE;
}
return mNextStream->OnStopRequest(request, ctxt, status);
}
NS_IMETHODIMP
ImageListener::OnDataAvailable(nsIRequest* request, nsISupports *ctxt,
nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count)
{
if (nsnull == mNextStream) {
return NS_ERROR_FAILURE;
}
return mNextStream->OnDataAvailable(request, ctxt, inStr, sourceOffset, count);
}
//----------------------------------------------------------------------
NS_EXPORT nsresult
NS_NewImageDocument(nsIDocument** aInstancePtrResult)
{
nsImageDocument* doc = new nsImageDocument();
NS_ENSURE_TRUE(doc, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = doc->Init();
if (NS_FAILED(rv)) {
delete doc;
return rv;
}
*aInstancePtrResult = doc;
NS_ADDREF(*aInstancePtrResult);
return NS_OK;
}
nsImageDocument::nsImageDocument()
: mVisibleWidth(0),
mVisibleHeight(0),
mImageWidth(0),
mImageHeight(0),
mImageResizingEnabled(PR_FALSE),
mImageIsOverflowing(PR_FALSE),
mImageIsResized(PR_FALSE)
{
mBlack = NS_RGB(0, 0, 0);
}
nsImageDocument::~nsImageDocument()
{
}
NS_IMETHODIMP
nsImageDocument::StartDocumentLoad(const char* aCommand,
nsIChannel* aChannel,
nsILoadGroup* aLoadGroup,
nsISupports* aContainer,
nsIStreamListener **aDocListener,
PRBool aReset,
nsIContentSink* aSink)
{
NS_ASSERTION(aDocListener, "null aDocListener");
NS_ENSURE_ARG_POINTER(aContainer);
mContainer = dont_AddRef(NS_GetWeakReference(aContainer));
NS_IMPL_ADDREF_INHERITED(nsImageDocument, nsHTMLDocument)
NS_IMPL_RELEASE_INHERITED(nsImageDocument, nsHTMLDocument)
NS_INTERFACE_MAP_BEGIN(nsImageDocument)
NS_INTERFACE_MAP_ENTRY(nsIImageDocument)
NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
NS_INTERFACE_MAP_ENTRY(imgIDecoderObserver)
NS_INTERFACE_MAP_ENTRY(imgIContainerObserver)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(ImageDocument)
NS_INTERFACE_MAP_END_INHERITING(nsHTMLDocument)
nsresult
nsImageDocument::Init()
{
nsresult rv = nsHTMLDocument::Init();
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
if (prefBranch) {
PRBool temp = PR_FALSE;
prefBranch->GetBoolPref(AUTOMATIC_IMAGE_RESIZING_PREF, &temp);
mImageResizingEnabled = temp;
}
// Create a bundle for the localization
nsCOMPtr<nsIStringBundleService> stringService(
do_GetService(NS_STRINGBUNDLE_CONTRACTID));
if (stringService) {
stringService->CreateBundle(NSIMAGEDOCUMENT_PROPERTIES_URI,
getter_AddRefs(mStringBundle));
}
return NS_OK;
}
NS_IMETHODIMP
nsImageDocument::StartDocumentLoad(const char* aCommand,
nsIChannel* aChannel,
nsILoadGroup* aLoadGroup,
nsISupports* aContainer,
nsIStreamListener** aDocListener,
PRBool aReset,
nsIContentSink* aSink)
{
nsresult rv = nsDocument::StartDocumentLoad(aCommand, aChannel, aLoadGroup,
aContainer, aDocListener, aReset,
aSink);
@ -262,15 +210,12 @@ nsImageDocument::StartDocumentLoad(const char* aCommand,
// Create synthetic document
rv = CreateSyntheticDocument();
if (NS_OK != rv) {
if (NS_FAILED(rv)) {
return rv;
}
*aDocListener = new ImageListener(this);
if (!*aDocListener)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aDocListener);
NS_ASSERTION(aDocListener, "null aDocListener");
NS_ADDREF(*aDocListener = this);
return NS_OK;
}
@ -283,11 +228,259 @@ nsImageDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObjec
// going away soon. Drop our ref to imgRequest so that we don't end
// up leaking due to cycles through imgLib
mImageRequest = nsnull;
if (mImageResizingEnabled) {
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mImageElement);
target->RemoveEventListener(NS_LITERAL_STRING("click"), this, PR_FALSE);
target = do_QueryInterface(mScriptGlobalObject);
target->RemoveEventListener(NS_LITERAL_STRING("resize"), this, PR_FALSE);
target->RemoveEventListener(NS_LITERAL_STRING("keypress"), this, PR_FALSE);
}
}
else {
if (mImageResizingEnabled) {
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mImageElement);
target->AddEventListener(NS_LITERAL_STRING("click"), this, PR_FALSE);
target = do_QueryInterface(aScriptGlobalObject);
target->AddEventListener(NS_LITERAL_STRING("resize"), this, PR_FALSE);
target->AddEventListener(NS_LITERAL_STRING("keypress"), this, PR_FALSE);
}
}
return nsHTMLDocument::SetScriptGlobalObject(aScriptGlobalObject);
}
NS_IMETHODIMP
nsImageDocument::GetImageResizingEnabled(PRBool* aImageResizingEnabled)
{
*aImageResizingEnabled = mImageResizingEnabled;
return NS_OK;
}
NS_IMETHODIMP
nsImageDocument::GetImageIsOverflowing(PRBool* aImageIsOverflowing)
{
*aImageIsOverflowing = mImageIsOverflowing;
return NS_OK;
}
NS_IMETHODIMP
nsImageDocument::GetImageIsResized(PRBool* aImageIsResized)
{
*aImageIsResized = mImageIsResized;
return NS_OK;
}
NS_IMETHODIMP
nsImageDocument::ShrinkToFit()
{
if (mImageResizingEnabled) {
nsCOMPtr<nsIDOMHTMLImageElement> image = do_QueryInterface(mImageElement);
float ratio = PR_MIN((float)mVisibleWidth / mImageWidth,
(float)mVisibleHeight / mImageHeight);
image->SetWidth(NSToCoordFloor(mImageWidth * ratio));
mImageElement->SetAttribute(NS_LITERAL_STRING("style"),
NS_LITERAL_STRING("cursor: move"));
mImageIsResized = PR_TRUE;
}
return NS_OK;
}
NS_IMETHODIMP
nsImageDocument::RestoreImage()
{
if (mImageResizingEnabled) {
mImageElement->RemoveAttribute(NS_LITERAL_STRING("width"));
if (!mImageIsOverflowing) {
mImageElement->RemoveAttribute(NS_LITERAL_STRING("style"));
}
mImageIsResized = PR_FALSE;
}
return NS_OK;
}
NS_IMETHODIMP
nsImageDocument::ToggleImageSize()
{
if (mImageResizingEnabled) {
if (mImageIsResized) {
RestoreImage();
}
else if (mImageIsOverflowing) {
ShrinkToFit();
}
}
return NS_OK;
}
NS_IMETHODIMP
nsImageDocument::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
{
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
if (!channel) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIPresShell> shell;
nsCOMPtr<nsIPresContext> context;
GetShellAt(0, getter_AddRefs(shell));
if (shell) {
shell->GetPresContext(getter_AddRefs(context));
}
nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1"));
il->LoadImageWithChannel(channel, this, context, getter_AddRefs(mNextStream),
getter_AddRefs(mImageRequest));
StartLayout();
if (mNextStream) {
return mNextStream->OnStartRequest(request, ctxt);
}
return NS_OK;
}
NS_IMETHODIMP
nsImageDocument::OnStopRequest(nsIRequest* request, nsISupports *ctxt,
nsresult status)
{
UpdateTitle();
if (mNextStream) {
return mNextStream->OnStopRequest(request, ctxt, status);
}
return NS_OK;
}
NS_IMETHODIMP
nsImageDocument::OnDataAvailable(nsIRequest* request, nsISupports *ctxt,
nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count)
{
if (mNextStream) {
return mNextStream->OnDataAvailable(request, ctxt, inStr, sourceOffset, count);
}
return NS_OK;
}
NS_IMETHODIMP
nsImageDocument::OnStartDecode(imgIRequest* aRequest,
nsISupports* aCX)
{
return NS_OK;
}
NS_IMETHODIMP
nsImageDocument::OnStartContainer(imgIRequest* aRequest,
nsISupports* aCX,
imgIContainer* aImage)
{
aImage->GetWidth(&mImageWidth);
aImage->GetHeight(&mImageHeight);
if (mImageResizingEnabled) {
CheckOverflowing();
}
return NS_OK;
}
NS_IMETHODIMP
nsImageDocument::OnStartFrame(imgIRequest* aRequest,
nsISupports* aCX,
gfxIImageFrame* aFrame)
{
return NS_OK;
}
NS_IMETHODIMP
nsImageDocument::OnDataAvailable(imgIRequest* aRequest,
nsISupports *aCX,
gfxIImageFrame* aFrame,
const nsRect* aRect)
{
return NS_OK;
}
NS_IMETHODIMP
nsImageDocument::OnStopFrame(imgIRequest* aRequest,
nsISupports* aCX,
gfxIImageFrame* aFrame)
{
return NS_OK;
}
NS_IMETHODIMP
nsImageDocument::OnStopContainer(imgIRequest* aRequest,
nsISupports* aCX,
imgIContainer* aImage)
{
return NS_OK;
}
NS_IMETHODIMP
nsImageDocument::OnStopDecode(imgIRequest* aRequest,
nsISupports* aCX,
nsresult status,
const PRUnichar* statusArg)
{
return NS_OK;
}
NS_IMETHODIMP
nsImageDocument::FrameChanged(imgIContainer* aContainer,
nsISupports *aCX,
gfxIImageFrame* aFrame,
nsRect* aDirtyRect)
{
return NS_OK;
}
NS_IMETHODIMP
nsImageDocument::HandleEvent(nsIDOMEvent* aEvent)
{
nsAutoString eventType;
aEvent->GetType(eventType);
if (eventType.Equals(NS_LITERAL_STRING("resize"))) {
CheckOverflowing();
}
else if (eventType.Equals(NS_LITERAL_STRING("click"))) {
ToggleImageSize();
}
else if (eventType.Equals(NS_LITERAL_STRING("keypress"))) {
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aEvent);
PRUint32 charCode;
keyEvent->GetCharCode(&charCode);
// plus key
if (charCode == 0x2B) {
if (mImageIsResized) {
RestoreImage();
}
}
// minus key
else if (charCode == 0x2D) {
if (mImageIsOverflowing) {
ShrinkToFit();
}
}
}
return NS_OK;
}
nsresult
nsImageDocument::CreateSyntheticDocument()
{
@ -300,9 +493,9 @@ nsImageDocument::CreateSyntheticDocument()
*getter_AddRefs(nodeInfo));
NS_ENSURE_SUCCESS(rv, rv);
nsIHTMLContent* root;
rv = NS_NewHTMLHtmlElement(&root, nodeInfo);
if (NS_OK != rv) {
nsCOMPtr<nsIHTMLContent> root;
rv = NS_NewHTMLHtmlElement(getter_AddRefs(root), nodeInfo);
if (NS_FAILED(rv)) {
return rv;
}
root->SetDocument(this, PR_FALSE, PR_TRUE);
@ -313,179 +506,155 @@ nsImageDocument::CreateSyntheticDocument()
*getter_AddRefs(nodeInfo));
NS_ENSURE_SUCCESS(rv, rv);
nsIHTMLContent* body;
rv = NS_NewHTMLBodyElement(&body, nodeInfo);
if (NS_OK != rv) {
nsCOMPtr<nsIHTMLContent> body;
rv = NS_NewHTMLBodyElement(getter_AddRefs(body), nodeInfo);
if (NS_FAILED(rv)) {
return rv;
}
body->SetDocument(this, PR_FALSE, PR_TRUE);
rv = mNodeInfoManager->GetNodeInfo(nsHTMLAtoms::p, nsnull, kNameSpaceID_None,
*getter_AddRefs(nodeInfo));
NS_ENSURE_SUCCESS(rv, rv);
nsIHTMLContent* center;
rv = NS_NewHTMLParagraphElement(&center, nodeInfo);
if (NS_OK != rv) {
return rv;
}
center->SetDocument(this, PR_FALSE, PR_TRUE);
mBodyContent = do_QueryInterface(body);
rv = mNodeInfoManager->GetNodeInfo(nsHTMLAtoms::img, nsnull,
kNameSpaceID_None,
*getter_AddRefs(nodeInfo));
NS_ENSURE_SUCCESS(rv, rv);
nsIHTMLContent* image;
rv = NS_NewHTMLImageElement(&image, nodeInfo);
if (NS_OK != rv) {
nsCOMPtr<nsIHTMLContent> image;
rv = NS_NewHTMLImageElement(getter_AddRefs(image), nodeInfo);
if (NS_FAILED(rv)) {
return rv;
}
image->SetDocument(this, PR_FALSE, PR_TRUE);
mImageElement = do_QueryInterface(image);
nsCAutoString src;
mDocumentURL->GetSpec(src);
NS_ConvertUTF8toUCS2 src_string(src);
nsHTMLValue val(src_string);
NS_ConvertUTF8toUCS2 srcString(src);
nsHTMLValue val(srcString);
image->SetHTMLAttribute(nsHTMLAtoms::src, val, PR_FALSE);
// Create a stringbundle for localized error message
nsCOMPtr<nsIStringBundle> bundle;
nsCOMPtr<nsIStringBundleService> stringService =
do_GetService(kStringBundleServiceCID, &rv);
if (NS_SUCCEEDED(rv) && stringService)
rv = stringService->CreateBundle(NSIMAGEDOCUMENT_PROPERTIES_URI, getter_AddRefs(bundle));
if (NS_SUCCEEDED(rv) && bundle) {
const PRUnichar* formatString[1] = { src_string.get() };
if (mStringBundle) {
const PRUnichar* formatString[1] = { srcString.get() };
nsXPIDLString errorMsg;
rv = bundle->FormatStringFromName(NS_LITERAL_STRING("InvalidImage").get(), formatString, 1, getter_Copies(errorMsg));
rv = mStringBundle->FormatStringFromName(NS_LITERAL_STRING("InvalidImage").get(),
formatString, 1, getter_Copies(errorMsg));
nsHTMLValue errorText(errorMsg);
image->SetHTMLAttribute(nsHTMLAtoms::alt, errorText, PR_FALSE);
}
root->AppendChildTo(body, PR_FALSE, PR_FALSE);
center->AppendChildTo(image, PR_FALSE, PR_FALSE);
body->AppendChildTo(center, PR_FALSE, PR_FALSE);
NS_RELEASE(image);
NS_RELEASE(center);
NS_RELEASE(body);
NS_RELEASE(root);
body->AppendChildTo(image, PR_FALSE, PR_FALSE);
return NS_OK;
}
void
nsresult
nsImageDocument::CheckOverflowing()
{
nsCOMPtr<nsIPresShell> shell;
GetShellAt(0, getter_AddRefs(shell));
if (!shell) {
return NS_OK;
}
nsCOMPtr<nsIPresContext> context;
shell->GetPresContext(getter_AddRefs(context));
nsRect visibleArea;
context->GetVisibleArea(visibleArea);
nsCOMPtr<nsIStyleContext> styleContext;
nsCOMPtr<nsIContent> content = do_QueryInterface(mBodyContent);
context->ResolveStyleContextFor(content, nsnull, getter_AddRefs(styleContext));
const nsStyleMargin* marginData =
(const nsStyleMargin*)styleContext->GetStyleData(eStyleStruct_Margin);
nsMargin margin;
marginData->GetMargin(margin);
visibleArea.Deflate(margin);
nsStyleBorderPadding bPad;
styleContext->GetBorderPaddingFor(bPad);
bPad.GetBorderPadding(margin);
visibleArea.Deflate(margin);
float t2p;
context->GetTwipsToPixels(&t2p);
mVisibleWidth = NSTwipsToIntPixels(visibleArea.width, t2p);
mVisibleHeight = NSTwipsToIntPixels(visibleArea.height, t2p);
mImageIsOverflowing = mImageWidth > mVisibleWidth || mImageHeight > mVisibleHeight;
if (mImageIsOverflowing) {
ShrinkToFit();
}
else if (mImageIsResized) {
RestoreImage();
}
return NS_OK;
}
nsresult
nsImageDocument::StartLayout()
{
// Reset scrolling to default settings for this shell.
// This must happen before the initial reflow, when we create the root frame
nsCOMPtr<nsIScrollable> scrollableContainer(do_QueryReferent(mContainer));
nsCOMPtr<nsIScrollable> scrollableContainer(do_QueryReferent(mDocumentContainer));
if (scrollableContainer) {
scrollableContainer->ResetScrollbarPreferences();
}
PRInt32 i, ns = GetNumberOfShells();
for (i = 0; i < ns; i++) {
PRInt32 numberOfShells = GetNumberOfShells();
for (PRInt32 i = 0; i < numberOfShells; i++) {
nsCOMPtr<nsIPresShell> shell;
GetShellAt(i, getter_AddRefs(shell));
if (nsnull != shell) {
// Make shell an observer for next time
if (shell) {
// Make shell an observer for next time.
shell->BeginObservingDocument();
// Resize-reflow this time
nsCOMPtr<nsIPresContext> cx;
shell->GetPresContext(getter_AddRefs(cx));
nsRect r;
cx->GetVisibleArea(r);
shell->InitialReflow(r.width, r.height);
// Initial-reflow this time.
nsCOMPtr<nsIPresContext> context;
shell->GetPresContext(getter_AddRefs(context));
nsRect visibleArea;
context->GetVisibleArea(visibleArea);
shell->InitialReflow(visibleArea.width, visibleArea.height);
// Now trigger a refresh
// XXX It's unfortunate that this has to be here
// Now trigger a refresh.
nsCOMPtr<nsIViewManager> vm;
shell->GetViewManager(getter_AddRefs(vm));
if (vm) {
vm->EnableRefresh(NS_VMREFRESH_IMMEDIATE);
}
}
}
}
nsresult
nsImageDocument::EndLayout(nsISupports *ctxt,
nsresult status)
{
// Layout has completed: now update the title
UpdateTitle();
return NS_OK;
}
// NOTE: call this AFTER the shell has been installed as an observer of the
// document so the update notification gets processed by the shell
// and it updates the titlebar
nsresult nsImageDocument::UpdateTitle( void )
nsresult nsImageDocument::UpdateTitle()
{
#ifdef USE_EXTENSION_FOR_TYPE
// XXX TEMPORARY XXX
// We want to display the image type, however there is no way to right now
// so instead we just get the image-extension
// - get the URL interface, get the extension, convert to upper-case
// Unless the Imagerequest or Image can tell us the type this is the best we can do.
nsCOMPtr<nsIURL> url = do_QueryInterface(mDocumentURL);
if (url) {
nsXPIDLCString extension;
url->GetFileExtension(getter_Copies(extension));
ToUpperCase(extension);
titleStr.AppendWithConversion(extension);
}
#endif
nsCOMPtr<nsIStringBundle> bundle;
nsresult rv;
// Create a bundle for the localization
nsCOMPtr<nsIStringBundleService> stringService =
do_GetService(kStringBundleServiceCID, &rv);
if (NS_SUCCEEDED(rv) && stringService) {
rv = stringService->CreateBundle(NSIMAGEDOCUMENT_PROPERTIES_URI, getter_AddRefs(bundle));
}
if (NS_SUCCEEDED(rv) && bundle) {
nsXPIDLString valUni;
if (mStringBundle) {
nsXPIDLString fileStr;
nsAutoString widthStr;
nsAutoString heightStr;
nsXPIDLString fileStr;
nsAutoString typeStr;
PRUint32 width = 0, height = 0;
nsXPIDLString valUni;
nsCOMPtr<nsIURL> url = do_QueryInterface(mDocumentURL);
if (url) {
nsCAutoString pName;
url->GetFileName(pName);
fileStr.Assign(NS_ConvertUTF8toUCS2(pName));
nsCAutoString fileName;
url->GetFileName(fileName);
fileStr.Assign(NS_ConvertUTF8toUCS2(fileName));
}
widthStr.AppendInt(mImageWidth);
heightStr.AppendInt(mImageHeight);
if (mImageRequest) {
imgIContainer* imgContainer;
rv = mImageRequest->GetImage(&imgContainer);
if (NS_SUCCEEDED(rv) && imgContainer) {
nscoord w = 0, h = 0;
imgContainer->GetWidth(&w);
imgContainer->GetHeight(&h);
width = w;
height = h;
NS_RELEASE(imgContainer);
}
widthStr.AppendInt(width);
heightStr.AppendInt(height);
nsXPIDLCString mimeType;
mImageRequest->GetMimeType(getter_Copies(mimeType));
ToUpperCase(mimeType);
@ -512,31 +681,54 @@ nsresult nsImageDocument::UpdateTitle( void )
CopyASCIItoUCS2(mimeType, typeStr);
}
}
// If we got a filename, display it
if (!fileStr.IsEmpty()) {
// if we got a valid size (sometimes we do not) then display it
if (width != 0 && height != 0){
if (mImageWidth != 0 && mImageHeight != 0){
const PRUnichar *formatStrings[4] = {fileStr.get(), typeStr.get(), widthStr.get(), heightStr.get()};
rv = bundle->FormatStringFromName(NS_LITERAL_STRING("ImageTitleWithDimensionsAndFile").get(), formatStrings, 4, getter_Copies(valUni));
mStringBundle->FormatStringFromName(NS_LITERAL_STRING("ImageTitleWithDimensionsAndFile").get(), formatStrings, 4, getter_Copies(valUni));
} else {
const PRUnichar *formatStrings[2] = {fileStr.get(), typeStr.get()};
rv = bundle->FormatStringFromName(NS_LITERAL_STRING("ImageTitleWithoutDimensions").get(), formatStrings, 2, getter_Copies(valUni));
mStringBundle->FormatStringFromName(NS_LITERAL_STRING("ImageTitleWithoutDimensions").get(), formatStrings, 2, getter_Copies(valUni));
}
} else {
// if we got a valid size (sometimes we do not) then display it
if (width != 0 && height != 0){
if (mImageWidth != 0 && mImageHeight != 0){
const PRUnichar *formatStrings[3] = {typeStr.get(), widthStr.get(), heightStr.get()};
rv = bundle->FormatStringFromName(NS_LITERAL_STRING("ImageTitleWithDimensions").get(), formatStrings, 3, getter_Copies(valUni));
mStringBundle->FormatStringFromName(NS_LITERAL_STRING("ImageTitleWithDimensions").get(), formatStrings, 3, getter_Copies(valUni));
} else {
const PRUnichar *formatStrings[1] = {typeStr.get()};
rv = bundle->FormatStringFromName(NS_LITERAL_STRING("ImageTitleWithNeitherDimensionsNorFile").get(), formatStrings, 1, getter_Copies(valUni));
mStringBundle->FormatStringFromName(NS_LITERAL_STRING("ImageTitleWithNeitherDimensionsNorFile").get(), formatStrings, 1, getter_Copies(valUni));
}
}
if (NS_SUCCEEDED(rv) && valUni) {
if (valUni) {
// set it on the document
SetTitle(valUni);
}
}
return NS_OK;
}
nsresult
NS_NewImageDocument(nsIDocument** aResult)
{
nsImageDocument* doc = new nsImageDocument();
if (!doc) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult rv = doc->Init();
if (NS_FAILED(rv)) {
delete doc;
return rv;
}
NS_ADDREF(*aResult = doc);
return NS_OK;
}

Просмотреть файл

@ -879,6 +879,13 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIImageDocument.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIWyciwygChannel.idl</PATH>
@ -1036,6 +1043,11 @@
<PATH>nsITextAreaElement.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIImageDocument.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIWyciwygChannel.idl</PATH>
@ -1914,6 +1926,13 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIImageDocument.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIWyciwygChannel.idl</PATH>
@ -2071,6 +2090,11 @@
<PATH>nsITextAreaElement.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIImageDocument.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIWyciwygChannel.idl</PATH>
@ -2233,6 +2257,12 @@
<PATH>nsITextAreaElement.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>headers</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIImageDocument.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>headers</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>

Просмотреть файл

@ -87,6 +87,7 @@ enum nsDOMClassInfoID {
eDOMClassInfo_HTMLOptionCollection_id,
eDOMClassInfo_HTMLFormControlCollection_id,
eDOMClassInfo_HTMLGenericCollection_id,
eDOMClassInfo_ImageDocument_id,
// HTML element classes
eDOMClassInfo_HTMLAnchorElement_id,

Просмотреть файл

@ -110,6 +110,7 @@
#include "nsIDOMNSHTMLFormControlList.h"
#include "nsIDOMHTMLCollection.h"
#include "nsIHTMLDocument.h"
#include "nsIImageDocument.h"
// HTMLSelectElement helper includes
#include "nsIDOMHTMLSelectElement.h"
@ -471,6 +472,9 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(HTMLDocument, nsHTMLDocumentSH,
DOCUMENT_SCRIPTABLE_FLAGS |
nsIXPCScriptable::WANT_ENUMERATE)
NS_DEFINE_CLASSINFO_DATA(ImageDocument, nsHTMLDocumentSH,
DOCUMENT_SCRIPTABLE_FLAGS |
nsIXPCScriptable::WANT_ENUMERATE)
NS_DEFINE_CLASSINFO_DATA(HTMLCollection, nsHTMLCollectionSH,
ARRAY_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(HTMLOptionCollection,
@ -1415,6 +1419,21 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Node)
DOM_CLASSINFO_MAP_END_WITH_XPATH
DOM_CLASSINFO_MAP_BEGIN(ImageDocument, nsIImageDocument)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLDocument)
DOM_CLASSINFO_MAP_ENTRY(nsIImageDocument)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSHTMLDocument)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSDocument)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentEvent)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentStyle)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentView)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentRange)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentTraversal)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentXBL)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Node)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(HTMLCollection, nsIDOMHTMLCollection)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeList)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLCollection)

Просмотреть файл

@ -93,6 +93,7 @@ pref("browser.anchor_color", "#0000EE");
pref("browser.visited_color", "#551A8B");
pref("browser.underline_anchors", true);
pref("browser.blink_allowed", true);
pref("browser.enable_automatic_image_resizing", false);
pref("browser.display.use_focus_colors", false);
pref("browser.display.focus_background_color", "#117722");

Просмотреть файл

@ -83,6 +83,11 @@
accesskey="&copyLinkCmd.accesskey;"
command="cmd_copyLink"/>
<menuseparator id="context-sep-copylink"/>
<menuitem id="context-fitimage"
type="checkbox"
label="&fitImageCmd.label;"
accesskey="&fitImageCmd.accesskey;"
oncommand="gContextMenu.toggleImageSize();"/>
<menuitem id="context-viewimage"
label="&viewImageCmd.label;"
accesskey="&viewImageCmd.accesskey;"

Просмотреть файл

@ -137,8 +137,14 @@ nsContextMenu.prototype = {
// Disable the Set As Wallpaper menu item if we're still trying to load the image
this.setItemAttr( "context-setWallpaper", "disabled", (("complete" in this.target) && !this.target.complete) ? "true" : null );
this.showItem( "context-fitimage", this.onStandaloneImage && _content.document.imageResizingEnabled );
if ( this.onStandaloneImage && _content.document.imageResizingEnabled ) {
this.setItemAttr( "context-fitimage", "disabled", _content.document.imageIsOverflowing ? null : "true");
this.setItemAttr( "context-fitimage", "checked", _content.document.imageIsResized ? "true" : null);
}
// View Image depends on whether an image was clicked on.
this.showItem( "context-viewimage", this.onImage );
this.showItem( "context-viewimage", this.onImage && !this.onStandaloneImage);
// View background image depends on whether there is one.
this.showItem( "context-viewbgimage", !( this.inDirList || this.onImage || this.isTextSelected || this.onLink || this.onTextInput ) );
@ -218,6 +224,7 @@ nsContextMenu.prototype = {
}
// Initialize contextual info.
this.onImage = false;
this.onStandaloneImage = false;
this.onMetaDataItem = false;
this.onTextInput = false;
this.imageURL = "";
@ -235,6 +242,11 @@ nsContextMenu.prototype = {
if ( this.target.localName.toUpperCase() == "IMG" ) {
this.onImage = true;
this.imageURL = this.target.src;
var documentType = window._content.document.contentType;
if ( documentType.substr(0,6) == "image/" )
this.onStandaloneImage = true;
// Look for image map.
var mapName = this.target.getAttribute( "usemap" );
if ( mapName ) {
@ -574,10 +586,13 @@ nsContextMenu.prototype = {
BrowserViewSourceOfDocument(this.target.ownerDocument);
},
viewInfo : function () {
BrowserPageInfo();
BrowserPageInfo();
},
viewFrameInfo : function () {
BrowserPageInfo(this.target.ownerDocument);
BrowserPageInfo(this.target.ownerDocument);
},
toggleImageSize : function () {
_content.document.toggleImageSize();
},
// Change current window to the URL of the image.
viewImage : function () {

Просмотреть файл

@ -39,6 +39,8 @@
<!ENTITY viewPageInfoCmd.accesskey "I">
<!ENTITY viewFrameInfoCmd.label "View Frame Info">
<!ENTITY viewFrameInfoCmd.accesskey "I">
<!ENTITY fitImageCmd.label "Fit Image to Window">
<!ENTITY fitImageCmd.accesskey "F">
<!ENTITY viewImageCmd.label "View Image">
<!ENTITY viewImageCmd.accesskey "I">
<!ENTITY viewBGImageCmd.label "View Background Image">

Просмотреть файл

@ -37,7 +37,10 @@
<script type="application/x-javascript">
<![CDATA[
var panel = "chrome://communicator/content/pref/pref-appearance.xul";
var _elementIDs = ["generalStartupBrowser", "toolbarStyle", "showHideTooltips", "useSiteIcons"];
var _elementIDs = [
"generalStartupBrowser", "toolbarStyle", "showHideTooltips",
"useSiteIcons", "enableAutomaticImageResizing"
];
]]>
</script>
@ -71,6 +74,11 @@
accesskey="&useSiteIcons.accesskey;"
prefstring="browser.chrome.site_icons"/>
<checkbox id="enableAutomaticImageResizing"
label="&enableAutomaticImageResizing.label;"
accesskey="&enableAutomaticImageResizing.accesskey;"
prefstring="browser.enable_automatic_image_resizing"/>
<separator/>
</vbox>

Просмотреть файл

@ -27,6 +27,8 @@
<!ENTITY showHideTooltips.accesskey "t">
<!ENTITY useSiteIcons.label "Show Web Site Icons">
<!ENTITY useSiteIcons.accesskey "i">
<!ENTITY enableAutomaticImageResizing.label "Enable automatic image resizing">
<!ENTITY enableAutomaticImageResizing.accesskey "r">
<!--LOCALIZATION NOTE (languageList.txt.label): Don't translate "&brandShortName;".
Place &brandShortName; in the phrase where the name of the application should appear