зеркало из https://github.com/mozilla/pjs.git
fixing crasher bug 74270. r=brendan, blizzard, sr=tor@cs.brown.edu. a=blizzard
fixing crasher bug 76032. r=tor@cs.brown.edu sr=blizzard. a=brendan fixing unix image scaling bug 74313. r=me (on syd's code) r=syd (on the rest of the code), sr=tor@cs.brown.edu. a=asa
This commit is contained in:
Родитель
78d6fb584b
Коммит
8be26d786f
|
@ -33,11 +33,11 @@ REQUIRES = xpcom string img widget view util dom pref js uconv necko unicharutil
|
|||
|
||||
CSRCS = nsPrintdGTK.c
|
||||
|
||||
ifndef HAVE_GDK_PIXBUF
|
||||
ifdef HAVE_XIE
|
||||
CSRCS += XIE.c
|
||||
endif
|
||||
endif
|
||||
|
||||
CSRCS += scale.c
|
||||
|
||||
CPPSRCS = \
|
||||
nsDeviceContextGTK.cpp \
|
||||
|
@ -77,12 +77,11 @@ DEFINES += -DHAVE_GDK_PIXBUF
|
|||
GFX_PIXBUF_LIBS += $(MOZ_GDK_PIXBUF_LIBS)
|
||||
CXXFLAGS += $(MOZ_GDK_PIXBUF_CFLAGS)
|
||||
CFLAGS += $(MOZ_GDK_PIXBUF_CFLAGS)
|
||||
else
|
||||
endif
|
||||
ifdef HAVE_XIE
|
||||
DEFINES += -DHAVE_XIE
|
||||
GFX_XIE_LIBS += $(MOZ_XIE_LIBS)
|
||||
endif
|
||||
endif
|
||||
|
||||
EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS) \
|
||||
-lgkgfx \
|
||||
|
|
|
@ -59,16 +59,14 @@ DoFlo(Display *display,
|
|||
float coeffs[6];
|
||||
XieConstant constant;
|
||||
XiePhototag idx = 0, src;
|
||||
/* static PRBool firsttime = PR_TRUE;
|
||||
static XiePhotomap pmap;
|
||||
*/
|
||||
|
||||
/* create the pretty flo graph */
|
||||
|
||||
|
||||
|
||||
/* import */
|
||||
XieFloImportDrawable(&photoElement[idx], aSrc, aSX, aSY, aSWidth, aSHeight, 0, PR_FALSE);
|
||||
XieFloImportDrawable(&photoElement[idx], aSrc,
|
||||
aSX, aSY, aSWidth, aSHeight,
|
||||
0, PR_FALSE);
|
||||
++idx;
|
||||
src = idx;
|
||||
|
||||
|
@ -155,7 +153,7 @@ DrawScaledImageXIE(Display *display,
|
|||
|
||||
photoElement = XieAllocatePhotofloGraph(3);
|
||||
|
||||
/* we want to destroy this at shutdown
|
||||
/* XXX we want to destroy this at shutdown
|
||||
XieDestroyPhotospace(display, photospace);
|
||||
*/
|
||||
}
|
||||
|
@ -170,9 +168,11 @@ DrawScaledImageXIE(Display *display,
|
|||
alphaMask = gdk_pixmap_new(aSrcMask, aDWidth, aDHeight, 1);
|
||||
destMask = GDK_WINDOW_XWINDOW(alphaMask);
|
||||
gc = gdk_gc_new(alphaMask);
|
||||
DoFlo(display, destMask, GDK_GC_XGC(gc), GDK_WINDOW_XWINDOW(aSrcMask), aSrcWidth, aSrcHeight,
|
||||
aSX, aSY, aSWidth, aSHeight,
|
||||
aDX, aDY, aDWidth, aDHeight);
|
||||
/* run the flo on the alpha mask to get a scaled alpha mask */
|
||||
DoFlo(display, destMask, GDK_GC_XGC(gc), GDK_WINDOW_XWINDOW(aSrcMask),
|
||||
aSrcWidth, aSrcHeight,
|
||||
aSX, aSY, aSWidth, aSHeight,
|
||||
aDX, aDY, aDWidth, aDHeight);
|
||||
gdk_gc_unref(gc);
|
||||
|
||||
gc = gdk_gc_new(aDest);
|
||||
|
@ -187,9 +187,11 @@ DrawScaledImageXIE(Display *display,
|
|||
gdk_gc_ref(gc);
|
||||
}
|
||||
|
||||
DoFlo(display, exportDrawable, GDK_GC_XGC(gc), importDrawable, aSrcWidth, aSrcHeight,
|
||||
aSX, aSY, aSWidth, aSHeight,
|
||||
aDX, aDY, aDWidth, aDHeight);
|
||||
/* run the flo on the image to get a the scaled image */
|
||||
DoFlo(display, exportDrawable, GDK_GC_XGC(gc), importDrawable,
|
||||
aSrcWidth, aSrcHeight,
|
||||
aSX, aSY, aSWidth, aSHeight,
|
||||
aDX, aDY, aDWidth, aDHeight);
|
||||
|
||||
if (alphaMask)
|
||||
gdk_pixmap_unref(alphaMask);
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
* Stuart Parmenter <pavlov@netscape.com>
|
||||
*/
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
#ifdef HAVE_XIE
|
||||
PRBool
|
||||
DrawScaledImageXIE(Display *display,
|
||||
GdkDrawable *aDest,
|
||||
GdkGC *aGC,
|
||||
GdkDrawable *aSrc,
|
||||
GdkDrawable *aSrcMask,
|
||||
PRInt32 aSrcWidth,
|
||||
PRInt32 aSrcHeight,
|
||||
PRInt32 aSX,
|
||||
PRInt32 aSY,
|
||||
PRInt32 aSWidth,
|
||||
PRInt32 aSHeight,
|
||||
PRInt32 aDX,
|
||||
PRInt32 aDY,
|
||||
PRInt32 aDWidth,
|
||||
PRInt32 aDHeight);
|
||||
#endif
|
||||
|
||||
PR_END_EXTERN_C
|
|
@ -20,16 +20,17 @@
|
|||
* Contributor(s):
|
||||
* Stuart Parmenter <pavlov@netscape.com>
|
||||
* Tim Rowley <tor@cs.brown.edu> -- 8bit alpha compositing
|
||||
* Syd Logan <syd@netscape.com> -- simple Nearest Neighbor scaling
|
||||
*/
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
#ifdef HAVE_GDK_PIXBUF
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#else
|
||||
#include "drawers.h"
|
||||
#endif
|
||||
|
||||
#include "drawers.h"
|
||||
|
||||
#include "nsImageGTK.h"
|
||||
#include "nsRenderingContextGTK.h"
|
||||
|
||||
|
@ -349,9 +350,12 @@ static PRTime gConvertTime, gAlphaTime, gCopyStart, gCopyEnd, gStartTime, gPixma
|
|||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImageGTK::DrawScaled(nsIRenderingContext &aContext, nsDrawingSurface aSurface,
|
||||
PRInt32 aSX, PRInt32 aSY, PRInt32 aSWidth, PRInt32 aSHeight,
|
||||
PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight)
|
||||
nsImageGTK::DrawScaled(nsIRenderingContext &aContext,
|
||||
nsDrawingSurface aSurface,
|
||||
PRInt32 aSX, PRInt32 aSY,
|
||||
PRInt32 aSWidth, PRInt32 aSHeight,
|
||||
PRInt32 aDX, PRInt32 aDY,
|
||||
PRInt32 aDWidth, PRInt32 aDHeight)
|
||||
{
|
||||
|
||||
PRInt32 origSHeight = aSHeight, origDHeight = aDHeight;
|
||||
|
@ -366,7 +370,7 @@ nsImageGTK::DrawScaled(nsIRenderingContext &aContext, nsDrawingSurface aSurface,
|
|||
// limit the size of the blit to the amount of the image read in
|
||||
if (aSX + aSWidth > mDecodedX2) {
|
||||
aDWidth -= ((aSX + aSWidth - mDecodedX2)*origDWidth)/origSWidth;
|
||||
aSWidth = mDecodedX2 - mDecodedX1;
|
||||
aSWidth -= (aSX + aSWidth) - mDecodedX2;
|
||||
}
|
||||
if (aSX < mDecodedX1) {
|
||||
aDX += ((mDecodedX1 - aSX)*origDWidth)/origSWidth;
|
||||
|
@ -375,7 +379,7 @@ nsImageGTK::DrawScaled(nsIRenderingContext &aContext, nsDrawingSurface aSurface,
|
|||
|
||||
if (aSY + aSHeight > mDecodedY2) {
|
||||
aDHeight -= ((aSY + aSHeight - mDecodedY2)*origDHeight)/origSHeight;
|
||||
aSHeight = mDecodedY2 - mDecodedY1;
|
||||
aSHeight -= (aSY + aSHeight) - mDecodedY2;
|
||||
}
|
||||
if (aSY < mDecodedY1) {
|
||||
aDY += ((mDecodedY1 - aSY)*origDHeight)/origSHeight;
|
||||
|
@ -391,66 +395,15 @@ nsImageGTK::DrawScaled(nsIRenderingContext &aContext, nsDrawingSurface aSurface,
|
|||
CreateAlphaBitmap(mWidth, mHeight);
|
||||
}
|
||||
|
||||
#ifdef HAVE_GDK_PIXBUF
|
||||
|
||||
GdkGC *copyGC;
|
||||
if (mAlphaPixmap) {
|
||||
NS_WARNING("alpha bitmask not scaled!\n");
|
||||
if (mGC) {
|
||||
copyGC = gdk_gc_ref(mGC);
|
||||
} else {
|
||||
mGC = gdk_gc_new(drawing->GetDrawable());
|
||||
GdkGC *gc = ((nsRenderingContextGTK&)aContext).GetGC();
|
||||
gdk_gc_copy(mGC, gc);
|
||||
gdk_gc_unref(gc); // unref the one we got
|
||||
copyGC = gdk_gc_ref(mGC);
|
||||
|
||||
SetupGCForAlpha(copyGC, aDX-aSX, aDY-aSY);
|
||||
}
|
||||
} else {
|
||||
// don't make a copy... we promise not to change it
|
||||
copyGC = ((nsRenderingContextGTK&)aContext).GetGC();
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((mAlphaDepth==8) && mAlphaValid) {
|
||||
NS_WARNING("can't do 8bit alpha stretched images currently\n");
|
||||
// DrawComposited(aContext, aSurface, aSX, aSY, aDX, aDY, aSWidth, aSHeight);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#if defined(HAVE_GDK_PIXBUF)
|
||||
// Draw with GdkPixbuf
|
||||
GdkPixbuf *tmpPb =
|
||||
gdk_pixbuf_new_from_data(mImageBits,
|
||||
GDK_COLORSPACE_RGB, PR_FALSE, 8,
|
||||
mWidth, mHeight,
|
||||
mRowBytes, nsnull, nsnull);
|
||||
|
||||
GdkPixbuf *newPb = gdk_pixbuf_new(GDK_COLORSPACE_RGB, PR_FALSE,
|
||||
8,
|
||||
aDWidth, aDHeight);
|
||||
|
||||
gdk_pixbuf_scale(tmpPb, newPb, 0, 0, aDWidth, aDHeight,
|
||||
0, 0,
|
||||
(double)aDWidth / (double)aSWidth,
|
||||
(double)aDHeight / (double)aSHeight,
|
||||
GDK_INTERP_NEAREST);
|
||||
|
||||
gdk_pixbuf_render_to_drawable(newPb,
|
||||
drawing->GetDrawable(),
|
||||
copyGC,
|
||||
0, 0,
|
||||
aDX, aDY,
|
||||
aDWidth, aDHeight,
|
||||
GDK_RGB_DITHER_MAX, 0, 0);
|
||||
|
||||
gdk_gc_unref(copyGC);
|
||||
gdk_pixbuf_unref(tmpPb);
|
||||
gdk_pixbuf_unref(newPb);
|
||||
|
||||
#elif defined(HAVE_XIE)
|
||||
PRBool succeeded = PR_FALSE;
|
||||
|
||||
#ifdef HAVE_XIE
|
||||
// Draw with XIE
|
||||
|
||||
// don't make a copy... we promise not to change it
|
||||
|
@ -458,32 +411,115 @@ nsImageGTK::DrawScaled(nsIRenderingContext &aContext, nsDrawingSurface aSurface,
|
|||
|
||||
// DrawScaledImageXIE will copy the GC if it needs to change it.
|
||||
|
||||
PRBool succeeded = DrawScaledImageXIE(GDK_DISPLAY(),
|
||||
drawing->GetDrawable(),
|
||||
gc,
|
||||
mImagePixmap,
|
||||
mAlphaPixmap,
|
||||
mWidth, mHeight,
|
||||
aSX, aSY,
|
||||
aSWidth, aSHeight,
|
||||
aDX, aDY,
|
||||
aDWidth, aDHeight);
|
||||
succeeded = DrawScaledImageXIE(GDK_DISPLAY(),
|
||||
drawing->GetDrawable(),
|
||||
gc,
|
||||
mImagePixmap,
|
||||
mAlphaPixmap,
|
||||
mWidth, mHeight,
|
||||
aSX, aSY,
|
||||
aSWidth, aSHeight,
|
||||
aDX, aDY,
|
||||
aDWidth, aDHeight);
|
||||
|
||||
gdk_gc_unref(gc);
|
||||
|
||||
if (!succeeded) {
|
||||
NS_WARNING("unable to draw scaled image :(");
|
||||
}
|
||||
#else
|
||||
printf("no way to scale images :(\n");
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GDK_PIXBUF
|
||||
if (!succeeded) {
|
||||
GdkGC *copyGC;
|
||||
if (mAlphaPixmap) {
|
||||
NS_WARNING("alpha bitmask not scaled!\n");
|
||||
if (mGC) {
|
||||
copyGC = gdk_gc_ref(mGC);
|
||||
} else {
|
||||
mGC = gdk_gc_new(drawing->GetDrawable());
|
||||
GdkGC *gc = ((nsRenderingContextGTK&)aContext).GetGC();
|
||||
gdk_gc_copy(mGC, gc);
|
||||
gdk_gc_unref(gc); // unref the one we got
|
||||
copyGC = gdk_gc_ref(mGC);
|
||||
|
||||
SetupGCForAlpha(copyGC, aDX-aSX, aDY-aSY);
|
||||
}
|
||||
} else {
|
||||
// don't make a copy... we promise not to change it
|
||||
copyGC = ((nsRenderingContextGTK&)aContext).GetGC();
|
||||
}
|
||||
|
||||
// Draw with GdkPixbuf
|
||||
GdkPixbuf *tmpPb =
|
||||
gdk_pixbuf_new_from_data(mImageBits,
|
||||
GDK_COLORSPACE_RGB, PR_FALSE, 8,
|
||||
mWidth, mHeight,
|
||||
mRowBytes, nsnull, nsnull);
|
||||
|
||||
GdkPixbuf *newPb = gdk_pixbuf_new(GDK_COLORSPACE_RGB, PR_FALSE,
|
||||
8,
|
||||
aDWidth, aDHeight);
|
||||
|
||||
gdk_pixbuf_scale(tmpPb, newPb, 0, 0, aDWidth, aDHeight,
|
||||
0, 0,
|
||||
(double)aDWidth / (double)aSWidth,
|
||||
(double)aDHeight / (double)aSHeight,
|
||||
GDK_INTERP_NEAREST);
|
||||
|
||||
gdk_pixbuf_render_to_drawable(newPb,
|
||||
drawing->GetDrawable(),
|
||||
copyGC,
|
||||
0, 0,
|
||||
aDX, aDY,
|
||||
aDWidth, aDHeight,
|
||||
GDK_RGB_DITHER_MAX, 0, 0);
|
||||
|
||||
succeeded = PR_TRUE;
|
||||
|
||||
gdk_gc_unref(copyGC);
|
||||
gdk_pixbuf_unref(tmpPb);
|
||||
gdk_pixbuf_unref(newPb);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!succeeded) {
|
||||
// don't make a copy... we promise not to change it
|
||||
GdkGC *gc = ((nsRenderingContextGTK&)aContext).GetGC();
|
||||
|
||||
|
||||
#if 1
|
||||
// this should work, but isn't very fast (espically over remote connections
|
||||
succeeded = DrawScaledImageNN(GDK_DISPLAY(),
|
||||
drawing->GetDrawable(),
|
||||
gc,
|
||||
mImagePixmap,
|
||||
mAlphaPixmap,
|
||||
mWidth, mHeight,
|
||||
aSX, aSY,
|
||||
aSWidth, aSHeight,
|
||||
aDX, aDY,
|
||||
aDWidth, aDHeight);
|
||||
#else
|
||||
// XXX this doesn't work very well.
|
||||
succeeded = DrawScaledImageBitsNN(GDK_DISPLAY(),
|
||||
drawing->GetDrawable(),
|
||||
gc,
|
||||
mImageBits,
|
||||
mRowBytes,
|
||||
mAlphaBits,
|
||||
mWidth, mHeight,
|
||||
aSX, aSY,
|
||||
aSWidth, aSHeight,
|
||||
aDX, aDY,
|
||||
aDWidth, aDHeight);
|
||||
#endif
|
||||
|
||||
gdk_gc_unref(gc);
|
||||
}
|
||||
|
||||
mFlags = 0;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// Draw the bitmap, this method has a source and destination coordinates
|
||||
NS_IMETHODIMP
|
||||
nsImageGTK::Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface,
|
||||
|
@ -505,23 +541,39 @@ nsImageGTK::Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface,
|
|||
aDX, aDY, aDWidth, aDHeight);
|
||||
}
|
||||
|
||||
if (aSX < mDecodedX1) {
|
||||
aSWidth -= mDecodedX1 - aSX;
|
||||
aDX += mDecodedX1 - aSX;
|
||||
aSX += mDecodedX1 - aSX;
|
||||
if (aSWidth <= 0 || aDWidth <= 0 || aSHeight <= 0 || aDHeight <= 0) {
|
||||
NS_ASSERTION(aSWidth > 0 && aDWidth > 0 && aSHeight > 0 && aDHeight > 0,
|
||||
"You can't draw an image with a 0 width or height!");
|
||||
return NS_OK;
|
||||
}
|
||||
if (aSX + aSWidth > mDecodedX2) {
|
||||
aSWidth -= aSX + aSWidth - mDecodedX2;
|
||||
|
||||
// limit the size of the blit to the amount of the image read in
|
||||
PRInt32 j = aSX + aSWidth;
|
||||
PRInt32 z;
|
||||
if (j > mDecodedX2) {
|
||||
z = j - mDecodedX2;
|
||||
aDWidth -= z;
|
||||
aSWidth -= z;
|
||||
}
|
||||
if (aSX < mDecodedX1) {
|
||||
aDX += mDecodedX1 - aSX;
|
||||
aSX = mDecodedX1;
|
||||
}
|
||||
|
||||
j = aSY + aSHeight;
|
||||
if (j > mDecodedY2) {
|
||||
z = j - mDecodedY2;
|
||||
aDHeight -= z;
|
||||
aSHeight -= z;
|
||||
}
|
||||
if (aSY < mDecodedY1) {
|
||||
aSHeight -= mDecodedY1 - aSY;
|
||||
aDY += mDecodedY1 - aSY;
|
||||
aSY += mDecodedY1 - aSY;
|
||||
}
|
||||
if (aSY + aSHeight > mDecodedY2) {
|
||||
aSHeight -= (aSY + aSHeight) - mDecodedY2;
|
||||
aSY = mDecodedY1;
|
||||
}
|
||||
|
||||
if (aDWidth <= 0 || aDHeight <= 0 || aSWidth <= 0 || aSHeight <= 0)
|
||||
return NS_OK;
|
||||
|
||||
if ((mAlphaDepth==8) && mAlphaValid) {
|
||||
DrawComposited(aContext, aSurface, aSX, aSY, aDX, aDY, aSWidth, aSHeight);
|
||||
return NS_OK;
|
||||
|
|
|
@ -110,6 +110,7 @@ public:
|
|||
NS_IMETHOD LockImagePixels(PRBool aMaskPixels);
|
||||
NS_IMETHOD UnlockImagePixels(PRBool aMaskPixels);
|
||||
|
||||
|
||||
private:
|
||||
/**
|
||||
* Calculate the amount of memory needed for the initialization of the image
|
||||
|
|
|
@ -208,7 +208,11 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
GdkGC *GetGC() { return gdk_gc_ref(mGC); }
|
||||
GdkGC *GetGC() {
|
||||
if (!mGC)
|
||||
UpdateGC();
|
||||
return gdk_gc_ref(mGC);
|
||||
}
|
||||
|
||||
// handle drawing 8 bit data with a 16 bit font
|
||||
static void Widen8To16AndDraw(GdkDrawable *drawable,
|
||||
|
|
|
@ -0,0 +1,330 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
* Syd Logan <syd@netscape.com>
|
||||
* Stuart Parmenter <pavlov@netscape.com>
|
||||
*/
|
||||
|
||||
#include "drawers.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
#include "nspr.h"
|
||||
|
||||
XImage *
|
||||
NNScaleImage(Display *display, XImage *img,
|
||||
double factorX, double factorY,
|
||||
PRInt32 aSWidth, PRInt32 aSHeight,
|
||||
PRInt32 newWidth, PRInt32 newHeight)
|
||||
{
|
||||
XImage *newImg;
|
||||
PRUint32 pixel;
|
||||
PRInt16 i, j, xsrc, ysrc;
|
||||
PRUint32 size;
|
||||
char *data;
|
||||
|
||||
size = newWidth * newHeight * img->depth;
|
||||
data = (char *) PR_Malloc(size);
|
||||
|
||||
if (!data) {
|
||||
return (XImage *) NULL;
|
||||
}
|
||||
|
||||
newImg = XCreateImage(display, DefaultVisual(display, 0),
|
||||
img->depth,
|
||||
img->format,
|
||||
0, 0, newWidth, newHeight,
|
||||
img->bitmap_pad, 0);
|
||||
newImg->data = data;
|
||||
|
||||
if (factorX == 1) {
|
||||
/* an obvious optimization is to bypass XPutPixel
|
||||
and to memcpy rows in img->data if factorX is 1
|
||||
*/
|
||||
|
||||
char *dptr, *sptr;
|
||||
PRUint32 rowsize;
|
||||
|
||||
dptr = newImg->data;
|
||||
rowsize = img->bytes_per_line;
|
||||
for (i = 0; i < newHeight; i++) {
|
||||
ysrc = (PRInt16) (i * factorY);
|
||||
sptr = img->data + ysrc * rowsize;
|
||||
memcpy(dptr, sptr, rowsize);
|
||||
dptr += rowsize;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < newWidth; i++) {
|
||||
xsrc = (PRInt16) (i * factorX);
|
||||
for (j = 0; j < newHeight; j++) {
|
||||
ysrc = (PRInt16) (j * factorY);
|
||||
pixel = XGetPixel(img, xsrc, ysrc);
|
||||
XPutPixel(newImg, i, j, pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
return newImg;
|
||||
}
|
||||
|
||||
|
||||
static PRBool
|
||||
DoScale(Display *aDisplay,
|
||||
Drawable aDest,
|
||||
GC aGC,
|
||||
Drawable aSrc,
|
||||
PRInt32 aSrcWidth,
|
||||
PRInt32 aSrcHeight,
|
||||
PRInt32 aSX,
|
||||
PRInt32 aSY,
|
||||
PRInt32 aSWidth,
|
||||
PRInt32 aSHeight,
|
||||
PRInt32 aDX,
|
||||
PRInt32 aDY,
|
||||
PRInt32 aDWidth,
|
||||
PRInt32 aDHeight)
|
||||
{
|
||||
XImage *srcImg = (XImage*)NULL;
|
||||
XImage *dstImg = (XImage*)NULL;
|
||||
|
||||
double factorX = (double)aSrcWidth / (double)aDWidth;
|
||||
double factorY = (double)aSrcHeight / (double)aDHeight;
|
||||
|
||||
srcImg = XGetImage(aDisplay, aSrc,
|
||||
aSX, aSY, aSrcWidth, aSrcHeight,
|
||||
AllPlanes, ZPixmap);
|
||||
|
||||
if (!srcImg)
|
||||
return PR_FALSE;
|
||||
|
||||
dstImg = NNScaleImage(aDisplay, srcImg, factorX, factorY,
|
||||
aSWidth, aSHeight,
|
||||
aDWidth, aDHeight);
|
||||
|
||||
XDestroyImage(srcImg);
|
||||
srcImg = (XImage*)NULL;
|
||||
|
||||
if (!dstImg)
|
||||
return PR_FALSE;
|
||||
|
||||
XPutImage(aDisplay, aDest, aGC, dstImg,
|
||||
0, 0,
|
||||
aDX, aDY,
|
||||
aDWidth, aDHeight);
|
||||
|
||||
PR_Free(dstImg->data); /* we allocated data, don't let Xlib free */
|
||||
dstImg->data = (char *) NULL; /* setting NULL is important!! */
|
||||
|
||||
XDestroyImage(dstImg);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
DrawScaledImageNN(Display *display,
|
||||
GdkDrawable *aDest,
|
||||
GdkGC *aGC,
|
||||
GdkDrawable *aSrc,
|
||||
GdkDrawable *aSrcMask,
|
||||
PRInt32 aSrcWidth,
|
||||
PRInt32 aSrcHeight,
|
||||
PRInt32 aSX,
|
||||
PRInt32 aSY,
|
||||
PRInt32 aSWidth,
|
||||
PRInt32 aSHeight,
|
||||
PRInt32 aDX,
|
||||
PRInt32 aDY,
|
||||
PRInt32 aDWidth,
|
||||
PRInt32 aDHeight)
|
||||
{
|
||||
Drawable importDrawable = GDK_WINDOW_XWINDOW(aSrc);
|
||||
Drawable exportDrawable = GDK_WINDOW_XWINDOW(aDest);
|
||||
|
||||
GdkPixmap *alphaMask = (GdkPixmap*)NULL;
|
||||
|
||||
GdkGC *gc = (GdkGC*)NULL;
|
||||
|
||||
if (aSrcMask) {
|
||||
Drawable destMask;
|
||||
|
||||
alphaMask = gdk_pixmap_new(aSrcMask, aDWidth, aDHeight, 1);
|
||||
destMask = GDK_WINDOW_XWINDOW(alphaMask);
|
||||
|
||||
gc = gdk_gc_new(alphaMask);
|
||||
|
||||
DoScale(display,
|
||||
GDK_WINDOW_XWINDOW(alphaMask), /* dest */
|
||||
GDK_GC_XGC(gc),
|
||||
GDK_WINDOW_XWINDOW(aSrcMask), /* src */
|
||||
aSrcWidth, aSrcHeight,
|
||||
aSX, aSY,
|
||||
aSWidth, aSHeight,
|
||||
aDX, aDY,
|
||||
aDWidth, aDHeight);
|
||||
|
||||
gdk_gc_unref(gc);
|
||||
|
||||
gc = gdk_gc_new(aDest);
|
||||
gdk_gc_copy(gc, aGC);
|
||||
gdk_gc_set_clip_mask(gc, alphaMask);
|
||||
gdk_gc_set_clip_origin(gc, 0, 0);
|
||||
}
|
||||
|
||||
if (!gc) {
|
||||
gc = aGC;
|
||||
gdk_gc_ref(gc);
|
||||
}
|
||||
|
||||
DoScale(display,
|
||||
exportDrawable,
|
||||
GDK_GC_XGC(gc),
|
||||
importDrawable,
|
||||
aSrcWidth, aSrcHeight,
|
||||
aSX, aSY,
|
||||
aSWidth, aSHeight,
|
||||
aDX, aDY,
|
||||
aDWidth, aDHeight);
|
||||
|
||||
if (alphaMask)
|
||||
gdk_pixmap_unref(alphaMask);
|
||||
|
||||
gdk_gc_unref(gc);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define SCALE_SHIFT 16
|
||||
|
||||
static void
|
||||
pixops_scale_nearest (guchar *dest_buf,
|
||||
int render_x0,
|
||||
int render_y0,
|
||||
int render_x1,
|
||||
int render_y1,
|
||||
int dest_rowstride,
|
||||
int dest_channels,
|
||||
const guchar *src_buf,
|
||||
int src_width,
|
||||
int src_height,
|
||||
int src_rowstride,
|
||||
int src_channels,
|
||||
double scale_x,
|
||||
double scale_y)
|
||||
{
|
||||
int i, j;
|
||||
int x;
|
||||
int x_step = (1 << SCALE_SHIFT) / scale_x;
|
||||
int y_step = (1 << SCALE_SHIFT) / scale_y;
|
||||
|
||||
printf("%f,%f\n", scale_x, scale_y);
|
||||
|
||||
PR_ASSERT(src_channels == dest_channels);
|
||||
|
||||
for (i = 0; i < (render_y1 - render_y0); i++) {
|
||||
const guchar *src = src_buf + (((i + render_y0) * y_step + y_step / 2) >> SCALE_SHIFT) * src_rowstride;
|
||||
guchar *dest = dest_buf + i * dest_rowstride;
|
||||
|
||||
x = render_x0 * x_step + x_step / 2;
|
||||
|
||||
for (j=0; j < (render_x1 - render_x0); j++) {
|
||||
const guchar *p = src + (x >> SCALE_SHIFT) * src_channels;
|
||||
|
||||
dest[0] = p[0];
|
||||
dest[1] = p[1];
|
||||
dest[2] = p[2];
|
||||
|
||||
dest += dest_channels;
|
||||
x += x_step;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PRBool
|
||||
DrawScaledImageBitsNN(Display *display,
|
||||
GdkDrawable *aDest,
|
||||
GdkGC *aGC,
|
||||
const PRUint8 *aSrc,
|
||||
PRInt32 aBytesPerRow,
|
||||
const PRUint8 *aSrcMask,
|
||||
PRInt32 aSrcWidth,
|
||||
PRInt32 aSrcHeight,
|
||||
PRInt32 aSX,
|
||||
PRInt32 aSY,
|
||||
PRInt32 aSWidth,
|
||||
PRInt32 aSHeight,
|
||||
PRInt32 aDX,
|
||||
PRInt32 aDY,
|
||||
PRInt32 aDWidth,
|
||||
PRInt32 aDHeight)
|
||||
{
|
||||
const guchar *inBuffer = (const guchar*)aSrc;
|
||||
PRInt32 destBytesPerRow;
|
||||
PRInt32 size = 0;
|
||||
guchar *outBuffer = (guchar*)NULL;
|
||||
GdkGC *gc;
|
||||
|
||||
printf("scaling image from %dx%d to %dx%d\n", aSrcWidth, aSrcHeight, aDWidth, aDHeight);
|
||||
printf("source: (%d,%d) -- dest: (%d,%d)\n", aSX, aSY, aDX, aDY);
|
||||
|
||||
destBytesPerRow = (aDWidth * 24) >> 5;
|
||||
if ((aDWidth * 3) & 0x1F) {
|
||||
destBytesPerRow++;
|
||||
}
|
||||
destBytesPerRow <<= 2;
|
||||
|
||||
size = destBytesPerRow * aDHeight;
|
||||
|
||||
printf("making buffer for dest... %d bytes\n", size);
|
||||
|
||||
outBuffer = (guchar *)PR_Calloc(size, 1);
|
||||
if (!outBuffer)
|
||||
return PR_FALSE;
|
||||
|
||||
pixops_scale_nearest(outBuffer, /* out buffer */
|
||||
0, 0, /* dest_x, dest_y */
|
||||
aDWidth, aDHeight, /* dest_width, dest_height */
|
||||
destBytesPerRow, 3, /* dest_row_stride, dest_num_chans */
|
||||
inBuffer, /* in buffer */
|
||||
aSrcWidth, aSrcHeight, /* src_width, src_height */
|
||||
aBytesPerRow, 3, /* src_row_stride, src_num_chans */
|
||||
(double)aSrcWidth / (double)aDWidth, /* scale_x */
|
||||
(double)aSrcHeight / (double)aDHeight); /* scale_y */
|
||||
|
||||
|
||||
gc = gdk_gc_new(aDest);
|
||||
|
||||
gdk_draw_rgb_image(aDest, gc,
|
||||
aDX, aDY, aDWidth, aDHeight,
|
||||
GDK_RGB_DITHER_MAX,
|
||||
outBuffer, destBytesPerRow);
|
||||
gdk_gc_unref(gc);
|
||||
|
||||
PR_Free(outBuffer);
|
||||
|
||||
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
Загрузка…
Ссылка в новой задаче