Alpha fixes

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@14152 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Adam Fedor 2002-07-15 02:50:59 +00:00
parent fbda96e6a9
commit 28e92746b8
3 changed files with 138 additions and 136 deletions

View file

@ -1,3 +1,15 @@
2002-07-14 Adam Fedor <fedor@gnu.org>
* Source/x11/XGServer.m ([XGServer -dealloc]): Don't close
the display (except when DEBUG), till we figure out why it
always crashes here.
2002-07-13 Adam Fedor <fedor@gnu.org>
* Source/xlib/XGBitmap.m (_pixmap_combine_alpha): Fix and
cleanup alpha blending (Rescale by alpha)
(_bitmap_combine_alpha): Idem. (Patch from deek@d2dc.net).
2002-06-28 Adam Fedor <fedor@gnu.org> 2002-06-28 Adam Fedor <fedor@gnu.org>
* Source/xlib/XGFont.m ([XGFontInfo -xCharStructForGlyph:glyph]): * Source/xlib/XGFont.m ([XGFontInfo -xCharStructForGlyph:glyph]):

View file

@ -420,7 +420,11 @@ _parse_display_name(NSString *name, int *dn, int *sn)
DESTROY(inputServer); DESTROY(inputServer);
[self _destroyServerWindows]; [self _destroyServerWindows];
NSFreeMapTable(screenList); NSFreeMapTable(screenList);
#ifdef DEBUG
/* FIXME: Avoid doing this until we figure out why we always
segfault here */
XCloseDisplay(dpy); XCloseDisplay(dpy);
#endif
[super dealloc]; [super dealloc];
} }

View file

@ -54,26 +54,26 @@
#define InitRGBShiftsAndMasks(rs,rw,gs,gw,bs,bw,as,aw) \ #define InitRGBShiftsAndMasks(rs,rw,gs,gw,bs,bw,as,aw) \
do { \ do { \
_rshift = rs; \ _rshift = (rs); \
_rmask = (1<<rw) -1; \ _rmask = (1<<(rw)) -1; \
_rwidth = rw; \ _rwidth = (rw); \
_gshift = gs; \ _gshift = (gs); \
_gmask = (1<<gw) -1; \ _gmask = (1<<(gw)) -1; \
_gwidth = gw; \ _gwidth = (gw); \
_bshift = bs; \ _bshift = (bs); \
_bmask = (1<<bw) -1; \ _bmask = (1<<(bw)) -1; \
_bwidth = bw; \ _bwidth = (bw); \
_amask = (1<<aw) -1; \ _amask = (1<<(aw)) -1; \
_ashift = as; \ _ashift = (as); \
_awidth = aw; \ _awidth = (aw); \
} while(0) } while(0)
#define PixelToRGB(pixel,r,g,b) \ #define PixelToRGB(pixel,r,g,b) \
do { \ do { \
r = (pixel >> _rshift) & _rmask; \ (r) = (pixel >> _rshift) & _rmask; \
g = (pixel >> _gshift) & _gmask; \ (g) = (pixel >> _gshift) & _gmask; \
b = (pixel >> _bshift) & _bmask; \ (b) = (pixel >> _bshift) & _bmask; \
} while(0) } while(0)
/* Note that RGBToPixel assumes that the /* Note that RGBToPixel assumes that the
@ -88,6 +88,10 @@
|((b) << _bshift); \ |((b) << _bshift); \
} while(0) } while(0)
#define CLAMP(a) \
do { \
(a) = MAX(0, MIN(255, (a))); \
} while (0)
/* Composite source image (pixmap) onto a destination image with alpha. /* Composite source image (pixmap) onto a destination image with alpha.
Only works for op=Sover now Only works for op=Sover now
@ -107,14 +111,9 @@ _pixmap_combine_alpha(RContext *context,
float fraction) float fraction)
{ {
unsigned long pixel; unsigned long pixel;
unsigned short oldAlpha = 0;
unsigned long oldPixel = 0; unsigned long oldPixel = 0;
unsigned short oldAr = 0;
unsigned short oldAg = 0; fraction = MAX(0.0, MIN(1.0, fraction));
unsigned short oldAb = 0;
unsigned char oldBr = 0;
unsigned char oldBg = 0;
unsigned char oldBb = 0;
if (drawMechanism == XGDM_FAST15 if (drawMechanism == XGDM_FAST15
|| drawMechanism == XGDM_FAST16 || drawMechanism == XGDM_FAST16
@ -144,68 +143,70 @@ _pixmap_combine_alpha(RContext *context,
//which picture goes wrong. //which picture goes wrong.
InitRGBShiftsAndMasks(11,5,5,6,0,5,0,8); InitRGBShiftsAndMasks(11,5,5,6,0,5,0,8);
} }
for (row = 0; row < srect.height; row++) for (row = 0; row < srect.height; row++)
{ {
unsigned col; unsigned col;
for (col = 0; col < srect.width; col++) for (col = 0; col < srect.width; col++)
{ {
unsigned r, g, b, alpha; unsigned sr, sg, sb, sa; // source
pixel = XGetPixel(source_im->image, unsigned dr, dg, db, da; // dest
col+srect.x, row+srect.y); double alpha, ialpha;
PixelToRGB(pixel,r,g,b); // Get the source pixel information
pixel = XGetPixel (source_im->image, srect.x+col, srect.y+row);
PixelToRGB (pixel, sr, sg, sb);
pixel = 255;
if (source_alpha) if (source_alpha)
{
pixel = XGetPixel(source_alpha->image, pixel = XGetPixel(source_alpha->image,
col+srect.x, row+srect.y); srect.x+col, srect.y+row);
sa = (pixel >> _ashift) & _amask;
if (fraction < 1)
pixel *= fraction;
alpha = (pixel >> _ashift) & _amask;
if (alpha == 0)
continue; // background unchanged.
if (alpha != _amask)
{ // We really have something to mix!
unsigned short ialpha = _amask - alpha;
/*
* Get the background pixel and convert to RGB.
*/
pixel = XGetPixel(dest_im->image, col, row);
if (pixel != oldPixel)
{
oldPixel = pixel;
PixelToRGB(pixel, oldBr,oldBg,oldBb);
oldAlpha = 0;
}
if (alpha != oldAlpha)
{
oldAlpha = alpha;
oldAr = ialpha * oldBr;
oldAg = ialpha * oldBg;
oldAb = ialpha * oldBb;
}
// mix in alpha to produce RGB out
r = (oldAr + (r*alpha))/_amask;
g = (oldAg + (g*alpha))/_amask;
b = (oldAb + (b*alpha))/_amask;
} }
RGBToPixel(r,g,b,pixel); else
sa = _amask;
if (sa == 0) // dest wouldn't be changed
continue;
if (fraction < 1.0)
sa *= fraction;
alpha = ((double) sa) / _amask;
// Now get dest pixel
pixel = XGetPixel(dest_im->image, col, row);
PixelToRGB (pixel, dr, dg, db);
if (dest_alpha)
{
pixel = XGetPixel(dest_alpha->image, col, row);
da = (pixel >> _ashift) & _amask;
}
else // no alpha channel, background is opaque
da = _amask;
ialpha = (1.0 - alpha);
dr = (sr * alpha) + (dr * ialpha);
dg = (sg * alpha) + (dg * ialpha);
db = (sb * alpha) + (db * ialpha);
// calc final alpha
if (sa == _amask || da == _amask)
da = _amask;
else
da = sa + (da * ialpha);
CLAMP(dr);
CLAMP(dg);
CLAMP(db);
CLAMP(da);
RGBToPixel(dr, dg, db, pixel);
XPutPixel(dest_im->image, col, row, pixel); XPutPixel(dest_im->image, col, row, pixel);
if (dest_alpha) if (dest_alpha)
{ XPutPixel(dest_alpha->image, col, row, da << _ashift);
unsigned short dalpha;
unsigned long dpixel;
/* Alpha gets mixed the same as all the
other color components */
dpixel = XGetPixel(dest_alpha->image, col, row);
dalpha = (dpixel >> _ashift) & _amask;
dalpha = alpha + dalpha * (_amask - alpha)/_amask;
XPutPixel(dest_alpha->image, col, row, dalpha << _ashift );
}
} }
} }
} }
@ -222,7 +223,6 @@ _pixmap_combine_alpha(RContext *context,
pixel = (unsigned long)-1; // Never valid? pixel = (unsigned long)-1; // Never valid?
c2.pixel = pixel; c2.pixel = pixel;
for (row = 0; row < srect.height; row++) for (row = 0; row < srect.height; row++)
{ {
unsigned col; unsigned col;
@ -858,14 +858,6 @@ _bitmap_combine_alpha(RContext *context,
{ {
unsigned long pixel; unsigned long pixel;
unsigned short oldAlpha = 0;
unsigned long oldPixel = 0;
unsigned short oldAr = 0;
unsigned short oldAg = 0;
unsigned short oldAb = 0;
unsigned char oldBr = 0;
unsigned char oldBg = 0;
unsigned char oldBb = 0;
/* Two cases, the *_FAST* method, which /* Two cases, the *_FAST* method, which
is covered in the first a part of the if is covered in the first a part of the if
@ -915,74 +907,68 @@ _bitmap_combine_alpha(RContext *context,
for (col = 0; col < drect.width; col++) for (col = 0; col < drect.width; col++)
{ {
unsigned short r = *rptr++; unsigned short sr = (*rptr++ >> (8 - _rwidth));
unsigned short g = *gptr++; unsigned short sg = (*gptr++ >> (8 - _gwidth));
unsigned short b = *bptr++; unsigned short sb = (*bptr++ >> (8 - _bwidth));
unsigned short alpha = *aptr++;; unsigned short sa = (*aptr++ >> (8 - _awidth));
unsigned dr, dg, db, da;
double alpha = (double) sa / ((1 << _rwidth) - 1);
if (sa == 0) // dest wouldn't be changed
continue;
/* /*
* Convert 8-bit components down to the 5-bit values * Unscale alpha value in each color component
* that the display system can actually handle.
*/ */
r >>= (8 - _rwidth); if (sa < _amask)
g >>= (8 - _gwidth);
b >>= (8 - _bwidth);
if (has_alpha)
{ {
if (dest_alpha) double multiplier = (double) _amask / sa;
{
unsigned short dalpha; sr *= multiplier;
unsigned long dpixel; sg *= multiplier;
/* Alpha gets mixed the same as all the sb *= multiplier;
other color components */ }
dpixel = XGetPixel(dest_alpha->image, col, row);
dalpha = (dpixel >> _ashift) & _amask;
dalpha = alpha + dalpha * (_amask - alpha)/_amask;
XPutPixel(dest_alpha->image, col, row,
dalpha << _ashift);
}
if (alpha == 0)
continue; // background unchanged.
if (alpha != _amask) // get the destination pixel
{ pixel = XGetPixel(dest_im->image, col, row);
unsigned short ialpha = _amask - alpha; PixelToRGB(pixel, dr, dg, db);
/*
* Get the background pixel and convert to RGB. if (dest_alpha)
*/ {
pixel = XGetPixel(dest_im->image, col, row); pixel = XGetPixel(dest_alpha->image, col, row);
if (pixel != oldPixel) da = (pixel >> _ashift) & _amask;
{ }
oldPixel = pixel; else // no alpha channel, background is opaque
PixelToRGB(pixel,oldBr,oldBg,oldBb); da = _amask;
oldAlpha = 0;
}
if (alpha != oldAlpha)
{
oldAlpha = alpha;
oldAr = ialpha * oldBr;
oldAg = ialpha * oldBg;
oldAb = ialpha * oldBb;
}
// mix in alpha to produce RGB out if (sa == _amask || da == 0) // source only
r = (oldAr + (r * alpha)) / _amask; {
g = (oldAg + (g * alpha)) / _amask; dr = sr;
b = (oldAb + (b * alpha)) / _amask; dg = sg;
} db = sb;
da = sa;
} }
else else
{ {
/* Not using alpha, but we still have to set it double ialpha = (1.0 - alpha);
in the pixmap */ dr = (sr * alpha) + (dr * ialpha);
if (dest_alpha) dg = (sg * alpha) + (dg * ialpha);
XPutPixel(dest_alpha->image, col, row, db = (sb * alpha) + (db * ialpha);
_amask << _ashift); if (da == _amask || da == _amask)
da = _amask;
else
da = sa + (da * ialpha);
} }
RGBToPixel(r,g,b,pixel); CLAMP(dr);
CLAMP(dg);
CLAMP(db);
CLAMP(da);
RGBToPixel(dr, dg, db, pixel);
XPutPixel(dest_im->image, col, row, pixel); XPutPixel(dest_im->image, col, row, pixel);
if (dest_alpha)
XPutPixel(dest_alpha->image, col, row, da << _ashift);
} }
} }
} }