From 9fcf1bbca71b4a856149a854a4c4f4e8d8bbf9e3 Mon Sep 17 00:00:00 2001 From: "pavlov%netscape.com" Date: Fri, 30 Mar 2001 07:05:28 +0000 Subject: [PATCH] fix for bug 73161 r=bryner,syd sr=waterson --- gfx/src/gtk/Makefile.in | 22 +++- gfx/src/gtk/XIE.c | 201 +++++++++++++++++++++++++++++++++++++ gfx/src/gtk/drawers.h | 51 ++++++++++ gfx/src/gtk/nsImageGTK.cpp | 141 +++++++++++++++++++++++++- gfx/src/gtk/nsImageGTK.h | 5 + 5 files changed, 415 insertions(+), 5 deletions(-) create mode 100644 gfx/src/gtk/XIE.c create mode 100644 gfx/src/gtk/drawers.h diff --git a/gfx/src/gtk/Makefile.in b/gfx/src/gtk/Makefile.in index 57a9b22768e9..5ba84e81b12d 100644 --- a/gfx/src/gtk/Makefile.in +++ b/gfx/src/gtk/Makefile.in @@ -33,6 +33,12 @@ REQUIRES = xpcom string img widget view util dom pref js uconv appshell necko un CSRCS = nsPrintdGTK.c +ifndef HAVE_GDK_PIXBUF +ifdef HAVE_XIE +CSRCS += XIE.c +endif +endif + CPPSRCS = \ nsDeviceContextGTK.cpp \ nsDeviceContextSpecFactoryG.cpp \ @@ -54,7 +60,7 @@ include $(topsrcdir)/config/rules.mk ifndef MOZ_MONOLITHIC_TOOLKIT EXTRA_DSO_LDOPTS += $(MOZ_GTK_LDFLAGS) -CXXFLAGS += $(MOZ_GTK_CFLAGS) +CXXFLAGS += $(MOZ_GTK_CFLAGS) CFLAGS += $(MOZ_GTK_CFLAGS) else EXTRA_DSO_LDOPTS += $(TK_LIBS) @@ -66,9 +72,23 @@ ifdef MOZ_ENABLE_XINERAMA GFX_XINERAMA_LIBS += $(MOZ_XINERAMA_LIBS) endif +ifdef HAVE_GDK_PIXBUF +DEFINES += -DHAVE_GDK_PIXBUF +GFX_PIXBUF_LIBS += $(MOZ_GDK_PIXBUF_LIBS) +CXXFLAGS += $(MOZ_GDK_PIXBUF_CFLAGS) +CFLAGS += $(MOZ_GDK_PIXBUF_CFLAGS) +else +ifdef HAVE_XIE +DEFINES += -DHAVE_XIE +GFX_XIE_LIBS += $(MOZ_XIE_LIBS) +endif +endif + EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS) \ -lgkgfx \ $(GFX_XINERAMA_LIBS) \ + $(GFX_PIXBUF_LIBS) \ + $(GFX_XIE_LIBS) \ -lgtksuperwin \ $(MOZ_JS_LIBS) \ $(NULL) diff --git a/gfx/src/gtk/XIE.c b/gfx/src/gtk/XIE.c new file mode 100644 index 000000000000..acdbfb416911 --- /dev/null +++ b/gfx/src/gtk/XIE.c @@ -0,0 +1,201 @@ +/* -*- 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 + * Syd Logan + */ + +#include "drawers.h" + +#ifdef HAVE_XIE + +#include + +#include +#include + +#include + +/*#define DEBUG_XIE 1*/ + +static PRBool inited = PR_FALSE; +static XiePhotospace gPhotospace; +static XiePhotoElement *photoElement; + +static void +DoFlo(Display *display, + 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) +{ + XieExtensionInfo *info; + 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); + ++idx; + src = idx; + + /* do the scaling stuff */ + coeffs[0] = (float)aSrcWidth / (float)aDWidth; + coeffs[1] = 0.0; + coeffs[2] = 0.0; + coeffs[3] = (float)aSrcHeight / (float)aDHeight; + coeffs[4] = 0.0; + coeffs[5] = 0.0; + + constant[0] = 128.0; + constant[1] = 128.0; + constant[2] = 128.0; + + XieFloGeometry(&photoElement[idx], src, aDWidth, aDHeight, + coeffs, + constant, + 0x07, + xieValGeomNearestNeighbor, + NULL); + ++idx; + + /* export */ + XieFloExportDrawable(&photoElement[idx], idx, aDest, aGC, + (aDX - aSX), + (aDY - aSY)); + ++idx; + + + /* do the scale thing baby */ + XieExecuteImmediate(display, gPhotospace, 1, PR_FALSE, photoElement, idx); + + + /* + XieFreePhotofloGraph(photoElement, 3); + */ + +#ifdef DEBUG_XIE + gdk_flush(); +#endif +} + + + + +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) +{ + Drawable importDrawable = GDK_WINDOW_XWINDOW(aSrc); + Drawable exportDrawable = GDK_WINDOW_XWINDOW(aDest); + + GdkPixmap *alphaMask = NULL; + + GdkGC *gc = NULL; + +#ifdef DEBUG_XIE + printf("DrawScaledImageXIE\n"); +#endif + + if (!inited) { + XieExtensionInfo *info; + inited = PR_TRUE; + if (!XieInitialize(display, &info)) + return PR_FALSE; + + /* create the photospace (we only need to do this once) */ + gPhotospace = XieCreatePhotospace(display); + + photoElement = XieAllocatePhotofloGraph(3); + + /* we want to destroy this at shutdown + XieDestroyPhotospace(display, photospace); + */ + } + + if (aSrcMask) { + Drawable destMask; + +#ifdef DEBUG_XIE + fprintf(stderr, "DrawScaledImageXIE with alpha mask\n"); +#endif + + 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); + 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, aDX + aSX, aDY + aSY); + } + + if (!gc) { + gc = aGC; + gdk_gc_ref(gc); + } + + DoFlo(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; +} + +#endif diff --git a/gfx/src/gtk/drawers.h b/gfx/src/gtk/drawers.h new file mode 100644 index 000000000000..b3ee85941928 --- /dev/null +++ b/gfx/src/gtk/drawers.h @@ -0,0 +1,51 @@ +/* -*- 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 + */ + +#include "prtypes.h" + +#include + +#include + +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 diff --git a/gfx/src/gtk/nsImageGTK.cpp b/gfx/src/gtk/nsImageGTK.cpp index 4dd39c665ee3..61850424c393 100644 --- a/gfx/src/gtk/nsImageGTK.cpp +++ b/gfx/src/gtk/nsImageGTK.cpp @@ -24,6 +24,12 @@ #include #include +#ifdef HAVE_GDK_PIXBUF +#include +#else +#include "drawers.h" +#endif + #include "nsImageGTK.h" #include "nsRenderingContextGTK.h" @@ -341,6 +347,128 @@ void nsImageGTK::ImageUpdated(nsIDeviceContext *aContext, static PRTime gConvertTime, gAlphaTime, gCopyStart, gCopyEnd, gStartTime, gPixmapTime, gEndTime; #endif + +NS_IMETHODIMP +nsImageGTK::DrawScaled(nsIRenderingContext &aContext, nsDrawingSurface aSurface, + PRInt32 aSX, PRInt32 aSY, PRInt32 aSWidth, PRInt32 aSHeight, + PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight) +{ + if (aSX < mDecodedX1) { + aSWidth -= mDecodedX1 - aSX; + aDX += mDecodedX1 - aSX; + aSX += mDecodedX1 - aSX; + } + if (aSX + aSWidth > mDecodedX2) { + aSWidth -= aSX + aSWidth - mDecodedX2; + } + if (aSY < mDecodedY1) { + aSHeight -= mDecodedY1 - aSY; + aDY += mDecodedY1 - aSY; + aSY += mDecodedY1 - aSY; + } + if (aSY + aSHeight > mDecodedY2) { + aSHeight -= (aSY + aSHeight) - mDecodedY2; + } + + nsDrawingSurfaceGTK *drawing = (nsDrawingSurfaceGTK*)aSurface; + + if (mAlphaDepth == 1) { + 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)aDWidth / (double)aSHeight, + GDK_INTERP_NEAREST); + + gdk_pixbuf_render_to_drawable(newPb, + drawing->GetDrawable(), + copyGC, + aSX, aSY, + aDX + aSX, aDY + aSY, + aDWidth, aDHeight, + GDK_RGB_DITHER_MAX, 0, 0); + + gdk_gc_unref(copyGC); + gdk_pixbuf_unref(tmpPb); + gdk_pixbuf_unref(newPb); + +#elif defined(HAVE_XIE) + + // Draw with XIE + + // don't make a copy... we promise not to change it + GdkGC *gc = ((nsRenderingContextGTK&)aContext).GetGC(); + + // 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); + + gdk_gc_unref(gc); + + if (!succeeded) { + NS_WARNING("unable to draw scaled image :("); + } +#else + printf("no way to scale images :(\n"); +#endif + + mFlags = 0; + + return NS_OK; +} + + // Draw the bitmap, this method has a source and destination coordinates NS_IMETHODIMP nsImageGTK::Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface, @@ -351,12 +479,17 @@ nsImageGTK::Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface, #ifdef TRACE_IMAGE_ALLOCATION - printf("nsImageGTK::Draw(this=%p) (%d, %d, %d, %d), (%d, %d, %d, %d)\n", - this, - aSX, aSY, aSWidth, aSHeight, - aDX, aDY, aDWidth, aDHeight); + printf("nsImageGTK::Draw(this=%p) (%d, %d, %d, %d), (%d, %d, %d, %d)\n", + this, + aSX, aSY, aSWidth, aSHeight, + aDX, aDY, aDWidth, aDHeight); #endif + if (aSWidth != aDWidth || aSHeight != aDHeight) { + return DrawScaled(aContext, aSurface, aSX, aSY, aSWidth, aSHeight, + aDX, aDY, aDWidth, aDHeight); + } + if (aSX < mDecodedX1) { aSWidth -= mDecodedX1 - aSX; aDX += mDecodedX1 - aSX; diff --git a/gfx/src/gtk/nsImageGTK.h b/gfx/src/gtk/nsImageGTK.h index 5c066ab8f4e9..420704bf44db 100644 --- a/gfx/src/gtk/nsImageGTK.h +++ b/gfx/src/gtk/nsImageGTK.h @@ -126,6 +126,11 @@ private: void ComputePaletteSize(PRIntn nBitCount); private: + + NS_IMETHOD DrawScaled(nsIRenderingContext &aContext, nsDrawingSurface aSurface, + PRInt32 aSX, PRInt32 aSY, PRInt32 aSWidth, PRInt32 aSHeight, + PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight); + static unsigned scaled6[1<<6]; static unsigned scaled5[1<<5];