Fix for 18502, Christian Biesinger's BMP decoder and my ICO decoder. r/sr=pavlov,jband

This commit is contained in:
hyatt%netscape.com 2001-11-03 07:10:51 +00:00
Родитель 764ac7809e
Коммит 79f6e4162f
26 изменённых файлов: 1947 добавлений и 14 удалений

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

@ -805,6 +805,7 @@ fi
modules/libpr0n/decoders/png/Makefile modules/libpr0n/decoders/png/Makefile
modules/libpr0n/decoders/ppm/Makefile modules/libpr0n/decoders/ppm/Makefile
modules/libpr0n/decoders/jpeg/Makefile modules/libpr0n/decoders/jpeg/Makefile
modules/libpr0n/decoders/bmp/Makefile
" "
MAKEFILES_gfx2=" MAKEFILES_gfx2="

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

@ -113,6 +113,8 @@ static char* gImageTypes[] = {
"image/x-png", "image/x-png",
"image/x-art", "image/x-art",
"image/x-jg", "image/x-jg",
"image/bmp",
"image/x-icon",
0 0
}; };

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

@ -113,6 +113,8 @@ static char* gImageTypes[] = {
"image/x-png", "image/x-png",
"image/x-art", "image/x-art",
"image/x-jg", "image/x-jg",
"image/bmp",
"image/x-icon",
0 0
}; };

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

@ -377,6 +377,8 @@ nsObjectFrame::GetSkipSides() const
#define IMAGE_EXT_JPG "jpg" #define IMAGE_EXT_JPG "jpg"
#define IMAGE_EXT_PNG "png" #define IMAGE_EXT_PNG "png"
#define IMAGE_EXT_XBM "xbm" #define IMAGE_EXT_XBM "xbm"
#define IMAGE_EXT_BMP "bmp"
#define IMAGE_EXT_ICO "ico"
// #define DO_DIRTY_INTERSECT 1 // enable dirty rect intersection during paint // #define DO_DIRTY_INTERSECT 1 // enable dirty rect intersection during paint
@ -399,7 +401,9 @@ void nsObjectFrame::IsSupportedImage(nsIContent* aContent, PRBool* aImage)
type.EqualsIgnoreCase(IMAGE_PPM) || type.EqualsIgnoreCase(IMAGE_PPM) ||
type.EqualsIgnoreCase(IMAGE_XBM) || type.EqualsIgnoreCase(IMAGE_XBM) ||
type.EqualsIgnoreCase(IMAGE_XBM2)|| type.EqualsIgnoreCase(IMAGE_XBM2)||
type.EqualsIgnoreCase(IMAGE_XBM3)) type.EqualsIgnoreCase(IMAGE_XBM3)||
type.EqualsIgnoreCase(IMAGE_BMP) ||
type.EqualsIgnoreCase(IMAGE_ICO))
{ {
*aImage = PR_TRUE; *aImage = PR_TRUE;
} }
@ -432,7 +436,9 @@ void nsObjectFrame::IsSupportedImage(nsIContent* aContent, PRBool* aImage)
if(ext.EqualsIgnoreCase(IMAGE_EXT_GIF) || if(ext.EqualsIgnoreCase(IMAGE_EXT_GIF) ||
ext.EqualsIgnoreCase(IMAGE_EXT_JPG) || ext.EqualsIgnoreCase(IMAGE_EXT_JPG) ||
ext.EqualsIgnoreCase(IMAGE_EXT_PNG) || ext.EqualsIgnoreCase(IMAGE_EXT_PNG) ||
ext.EqualsIgnoreCase(IMAGE_EXT_XBM)) ext.EqualsIgnoreCase(IMAGE_EXT_XBM) ||
ext.EqualsIgnoreCase(IMAGE_EXT_BMP) ||
ext.EqualsIgnoreCase(IMAGE_EXT_ICO))
{ {
*aImage = PR_TRUE; *aImage = PR_TRUE;
} }

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

@ -377,6 +377,8 @@ nsObjectFrame::GetSkipSides() const
#define IMAGE_EXT_JPG "jpg" #define IMAGE_EXT_JPG "jpg"
#define IMAGE_EXT_PNG "png" #define IMAGE_EXT_PNG "png"
#define IMAGE_EXT_XBM "xbm" #define IMAGE_EXT_XBM "xbm"
#define IMAGE_EXT_BMP "bmp"
#define IMAGE_EXT_ICO "ico"
// #define DO_DIRTY_INTERSECT 1 // enable dirty rect intersection during paint // #define DO_DIRTY_INTERSECT 1 // enable dirty rect intersection during paint
@ -399,7 +401,9 @@ void nsObjectFrame::IsSupportedImage(nsIContent* aContent, PRBool* aImage)
type.EqualsIgnoreCase(IMAGE_PPM) || type.EqualsIgnoreCase(IMAGE_PPM) ||
type.EqualsIgnoreCase(IMAGE_XBM) || type.EqualsIgnoreCase(IMAGE_XBM) ||
type.EqualsIgnoreCase(IMAGE_XBM2)|| type.EqualsIgnoreCase(IMAGE_XBM2)||
type.EqualsIgnoreCase(IMAGE_XBM3)) type.EqualsIgnoreCase(IMAGE_XBM3)||
type.EqualsIgnoreCase(IMAGE_BMP) ||
type.EqualsIgnoreCase(IMAGE_ICO))
{ {
*aImage = PR_TRUE; *aImage = PR_TRUE;
} }
@ -432,7 +436,9 @@ void nsObjectFrame::IsSupportedImage(nsIContent* aContent, PRBool* aImage)
if(ext.EqualsIgnoreCase(IMAGE_EXT_GIF) || if(ext.EqualsIgnoreCase(IMAGE_EXT_GIF) ||
ext.EqualsIgnoreCase(IMAGE_EXT_JPG) || ext.EqualsIgnoreCase(IMAGE_EXT_JPG) ||
ext.EqualsIgnoreCase(IMAGE_EXT_PNG) || ext.EqualsIgnoreCase(IMAGE_EXT_PNG) ||
ext.EqualsIgnoreCase(IMAGE_EXT_XBM)) ext.EqualsIgnoreCase(IMAGE_EXT_XBM) ||
ext.EqualsIgnoreCase(IMAGE_EXT_BMP) ||
ext.EqualsIgnoreCase(IMAGE_EXT_ICO))
{ {
*aImage = PR_TRUE; *aImage = PR_TRUE;
} }

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

@ -88,19 +88,160 @@
#include "nsIStyleSet.h" #include "nsIStyleSet.h"
#include "nsIStyleContext.h" #include "nsIStyleContext.h"
#include "nsBoxLayoutState.h" #include "nsBoxLayoutState.h"
#include "nsIDOMDocument.h"
#include "nsIEventQueueService.h"
#include "nsIServiceManager.h" #include "nsIServiceManager.h"
#include "nsIURI.h" #include "nsIURI.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "nsGUIEvent.h"
#include "nsFormControlHelper.h" #include "nsFormControlHelper.h"
#define ONLOAD_CALLED_TOO_EARLY 1 #define ONLOAD_CALLED_TOO_EARLY 1
static void PR_CALLBACK
HandleImagePLEvent(nsIContent *aContent, PRUint32 aMessage, PRUint32 aFlags)
{
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aContent));
if (!node) {
NS_ERROR("null or non-DOM node passed to HandleImagePLEvent!");
return;
}
nsCOMPtr<nsIDOMDocument> dom_doc;
node->GetOwnerDocument(getter_AddRefs(dom_doc));
nsCOMPtr<nsIDocument> doc(do_QueryInterface(dom_doc));
if (!doc) {
return;
}
nsCOMPtr<nsIPresShell> pres_shell;
doc->GetShellAt(0, getter_AddRefs(pres_shell));
if (!pres_shell) {
return;
}
nsCOMPtr<nsIPresContext> pres_context;
pres_shell->GetPresContext(getter_AddRefs(pres_context));
if (!pres_context) {
return;
}
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event;
event.eventStructType = NS_EVENT;
event.message = aMessage;
aContent->HandleDOMEvent(pres_context, &event, nsnull, aFlags, &status);
}
static void PR_CALLBACK
HandleImageOnloadPLEvent(PLEvent *aEvent)
{
nsIContent *content = (nsIContent *)PL_GetEventOwner(aEvent);
HandleImagePLEvent(content, NS_IMAGE_LOAD,
NS_EVENT_FLAG_INIT | NS_EVENT_FLAG_CANT_BUBBLE);
NS_RELEASE(content);
}
static void PR_CALLBACK
HandleImageOnerrorPLEvent(PLEvent *aEvent)
{
nsIContent *content = (nsIContent *)PL_GetEventOwner(aEvent);
HandleImagePLEvent(content, NS_IMAGE_ERROR, NS_EVENT_FLAG_INIT);
NS_RELEASE(content);
}
static void PR_CALLBACK
DestroyImagePLEvent(PLEvent* aEvent)
{
delete aEvent;
}
// Fire off a PLEvent that'll asynchronously call the image elements
// onload handler once handled. This is needed since the image library
// can't decide if it wants to call it's observer methods
// synchronously or asynchronously. If an image is loaded from the
// cache the notifications come back synchronously, but if the image
// is loaded from the netswork the notifications come back
// asynchronously.
void
FireDOMEvent(nsIContent* aContent, PRUint32 aMessage)
{
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
nsCOMPtr<nsIEventQueueService> event_service =
do_GetService(kEventQueueServiceCID);
if (!event_service) {
NS_WARNING("Failed to get event queue service");
return;
}
nsCOMPtr<nsIEventQueue> event_queue;
event_service->GetThreadEventQueue(NS_CURRENT_THREAD,
getter_AddRefs(event_queue));
if (!event_queue) {
NS_WARNING("Failed to get event queue from service");
return;
}
PLEvent *event = new PLEvent;
if (!event) {
// Out of memory, but none of our callers care, so just warn and
// don't fire the event
NS_WARNING("Out of memory?");
return;
}
PLHandleEventProc f;
switch (aMessage) {
case NS_IMAGE_LOAD :
f = (PLHandleEventProc)::HandleImageOnloadPLEvent;
break;
case NS_IMAGE_ERROR :
f = (PLHandleEventProc)::HandleImageOnerrorPLEvent;
break;
default:
NS_WARNING("Huh, I don't know how to fire this type of event?!");
return;
}
PL_InitEvent(event, aContent, f, (PLDestroyEventProc)::DestroyImagePLEvent);
// The event owns the content pointer now.
NS_ADDREF(aContent);
event_queue->PostEvent(event);
}
// //
// NS_NewToolbarFrame // NS_NewImageBoxFrame
// //
// Creates a new Toolbar frame and returns it in |aNewFrame| // Creates a new image frame and returns it in |aNewFrame|
// //
nsresult nsresult
NS_NewImageBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) NS_NewImageBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame )
@ -615,9 +756,13 @@ NS_IMETHODIMP nsImageBoxFrame::OnStopContainer(imgIRequest *request, nsIPresCont
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP nsImageBoxFrame::OnStopDecode(imgIRequest *request, nsIPresContext *aPresContext, nsresult status, const PRUnichar *statusArg) NS_IMETHODIMP nsImageBoxFrame::OnStopDecode(imgIRequest *request, nsIPresContext *aPresContext, nsresult aStatus, const PRUnichar *statusArg)
{ {
return NS_ERROR_NOT_IMPLEMENTED; if (NS_FAILED(aStatus))
// Fire an onerror DOM event.
FireDOMEvent(mContent, NS_IMAGE_ERROR);
return NS_OK;
} }
NS_IMETHODIMP nsImageBoxFrame::FrameChanged(imgIContainer *container, nsIPresContext *aPresContext, gfxIImageFrame *newframe, nsRect * dirtyRect) NS_IMETHODIMP nsImageBoxFrame::FrameChanged(imgIContainer *container, nsIPresContext *aPresContext, gfxIImageFrame *newframe, nsRect * dirtyRect)
@ -703,7 +848,9 @@ NS_IMETHODIMP nsImageBoxListener::OnStopDecode(imgIRequest *request, nsISupports
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
nsCOMPtr<nsIPresContext> pc(do_QueryInterface(cx)); nsCOMPtr<nsIPresContext> pc(do_QueryInterface(cx));
return mFrame->OnStopDecode(request, pc, status, statusArg); nsresult rv = mFrame->OnStopDecode(request, pc, status, statusArg);
return rv;
} }
NS_IMETHODIMP nsImageBoxListener::FrameChanged(imgIContainer *container, nsISupports *cx, gfxIImageFrame *newframe, nsRect * dirtyRect) NS_IMETHODIMP nsImageBoxListener::FrameChanged(imgIContainer *container, nsISupports *cx, gfxIImageFrame *newframe, nsRect * dirtyRect)

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

@ -533,7 +533,7 @@ nsOutlinerBodyFrame::SetFocused(PRBool aFocused)
NS_IMETHODIMP NS_IMETHODIMP
nsOutlinerBodyFrame::GetOutlinerBody(nsIDOMElement** aElement) nsOutlinerBodyFrame::GetOutlinerBody(nsIDOMElement** aElement)
{ {
NS_ASSERTION(mContent, "no content, see bug #104878"); //NS_ASSERTION(mContent, "no content, see bug #104878");
if (!mContent) if (!mContent)
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;

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

@ -533,7 +533,7 @@ nsOutlinerBodyFrame::SetFocused(PRBool aFocused)
NS_IMETHODIMP NS_IMETHODIMP
nsOutlinerBodyFrame::GetOutlinerBody(nsIDOMElement** aElement) nsOutlinerBodyFrame::GetOutlinerBody(nsIDOMElement** aElement)
{ {
NS_ASSERTION(mContent, "no content, see bug #104878"); //NS_ASSERTION(mContent, "no content, see bug #104878");
if (!mContent) if (!mContent)
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;

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

@ -448,7 +448,9 @@ mime_find_class (const char *content_type, MimeHeaders *hdrs,
!nsCRT::strcasecmp(content_type, IMAGE_PNG) || !nsCRT::strcasecmp(content_type, IMAGE_PNG) ||
!nsCRT::strcasecmp(content_type, IMAGE_XBM) || !nsCRT::strcasecmp(content_type, IMAGE_XBM) ||
!nsCRT::strcasecmp(content_type, IMAGE_XBM2) || !nsCRT::strcasecmp(content_type, IMAGE_XBM2) ||
!nsCRT::strcasecmp(content_type, IMAGE_XBM3)) !nsCRT::strcasecmp(content_type, IMAGE_XBM3) ||
!nsCRT::strcasecmp(content_type, IMAGE_BMP) ||
!nsCRT::strcasecmp(content_type, IMAGE_ICO))
clazz = (MimeObjectClass *)&mimeInlineImageClass; clazz = (MimeObjectClass *)&mimeInlineImageClass;
#ifdef ENABLE_SMIME #ifdef ENABLE_SMIME

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

@ -26,7 +26,7 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk include $(DEPTH)/config/autoconf.mk
DIRS = ppm png gif jpeg DIRS = ppm png gif jpeg bmp
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk

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

@ -0,0 +1,49 @@
#
# 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 Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Christian Biesinger <cbiesinger@web.de>
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = imgbmp
LIBRARY_NAME = imgbmp
EXPORT_LIBRARY = 1
IS_COMPONENT = 1
MODULE_NAME = nsBMPModule
REQUIRES = xpcom \
necko \
gfx \
gfx2 \
imglib2 \
string \
$(NULL)
CPPSRCS = nsBMPDecoder.cpp nsICODecoder.cpp nsBMPModule.cpp
EXTRA_DSO_LDOPTS = $(MOZ_COMPONENT_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk

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

@ -0,0 +1,51 @@
#!nmake
#
# 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 Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Christian Biesinger <cbiesinger@web.de>
#
DEPTH=..\..\..\..
MODULE = imgbmp
REQUIRES = xpcom \
necko \
gfx \
gfx2 \
imglib2 \
string \
$(NULL)
include <$(DEPTH)/config/config.mak>
LIBRARY_NAME = imgbmp
MODULE_NAME = nsBMPModule
OBJS = \
.\$(OBJDIR)\nsBMPModule.obj \
.\$(OBJDIR)\nsBMPDecoder.obj \
.\$(OBJDIR)\nsICODecoder.obj \
$(NULL)
LLIBS=\
$(LIBNSPR) \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\gkgfx.lib \
$(NULL)
include <$(DEPTH)\config\rules.mak>

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

@ -0,0 +1,474 @@
/* vim:set tw=80 expandtab softtabstop=4 ts=4 sw=4: */
/* ----- BEGIN LICENSE BLOCK -----
* Version: MPL 1.1/LGPL 2.1/GPL 2.0
*
* 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 the Mozilla BMP Decoder.
*
* The Initial Developer of the Original Code is Christian Biesinger
* <cbiesinger@web.de>. Portions created by Christian Biesinger are
* Copyright (C) 2001 Christian Biesinger. 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 LGPL or the GPL. 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 ----- */
/* I got the format description from http://www.daubnet.com/formats/BMP.html */
/* This does not yet work in this version:
* o) Compressed Bitmaps, including ones using bitfields
* This decoder was tested on Windows, Linux and Mac. */
/* This is a Cross-Platform BMP Decoder, which should work everywhere, including
* Big-Endian machines like the PowerPC. */
#include "nsBMPDecoder.h"
#include "nsIInputStream.h"
#include "nsIComponentManager.h"
#include "nsIImage.h"
#include "nsMemory.h"
#include "imgIContainerObserver.h"
#include "nsRect.h"
#include "imgILoad.h"
#include "prcpucfg.h" // To get IS_LITTLE_ENDIAN / IS_BIG_ENDIAN
#include "ImageLogging.h"
PRLogModuleInfo *gBMPLog = PR_NewLogModule("BMPDecoder");
NS_IMPL_ISUPPORTS1(nsBMPDecoder, imgIDecoder)
nsBMPDecoder::nsBMPDecoder()
{
NS_INIT_ISUPPORTS();
mColors = nsnull;
mRow = nsnull;
mPos = mNumColors = mRowBytes = mCurLine = 0;
mLOH = 54;
}
nsBMPDecoder::~nsBMPDecoder()
{
}
NS_IMETHODIMP nsBMPDecoder::Init(imgILoad *aLoad)
{
PR_LOG(gBMPLog, PR_LOG_DEBUG, ("nsBMPDecoder::Init(%p)\n", aLoad));
NS_ENSURE_ARG_POINTER(aLoad);
mObserver = do_QueryInterface(aLoad);
mImage = do_CreateInstance("@mozilla.org/image/container;1");
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;
nsresult rv = aLoad->SetImage(mImage);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHODIMP nsBMPDecoder::Close()
{
PR_LOG(gBMPLog, PR_LOG_DEBUG, ("nsBMPDecoder::Close()\n"));
mPos = 0;
delete[] mColors;
mColors = nsnull;
mNumColors = 0;
delete[] mRow;
mRow = nsnull;
mRowBytes = 0;
mCurLine = 0;
if (mObserver) {
mObserver->OnStopContainer(nsnull, nsnull, mImage);
mObserver->OnStopDecode(nsnull, nsnull, NS_OK, nsnull);
mObserver = nsnull;
}
mImage = nsnull;
mFrame = nsnull;
mLOH = 54;
return NS_OK;
}
NS_IMETHODIMP nsBMPDecoder::Flush()
{
mFrame->SetMutable(PR_FALSE);
return NS_OK;
}
NS_IMETHODIMP nsBMPDecoder::WriteFrom(nsIInputStream *aInStr, PRUint32 aCount, PRUint32 *aRetval)
{
PR_LOG(gBMPLog, PR_LOG_DEBUG, ("nsBMPDecoder::WriteFrom(%p, %lu, %p)\n", aInStr, aCount, aRetval));
NS_ENSURE_ARG_POINTER(aInStr);
NS_ENSURE_ARG_POINTER(aRetval);
char* buffer = new char[aCount];
if (!buffer) {
return NS_ERROR_OUT_OF_MEMORY;
}
unsigned int realCount = aCount;
nsresult rv = aInStr->Read(buffer, aCount, &realCount);
NS_ENSURE_SUCCESS(rv, rv);
*aRetval = realCount;
rv = ProcessData(buffer, realCount);
delete []buffer;
return rv;
}
// ----------------------------------------
// Actual Data Processing
// ----------------------------------------
inline nsresult nsBMPDecoder::SetPixel(PRUint8*& aDecoded, PRUint8 idx)
{
PRUint8 red, green, blue;
red = mColors[idx].red;
green = mColors[idx].green;
blue = mColors[idx].blue;
return SetPixel(aDecoded, red, green, blue);
}
inline nsresult nsBMPDecoder::SetPixel(PRUint8*& aDecoded, PRUint8 aRed, PRUint8 aGreen, PRUint8 aBlue)
{
#if defined(XP_MAC) || defined(XP_MACOSX)
*aDecoded++ = 0; // Mac needs this padding byte
#endif
#ifdef USE_RGB
*aDecoded++ = aRed;
*aDecoded++ = aGreen;
*aDecoded++ = aBlue;
#else
*aDecoded++ = aBlue;
*aDecoded++ = aGreen;
*aDecoded++ = aRed;
#endif
return NS_OK;
}
inline nsresult nsBMPDecoder::Set4BitPixel(PRUint8*& aDecoded, PRUint8 aData, PRUint32& aPos)
{
PRUint8 idx = aData >> 4;
nsresult rv = SetPixel(aDecoded, idx);
if ((++aPos >= mBIH.width) || NS_FAILED(rv))
return rv;
idx = aData & 0xF;
rv = SetPixel(aDecoded, idx);
++aPos;
return rv;
}
inline nsresult nsBMPDecoder::SetData(PRUint8* aData)
{
NS_ENSURE_ARG_POINTER(aData);
PRUint32 bpr;
nsresult rv;
rv = mFrame->GetImageBytesPerRow(&bpr);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 offset = (mCurLine - 1) * bpr;
rv = mFrame->SetImageData(aData, bpr, offset);
NS_ENSURE_SUCCESS(rv, rv);
nsRect r(0, mCurLine, mBIH.width, 1);
rv = mObserver->OnDataAvailable(nsnull, nsnull, mFrame, &r);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_METHOD nsBMPDecoder::ProcessData(const char* aBuffer, PRUint32 aCount)
{
if (!aCount) // aCount=0 means EOF
return NS_OK;
nsresult rv;
if (mPos < 18) { /* In BITMAPFILEHEADER */
PRUint32 toCopy = 18 - mPos;
if (toCopy > aCount)
toCopy = aCount;
nsCRT::memcpy(mRawBuf + mPos, aBuffer, toCopy);
mPos += toCopy;
aCount -= toCopy;
aBuffer += toCopy;
}
if (mPos == 18) {
rv = mObserver->OnStartDecode(nsnull, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
ProcessFileHeader();
if (mBFH.signature[0] != 'B' || mBFH.signature[1] != 'M')
return NS_ERROR_FAILURE;
if (mBFH.bihsize == 12)
mLOH = 26;
}
if (mPos >= 18 && mPos < mLOH) { /* In BITMAPINFOHEADER */
PRUint32 toCopy = mLOH - mPos;
if (toCopy > aCount)
toCopy = aCount;
nsCRT::memcpy(mRawBuf + (mPos - 18), aBuffer, toCopy);
mPos += toCopy;
aCount -= toCopy;
aBuffer += toCopy;
}
if (mPos == mLOH) {
ProcessInfoHeader();
PR_LOG(gBMPLog, PR_LOG_DEBUG, ("BMP image is %lux%lux%lu. compression=%lu\n",
mBIH.width, mBIH.height, mBIH.bpp, mBIH.compression));
if (mBIH.compression) {
PR_LOG(gBMPLog, PR_LOG_DEBUG, ("Don't yet support compressed BMPs\n"));
return NS_ERROR_FAILURE;
}
if (mBIH.bpp <= 8) {
switch (mBIH.bpp) {
case 1:
mNumColors = 2;
break;
case 4:
mNumColors = 16;
break;
case 8:
mNumColors = 256;
break;
default:
return NS_ERROR_FAILURE;
}
if (mBIH.colors)
mNumColors = mBIH.colors;
mColors = new colorTable[mNumColors];
if (!mColors)
return NS_ERROR_OUT_OF_MEMORY;
}
rv = mImage->Init(mBIH.width, mBIH.height, mObserver);
NS_ENSURE_SUCCESS(rv, rv);
rv = mObserver->OnStartContainer(nsnull, nsnull, mImage);
NS_ENSURE_SUCCESS(rv, rv);
mCurLine = mBIH.height;
mRow = new PRUint8[(mBIH.width * mBIH.bpp)/8 + 4];
// +4 because the line is padded to a 4 bit boundary, but I don't want
// to make exact calculations here, that's unnecessary.
// Also, it compensates rounding error.
if (!mRow) {
return NS_ERROR_OUT_OF_MEMORY;
}
rv = mFrame->Init(0, 0, mBIH.width, mBIH.height, GFXFORMAT);
NS_ENSURE_SUCCESS(rv, rv);
rv = mImage->AppendFrame(mFrame);
NS_ENSURE_SUCCESS(rv, rv);
mObserver->OnStartFrame(nsnull, nsnull, mFrame);
NS_ENSURE_SUCCESS(rv, rv);
}
PRUint8 bpc; // bytes per color
bpc = (mBFH.bihsize == 12) ? 3 : 4; // OS/2 Bitmaps have no padding byte
if (mColors && (mPos >= mLOH && (mPos < (mLOH + mNumColors * bpc)))) {
// We will receive (mNumColors * 4) bytes of color data
PRUint32 colorBytes = mPos - mLOH; // Number of bytes already received
PRUint8 colorNum = colorBytes / bpc; // Color which is currently received
PRUint8 at = colorBytes % bpc;
while (aCount && (mPos < (mLOH + mNumColors * bpc))) {
switch (at) {
case 0:
mColors[colorNum].blue = *aBuffer;
break;
case 1:
mColors[colorNum].green = *aBuffer;
break;
case 2:
mColors[colorNum].red = *aBuffer;
colorNum++;
break;
case 3:
// This is a padding byte
break;
}
mPos++; aBuffer++; aCount--;
at = (at + 1) % bpc;
}
}
while (aCount && (mPos < mBFH.dataoffset)) { // Skip whatever is between header and data
mPos++; aBuffer++; aCount--;
}
if (++mPos >= mBFH.dataoffset) {
if (!mBIH.compression) {
// Need to increment mPos, else we might get to mPos==mLOH again
// From now on, mPos is irrelevant
PRUint32 rowSize = (mBIH.bpp * mBIH.width + 7) / 8; // +7 to round up
if (rowSize % 4)
rowSize += (4 - (rowSize % 4)); // Pad to DWORD Boundary
PRUint32 toCopy;
do {
toCopy = rowSize - mRowBytes;
if (toCopy) {
if (toCopy > aCount)
toCopy = aCount;
nsCRT::memcpy(mRow + mRowBytes, aBuffer, toCopy);
aCount -= toCopy;
aBuffer += toCopy;
mRowBytes += toCopy;
}
if ((rowSize - mRowBytes) == 0) {
PRUint32 bpr;
rv = mFrame->GetImageBytesPerRow(&bpr);
NS_ENSURE_SUCCESS(rv, rv);
PRUint8* decoded = new PRUint8[bpr];
if (!decoded)
return NS_ERROR_OUT_OF_MEMORY;
PRUint8* p = mRow;
PRUint8* d = decoded;
PRUint32 lpos = 0;
switch (mBIH.bpp) {
case 1:
while (lpos < mBIH.width) {
PRInt8 bit;
PRUint8 idx;
for (bit = 7; bit >= 0; bit--) {
if (lpos >= mBIH.width)
break;
idx = (*p >> bit) & 1;
SetPixel(d, idx);
++lpos;
}
++p;
}
break;
case 4:
while (lpos < mBIH.width) {
Set4BitPixel(d, *p, lpos);
++p;
}
break;
case 8:
while (lpos < mBIH.width) {
SetPixel(d, *p);
++lpos;
++p;
}
break;
case 16:
while (lpos < mBIH.width) {
SetPixel(d,
(p[1] & 124) << 1,
((p[1] & 3) << 6) | ((p[0] & 224) >> 2),
(p[0] & 31) << 3);
++lpos;
p+=2;
}
break;
case 32:
case 24:
while (lpos < mBIH.width) {
SetPixel(d, p[2], p[1], p[0]);
p += 2;
++lpos;
if (mBIH.bpp == 32)
p++; // Padding byte
++p;
}
break;
default:
// This is probably the wrong place to check this...
return NS_ERROR_FAILURE;
}
nsresult rv = SetData(decoded);
delete[] decoded;
NS_ENSURE_SUCCESS(rv, rv);
if (mCurLine == 1) { // Finished last line
return mObserver->OnStopFrame(nsnull, nsnull, mFrame);
}
mCurLine--; mRowBytes = 0;
}
} while (aCount > 0);
}
}
return NS_OK;
}
void nsBMPDecoder::ProcessFileHeader()
{
nsCRT::memset(&mBFH, 0, sizeof(mBFH));
DOCOPY(&mBFH.signature, mRawBuf);
DOCOPY(&mBFH.filesize, mRawBuf + 2);
DOCOPY(&mBFH.reserved, mRawBuf + 6);
DOCOPY(&mBFH.dataoffset, mRawBuf + 10);
DOCOPY(&mBFH.bihsize, mRawBuf + 14);
// Now correct the endianness of the header
mBFH.filesize = LITTLE_TO_NATIVE32(mBFH.filesize);
mBFH.dataoffset = LITTLE_TO_NATIVE32(mBFH.dataoffset);
mBFH.bihsize = LITTLE_TO_NATIVE32(mBFH.bihsize);
}
void nsBMPDecoder::ProcessInfoHeader()
{
nsCRT::memset(&mBIH, 0, sizeof(mBIH));
if (mBFH.bihsize == 12) { // OS/2 Bitmap
nsCRT::memcpy(&mBIH.width, mRawBuf, 2);
nsCRT::memcpy(&mBIH.height, mRawBuf + 2, 2);
DOCOPY(&mBIH.planes, mRawBuf + 4);
DOCOPY(&mBIH.bpp, mRawBuf + 6);
}
else {
DOCOPY(&mBIH.width, mRawBuf);
DOCOPY(&mBIH.height, mRawBuf + 4);
DOCOPY(&mBIH.planes, mRawBuf + 8);
DOCOPY(&mBIH.bpp, mRawBuf + 10);
DOCOPY(&mBIH.compression, mRawBuf + 12);
DOCOPY(&mBIH.image_size, mRawBuf + 16);
DOCOPY(&mBIH.xppm, mRawBuf + 20);
DOCOPY(&mBIH.yppm, mRawBuf + 24);
DOCOPY(&mBIH.colors, mRawBuf + 28);
DOCOPY(&mBIH.important_colors, mRawBuf + 32);
}
// Convert endianness
mBIH.width = LITTLE_TO_NATIVE32(mBIH.width);
mBIH.height = LITTLE_TO_NATIVE32(mBIH.height);
mBIH.planes = LITTLE_TO_NATIVE16(mBIH.planes);
mBIH.bpp = LITTLE_TO_NATIVE16(mBIH.bpp);
mBIH.compression = LITTLE_TO_NATIVE32(mBIH.compression);
mBIH.image_size = LITTLE_TO_NATIVE32(mBIH.image_size);
mBIH.xppm = LITTLE_TO_NATIVE32(mBIH.xppm);
mBIH.yppm = LITTLE_TO_NATIVE32(mBIH.yppm);
mBIH.colors = LITTLE_TO_NATIVE32(mBIH.colors);
mBIH.important_colors = LITTLE_TO_NATIVE32(mBIH.important_colors);
}

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

@ -0,0 +1,172 @@
/* vim:set tw=80 expandtab softtabstop=4 ts=4 sw=4: */
/* ----- BEGIN LICENSE BLOCK -----
* Version: MPL 1.1/LGPL 2.1/GPL 2.0
*
* 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 the Mozilla BMP Decoder.
*
* The Initial Developer of the Original Code is Christian Biesinger
* <cbiesinger@web.de>. Portions created by Christian Biesinger are
* Copyright (C) 2001 Christian Biesinger. 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 LGPL or the GPL. 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 _nsBMPDecoder_h
#define _nsBMPDecoder_h
#include "nsCOMPtr.h"
#include "imgIDecoder.h"
#include "imgIContainer.h"
#include "imgIDecoderObserver.h"
#include "gfxIImageFrame.h"
#define NS_BMPDECODER_CID \
{ /* {78c61626-4d1f-4843-9364-4652d98ff6e1} */ \
0x78c61626, \
0x4d1f, \
0x4843, \
{ 0x93, 0x64, 0x46, 0x52, 0xd9, 0x8f, 0xf6, 0xe1 } \
}
struct BMPFILEHEADER {
char signature[2]; // String "BM"
PRUint32 filesize;
PRInt32 reserved; // Zero
PRUint32 dataoffset; // Offset to raster data
PRUint32 bihsize;
};
struct BMPINFOHEADER {
PRUint32 width;
PRUint32 height;
PRUint16 planes; // =1
PRUint16 bpp; // Bits per pixel.
// The rest of the header is not available in OS/2 BMP Files
PRUint32 compression; // 0=no compression 1=8bit RLE 2=4bit RLE
PRUint32 image_size; // (compressed) image size. Can be 0 if compression==0
PRUint32 xppm; // Pixels per meter, horizontal
PRUint32 yppm; // Pixels per meter, vertical
PRUint32 colors; // Used Colors
PRUint32 important_colors; // Number of important colors. 0=all
};
struct colorTable {
PRUint8 red;
PRUint8 green;
PRUint8 blue;
};
struct bitFields {
PRUint32 red;
PRUint32 green;
PRUint32 blue;
};
#define DOCOPY(dest, src) nsCRT::memcpy(dest, src, sizeof(dest))
#if defined WORDS_BIGENDIAN || defined IS_BIG_ENDIAN
#define LITTLE_TO_NATIVE16(x) ((((x) & 0xFF) << 8) | ((x) >> 8))
#define LITTLE_TO_NATIVE32(x) ((((x) & 0xFF) << 24) | \
((((x) >> 8) & 0xFF) << 16) | \
((((x) >> 16) & 0xFF) << 8) | \
((x) >> 24))
#else
#define LITTLE_TO_NATIVE16(x) x
#define LITTLE_TO_NATIVE32(x) x
#endif
#define BI_RLE8 1
#define BI_RLE4 2
#define BI_BITFIELDS 3
#if defined(XP_PC) || defined(XP_BEOS) || defined(MOZ_WIDGET_PHOTON)
#define GFXFORMAT gfxIFormats::BGR
#else
#define USE_RGB
#define GFXFORMAT gfxIFormats::RGB
#endif
class nsBMPDecoder : public imgIDecoder
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGIDECODER
nsBMPDecoder();
virtual ~nsBMPDecoder();
private:
/** Processes the data.
* @param aBuffer Data to process.
* @oaram count Number of bytes in mBuffer */
NS_METHOD ProcessData(const char* aBuffer, PRUint32 aCount);
/** Sets the pixel data in aDecoded to the given values.
* The variable passed in as aDecoded will be moved on 3 bytes! */
inline nsresult SetPixel(PRUint8*& aDecoded, PRUint8 aIdx);
inline nsresult SetPixel(PRUint8*& aDecoded, PRUint8 aRed, PRUint8 aGreen, PRUint8 aBlue);
/** Sets one or two pixels; it is ensured that aPos is <= mBIH.width
* @param aDecoded where the data is stored. Will be moved 3 or 6 bytes,
* depending on whether one or two pixels are written.
* @param aData The values for the two pixels
* @param aPos Current position. Is incremented by one or two. */
inline nsresult Set4BitPixel(PRUint8*& aDecoded, PRUint8 aData, PRUint32& aPos);
/** Sets the image data at specified position. mCurLine is used
* to get the row
* @param aData The data */
inline nsresult SetData(PRUint8* aData);
nsCOMPtr<imgIDecoderObserver> mObserver;
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<gfxIImageFrame> mFrame;
PRUint32 mPos;
BMPFILEHEADER mBFH;
BMPINFOHEADER mBIH;
char mRawBuf[36];
PRUint32 mLOH; // Length of the header
PRUint32 mNumColors;
colorTable *mColors;
PRUint8 *mRow; // Holds one raw line of the image
PRUint32 mRowBytes; // How many bytes of the row were already received
PRUint32 mCurLine;
void ProcessFileHeader();
void ProcessInfoHeader();
};
#endif

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

@ -0,0 +1,52 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim:set tw=80 expandtab softtabstop=4 ts=4 sw=4:
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Chris Saari <saari@netscape.com>
* Christian Biesinger <cbiesinger@web.de>
* David Hyatt <hyatt@netscape.com>
*/
#include "nsBMPDecoder.h"
#include "nsICODecoder.h"
#include "nsIComponentManager.h"
#include "nsIGenericFactory.h"
#include "nsISupports.h"
#include "nsCOMPtr.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsICODecoder)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBMPDecoder)
static nsModuleComponentInfo components[] =
{
{ "ICO Decoder",
NS_ICODECODER_CID,
"@mozilla.org/image/decoder;2?type=image/x-icon",
nsICODecoderConstructor, },
{ "BMP Decoder",
NS_BMPDECODER_CID,
"@mozilla.org/image/decoder;2?type=image/bmp",
nsBMPDecoderConstructor, },
};
NS_IMPL_NSGETMODULE(nsBMPModule, components)

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

@ -0,0 +1,555 @@
/* vim:set tw=80 expandtab softtabstop=4 ts=4 sw=4: */
/* ----- BEGIN LICENSE BLOCK -----
* Version: MPL 1.1/LGPL 2.1/GPL 2.0
*
* 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 the Mozilla ICO Decoder.
*
* The Initial Developer of the Original Code is Netscape.
* Portions created by Netscape are
* Copyright (C) 2001 Netscape. All
* Rights Reserved.
*
* Contributor(s):
* David Hyatt <hyatt@netscape.com> (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 LGPL or the GPL. 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 ----- */
/* This is a Cross-Platform ICO Decoder, which should work everywhere, including
* Big-Endian machines like the PowerPC. */
#include "nsICODecoder.h"
#include "nsIInputStream.h"
#include "nsIComponentManager.h"
#include "nsIImage.h"
#include "nsMemory.h"
#include "imgIContainerObserver.h"
#include "nsRect.h"
#include "nsCRT.h"
#include "imgILoad.h"
#include "prcpucfg.h" // To get IS_LITTLE_ENDIAN / IS_BIG_ENDIAN
NS_IMPL_ISUPPORTS1(nsICODecoder, imgIDecoder)
#define ICONCOUNTOFFSET 4
#define DIRENTRYOFFSET 6
#define BITMAPINFOSIZE 40
#define PREFICONSIZE 16
nsICODecoder::nsICODecoder()
{
NS_INIT_ISUPPORTS();
mPos = mNumColors = mCurLine = mRowBytes = mImageOffset = mCurrIcon = 0;
mColors = nsnull;
mRow = nsnull;
mDecodingAndMask = PR_FALSE;
}
nsICODecoder::~nsICODecoder()
{
}
NS_IMETHODIMP nsICODecoder::Init(imgILoad *aLoad)
{
mObserver = do_QueryInterface(aLoad);
mImage = do_CreateInstance("@mozilla.org/image/container;1");
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()
{
if (mObserver) {
mObserver->OnStopContainer(nsnull, nsnull, mImage);
mObserver->OnStopDecode(nsnull, nsnull, NS_OK, nsnull);
mObserver = nsnull;
}
mImage = nsnull;
mFrame = nsnull;
mPos = 0;
delete[] mColors;
mColors = nsnull;
mCurLine = 0;
mRowBytes = 0;
mImageOffset = 0;
mCurrIcon = 0;
mNumIcons = 0;
delete[] mRow;
mRow = nsnull;
mDecodingAndMask = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP nsICODecoder::Flush()
{
return NS_OK;
}
NS_IMETHODIMP nsICODecoder::WriteFrom(nsIInputStream *aInStr, PRUint32 aCount, PRUint32 *aRetval)
{
char* buffer = new char[aCount];
if (!buffer)
return NS_ERROR_OUT_OF_MEMORY;
unsigned int realCount = aCount;
nsresult rv = aInStr->Read(buffer, aCount, &realCount);
NS_ENSURE_SUCCESS(rv, rv);
*aRetval = realCount;
rv = ProcessData(buffer, realCount);
delete []buffer;
return rv;
}
nsresult nsICODecoder::ProcessData(const char* aBuffer, PRUint32 aCount) {
if (!aCount) // aCount=0 means EOF
return NS_OK;
while (aCount && (mPos < ICONCOUNTOFFSET)) { // Skip to the # of icons.
mPos++; aBuffer++; aCount--;
}
if (mPos == ICONCOUNTOFFSET && aCount >= 2) {
mNumIcons = LITTLE_TO_NATIVE16(((PRUint16*)aBuffer)[0]);
aBuffer += 2;
mPos += 2;
}
if (mNumIcons == 0)
return NS_OK; // Nothing to do.
while (mCurrIcon < mNumIcons) {
if (mPos >= DIRENTRYOFFSET + (mCurrIcon*sizeof(mDirEntryArray)) &&
mPos < DIRENTRYOFFSET + ((mCurrIcon+1)*sizeof(mDirEntryArray))) {
PRUint32 toCopy = sizeof(mDirEntryArray) - (mPos - DIRENTRYOFFSET - mCurrIcon*sizeof(mDirEntryArray));
if (toCopy > aCount)
toCopy = aCount;
nsCRT::memcpy(mDirEntryArray + sizeof(mDirEntryArray) - toCopy, aBuffer, toCopy);
mPos += toCopy;
aCount -= toCopy;
aBuffer += toCopy;
}
if (mPos == 22+mCurrIcon*sizeof(mDirEntryArray)) {
ProcessDirEntry();
mCurrIcon++;
if (mImageOffset == 0 && ((mDirEntry.mWidth == PREFICONSIZE && mDirEntry.mHeight == PREFICONSIZE) || mCurrIcon == mNumIcons))
mImageOffset = mDirEntry.mImageOffset;
}
}
while (aCount && mPos < mImageOffset) { // Skip to our offset
mPos++; aBuffer++; aCount--;
}
if (mCurrIcon == mNumIcons && mPos >= mImageOffset && mPos < mImageOffset + BITMAPINFOSIZE) {
// We've found the icon.
PRUint32 toCopy = sizeof(mBIHraw) - (mPos - mImageOffset);
if (toCopy > aCount)
toCopy = aCount;
nsCRT::memcpy(mBIHraw + (mPos - mImageOffset), aBuffer, toCopy);
mPos += toCopy;
aCount -= toCopy;
aBuffer += toCopy;
}
if (mPos == mImageOffset + BITMAPINFOSIZE) {
ProcessInfoHeader();
if (mBIH.bpp <= 8) {
switch (mBIH.bpp) {
case 1:
mNumColors = 2;
break;
case 4:
mNumColors = 16;
break;
case 8:
mNumColors = 256;
break;
default:
return NS_ERROR_FAILURE;
}
mColors = new colorTable[mNumColors];
if (!mColors)
return NS_ERROR_OUT_OF_MEMORY;
}
// Adjust the height of the icon. The height is additive and is including
// both the XOR and AND masks. Therefore the height is twice as big and
// we can just divide by 2.
mBIH.height /= 2;
nsresult rv = mImage->Init(mBIH.width, mBIH.height, mObserver);
NS_ENSURE_SUCCESS(rv, rv);
rv = mObserver->OnStartContainer(nsnull, nsnull, mImage);
NS_ENSURE_SUCCESS(rv, rv);
mCurLine = mBIH.height;
mRow = new PRUint8[(mBIH.width * mBIH.bpp)/8 + 4];
// +4 because the line is padded to a 4 bit boundary, but I don't want
// to make exact calculations here, that's unnecessary.
// Also, it compensates rounding error.
if (!mRow)
return NS_ERROR_OUT_OF_MEMORY;
rv = mFrame->Init(0, 0, mBIH.width, mBIH.height, GFXFORMATALPHA);
NS_ENSURE_SUCCESS(rv, rv);
rv = mImage->AppendFrame(mFrame);
NS_ENSURE_SUCCESS(rv, rv);
mObserver->OnStartFrame(nsnull, nsnull, mFrame);
NS_ENSURE_SUCCESS(rv, rv);
}
if (mColors && (mPos >= mImageOffset + BITMAPINFOSIZE) &&
(mPos < (mImageOffset + BITMAPINFOSIZE + mNumColors * 4))) {
// We will receive (mNumColors * 4) bytes of color data
PRUint32 colorBytes = mPos - (mImageOffset + 40); // Number of bytes already received
PRUint8 colorNum = colorBytes / 4; // Color which is currently received
PRUint8 at = colorBytes % 4;
while (aCount && (mPos < (mImageOffset + BITMAPINFOSIZE + mNumColors * 4))) {
switch (at) {
case 0:
mColors[colorNum].blue = *aBuffer;
break;
case 1:
mColors[colorNum].green = *aBuffer;
break;
case 2:
mColors[colorNum].red = *aBuffer;
break;
case 3:
colorNum++; // This is a padding byte
break;
}
mPos++; aBuffer++; aCount--;
at = (at + 1) % 4;
}
}
if (!mDecodingAndMask && (mPos >= (mImageOffset + BITMAPINFOSIZE + mNumColors*4))) {
// Increment mPos to avoid re-processing the info header and/or color table.
mPos++;
PRUint32 rowSize = (mBIH.bpp * mBIH.width + 7) / 8; // +7 to round up
if (rowSize % 4)
rowSize += (4 - (rowSize % 4)); // Pad to DWORD Boundary
PRUint32 toCopy;
do {
toCopy = rowSize - mRowBytes;
if (toCopy) {
if (toCopy > aCount)
toCopy = aCount;
nsCRT::memcpy(mRow + mRowBytes, aBuffer, toCopy);
aCount -= toCopy;
aBuffer += toCopy;
mRowBytes += toCopy;
}
if ((rowSize - mRowBytes) == 0) {
PRUint8* decoded;
#ifdef XP_MAC
decoded = new PRUint8[mBIH.width * 4];
#else
decoded = new PRUint8[mBIH.width * 3];
#endif
if (!decoded)
return NS_ERROR_OUT_OF_MEMORY;
PRUint8* p = mRow;
PRUint8* d = decoded;
PRUint32 lpos = 0;
switch (mBIH.bpp) {
case 1:
while (lpos < mBIH.width) {
PRInt8 bit;
PRUint8 idx;
for (bit = 7; bit >= 0; bit--) {
if (lpos >= mBIH.width)
break;
idx = (*p >> bit) & 1;
SetPixel(d, idx);
++lpos;
}
++p;
}
break;
case 4:
while (lpos < mBIH.width) {
Set4BitPixel(d, *p, lpos);
++p;
}
break;
case 8:
while (lpos < mBIH.width) {
SetPixel(d, *p);
++lpos;
++p;
}
break;
case 16:
while (lpos < mBIH.width) {
SetPixel(d,
(p[1] & 124) << 1,
((p[1] & 3) << 6) | ((p[0] & 224) >> 2),
(p[0] & 31) << 3);
++lpos;
p+=2;
}
break;
case 32:
case 24:
while (lpos < mBIH.width) {
SetPixel(d, p[2], p[1], p[0]);
p += 2;
++lpos;
if (mBIH.bpp == 32)
p++; // Padding byte
++p;
}
break;
default:
// This is probably the wrong place to check this...
return NS_ERROR_FAILURE;
}
nsresult rv = SetData(decoded);
delete[] decoded;
NS_ENSURE_SUCCESS(rv, rv);
if (mCurLine == 1)
mDecodingAndMask = PR_TRUE;
mCurLine--; mRowBytes = 0;
}
} while (!mDecodingAndMask && aCount > 0);
}
if (mDecodingAndMask) {
mRowBytes = 0;
mBIH.bpp = 1;
mCurLine = mBIH.height;
delete []mRow;
mRow = new PRUint8[(mBIH.width * mBIH.bpp)/8 + 4];
PRUint32 rowSize = (mBIH.bpp * mBIH.width + 7) / 8; // +7 to round up
if (rowSize % 4)
rowSize += (4 - (rowSize % 4)); // Pad to DWORD Boundary
PRUint32 toCopy;
do {
toCopy = rowSize - mRowBytes;
if (toCopy) {
if (toCopy > aCount)
toCopy = aCount;
nsCRT::memcpy(mRow + mRowBytes, aBuffer, toCopy);
aCount -= toCopy;
aBuffer += toCopy;
mRowBytes += toCopy;
}
if ((rowSize - mRowBytes) == 0) {
PRUint8* decoded;
decoded = new PRUint8[mBIH.width/4];
if (!decoded)
return NS_ERROR_OUT_OF_MEMORY;
PRUint8* p = mRow;
PRUint32 lpos = 0;
while (lpos < mBIH.width/4) {
PRUint8 idx = *p;
idx ^= 255; // We complement the value, since our method of storing transparency is opposite
// what Win32 uses in its masks.
decoded[lpos] = idx;
lpos++;
p++;
}
nsresult rv = SetAlphaData(decoded);
delete[] decoded;
NS_ENSURE_SUCCESS(rv, rv);
if (mCurLine == 1) {
mObserver->OnStopFrame(nsnull, nsnull, mFrame);
return NS_OK;
}
mCurLine--; mRowBytes = 0;
}
} while (aCount > 0);
}
return NS_OK;
}
void
nsICODecoder::ProcessDirEntry()
{
nsCRT::memset(&mDirEntry, 0, sizeof(mDirEntry));
DOCOPY(&mDirEntry.mWidth, mDirEntryArray);
DOCOPY(&mDirEntry.mHeight, mDirEntryArray+1);
DOCOPY(&mDirEntry.mColorCount, mDirEntryArray+2);
DOCOPY(&mDirEntry.mReserved, mDirEntryArray+3);
DOCOPY(&mDirEntry.mPlanes, mDirEntryArray+4);
mDirEntry.mPlanes = LITTLE_TO_NATIVE16(mDirEntry.mPlanes);
DOCOPY(&mDirEntry.mBitCount, mDirEntryArray+6);
mDirEntry.mBitCount = LITTLE_TO_NATIVE16(mDirEntry.mBitCount);
DOCOPY(&mDirEntry.mBytesInRes, mDirEntryArray+8);
mDirEntry.mBytesInRes = LITTLE_TO_NATIVE32(mDirEntry.mBytesInRes);
DOCOPY(&mDirEntry.mImageOffset, mDirEntryArray+12);
mDirEntry.mImageOffset = LITTLE_TO_NATIVE32(mDirEntry.mImageOffset);
}
void nsICODecoder::ProcessInfoHeader() {
nsCRT::memset(&mBIH, 0, sizeof(mBIH));
// Ignoring the size; it should always be 40 for icons, anyway
DOCOPY(&mBIH.width, mBIHraw + 4);
DOCOPY(&mBIH.height, mBIHraw + 8);
DOCOPY(&mBIH.planes, mBIHraw + 12);
DOCOPY(&mBIH.bpp, mBIHraw + 14);
DOCOPY(&mBIH.compression, mBIHraw + 16);
DOCOPY(&mBIH.image_size, mBIHraw + 20);
DOCOPY(&mBIH.xppm, mBIHraw + 24);
DOCOPY(&mBIH.yppm, mBIHraw + 28);
DOCOPY(&mBIH.colors, mBIHraw + 32);
DOCOPY(&mBIH.important_colors, mBIHraw + 36);
// Convert endianness
mBIH.width = LITTLE_TO_NATIVE32(mBIH.width);
mBIH.height = LITTLE_TO_NATIVE32(mBIH.height);
mBIH.planes = LITTLE_TO_NATIVE16(mBIH.planes);
mBIH.bpp = LITTLE_TO_NATIVE16(mBIH.bpp);
mBIH.compression = LITTLE_TO_NATIVE32(mBIH.compression);
mBIH.image_size = LITTLE_TO_NATIVE32(mBIH.image_size);
mBIH.xppm = LITTLE_TO_NATIVE32(mBIH.xppm);
mBIH.yppm = LITTLE_TO_NATIVE32(mBIH.yppm);
mBIH.colors = LITTLE_TO_NATIVE32(mBIH.colors);
mBIH.important_colors = LITTLE_TO_NATIVE32(mBIH.important_colors);
}
// ----------------------------------------
// Actual Data Processing
// ----------------------------------------
inline nsresult nsICODecoder::SetPixel(PRUint8*& aDecoded, PRUint8 idx) {
PRUint8 red, green, blue;
red = mColors[idx].red;
green = mColors[idx].green;
blue = mColors[idx].blue;
return SetPixel(aDecoded, red, green, blue);
}
inline nsresult nsICODecoder::SetPixel(PRUint8*& aDecoded, PRUint8 aRed, PRUint8 aGreen, PRUint8 aBlue) {
#ifdef XP_MAC
*aDecoded++ = 0; // Mac needs this padding byte
#endif
#ifdef USE_RGBA1
*aDecoded++ = aRed;
*aDecoded++ = aGreen;
*aDecoded++ = aBlue;
#else
*aDecoded++ = aBlue;
*aDecoded++ = aGreen;
*aDecoded++ = aRed;
#endif
return NS_OK;
}
inline nsresult nsICODecoder::Set4BitPixel(PRUint8*& aDecoded, PRUint8 aData, PRUint32& aPos)
{
PRUint8 idx = aData >> 4;
nsresult rv = SetPixel(aDecoded, idx);
if ((++aPos >= mBIH.width) || NS_FAILED(rv))
return rv;
idx = aData & 0xF;
rv = SetPixel(aDecoded, idx);
++aPos;
return rv;
}
inline nsresult nsICODecoder::SetData(PRUint8* aData)
{
NS_ENSURE_ARG_POINTER(aData);
PRUint32 bpr;
nsresult rv;
rv = mFrame->GetImageBytesPerRow(&bpr);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 offset = (mCurLine - 1) * bpr;
// XXX Possibly aData doesn't contain bpr bytes of data;
// will SetImageData access that data?
rv = mFrame->SetImageData(aData, bpr, offset);
NS_ENSURE_SUCCESS(rv, rv);
nsRect r(0, mCurLine, mBIH.width, 1);
rv = mObserver->OnDataAvailable(nsnull, nsnull, mFrame, &r);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
inline nsresult nsICODecoder::SetAlphaData(PRUint8* aData)
{
NS_ENSURE_ARG_POINTER(aData);
PRUint32 bpr;
nsresult rv;
mFrame->GetAlphaBytesPerRow(&bpr);
PRUint32 offset = (mCurLine - 1) * bpr;
// XXX Possibly aData doesn't contain bpr bytes of data;
// will SetImageData access that data?
rv = mFrame->SetAlphaData(aData, bpr, offset);
NS_ENSURE_SUCCESS(rv, rv);
nsRect r(0, mCurLine, mBIH.width, 1);
rv = mObserver->OnDataAvailable(nsnull, nsnull, mFrame, &r);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}

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

@ -0,0 +1,121 @@
/* vim:set tw=80 expandtab softtabstop=4 ts=4 sw=4: */
/* ----- BEGIN LICENSE BLOCK -----
* Version: MPL 1.1/LGPL 2.1/GPL 2.0
*
* 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 the Mozilla ICO Decoder.
*
* The Initial Developer of the Original Code is Netscape.
* Portions created by Netscape are
* Copyright (C) 2001 Netscape. All
* Rights Reserved.
*
* Contributor(s):
* David Hyatt <hyatt@netscape.com> (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 LGPL or the GPL. 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 _nsICODecoder_h
#define _nsICODecoder_h
#include "nsCOMPtr.h"
#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_PC) || defined(XP_BEOS) || defined(MOZ_WIDGET_PHOTON)
#define GFXFORMATALPHA gfxIFormats::BGR_A1
#else
#define USE_RGBA1
#define GFXFORMATALPHA gfxIFormats::RGB_A1
#endif
struct IconDirEntry
{
PRUint8 mWidth;
PRUint8 mHeight;
PRUint8 mColorCount;
PRUint8 mReserved;
PRUint16 mPlanes;
PRUint16 mBitCount;
PRUint32 mBytesInRes;
PRUint32 mImageOffset;
};
class nsICODecoder : public imgIDecoder
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGIDECODER
nsICODecoder();
virtual ~nsICODecoder();
private:
// Private helper methods
nsresult ProcessData(const char* aBuffer, PRUint32 aCount);
void ProcessDirEntry();
void ProcessInfoHeader();
nsresult SetPixel(PRUint8*& aDecoded, PRUint8 aIdx);
nsresult SetPixel(PRUint8*& aDecoded, PRUint8 aRed, PRUint8 aGreen, PRUint8 aBlue);
nsresult Set4BitPixel(PRUint8*& aDecoded, PRUint8 aData, PRUint32& aPos);
nsresult SetData(PRUint8* aData);
nsresult SetAlphaData(PRUint8* aData);
private:
nsCOMPtr<imgIDecoderObserver> mObserver;
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<gfxIImageFrame> mFrame;
PRBool mDecodingAndMask;
PRUint32 mPos;
PRUint16 mNumIcons;
PRUint16 mCurrIcon;
PRUint32 mImageOffset;
char mDirEntryArray[16];
IconDirEntry mDirEntry;
char mBIHraw[40];
BMPINFOHEADER mBIH;
PRUint32 mNumColors;
colorTable* mColors;
PRUint8* mRow; // Holds one raw line of the image
PRUint32 mRowBytes; // How many bytes of the row were already received
PRUint32 mCurLine;
};
#endif

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

@ -21,6 +21,6 @@
DEPTH=..\..\.. DEPTH=..\..\..
DIRS = ppm gif png jpeg icon\win icon DIRS = ppm gif png jpeg icon\win icon bmp
!include $(DEPTH)\config\rules.mak !include $(DEPTH)\config\rules.mak

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

@ -45,6 +45,14 @@
#include "nsString.h" #include "nsString.h"
#include "nsXPIDLString.h" #include "nsXPIDLString.h"
#include "prcpucfg.h" // To get IS_LITTLE_ENDIAN / IS_BIG_ENDIAN
#if defined WORDS_BIGENDIAN || defined IS_BIG_ENDIAN
#define LITTLE_TO_NATIVE16(x) ((((x) & 0xFF) << 8) | ((x) >> 8))
#else
#define LITTLE_TO_NATIVE16(x) x
#endif
#if defined(PR_LOGGING) #if defined(PR_LOGGING)
PRLogModuleInfo *gImgLog = PR_NewLogModule("imgRequest"); PRLogModuleInfo *gImgLog = PR_NewLogModule("imgRequest");
#endif #endif
@ -795,5 +803,96 @@ imgRequest::SniffMimeType(const char *buf, PRUint32 len)
return; return;
} }
if (len >= 2 && !nsCRT::strncmp(buf, "BM", 2)) {
mContentType = nsCRT::strndup("image/bmp", 9);
return;
}
// ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
// ALWAYS KEEP THIS SNIFF AT THE END OF THE FILE!
if (len >= 4 &&
((PRUint16*)buf)[0]==0 &&
(LITTLE_TO_NATIVE16(((PRUint16*)buf)[1]))==1) {
mContentType = nsCRT::strndup("image/x-icon", 12);
return;
}
if (len >= 2 && !nsCRT::strncmp(buf, "BM", 2)) {
mContentType = nsCRT::strndup("image/bmp", 9);
return;
}
// ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
if (len >= 4 && !nsCRT::memcmp(buf, "\000\000\001\000", 4)) {
mContentType = nsCRT::strndup("image/x-icon", 12);
return;
}
if (len >= 2 && !nsCRT::strncmp(buf, "BM", 2)) {
mContentType = nsCRT::strndup("image/bmp", 9);
return;
}
// ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
if (len >= 4 && !nsCRT::memcmp(buf, "\000\000\001\000", 4)) {
mContentType = nsCRT::strndup("image/x-icon", 12);
return;
}
if (len >= 2 && !nsCRT::strncmp(buf, "BM", 2)) {
mContentType = nsCRT::strndup("image/bmp", 9);
return;
}
// ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
if (len >= 4 && !nsCRT::memcmp(buf, "\000\000\001\000", 4)) {
mContentType = nsCRT::strndup("image/x-icon", 12);
return;
}
if (len >= 2 && !nsCRT::strncmp(buf, "BM", 2)) {
mContentType = nsCRT::strndup("image/bmp", 9);
return;
}
// ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
if (len >= 4 && !nsCRT::memcmp(buf, "\000\000\001\000", 4)) {
mContentType = nsCRT::strndup("image/x-icon", 12);
return;
}
if (len >= 2 && !nsCRT::strncmp(buf, "BM", 2)) {
mContentType = nsCRT::strndup("image/bmp", 9);
return;
}
// ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
if (len >= 4 && !nsCRT::memcmp(buf, "\000\000\001\000", 4)) {
mContentType = nsCRT::strndup("image/x-icon", 12);
return;
}
if (len >= 2 && !nsCRT::strncmp(buf, "BM", 2)) {
mContentType = nsCRT::strndup("image/bmp", 9);
return;
}
// ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
if (len >= 4 && !nsCRT::memcmp(buf, "\000\000\001\000", 4)) {
mContentType = nsCRT::strndup("image/x-icon", 12);
return;
}
if (len >= 2 && !nsCRT::strncmp(buf, "BM", 2)) {
mContentType = nsCRT::strndup("image/bmp", 9);
return;
}
// ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
if (len >= 4 && !nsCRT::memcmp(buf, "\000\000\001\000", 4)) {
mContentType = nsCRT::strndup("image/x-icon", 12);
return;
}
/* none of the above? I give up */ /* none of the above? I give up */
} }

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

@ -101,6 +101,8 @@
#define IMAGE_XBM3 "image/xbm" #define IMAGE_XBM3 "image/xbm"
#define IMAGE_ART "image/x-jg" #define IMAGE_ART "image/x-jg"
#define IMAGE_TIFF "image/tiff" #define IMAGE_TIFF "image/tiff"
#define IMAGE_BMP "image/bmp"
#define IMAGE_ICO "image/x-icon"
#define MESSAGE_EXTERNAL_BODY "message/external-body" #define MESSAGE_EXTERNAL_BODY "message/external-body"
#define MESSAGE_NEWS "message/news" #define MESSAGE_NEWS "message/news"

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

@ -492,6 +492,16 @@ nsXMLMIMEDataSource::InitFromHack() {
rv = AppendExtension(IMAGE_JPG, "jpg"); rv = AppendExtension(IMAGE_JPG, "jpg");
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
rv = AddMapping(IMAGE_BMP, "bmp", "BMP Image", nsnull);
if (NS_FAILED(rv)) return rv;
rv = AppendExtension(IMAGE_BMP, "bmp");
if (NS_FAILED(rv)) return rv;
rv = AddMapping(IMAGE_ICO, "ico", "ICO Image", nsnull);
if (NS_FAILED(rv)) return rv;
rv = AppendExtension(IMAGE_ICO, "ico");
if (NS_FAILED(rv)) return rv;
rv = AddMapping(IMAGE_PNG, "png", "PNG Image", nsnull); rv = AddMapping(IMAGE_PNG, "png", "PNG Image", nsnull);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;

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

@ -47,11 +47,18 @@
#include "nsXPIDLString.h" #include "nsXPIDLString.h"
#include "nsIPref.h" #include "nsIPref.h"
#include "prcpucfg.h" // To get IS_LITTLE_ENDIAN / IS_BIG_ENDIAN
#define MAX_BUFFER_SIZE 1024 #define MAX_BUFFER_SIZE 1024
static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID); static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
static NS_DEFINE_IID(kPrefServiceCID, NS_PREF_CID); static NS_DEFINE_IID(kPrefServiceCID, NS_PREF_CID);
#if defined WORDS_BIGENDIAN || defined IS_BIG_ENDIAN
#define LITTLE_TO_NATIVE16(x) ((((x) & 0xFF) << 8) | ((x) >> 8))
#else
#define LITTLE_TO_NATIVE16(x) x
#endif
nsUnknownDecoder::nsUnknownDecoder() nsUnknownDecoder::nsUnknownDecoder()
{ {
@ -401,6 +408,97 @@ void nsUnknownDecoder::SniffForImageMimeType(const char *buf, PRUint32 len)
return; return;
} }
if (len >= 2 && !nsCRT::strncmp(buf, "BM", 2)) {
mContentType = NS_LITERAL_CSTRING("image/bmp");
return;
}
// ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
// ALWAYS KEEP THIS SNIFF AT THE END OF THE FILE!
if (len >= 4 &&
((PRUint16*)buf)[0]==0 &&
(LITTLE_TO_NATIVE16(((PRUint16*)buf)[1]))==1) {
mContentType = NS_LITERAL_CSTRING("image/x-icon");
return;
}
if (len >= 2 && !nsCRT::strncmp(buf, "BM", 2)) {
mContentType = NS_LITERAL_CSTRING("image/bmp");
return;
}
// ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
if (len >= 4 && !nsCRT::memcmp(buf, "\000\000\001\000", 4)) {
mContentType = NS_LITERAL_CSTRING("image/x-icon");
return;
}
if (len >= 2 && !nsCRT::strncmp(buf, "BM", 2)) {
mContentType = NS_LITERAL_CSTRING("image/bmp");
return;
}
// ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
if (len >= 4 && !nsCRT::memcmp(buf, "\000\000\001\000", 4)) {
mContentType = NS_LITERAL_CSTRING("image/x-icon");
return;
}
if (len >= 2 && !nsCRT::strncmp(buf, "BM", 2)) {
mContentType = NS_LITERAL_CSTRING("image/bmp");
return;
}
// ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
if (len >= 4 && !nsCRT::memcmp(buf, "\000\000\001\000", 4)) {
mContentType = NS_LITERAL_CSTRING("image/x-icon");
return;
}
if (len >= 2 && !nsCRT::strncmp(buf, "BM", 2)) {
mContentType = NS_LITERAL_CSTRING("image/bmp");
return;
}
// ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
if (len >= 4 && !nsCRT::memcmp(buf, "\000\000\001\000", 4)) {
mContentType = NS_LITERAL_CSTRING("image/x-icon");
return;
}
if (len >= 2 && !nsCRT::strncmp(buf, "BM", 2)) {
mContentType = NS_LITERAL_CSTRING("image/bmp");
return;
}
// ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
if (len >= 4 && !nsCRT::memcmp(buf, "\000\000\001\000", 4)) {
mContentType = NS_LITERAL_CSTRING("image/x-icon");
return;
}
if (len >= 2 && !nsCRT::strncmp(buf, "BM", 2)) {
mContentType = NS_LITERAL_CSTRING("image/bmp");
return;
}
// ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
if (len >= 4 && !nsCRT::memcmp(buf, "\000\000\001\000", 4)) {
mContentType = NS_LITERAL_CSTRING("image/x-icon");
return;
}
if (len >= 2 && !nsCRT::strncmp(buf, "BM", 2)) {
mContentType = NS_LITERAL_CSTRING("image/bmp");
return;
}
// ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
if (len >= 4 && !nsCRT::memcmp(buf, "\000\000\001\000", 4)) {
mContentType = NS_LITERAL_CSTRING("image/x-icon");
return;
}
/* none of the above? I give up */ /* none of the above? I give up */
} }

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

@ -101,6 +101,8 @@ static nsDefaultMimeTypeEntry defaultMimeEntries [] =
{ IMAGE_GIF, "gif", "GIF Image", 0,0 }, { IMAGE_GIF, "gif", "GIF Image", 0,0 },
{ IMAGE_JPG, "jpeg,jpg", "JPEG Image", 0, 0 }, { IMAGE_JPG, "jpeg,jpg", "JPEG Image", 0, 0 },
{ IMAGE_PNG, "png", "PNG Image", 0, 0 }, { IMAGE_PNG, "png", "PNG Image", 0, 0 },
{ IMAGE_BMP, "bmp", "BMP Image", 0, 0 },
{ IMAGE_ICO, "ico", "ICO Image", 0, 0 },
{ APPLICATION_XPINSTALL, "xpi", "XPInstall Install", 'xpi*','MOSS' }, { APPLICATION_XPINSTALL, "xpi", "XPInstall Install", 'xpi*','MOSS' },
}; };

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

@ -1069,6 +1069,86 @@ static nsModuleComponentInfo components[] = {
NS_CONTENT_HANDLER_CONTRACTID_PREFIX"image/png", NS_CONTENT_HANDLER_CONTRACTID_PREFIX"image/png",
nsBrowserContentHandlerConstructor nsBrowserContentHandlerConstructor
}, },
{ "Browser Content Handler",
NS_BROWSERCONTENTHANDLER_CID,
NS_CONTENT_HANDLER_CONTRACTID_PREFIX"image/bmp",
nsBrowserContentHandlerConstructor
},
{ "Browser Content Handler",
NS_BROWSERCONTENTHANDLER_CID,
NS_CONTENT_HANDLER_CONTRACTID_PREFIX"image/x-icon",
nsBrowserContentHandlerConstructor
},
{ "Browser Content Handler",
NS_BROWSERCONTENTHANDLER_CID,
NS_CONTENT_HANDLER_CONTRACTID_PREFIX"image/bmp",
nsBrowserContentHandlerConstructor
},
{ "Browser Content Handler",
NS_BROWSERCONTENTHANDLER_CID,
NS_CONTENT_HANDLER_CONTRACTID_PREFIX"image/x-icon",
nsBrowserContentHandlerConstructor
},
{ "Browser Content Handler",
NS_BROWSERCONTENTHANDLER_CID,
NS_CONTENT_HANDLER_CONTRACTID_PREFIX"image/bmp",
nsBrowserContentHandlerConstructor
},
{ "Browser Content Handler",
NS_BROWSERCONTENTHANDLER_CID,
NS_CONTENT_HANDLER_CONTRACTID_PREFIX"image/x-icon",
nsBrowserContentHandlerConstructor
},
{ "Browser Content Handler",
NS_BROWSERCONTENTHANDLER_CID,
NS_CONTENT_HANDLER_CONTRACTID_PREFIX"image/bmp",
nsBrowserContentHandlerConstructor
},
{ "Browser Content Handler",
NS_BROWSERCONTENTHANDLER_CID,
NS_CONTENT_HANDLER_CONTRACTID_PREFIX"image/x-icon",
nsBrowserContentHandlerConstructor
},
{ "Browser Content Handler",
NS_BROWSERCONTENTHANDLER_CID,
NS_CONTENT_HANDLER_CONTRACTID_PREFIX"image/bmp",
nsBrowserContentHandlerConstructor
},
{ "Browser Content Handler",
NS_BROWSERCONTENTHANDLER_CID,
NS_CONTENT_HANDLER_CONTRACTID_PREFIX"image/x-icon",
nsBrowserContentHandlerConstructor
},
{ "Browser Content Handler",
NS_BROWSERCONTENTHANDLER_CID,
NS_CONTENT_HANDLER_CONTRACTID_PREFIX"image/bmp",
nsBrowserContentHandlerConstructor
},
{ "Browser Content Handler",
NS_BROWSERCONTENTHANDLER_CID,
NS_CONTENT_HANDLER_CONTRACTID_PREFIX"image/x-icon",
nsBrowserContentHandlerConstructor
},
{ "Browser Content Handler",
NS_BROWSERCONTENTHANDLER_CID,
NS_CONTENT_HANDLER_CONTRACTID_PREFIX"image/bmp",
nsBrowserContentHandlerConstructor
},
{ "Browser Content Handler",
NS_BROWSERCONTENTHANDLER_CID,
NS_CONTENT_HANDLER_CONTRACTID_PREFIX"image/x-icon",
nsBrowserContentHandlerConstructor
},
{ "Browser Content Handler",
NS_BROWSERCONTENTHANDLER_CID,
NS_CONTENT_HANDLER_CONTRACTID_PREFIX"image/bmp",
nsBrowserContentHandlerConstructor
},
{ "Browser Content Handler",
NS_BROWSERCONTENTHANDLER_CID,
NS_CONTENT_HANDLER_CONTRACTID_PREFIX"image/x-icon",
nsBrowserContentHandlerConstructor
},
{ "Browser Content Handler", { "Browser Content Handler",
NS_BROWSERCONTENTHANDLER_CID, NS_BROWSERCONTENTHANDLER_CID,
NS_CONTENT_HANDLER_CONTRACTID_PREFIX"application/http-index-format", NS_CONTENT_HANDLER_CONTRACTID_PREFIX"application/http-index-format",

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

@ -117,6 +117,7 @@ bin/components/libimggif.so
bin/components/libimgjpeg.so bin/components/libimgjpeg.so
bin/components/libimgpng.so bin/components/libimgpng.so
bin/components/libimgppm.so bin/components/libimgppm.so
bin/components/libimgbmp.so
bin/components/libjsurl.so bin/components/libjsurl.so
bin/components/liblwbrk.so bin/components/liblwbrk.so
bin/components/libmork.so bin/components/libmork.so

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

@ -128,6 +128,7 @@ bin\components\gkplugin.dll
bin\components\gkview.dll bin\components\gkview.dll
bin\components\imggif.dll bin\components\imggif.dll
bin\components\imgjpeg.dll bin\components\imgjpeg.dll
bin\components\imgbmp.dll
bin\components\imglib2.dll bin\components\imglib2.dll
bin\components\imglib2.xpt bin\components\imglib2.xpt
bin\components\imgpng.dll bin\components\imgpng.dll