From dcc91c6c387489b89ec3d3988762f66cea770e55 Mon Sep 17 00:00:00 2001 From: Massimo Del Fedele Date: Sun, 18 Jul 2010 12:26:11 +0200 Subject: [PATCH] DIB Engine: fixes against wine tests --- dlls/winedib.drv/bitblt.c | 68 +++--- dlls/winedib.drv/convert.c | 16 +- dlls/winedib.drv/dc.c | 32 +-- dlls/winedib.drv/dib.c | 405 ++++++++++++++++++++++++++++++++-- dlls/winedib.drv/dibdrv.h | 27 ++- dlls/winedib.drv/dibdrvbitmap.c | 124 ++++++++++- dlls/winedib.drv/graphics.c | 10 +- dlls/winedib.drv/palette.c | 63 ++++++ dlls/winedib.drv/pen_brush.c | 95 +++++--- dlls/winedib.drv/primitives_bitblt.c | 18 +- dlls/winedib.drv/primitives_color.c | 71 ++++-- dlls/winedib.drv/primitives_convert.c | 66 ++++-- dlls/winedib.drv/primitives_pixel.c | 44 ++-- 13 files changed, 883 insertions(+), 156 deletions(-) diff --git a/dlls/winedib.drv/bitblt.c b/dlls/winedib.drv/bitblt.c index db661428005..97feefdd96e 100644 --- a/dlls/winedib.drv/bitblt.c +++ b/dlls/winedib.drv/bitblt.c @@ -82,7 +82,7 @@ static BOOL BitBlt_ClipAreas(POINT *ps, POINT *pd, SIZE *sz, RECT*srcClip, RECT* ys1 = ps->y; xs2 = xs1 + w; ys2 = ys1 + h; - + /* if source clip area is not null, do first clipping on it */ if(srcClip) { @@ -91,7 +91,7 @@ static BOOL BitBlt_ClipAreas(POINT *ps, POINT *pd, SIZE *sz, RECT*srcClip, RECT* ysc1 = srcClip->top; xsc2 = srcClip->right; ysc2 = srcClip->bottom; - + /* order clip area rectangle points */ if(xsc1 > xsc2) intSwap(&xsc1, &xsc2); if(ysc1 > ysc2) intSwap(&ysc1, &ysc2); @@ -103,13 +103,12 @@ static BOOL BitBlt_ClipAreas(POINT *ps, POINT *pd, SIZE *sz, RECT*srcClip, RECT* /* clip on source clipping end point */ if(xs2 > xsc2) { dx = xs2 - xsc2; w -= dx; xd2 -= dx; xs2 = xsc2; } if(ys2 > ysc2) { dy = ys2 - ysc2; h -= dy; yd2 -= dy; ys2 = ysc2; } - + /* if already zero area, return false */ if(w <= 0 || h <= 0) return FALSE; } /* now do clipping on destination area */ - if(dstClip) { /* extract destination clipping area */ @@ -117,7 +116,7 @@ static BOOL BitBlt_ClipAreas(POINT *ps, POINT *pd, SIZE *sz, RECT*srcClip, RECT* ydc1 = dstClip->top; xdc2 = dstClip->right; ydc2 = dstClip->bottom; - + /* order clip area rectangle points */ if(xdc1 > xdc2) intSwap(&xdc1, &xdc2); if(ydc1 > ydc2) intSwap(&ydc1, &ydc2); @@ -267,6 +266,13 @@ BOOL _DIBDRV_InternalAlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, _DIBDRV_Sizes_ws2ds(physDevDst, &widthDst, &heightDst); _DIBDRV_Position_ws2ds(physDevSrc, &xSrc, &ySrc); _DIBDRV_Sizes_ws2ds(physDevSrc, &widthSrc, &heightSrc); + + /* from tests, it seems that negative coords on phys space are not allowed */ + if(xDst < 0 || yDst < 0 || xSrc < 0 || ySrc < 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } /* first clip on physical DC sizes */ setPoint(&pd, xDst, yDst); @@ -282,7 +288,7 @@ BOOL _DIBDRV_InternalAlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, else res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip); if(!res) - return FALSE; + return TRUE; xDst = pd.x; yDst = pd.y; xSrc = ps.x; ySrc = ps.y; widthDst = szDst.cx; heightDst = szDst.cy; @@ -317,9 +323,7 @@ BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT width BOOL res; POINT pd = {xDst, yDst}; - POINT ps = {xSrc, ySrc}; SIZE szDst = {widthDst, heightDst}; - SIZE szSrc = {widthSrc, heightSrc}; MAYBE(TRACE("physDevDst:%p(%s%s), xDst:%d, yDst:%d, widthDst:%d, heightDst:%d, physDevSrc:%p(%s%s), xSrc:%d, ySrc:%d, widthSrc:%d, heightSrc:%d\n", physDevDst, physDevDst->hasDIB ? "DIB-" : "DDB", physDevDst->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevDst->physBitmap) : "", @@ -327,10 +331,12 @@ BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT width physDevSrc, physDevSrc->hasDIB ? "DIB-" : "DDB", physDevSrc->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevSrc->physBitmap) : "", xSrc, ySrc, widthSrc, heightSrc)); - /* if sizes are null or negative, returns false */ - if(widthSrc <= 0 || heightSrc <= 0 || widthDst <= 0 || heightDst <= 0) + /* if sizes are null or negative, or source positions are negatives, returns false */ + if(widthSrc <= 0 || heightSrc <= 0 || + widthDst <= 0 || heightDst <= 0) { res = FALSE; + SetLastError(ERROR_INVALID_PARAMETER); goto fin; } @@ -360,18 +366,25 @@ BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT width /* DDB selected on dest DC -- must double-convert */ HBITMAP tmpDIB, stock; HDC tmpDC; - RECT srcClip = {0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height}; MAYBE(TRACE("Blending DIB->DDB\n")); - /* clip blit area */ - res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, 0); - if(!res) + /* we should anyways convert dest to physical coordinates here before processing + in order to check its consistency -- source coords will be converted/clipped later + As we do a conversion to a temporary DIB for destination, we don't care about it */ + _DIBDRV_Position_ws2ds(physDevDst, &pd.x, &pd.y); + _DIBDRV_Sizes_ws2ds(physDevDst, &szDst.cx, &szDst.cy); + + /* test shows that negatives origins are not allowed */ + if(pd.x < 0 || pd.y < 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + res = FALSE; goto fin; - xDst = pd.x; yDst = pd.y; widthDst = szDst.cx; heightDst = szDst.cy; - xSrc = ps.x; ySrc = ps.y; widthSrc = szSrc.cx; heightSrc = szSrc.cy; + } /* converts dest DDB onto a temporary DIB -- just the needed part */ - tmpDIB = _DIBDRV_ConvertDevDDBtoDIB(physDevDst->hdc, physDevSrc->hdc, xDst, yDst, widthDst, heightDst); + /* WARNING -- that one could fail if rectangle on dest id out of range */ + tmpDIB = _DIBDRV_ConvertDevDDBtoDIB(physDevDst->hdc, physDevSrc->hdc, pd.x, pd.y, szDst.cx, szDst.cy); if(!tmpDIB) { ERR("Couldn't convert dest DDB to DIB\n"); @@ -399,7 +412,7 @@ BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT width } /* blends source DIB onto temp DIB and re-blits onto dest DC */ - res = GdiAlphaBlend(tmpDC, 0, 0, widthDst, heightDst, physDevSrc->hdc, xSrc, ySrc, widthSrc, heightSrc, blendfn); + res = GdiAlphaBlend(tmpDC, 0, 0, szDst.cx, szDst.cy, physDevSrc->hdc, xSrc, ySrc, widthSrc, heightSrc, blendfn); if(!res) MAYBE(TRACE("AlphaBlend failed\n")); else @@ -438,6 +451,7 @@ BOOL _DIBDRV_InternalBitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, setPoint(&ps, xSrc, ySrc); setSize(&sz, width, height); setRect(&dstClip, 0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height); + if(physDevSrc) { setRect(&srcClip, 0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height); @@ -446,13 +460,13 @@ BOOL _DIBDRV_InternalBitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, else res = BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip); if(!res) - return FALSE; + return TRUE; xDst = pd.x; yDst = pd.y; xSrc = ps.x; ySrc = ps.y; width = sz.cx; height = sz.cy; /* then, do blitting for each dest clip area (no clipping on source) */ - res = FALSE; + res = TRUE; for(iRec = 0; iRec < physDevDst->regionRectCount; iRec++) { RECT *r = physDevDst->regionRects + iRec; @@ -462,8 +476,8 @@ BOOL _DIBDRV_InternalBitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, setSize(&sz, width, height); if(!BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip)) continue; - if(physDevDst->physBitmap.funcs->BitBlt(physDevDst, pd.x, pd.y, sz.cx, sz.cy, physDevSrc, ps.x, ps.y, rop)) - res = TRUE; + if(!physDevDst->physBitmap.funcs->BitBlt(physDevDst, pd.x, pd.y, sz.cx, sz.cy, physDevSrc, ps.x, ps.y, rop)) + res = FALSE; } return res; } @@ -503,8 +517,8 @@ BOOL DIBDRV_BitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, /* source is a DDB, must convert it to DIB */ /* don't clip on source */ - res = BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip); - if(!res) + res = !BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip); + if(res) goto noBlt2; xDst = pd.x; yDst = pd.y; width = sz.cx; height = sz.cy; xSrc = ps.x; ySrc = ps.y; @@ -596,11 +610,11 @@ BOOL DIBDRV_BitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, if(physDevSrc) { RECT srcClip = {0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height}; - res = BitBlt_ClipAreas(&ps, &pd, &sz, &srcClip, 0); + res = !BitBlt_ClipAreas(&ps, &pd, &sz, &srcClip, 0); } else - res = TRUE; - if(!res) + res = FALSE; + if(res) goto noBlt3; xDst = pd.x; yDst = pd.y; width = sz.cx; height = sz.cy; xSrc = ps.x; ySrc = ps.y; diff --git a/dlls/winedib.drv/convert.c b/dlls/winedib.drv/convert.c index dc18e14a47c..2f20ac12a1f 100644 --- a/dlls/winedib.drv/convert.c +++ b/dlls/winedib.drv/convert.c @@ -51,7 +51,7 @@ HBITMAP _DIBDRV_ConvertDIBtoDDB( HDC hdc, HBITMAP srcBmp, int startScan, int sca HDC tmpHdc; HBITMAP tmpBmp; int res; - + /* gets DIBSECTION data from source DIB */ if(GetObjectW(srcBmp, sizeof(DIBSECTION), &ds) != sizeof(DIBSECTION)) { @@ -87,13 +87,10 @@ HBITMAP _DIBDRV_ConvertDIBtoDDB( HDC hdc, HBITMAP srcBmp, int startScan, int sca /* gets the size of DIB palette and bitfields, if any */ bitFields = 0; - if(ds.dsBmih.biBitCount > 8) - { - colorUsed = 0; - if(ds.dsBmih.biCompression == BI_BITFIELDS) + colorUsed = 0; + if(ds.dsBmih.biCompression == BI_BITFIELDS) bitFields = 3; - } - else + else if(ds.dsBmih.biBitCount <= 8) { colorUsed = ds.dsBmih.biClrUsed; if(!colorUsed) @@ -131,9 +128,11 @@ HBITMAP _DIBDRV_ConvertDIBtoDDB( HDC hdc, HBITMAP srcBmp, int startScan, int sca HeapFree(GetProcessHeap(), 0, bmi); return 0; } - GetDIBColorTable(tmpHdc, 0, colorUsed, bmi->bmiColors); + if(!GetDIBColorTable(tmpHdc, 0, colorUsed, bmi->bmiColors)) + ERR("GetDIBColorTable failed\n"); SelectObject(tmpHdc, tmpBmp); DeleteDC(tmpHdc); + } /* fill the bitfields part, if any */ @@ -165,6 +164,7 @@ HBITMAP _DIBDRV_ConvertDIBtoDDB( HDC hdc, HBITMAP srcBmp, int startScan, int sca DeleteObject( hBmp ); return 0; } + return hBmp; } diff --git a/dlls/winedib.drv/dc.c b/dlls/winedib.drv/dc.c index 9ffceee13a3..f5324b0e582 100644 --- a/dlls/winedib.drv/dc.c +++ b/dlls/winedib.drv/dc.c @@ -80,6 +80,10 @@ static DWORD get_dpi( void ) return dpi; } +/* dummy function for pen/brush drawing primitives initializations */ +static void dummy4(DIBDRVPHYSDEV *physDev, int a, int b, int c) {} ; +static void dummy5(DIBDRVPHYSDEV *physDev, int a, int b, int c, int d) {} ; + /********************************************************************** * device_init * @@ -120,10 +124,6 @@ static void device_init(void) device_init_done = TRUE; } -/* dummy null function for pen and brush */ -static void dummy3(DIBDRVPHYSDEV *p, int a, int b, int c) {} -static void dummy4(DIBDRVPHYSDEV *p, int a, int b, int c, int d) {} - /********************************************************************** * DIBDRV_CreateDC */ @@ -180,22 +180,24 @@ BOOL DIBDRV_CreateDC( HDC hdc, DIBDRVPHYSDEV **pdev, LPCWSTR driver, LPCWSTR dev physDev->backgroundColor = 0; _DIBDRV_CalcAndXorMasks(physDev->rop2, 0, &physDev->backgroundAnd, &physDev->backgroundXor); + /* stock pen */ + physDev->penStyle = PS_NULL; physDev->penColor = 0; + physDev->penColorref = 0; _DIBDRV_CalcAndXorMasks(physDev->rop2, 0, &physDev->penAnd, &physDev->penXor); - - physDev->penStyle = PS_NULL; - physDev->penHLine = dummy3; - physDev->penVLine = dummy3; - physDev->penLine = dummy4; + physDev->penHLine = dummy4; + physDev->penVLine = dummy4; + physDev->penLine = dummy5; physDev->penPattern = NULL; - physDev->brushColor = 0; - _DIBDRV_CalcAndXorMasks(physDev->rop2, 0, &physDev->brushAnd, &physDev->brushXor); + /* stock brush */ + physDev->brushStyle = BS_NULL; + physDev->brushColor = 0x0; + physDev->brushColorref = 0x0; + _DIBDRV_CalcAndXorMasks(physDev->rop2, 0x0, &physDev->brushAnd, &physDev->brushXor); physDev->brushAnds = NULL; physDev->brushXors = NULL; - - physDev->brushStyle = BS_NULL; - physDev->brushHLine = dummy3; + physDev->brushHLine = dummy4; physDev->isBrushBitmap = FALSE; _DIBDRVBITMAP_Clear(&physDev->brushBitmap); @@ -215,7 +217,7 @@ BOOL DIBDRV_CreateDC( HDC hdc, DIBDRVPHYSDEV **pdev, LPCWSTR driver, LPCWSTR dev /* sets the result value and returns */ *pdev = physDev; - + return TRUE; } diff --git a/dlls/winedib.drv/dib.c b/dlls/winedib.drv/dib.c index 653148d8c16..41fb158a2da 100644 --- a/dlls/winedib.drv/dib.c +++ b/dlls/winedib.drv/dib.c @@ -25,6 +25,43 @@ WINE_DEFAULT_DEBUG_CHANNEL(dibdrv); +/* Default 1 BPP palette */ +static DWORD pal1[] = +{ + 0x000000, + 0xffffff +}; + +/* Default 4 BPP palette */ +static DWORD pal4[] = +{ + 0x000000,0x800000,0x008000,0x808000, + 0x000080,0x800080,0x008080,0x808080, + 0xc0c0c0,0xff0000,0x00ff00,0xffff00, + 0x0000ff,0xff00ff,0x00ffff,0xffffff +}; + +/* Default 8 BPP palette */ +static DWORD pal8[] = +{ + 0x000000,0x800000,0x008000,0x808000,0x000080,0x800080,0x008080,0xc0c0c0,0xc0dcc0,0xa6caf0,0x000000,0x000033,0x000066,0x000099,0x0000cc,0x0000ff, + 0x003300,0x003333,0x003366,0x003399,0x0033cc,0x0033ff,0x006600,0x006633,0x006666,0x006699,0x0066cc,0x0066ff,0x009900,0x009933,0x009966,0x009999, + 0x0099cc,0x0099ff,0x00cc00,0x00cc33,0x00cc66,0x00cc99,0x00cccc,0x00ccff,0x00ff00,0x00ff33,0x00ff66,0x00ff99,0x00ffcc,0x00ffff,0x330000,0x330033, + 0x330066,0x330099,0x3300cc,0x3300ff,0x333300,0x333333,0x333366,0x333399,0x3333cc,0x3333ff,0x336600,0x336633,0x336666,0x336699,0x3366cc,0x3366ff, + 0x339900,0x339933,0x339966,0x339999,0x3399cc,0x3399ff,0x33cc00,0x33cc33,0x33cc66,0x33cc99,0x33cccc,0x33ccff,0x33ff00,0x33ff33,0x33ff66,0x33ff99, + 0x33ffcc,0x33ffff,0x660000,0x660033,0x660066,0x660099,0x6600cc,0x6600ff,0x663300,0x663333,0x663366,0x663399,0x6633cc,0x6633ff,0x666600,0x666633, + 0x666666,0x666699,0x6666cc,0x6666ff,0x669900,0x669933,0x669966,0x669999,0x6699cc,0x6699ff,0x66cc00,0x66cc33,0x66cc66,0x66cc99,0x66cccc,0x66ccff, + 0x66ff00,0x66ff33,0x66ff66,0x66ff99,0x66ffcc,0x66ffff,0x990000,0x990033,0x990066,0x990099,0x9900cc,0x9900ff,0x993300,0x993333,0x993366,0x993399, + 0x9933cc,0x9933ff,0x996600,0x996633,0x996666,0x996699,0x9966cc,0x9966ff,0x999900,0x999933,0x999966,0x999999,0x9999cc,0x9999ff,0x99cc00,0x99cc33, + 0x99cc66,0x99cc99,0x99cccc,0x99ccff,0x99ff00,0x99ff33,0x99ff66,0x99ff99,0x99ffcc,0x99ffff,0xcc0000,0xcc0033,0xcc0066,0xcc0099,0xcc00cc,0xcc00ff, + 0xcc3300,0xcc3333,0xcc3366,0xcc3399,0xcc33cc,0xcc33ff,0xcc6600,0xcc6633,0xcc6666,0xcc6699,0xcc66cc,0xcc66ff,0xcc9900,0xcc9933,0xcc9966,0xcc9999, + 0xcc99cc,0xcc99ff,0xcccc00,0xcccc33,0xcccc66,0xcccc99,0xcccccc,0xccccff,0xccff00,0xccff33,0xccff66,0xccff99,0xccffcc,0xccffff,0xff0000,0xff0033, + 0xff0066,0xff0099,0xff00cc,0xff00ff,0xff3300,0xff3333,0xff3366,0xff3399,0xff33cc,0xff33ff,0xff6600,0xff6633,0xff6666,0xff6699,0xff66cc,0xff66ff, + 0xff9900,0xff9933,0xff9966,0xff9999,0xff99cc,0xff99ff,0xffcc00,0xffcc33,0xffcc66,0xffcc99,0xffcccc,0xffccff,0xffff00,0xffff33,0xffff66,0xffff99, + 0xffffcc,0xffffff,0x050500,0x050501,0x050502,0x050503,0x050504,0x050505,0xe8e8e8,0xe9e9e9,0xeaeaea,0xebebeb,0xececec,0xededed,0xeeeeee,0xefefef, + 0xf0f0f0,0xf1f1f1,0xf2f2f2,0xf3f3f3,0xf4f4f4,0xf5f5f5,0xfffbf0,0xa0a0a4,0x808080,0xf00000,0x00ff00,0xffff00,0x0000ff,0xff00ff,0x00ffff,0xffffff +}; + /*********************************************************************** * DIBDRV_CreateDIBSection */ @@ -46,15 +83,206 @@ HBITMAP DIBDRV_CreateDIBSection( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, * DIBDRV_GetDIBits */ INT DIBDRV_GetDIBits( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, UINT startscan, - UINT lines, LPCVOID bits, const BITMAPINFO *bmi, UINT coloruse ) + UINT lines, LPVOID bits, BITMAPINFO *info, UINT coloruse ) { INT res; - - MAYBE(TRACE("physDev:%p, hbitmap:%p, startscan:%d, lines:%d, bits:%p, bmi:%p, coloruse:%d\n", - physDev, hbitmap, startscan, lines, bits, bmi, coloruse)); + DIBSECTION ds; + DIBDRVBITMAP sBmp, dBmp; + DWORD *buf; + int iLine; + int size; + BOOL justInfo, justInfoHeader; + int requestedBpp; + RGBQUAD *colorTable; + int colorTableSize; + BITMAPINFO *sourceInfo; - /* GetDIBits reads bits from a DDB, so we should use the X11 driver */ - res = _DIBDRV_GetDisplayDriver()->pGetDIBits(physDev->X11PhysDev, hbitmap, startscan, lines, bits, bmi, coloruse); + MAYBE(TRACE("physDev:%p, hbitmap:%p, startscan:%d, lines:%d, bits:%p, info:%p, coloruse:%d\n", + physDev, hbitmap, startscan, lines, bits, info, coloruse)); + if(GetObjectW(hbitmap, sizeof(DIBSECTION), &ds) == sizeof(DIBSECTION)) + { + /* GetDIBits reads bits from a DIB, so we should use the engine driver */ + + /* for the moment, we don't support startscan != 0 */ + if(startscan != 0) + { + FIXME("startscan != 0 still not supported\n"); + return 0; + } + + /* sanity check */ + size = info->bmiHeader.biSize; + if(size != sizeof(BITMAPINFOHEADER) && size != sizeof(BITMAPCOREHEADER)) + { + ERR("Unknown header size %d\n", size); + return 0; + } + + /* get requested BPP */ + requestedBpp = info->bmiHeader.biBitCount; + + /* check wetrher we wants just the BITMAPINFO data */ + justInfo = (bits == NULL); + + /* check wether we wants just to get BITMAPINFOHEADER data */ + justInfoHeader = (requestedBpp == 0); + + if(!justInfo && justInfoHeader) + { + ERR("Bad requested BPP\n"); + return 0; + } + + /* copy / set missing DIB info */ + if(justInfo) + { + info->bmiHeader.biWidth = ds.dsBmih.biWidth; + info->bmiHeader.biHeight = ds.dsBmih.biHeight; + } + info->bmiHeader.biPlanes = 1; + if(justInfoHeader) + info->bmiHeader.biBitCount = ds.dsBmih.biBitCount; + if(size == sizeof(BITMAPINFOHEADER)) + { + if(justInfoHeader) + { + info->bmiHeader.biCompression = ds.dsBmih.biCompression; + info->bmiHeader.biXPelsPerMeter = ds.dsBmih.biXPelsPerMeter; + info->bmiHeader.biYPelsPerMeter = ds.dsBmih.biYPelsPerMeter; + info->bmiHeader.biClrUsed = ds.dsBmih.biClrUsed; + info->bmiHeader.biClrImportant = ds.dsBmih.biClrImportant; + } + info->bmiHeader.biSizeImage = ds.dsBmih.biSizeImage; + } + + /* width and height *must* match source's ones */ + if(info->bmiHeader.biWidth != ds.dsBmih.biWidth || + abs(info->bmiHeader.biHeight) != abs(ds.dsBmih.biHeight)) + { + ERR("Size of requested bitmap data don't match source's ones\n"); + return 0; + } + + /* if we just wants the BITMAPINFOHEADER data, we're done */ + if(justInfoHeader || (justInfo && ds.dsBmih.biBitCount > 8)) + return abs(info->bmiHeader.biHeight); + + /* we now have to get source data -- we need it for palette, for example */ + colorTableSize = 0; + if(ds.dsBmih.biBitCount <= 8) + colorTableSize = (1 << ds.dsBmih.biBitCount); + else if(ds.dsBmih.biCompression == BI_BITFIELDS) + colorTableSize = 3; + sourceInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER) + colorTableSize * sizeof(RGBQUAD)); + if(!sourceInfo) + { + ERR("HeapAlloc failed\n"); + return 0; + } + memcpy(sourceInfo, &ds.dsBmih, sizeof(BITMAPINFOHEADER)); + if(ds.dsBmih.biBitCount <= 8) + { + /* grab palette - well, we should. No way to do it by now.... + we should add a list HBITMAP <--> DIBDRVBITMAP and fiddle to many + , many parts of the engine. Not worth the effort by now. + So, we just synthesize the table */ + switch(requestedBpp) + { + case 1: + memcpy((BYTE *)sourceInfo + sizeof(BITMAPINFOHEADER), pal1, 2*sizeof(DWORD)); + break; + + case 4: + memcpy((BYTE *)sourceInfo + sizeof(BITMAPINFOHEADER), pal4, 16*sizeof(DWORD)); + break; + + case 8: + memcpy((BYTE *)sourceInfo + sizeof(BITMAPINFOHEADER), pal8, 256*sizeof(DWORD)); + break; + + default: + ERR("Unknown requested bith depth %d\n", requestedBpp); + _DIBDRVBITMAP_Free(&sBmp); + return 0; + } + } + else if(ds.dsBmih.biCompression == BI_BITFIELDS) + memcpy((BYTE *)sourceInfo + sizeof(BITMAPINFOHEADER), ds.dsBitfields, 3 * sizeof(RGBQUAD)); + _DIBDRVBITMAP_Clear(&sBmp); + if(!_DIBDRVBITMAP_InitFromBitmapinfo(&sBmp, sourceInfo)) + { + ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n"); + HeapFree(GetProcessHeap(), 0, sourceInfo); + return 0; + } + _DIBDRVBITMAP_Set_Bits(&sBmp, ds.dsBm.bmBits, FALSE); + HeapFree(GetProcessHeap(), 0, sourceInfo); + + /* now grab / synthesize the color table if needed */ + if(requestedBpp <= 8) + { + colorTable = (RGBQUAD *)((BYTE *)info + size); + if(requestedBpp == ds.dsBmih.biBitCount) + { + /* same source and dest format - copy color tables */ + memcpy(colorTable, sBmp.colorTable, colorTableSize); + } + else + { + /* different formats -- synthesize color table */ + switch(requestedBpp) + { + case 1: + memcpy(colorTable, pal1, 2*sizeof(DWORD)); + break; + + case 4: + memcpy(colorTable, pal4, 16*sizeof(DWORD)); + break; + + case 8: + memcpy(colorTable, pal8, 256*sizeof(DWORD)); + break; + + default: + ERR("Unknown requested bith depth %d\n", requestedBpp); + _DIBDRVBITMAP_Free(&sBmp); + return 0; + } + } + } + + /* if we just wanted DIB info, job is done */ + if(justInfo) + { + _DIBDRVBITMAP_Free(&sBmp); + return abs(info->bmiHeader.biHeight); + } + + /* Creates a DIBDRVBITMAP from dest dib */ + _DIBDRVBITMAP_Clear(&dBmp); + if(!_DIBDRVBITMAP_InitFromBitmapinfo(&dBmp, info)) + { + ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n"); + _DIBDRVBITMAP_Free(&sBmp); + return 0; + } + _DIBDRVBITMAP_Set_Bits(&dBmp, bits, FALSE); + + /* now we can do the bit conversion */ + buf = HeapAlloc(GetProcessHeap(), 0, ds.dsBmih.biWidth * sizeof(RGBQUAD)); + for(iLine = 0; iLine < lines; iLine++) + { + sBmp.funcs->GetLine(&sBmp, iLine, 0, ds.dsBmih.biWidth, buf); + dBmp.funcs->PutLine(&dBmp, iLine, 0, ds.dsBmih.biWidth, buf); + } + _DIBDRVBITMAP_Free(&sBmp); + _DIBDRVBITMAP_Free(&dBmp); + return lines; + } + else + /* GetDIBits reads bits from a DDB, use X11 driver */ + res = _DIBDRV_GetDisplayDriver()->pGetDIBits(physDev->X11PhysDev, hbitmap, startscan, lines, bits, info, coloruse); return res; } @@ -66,7 +294,10 @@ UINT DIBDRV_SetDIBColorTable( DIBDRVPHYSDEV *physDev, UINT start, UINT count, const RGBQUAD *colors ) { DIBDRVBITMAP *dib = &physDev->physBitmap; - +#if 0 + HBITMAP thisDIB; +#endif + MAYBE(TRACE("physDev:%p, start:%d, count:%d, colors:%p\n", physDev, start, count, colors)); /* SetDIBColorTable operates on a DIB, so we use the engine */ @@ -80,7 +311,7 @@ UINT DIBDRV_SetDIBColorTable( DIBDRVPHYSDEV *physDev, UINT start, UINT count, /* if dib hasn't a color table, or has a small one, we must before create/extend it */ - if(!(dib->colorTable)) + if(!dib->colorTable) { dib->colorTableSize = (1 << dib->bitCount); dib->colorTable = HeapAlloc(GetProcessHeap(), 0, sizeof(RGBQUAD) * dib->colorTableSize); @@ -104,6 +335,13 @@ UINT DIBDRV_SetDIBColorTable( DIBDRVPHYSDEV *physDev, UINT start, UINT count, memcpy(dib->colorTable + start, colors, sizeof(RGBQUAD) * count); dib->colorTableGrabbed = TRUE; + /* hack to make GDI32 sense the DIB color table change + (fixes a couple of todos in bitmap test suite */ +#if 0 + thisDIB = SelectObject(physDev->hdc, GetStockObject(OBJ_BITMAP)); + SelectObject(physDev->hdc, thisDIB); +#endif + return TRUE; } @@ -114,13 +352,59 @@ INT DIBDRV_SetDIBits( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, UINT startscan, UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT coloruse ) { INT res; + DIBSECTION ds; + DIBDRVBITMAP sBmp, dBmp; + DWORD *buf; + int iLine; MAYBE(TRACE("physDev:%p, hbitmap:%p, startscan:%d, lines:%d, bits:%p, bmi:%p, coloruse:%d\n", physDev, hbitmap, startscan, lines, bits, info, coloruse)); - /* SetDIBits writes bits to a DDB, so we should use the X11 driver */ - res = _DIBDRV_GetDisplayDriver()->pSetDIBits(physDev->X11PhysDev, hbitmap, startscan, lines, bits, info, coloruse); + if(GetObjectW(hbitmap, sizeof(DIBSECTION), &ds) == sizeof(DIBSECTION)) + { + /* SetDIBits writes bits to a DIB, so we should use the engine driver */ + + /* for the moment, we don't support startscan != 0 */ + if(startscan != 0) + { + FIXME("startscan != 0 still not supported\n"); + return 0; + } + + /* Creates a DIBDRVBITMAP from source dib */ + _DIBDRVBITMAP_Clear(&sBmp); + if(!_DIBDRVBITMAP_InitFromBitmapinfo(&sBmp, info)) + { + ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n"); + return 0; + } + _DIBDRVBITMAP_Set_Bits(&sBmp, (LPVOID)bits, FALSE); + + /* same for destination dib */ + if(!_DIBDRVBITMAP_InitFromHBITMAP(&dBmp, hbitmap, FALSE)) + { + ERR("_DIBDRVBITMAP_InitFromHBITMAP failed\n"); + _DIBDRVBITMAP_Free(&sBmp); + return 0; + } + + /* now we can do the bit conversion */ + buf = HeapAlloc(GetProcessHeap(), 0, ds.dsBmih.biWidth * sizeof(RGBQUAD)); + for(iLine = 0; iLine < lines; iLine++) + { + sBmp.funcs->GetLine(&sBmp, iLine, 0, ds.dsBmih.biWidth, buf); + dBmp.funcs->PutLine(&dBmp, iLine, 0, ds.dsBmih.biWidth, buf); + } + _DIBDRVBITMAP_Free(&sBmp); + _DIBDRVBITMAP_Free(&dBmp); + return lines; + } + else + { + /* SetDIBits writes bits to a DDB, so we should use the X11 driver */ + res = _DIBDRV_GetDisplayDriver()->pSetDIBits(physDev->X11PhysDev, hbitmap, startscan, lines, bits, info, coloruse); + } return res; } @@ -132,14 +416,105 @@ INT DIBDRV_SetDIBitsToDevice( DIBDRVPHYSDEV *physDev, INT xDest, INT yDest, DWOR UINT startscan, UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT coloruse ) { - INT res; + BITMAPINFO *bitmapInfo; + int bmInfoSize; + int dibHeight, dibWidth; + DIBDRVBITMAP sBmp; + int sLine, dLine, iLine; + void *buf; MAYBE(TRACE("physDev:%p, xDest:%d, yDest:%d, cx:%x, cy:%x, xSrc:%d, ySrc:%d, startscan:%d, lines:%d, bits:%p, info:%p, coloruse:%d\n", physDev, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, bits, info, coloruse)); - /* SetDIBitsToDevice operates on a physical device, so we should use the X11 driver */ - res = _DIBDRV_GetDisplayDriver()->pSetDIBitsToDevice(physDev->X11PhysDev, xDest, yDest, cx, cy, xSrc, ySrc, - startscan, lines, bits, info, coloruse); + if(physDev->hasDIB) + { + /* DIB section selected in, use DIB Engine */ + + /* inverts y on source -- FIXME: check if right with some tests, it seems so */ + ySrc = abs(info->bmiHeader.biHeight) - ySrc - cy; + + dibHeight = info->bmiHeader.biHeight; + dibWidth = info->bmiHeader.biWidth; - return res; + /* sanity check and source clipping on physical sizes */ + if(startscan >= abs(dibHeight)) + return 0; + if(startscan + lines > abs(dibHeight)) + lines = abs(dibHeight) - startscan; + + /* adjust height because of startscan */ + dibHeight += (dibHeight > 0 ? -startscan : startscan); + + if(xSrc >= dibWidth) + return 0; + if(xSrc + cx > dibWidth) + cx = dibWidth - xSrc; + if(ySrc > abs(dibHeight)) + return 0; + if(ySrc + cy > abs(dibHeight)) + cy = abs(dibHeight) - ySrc; + + ySrc -= startscan; + cy -= startscan; + if(cy <= 0) + return 0; + if(ySrc < 0) + { + yDest += ySrc; + cy += ySrc; + ySrc = 0; + } + if(cy <= 0) + return 0; + + /* grab a copy of BITMAPINFO */ + bmInfoSize = sizeof(BITMAPINFOHEADER); + if(info->bmiHeader.biCompression == BI_BITFIELDS) + bmInfoSize += 3 * sizeof(RGBQUAD); + else if (info->bmiHeader.biBitCount <= 8) + { + if(info->bmiHeader.biClrUsed) + bmInfoSize += info->bmiHeader.biClrUsed * sizeof(RGBQUAD); + else + bmInfoSize += (1 << info->bmiHeader.biBitCount) * sizeof(RGBQUAD); + } + if(!(bitmapInfo = HeapAlloc(GetProcessHeap(), 0, bmInfoSize))) + { + ERR("HeapAlloc failed\n"); + return 0; + } + memcpy(bitmapInfo, info, bmInfoSize); + bitmapInfo->bmiHeader.biHeight = dibHeight; + + /* create a DIBDRVBITMAP from BITMAPINFO data */ + _DIBDRVBITMAP_Clear(&sBmp); + if(!_DIBDRVBITMAP_InitFromBitmapinfo(&sBmp, bitmapInfo)) + { + ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n"); + HeapFree(GetProcessHeap, 0, bitmapInfo); + return 0; + } + HeapFree(GetProcessHeap(), 0, bitmapInfo); + _DIBDRVBITMAP_Set_Bits(&sBmp, (LPVOID)bits, FALSE); + + /* transfer lines to dest bitmap */ + if(!(buf = HeapAlloc(GetProcessHeap(), 0, cx * sizeof(RGBQUAD)))) + { + ERR("HeapAlloc failed\n"); + return 0; + } + for(sLine = ySrc, dLine = yDest, iLine = 0; iLine < cy; sLine++, dLine++, iLine++) + { + sBmp.funcs->GetLine(&sBmp, sLine, xSrc, cx, buf); + physDev->physBitmap.funcs->PutLine(&physDev->physBitmap, dLine, xDest, cx, buf); + } + HeapFree(GetProcessHeap(), 0, buf); + + return cy; + } + else + { + return _DIBDRV_GetDisplayDriver()->pSetDIBitsToDevice(physDev->X11PhysDev, xDest, yDest, cx, cy, xSrc, ySrc, + startscan, lines, bits, info, coloruse); + } } diff --git a/dlls/winedib.drv/dibdrv.h b/dlls/winedib.drv/dibdrv.h index 66cc1140676..8243d4b15ae 100644 --- a/dlls/winedib.drv/dibdrv.h +++ b/dlls/winedib.drv/dibdrv.h @@ -312,6 +312,11 @@ DWORD _DIBDRV_ROP3(DWORD p, DWORD s, DWORD d, BYTE rop); /* gets human-readable dib format name */ const char *_DIBDRVBITMAP_GetFormatName(DIBDRVBITMAP const *bmp); +/* sets/gets bits of a DIBDRVBITMAP taking in account if it's a top down + or a bottom-up DIB */ +void _DIBDRVBITMAP_Set_Bits(DIBDRVBITMAP *dib, void *bits, BOOL owns); +void *_DIBDRVBITMAP_Get_Bits(DIBDRVBITMAP *dib); + /* initializes dib from a bitmap : dib dib being initialized bi source BITMAPINFOHEADER with required DIB format info @@ -322,7 +327,7 @@ const char *_DIBDRVBITMAP_GetFormatName(DIBDRVBITMAP const *bmp); BOOL _DIBDRVBITMAP_InitFromBMIH(DIBDRVBITMAP *dib, const BITMAPINFOHEADER *bi, const DWORD *bit_fields, const RGBQUAD *color_table, void *bits); -BOOL _DIBDRVBITMAP_InitFromBitmapinfo(DIBDRVBITMAP *dib, BITMAPINFO *bmi); +BOOL _DIBDRVBITMAP_InitFromBitmapinfo(DIBDRVBITMAP *dib, const BITMAPINFO *bmi); /* initializes a DIBRDVBITMAP copying it from a source one Parameters : @@ -331,6 +336,13 @@ BOOL _DIBDRVBITMAP_InitFromBitmapinfo(DIBDRVBITMAP *dib, BITMAPINFO *bmi); copy TRUE->copy source pixel array FALSE->link to source pixel array */ BOOL _DIBDRVBITMAP_InitFromDibdrvbitmap(DIBDRVBITMAP *dib, const DIBDRVBITMAP *src, BOOL copy); +/* initializes a DIBRDVBITMAP from a DIB HBITMAP + Parameters : + bmp destination DIBDRVBITMAP + hbmp source HBITMAP + copyPixels TRUE->copy source pixel array FALSE->link to source pixel array */ +BOOL _DIBDRVBITMAP_InitFromHBITMAP(DIBDRVBITMAP *bmp, const HBITMAP hbmp, BOOL copyPixels); + /* creates a DIBRDVBITMAP copying format info from a source one Parameters : dib destination DIBDRVBITMAP @@ -413,4 +425,17 @@ void _DIBDRV_Sizes_ws2ds(DIBDRVPHYSDEV *physDev, int *w, int *h); /* converts a rectangle form Word space to Device space */ void _DIBDRV_Rect_ws2ds(DIBDRVPHYSDEV *physDev, const RECT *src, RECT *dst); +/* ********************************************************************* + * COLOR UTILITIES + * ********************************************************************/ + +/* maps a colorref to actual color */ +COLORREF _DIBDRV_MapColor(DIBDRVPHYSDEV *physDev, COLORREF color); + +/* gets nearest color index in DIB palette of a given colorref */ +DWORD _DIBDRV_GetNearestColorIndex(const DIBDRVBITMAP *dib, COLORREF color); + +/* gets nearest color to DIB palette color */ +DWORD _DIBDRV_GetNearestColor(const DIBDRVBITMAP *dib, COLORREF color); + #endif diff --git a/dlls/winedib.drv/dibdrvbitmap.c b/dlls/winedib.drv/dibdrvbitmap.c index 2c8c367a658..8e6b6531933 100644 --- a/dlls/winedib.drv/dibdrvbitmap.c +++ b/dlls/winedib.drv/dibdrvbitmap.c @@ -107,6 +107,41 @@ static void InitBitFields(DIBDRVBITMAP *dib, const DWORD *bit_fields) CalcShiftAndLen(dib->blueMask, &dib->blueShift, &dib->blueLen); } +/* sets/gets bits of a DIBDRVBITMAP taking in account if it's a top down + or a bottom-up DIB */ +void _DIBDRVBITMAP_Set_Bits(DIBDRVBITMAP *dib, void *bits, BOOL owns) +{ + /* checks whether dib is top-down or bottom-up one */ + if(dib->stride > 0) + { + /* top-down dib */ + dib->bits = bits; + } + else + { + /* bottom-up dib */ + /* data->bits always points to the top-left corner and the stride is -ve */ + dib->bits = (BYTE*)bits - (dib->height - 1) * dib->stride; + } + dib->ownsBits = owns; +} + +void *_DIBDRVBITMAP_Get_Bits(DIBDRVBITMAP * dib) +{ + /* checks whether dib is top-down or bottom-up one */ + if(dib->stride > 0) + { + /* top-down dib */ + return dib->bits; + } + else + { + /* bottom-up dib */ + /* data->bits always points to the top-left corner and the stride is -ve */ + return (BYTE*)dib->bits + (dib->height - 1) * dib->stride; + } +} + /* initializes dib from a bitmap : dib dib being initialized bi source BITMAPINFOHEADER with required DIB format info @@ -238,7 +273,7 @@ BOOL _DIBDRVBITMAP_InitFromBMIH(DIBDRVBITMAP *dib, const BITMAPINFOHEADER *bi, c return TRUE; } -BOOL _DIBDRVBITMAP_InitFromBitmapinfo(DIBDRVBITMAP *dib, BITMAPINFO *bmi) +BOOL _DIBDRVBITMAP_InitFromBitmapinfo(DIBDRVBITMAP *dib, const BITMAPINFO *bmi) { static const DWORD bit_fields_DIB32_RGB[3] = {0xff0000, 0x00ff00, 0x0000ff}; static const DWORD bit_fields_DIB16_RGB[3] = {0x7c00, 0x03e0, 0x001f}; @@ -343,6 +378,93 @@ BOOL _DIBDRVBITMAP_InitFromDibdrvbitmap(DIBDRVBITMAP *dib, const DIBDRVBITMAP *s return TRUE; } +/* initializes a DIBRDVBITMAP from a DIB HBITMAP + Parameters : + bmp destination DIBDRVBITMAP + hbmp source HBITMAP + copyPixels TRUE->copy source pixel array FALSE->link to source pixel array */ +BOOL _DIBDRVBITMAP_InitFromHBITMAP(DIBDRVBITMAP *bmp, const HBITMAP hbmp, BOOL copyPixels) +{ + BITMAPINFO *destInfo; + DIBSECTION ds; + int size; + + MAYBE(TRACE("bmp=%p, hbmp=%p, copyPixels = %s\n", bmp, hbmp, copyPixels ? "TRUE" : "FALSE")); + + /* be sure bitmap is empty */ + _DIBDRVBITMAP_Clear(bmp); + + /* gets source bitmap data */ + if(!(size = GetObjectW(hbmp, sizeof(DIBSECTION), &ds))) + { + ERR("Failed getting bitmap object\n"); + return FALSE; + } + if(size != sizeof(DIBSECTION)) + { + ERR("Bitmap is not a DIB section\n"); + return FALSE; + } + + destInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); + if(!destInfo) + { + ERR("HeapAlloc failed\n"); + return FALSE; + } + + memcpy(destInfo, &ds.dsBmih, sizeof(BITMAPINFOHEADER)); + if(ds.dsBmih.biCompression == BI_BITFIELDS) + memcpy((BITMAPINFOHEADER *)destInfo + 1, ds.dsBitfields, 3 * sizeof(RGBQUAD)); + else if(ds.dsBmih.biBitCount <= 8) + { + FIXME("Can't grab color table here.... syslvel lock\n"); + return FALSE; +#if 0 + HDC refDC = CreateCompatibleDC(0); + if(!refDC) + { + ERR("CreateCompatibleDC() failed\n"); + return FALSE; + } + if(!GetDIBits(refDC, hbmp, 0, 1, NULL, destInfo, DIB_RGB_COLORS)) + { + DeleteDC(refDC); + HeapFree(GetProcessHeap(), 0, destInfo); + ERR("GetDIBits failed\n"); + return FALSE; + } + DeleteDC(refDC); +#endif + } + if(!_DIBDRVBITMAP_InitFromBitmapinfo(bmp, destInfo)) + { + HeapFree(GetProcessHeap(), 0, destInfo); + ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n"); + return FALSE; + } + HeapFree(GetProcessHeap(), 0, destInfo); + if(copyPixels) + { + size = abs(bmp->stride) * bmp->height; + if(!(bmp->bits = HeapAlloc(GetProcessHeap(), 0, size))) + { + ERR("HeapAlloc failed\n"); + _DIBDRVBITMAP_Free(bmp); + return FALSE; + } + memcpy(bmp->bits, ds.dsBm.bmBits, size); + bmp->ownsBits = TRUE; + } + else + bmp->bits = ds.dsBm.bmBits; + if(bmp->stride < 0) + bmp->bits = (BYTE*)bmp->bits - (bmp->height - 1) * bmp->stride; + + return TRUE; +} + + /* creates a DIBRDVBITMAP copying format info from a source one Parameters : dib destination DIBDRVBITMAP diff --git a/dlls/winedib.drv/graphics.c b/dlls/winedib.drv/graphics.c index f62149c87e2..8e2c12ee2ca 100644 --- a/dlls/winedib.drv/graphics.c +++ b/dlls/winedib.drv/graphics.c @@ -132,7 +132,7 @@ static inline void SideIntersect(const POINT *p1, const POINT *p2, const RECT *r break; case TOP_SIDE: /* top */ inters->x = MulDiv(p2->x - p1->x, r->top - p1->y, p2->y - p1->y) + p1->x; - inters->y = r->bottom; + inters->y = r->top; break; case RIGHT_SIDE: /* right */ inters->x = r->right - 1; @@ -698,7 +698,7 @@ BOOL DIBDRV_Polygon( DIBDRVPHYSDEV *physDev, const POINT* ptw, int count ) { /* gets polygon bounding box -- for ytop and ybottom */ PolygonBoundingBox(clipped, clippedCount, &bBox); - + /* gets all ordered intersections of polygon with current scanline */ for(ys = bBox.top; ys < bBox.bottom; ys++) @@ -972,6 +972,12 @@ COLORREF DIBDRV_SetPixel( DIBDRVPHYSDEV *physDev, int x, int y, COLORREF color ) if(physDev->hasDIB) { + /* get real colorref */ + color = _DIBDRV_MapColor(physDev, color); + + /* map to pixel color / palette index */ + color = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, color); + _DIBDRV_Position_ws2ds(physDev, &x, &y); /* gets previous pixel */ diff --git a/dlls/winedib.drv/palette.c b/dlls/winedib.drv/palette.c index a1aa64804df..87016dab651 100644 --- a/dlls/winedib.drv/palette.c +++ b/dlls/winedib.drv/palette.c @@ -25,6 +25,69 @@ WINE_DEFAULT_DEBUG_CHANNEL(dibdrv); +/* maps a colorref to actual color */ +COLORREF _DIBDRV_MapColor(DIBDRVPHYSDEV *physDev, COLORREF color) +{ + WORD index; + RGBQUAD *palColor; + HPALETTE hPal; + PALETTEENTRY paletteEntry; + + switch(color >> 24) + { + case 0x10 : /* DIBINDEX */ + MAYBE(TRACE("DIBINDEX Color is %08x\n", color)); + index = color & 0xffff; + if(index >= physDev->physBitmap.colorTableSize) + { + WARN("DIBINDEX color out of range\n"); + return 0; + } + palColor = physDev->physBitmap.colorTable + index; + MAYBE(TRACE("Returning color %08x\n", RGB(palColor->rgbRed, palColor->rgbGreen, palColor->rgbBlue))); + return RGB(palColor->rgbRed, palColor->rgbGreen, palColor->rgbBlue); + + case 0x01: /* PALETTEINDEX */ + MAYBE(TRACE("PALETTEINDEX Color is %08x\n", color)); + index = color & 0xffff; + if(!(hPal = GetCurrentObject(physDev->hdc, OBJ_PAL))) + { + ERR("Couldn't get palette\n"); + return 0; + } + if (!GetPaletteEntries(hPal, index, 1, &paletteEntry)) + { + WARN("PALETTEINDEX(%x) : index %d is out of bounds, assuming black\n", color, index); + return 0; + } + MAYBE(TRACE("Returning color %08x\n", RGB(paletteEntry.peRed, paletteEntry.peGreen, paletteEntry.peBlue))); + return RGB(paletteEntry.peRed, paletteEntry.peGreen, paletteEntry.peBlue); + + case 0x02: /* PALETTERGB */ + return _DIBDRV_GetNearestColor(&physDev->physBitmap, color & 0xffffff); + + default: + /* RGB color -- we must process special case for monochrome bitmaps */ + if(physDev->physBitmap.bitCount == 1) + { + RGBQUAD *back = physDev->physBitmap.colorTable; + RGBQUAD *fore = back+1; + if(fore->rgbRed * fore->rgbRed + fore->rgbGreen * fore->rgbGreen + fore->rgbBlue * fore->rgbBlue < + back->rgbRed * back->rgbRed + back->rgbGreen * back->rgbGreen + back->rgbBlue * back->rgbBlue) + { + fore = back; + back = fore + 1; + } + if ( ((color >> 16) & 0xff) + ((color >> 8) & 0xff) + (color & 0xff) > 255*3/2) + return RGB(fore->rgbRed, fore->rgbGreen, fore->rgbBlue); + else + return RGB(back->rgbRed, back->rgbGreen, back->rgbBlue); + } + else + return color; + } +} + /*********************************************************************** * DIBDRV_RealizePalette */ diff --git a/dlls/winedib.drv/pen_brush.c b/dlls/winedib.drv/pen_brush.c index 7b15ece11e5..c40bfaf326e 100644 --- a/dlls/winedib.drv/pen_brush.c +++ b/dlls/winedib.drv/pen_brush.c @@ -51,7 +51,7 @@ static void SolidPenHLine(DIBDRVPHYSDEV *physDev, int x1, int x2, int y) physDev->physBitmap.funcs->SolidHLine(&physDev->physBitmap, x1, x2, y, physDev->penAnd, physDev->penXor); } -static void SolidPenVline(DIBDRVPHYSDEV *physDev, int x, int y1, int y2) +static void SolidPenVLine(DIBDRVPHYSDEV *physDev, int x, int y1, int y2) { OrderEndPoints(&y1, &y2); physDev->physBitmap.funcs->SolidVLine(&physDev->physBitmap, x, y1, y2, physDev->penAnd, physDev->penXor); @@ -65,7 +65,7 @@ static void WINAPI SolidPenLineCallback(int x, int y, LPARAM lparam) return; } -void SolidPenLine(DIBDRVPHYSDEV *physDev, int x1, int y1, int x2, int y2) +static void SolidPenLine(DIBDRVPHYSDEV *physDev, int x1, int y1, int x2, int y2) { LineDDA(x1, y1, x2, y2, SolidPenLineCallback, (LPARAM)physDev); } @@ -216,22 +216,29 @@ void _DIBDRV_ResetDashOrigin(DIBDRVPHYSDEV *physDev) physDev->markSpace = mark; } - +#if 0 /* For 1bpp bitmaps, unless the selected foreground color exactly matches foreground's colortable OR it's the WHITE color, the background color is used -- tested on WinXP */ static DWORD AdjustFgColor(DIBDRVPHYSDEV *physDev, COLORREF color) { + RGBQUAD *back = physDev->physBitmap.colorTable; RGBQUAD *fore = physDev->physBitmap.colorTable+1; - if((color & 0x00ffffff) == 0x00ffffff || - ( - fore->rgbRed == GetRValue(color) && - fore->rgbGreen == GetGValue(color) && - fore->rgbBlue == GetBValue(color) - )) - return 1; - return 0; + if( + fore->rgbRed == GetRValue(color) && + fore->rgbGreen == GetGValue(color) && + fore->rgbBlue == GetBValue(color)) + return 1; + else if( + back->rgbRed == GetRValue(color) && + back->rgbGreen == GetGValue(color) && + back->rgbBlue == GetBValue(color)) + return 0; + else if((color & 0x00ffffff) == 0x00ffffff) + return 1; + else + return 0; } static void FixupFgColors1(DIBDRVPHYSDEV *physDev) @@ -248,6 +255,45 @@ static void FixupFgColors1(DIBDRVPHYSDEV *physDev) physDev->brushAnds = NULL; physDev->brushXors = NULL; } +#endif + +#if 0 +/* For 1bpp bitmaps, unless the selected foreground color exactly + matches one of the colors in the colortable, then the color that + isn't the bkgnd color is used. */ +static DWORD AdjustFgColor(DIBDRVPHYSDEV *physDev, COLORREF color) +{ + RGBQUAD rgb; + int i; + + rgb.rgbRed = GetRValue(color); + rgb.rgbGreen = GetGValue(color); + rgb.rgbBlue = GetBValue(color); + + for(i = 0; i < physDev->physBitmap.colorTableSize; i++) + { + RGBQUAD *cur = physDev->physBitmap.colorTable + i; + if((rgb.rgbRed == cur->rgbRed) && (rgb.rgbGreen == cur->rgbGreen) && (rgb.rgbBlue == cur->rgbBlue)) + return i; + } + return ~physDev->backgroundColor & 1; +} + +static void FixupFgColors1(DIBDRVPHYSDEV *physDev) +{ + int rop = GetROP2(physDev->hdc); + + physDev->penColor = AdjustFgColor(physDev, physDev->penColorref); + physDev->brushColor = AdjustFgColor(physDev, physDev->brushColorref); + + _DIBDRV_CalcAndXorMasks(rop, physDev->penColor, &physDev->penAnd, &physDev->penXor); + _DIBDRV_CalcAndXorMasks(rop, physDev->brushColor, &physDev->brushAnd, &physDev->brushXor); + HeapFree(GetProcessHeap(), 0, physDev->brushAnds); + HeapFree(GetProcessHeap(), 0, physDev->brushXors); + physDev->brushAnds = NULL; + physDev->brushXors = NULL; +} +#endif static void SolidBrushHLine(DIBDRVPHYSDEV *physDev, int x1, int x2, int y) { @@ -310,23 +356,21 @@ HPEN DIBDRV_SelectPen( DIBDRVPHYSDEV *physDev, HPEN hpen ) { GetObjectW(hpen, sizeof(logpen), &logpen); - physDev->penColorref = logpen.lopnColor; - - if(physDev->physBitmap.bitCount == 1) - FixupFgColors1(physDev); - else - physDev->penColor = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, logpen.lopnColor); + physDev->penColorref = _DIBDRV_MapColor(physDev, logpen.lopnColor); + physDev->penColor = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, physDev->penColorref); _DIBDRV_CalcAndXorMasks(GetROP2(physDev->hdc), physDev->penColor, &physDev->penAnd, &physDev->penXor); + physDev->penStyle = logpen.lopnStyle; switch(logpen.lopnStyle) { default: ONCE(FIXME("Unhandled pen style %d\n", logpen.lopnStyle)); + physDev->penStyle = PS_SOLID; /* fall through */ case PS_SOLID: physDev->penHLine = SolidPenHLine; - physDev->penVLine = SolidPenVline; + physDev->penVLine = SolidPenVLine; physDev->penLine = SolidPenLine; physDev->penPattern = NULL; break; @@ -415,16 +459,13 @@ HBRUSH DIBDRV_SelectBrush( DIBDRVPHYSDEV *physDev, HBRUSH hbrush ) goto solid; case BS_SOLID: - physDev->brushColorref = logbrush.lbColor; + physDev->brushColorref = _DIBDRV_MapColor(physDev, logbrush.lbColor); solid: MAYBE(TRACE("SOLID Pattern -- color is %x\n", physDev->brushColorref)); physDev->brushStyle = BS_SOLID; physDev->brushHLine = SolidBrushHLine; - if(physDev->physBitmap.bitCount == 1) - FixupFgColors1(physDev); - else - physDev->brushColor = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, logbrush.lbColor); + physDev->brushColor = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, physDev->brushColorref); _DIBDRV_CalcAndXorMasks(physDev->rop2, physDev->brushColor, &physDev->brushAnd, &physDev->brushXor); @@ -496,8 +537,9 @@ HBRUSH DIBDRV_SelectBrush( DIBDRVPHYSDEV *physDev, HBRUSH hbrush ) { MAYBE(TRACE("NULL Pattern\n")); physDev->brushColorref = 0; + physDev->brushColor = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, 0); physDev->brushHLine = NullBrushHLine; - goto solid; + break; } case BS_PATTERN: @@ -601,10 +643,9 @@ COLORREF DIBDRV_SetBkColor( DIBDRVPHYSDEV *physDev, COLORREF color ) if(physDev->hasDIB) { - physDev->backgroundColor = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, color); + physDev->backgroundColor = _DIBDRV_MapColor(physDev, color); + physDev->backgroundColor = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, physDev->backgroundColor); - if(physDev->physBitmap.bitCount == 1) - FixupFgColors1(physDev); _DIBDRV_CalcAndXorMasks(physDev->rop2, physDev->backgroundColor, &physDev->backgroundAnd, &physDev->backgroundXor); res = TRUE; diff --git a/dlls/winedib.drv/primitives_bitblt.c b/dlls/winedib.drv/primitives_bitblt.c index 7feeb49ddef..27d573f74c0 100644 --- a/dlls/winedib.drv/primitives_bitblt.c +++ b/dlls/winedib.drv/primitives_bitblt.c @@ -25,6 +25,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(dibdrv); +static inline COLORREF SwapColors(DWORD c) +{ + return ((c & 0x0000ff) << 16) | (c & 0x00ff00) | ((c & 0xff0000) >> 16); + +} + /* shrinks a line -- srcWidth >= dstWidth */ static void ShrinkLine(DWORD *dst, int dstWidth, DWORD *src, int srcWidth) { @@ -407,9 +413,11 @@ BOOL _DIBDRV_BitBlt_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, srcBmp = NULL; dstBmp = &physDevDst->physBitmap; - /* gets pattern color, in case it's needed */ + /* gets pattern color, in case it's needed + it's NOT the COLORREF value (colors are swapped + NOR the pixel value (it's applied to a 32 BPP BI_RGB */ if(usePat) - patColor = physDevDst->brushColor; + patColor = SwapColors(physDevDst->brushColorref); else patColor = 0; @@ -658,9 +666,11 @@ BOOL _DIBDRV_StretchBlt_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, srcBmp = NULL; dstBmp = &physDevDst->physBitmap; - /* gets pattern color, in case it's needed */ + /* gets pattern color, in case it's needed + it's NOT the COLORREF value (colors are swapped + NOR the pixel value (it's applied to a 32 BPP BI_RGB */ if(usePat) - patColor = physDevDst->brushColor; + patColor = SwapColors(physDevDst->brushColorref); else patColor = 0; diff --git a/dlls/winedib.drv/primitives_color.c b/dlls/winedib.drv/primitives_color.c index 3ccc2e0d914..6c42b44dd4f 100644 --- a/dlls/winedib.drv/primitives_color.c +++ b/dlls/winedib.drv/primitives_color.c @@ -94,31 +94,30 @@ DWORD _DIBDRV_ColorToPixel16_BITFIELDS(const DIBDRVBITMAP *dib, COLORREF color) PutField16(b, dib->blueShift, dib->blueLen); } -DWORD _DIBDRV_ColorToPixelColortable(const DIBDRVBITMAP *dib, COLORREF color) +/* gets nearest color to DIB palette color */ +DWORD _DIBDRV_GetNearestColor(const DIBDRVBITMAP *dib, COLORREF color) +{ + RGBQUAD *c; + + if(dib->bitCount > 8) + return color; + + c = dib->colorTable + _DIBDRV_GetNearestColorIndex(dib, color); + return RGB(c->rgbRed, c->rgbGreen, c->rgbBlue); + +} + +/* gets nearest color index in DIB palette of a given colorref */ +DWORD _DIBDRV_GetNearestColorIndex(const DIBDRVBITMAP *dib, COLORREF color) { - int i, best_index = 0; DWORD r, g, b; + int i, best_index = 0; DWORD diff, best_diff = 0xffffffff; - + r = GetRValue(color); g = GetGValue(color); b = GetBValue(color); - /* just in case it's being called without color table - properly initialized */ - if(!dib->colorTableGrabbed) - return 0; - - /* for monochrome bitmaps, color is background - if not matching foreground */ - if(dib->colorTableSize == 2) - { - RGBQUAD *fore = dib->colorTable + 1; - if(r == fore->rgbRed && g == fore->rgbGreen && b == fore->rgbBlue) - return 1; - return 0; - } - for(i = 0; i < dib->colorTableSize; i++) { RGBQUAD *cur = dib->colorTable + i; @@ -140,3 +139,39 @@ DWORD _DIBDRV_ColorToPixelColortable(const DIBDRVBITMAP *dib, COLORREF color) } return best_index; } + +DWORD _DIBDRV_ColorToPixelColortable(const DIBDRVBITMAP *dib, COLORREF color) +{ + DWORD r, g, b; + + r = GetRValue(color); + g = GetGValue(color); + b = GetBValue(color); + + /* just in case it's being called without color table + properly initialized */ + if(!dib->colorTableGrabbed) + return 0; + + /* for monochrome bitmaps, color is : + foreground if matching foreground ctable + else background if matching background ctable + else foreground ix 0xffffff + else background */ + if(dib->colorTableSize == 2) + { + RGBQUAD *back = dib->colorTable; + RGBQUAD *fore = dib->colorTable + 1; + if(r == fore->rgbRed && g == fore->rgbGreen && b == fore->rgbBlue) + return 1; + else if(r == back->rgbRed && g == back->rgbGreen && b == back->rgbBlue) + return 0; + if((color & 0xffffff) == 0xffffff) + return 1; + else + return 0; + } + + /* otherwise looks for nearest color in palette */ + return _DIBDRV_GetNearestColorIndex(dib, color); +} diff --git a/dlls/winedib.drv/primitives_convert.c b/dlls/winedib.drv/primitives_convert.c index f8f87ce9220..24a5e77fdf8 100644 --- a/dlls/winedib.drv/primitives_convert.c +++ b/dlls/winedib.drv/primitives_convert.c @@ -31,6 +31,33 @@ static inline COLORREF SwapColors(DWORD c) } +static inline DWORD PlaceField32(BYTE c, int shift, int len) +{ + DWORD res = c; + if(len < 8) + res >>= (8 - len); + else + res <<= (len - 8); + return res << shift; +} + +static inline WORD PlaceField16(BYTE c, int shift, int len) +{ + WORD res = c; + if(len < 8) + res >>= (8 - len); + else + res <<= (len - 8); + return res << shift; +} + +static inline BYTE GetField32(DWORD dwColor, int shift, int len) +{ + dwColor = dwColor & (((1 << (len)) - 1) << shift); + dwColor = dwColor << (32 - (shift + len)) >> 24; + return dwColor; +} + /* ----------------------------------------------------------------*/ /* CONVERT PRIMITIVES */ /* converts (part of) line of any DIB format from/to DIB32_RGB one */ @@ -63,7 +90,7 @@ BOOL _DIBDRV_GetLine32_RGB(const DIBDRVBITMAP *bmp, INT line, INT startx, int wi BOOL _DIBDRV_GetLine32_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf) { - BYTE *bBuf = (BYTE *)buf; + DWORD *dwBuf = (DWORD *)buf; DWORD *src; #ifdef DIBDRV_CHECK_RANGES @@ -85,10 +112,10 @@ BOOL _DIBDRV_GetLine32_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, src = (DWORD *)((BYTE *)bmp->bits + line * bmp->stride + 4 * startx); for(; width ; width--) { - *bBuf++ = (*src & bmp->blueMask ) >> bmp->blueShift; - *bBuf++ = (*src & bmp->greenMask) >> bmp->greenShift; - *bBuf++ = (*src & bmp->redMask ) >> bmp->redShift; - *bBuf++ = 0x0; + *dwBuf++ = + GetField32(*src, bmp->redShift , bmp->redLen ) << 16 | + GetField32(*src, bmp->greenShift, bmp->greenLen) << 8 | + GetField32(*src, bmp->blueShift , bmp->blueLen ); src++; } return TRUE; @@ -184,6 +211,7 @@ BOOL _DIBDRV_GetLine16_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, for(; width ; width--) { b = *src++; + *dwBuf++ =((( b & bmp->blueMask) >> bmp->blueShift ) << ( 8 - bmp->blueLen )) | (((b & bmp->greenMask) >> bmp->greenShift) << (16 - bmp->greenLen)) | (((b & bmp->redMask ) >> bmp->redShift ) << (24 - bmp->redLen )); @@ -350,14 +378,14 @@ BOOL _DIBDRV_PutLine32_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, { DWORD *dwBuf = (DWORD *)buf; DWORD *dst = (DWORD *)((BYTE *)bmp->bits + line * bmp->stride + 4 * startx); - DWORD c; + RGBQUAD *c; for(; width; width--) { - c = *dwBuf++; + c = (RGBQUAD *)dwBuf++; *dst++ = - ((( c & 0x000000ff) << bmp->blueShift) & bmp->blueMask) | - ((((c & 0x0000ff00) >> 8) << bmp->greenShift) & bmp->greenMask) | - ((((c & 0x00ff0000) >> 16) << bmp->redShift) & bmp->redMask); + PlaceField32(c->rgbRed , bmp->redShift , bmp->redLen ) | + PlaceField32(c->rgbGreen, bmp->greenShift, bmp->greenLen) | + PlaceField32(c->rgbBlue , bmp->blueShift , bmp->blueLen ); } return TRUE; } @@ -386,6 +414,7 @@ BOOL _DIBDRV_PutLine16_RGB(const DIBDRVBITMAP *bmp, INT line, INT startx, int wi { c = *dwBuf++; *dst++ = + /* 0RRR|RRGG|GGGB|BBBB */ ((c & 0x000000f8) >> 3) | ((c & 0x0000f800) >> 6) | ((c & 0x00f80000) >> 9); @@ -506,8 +535,9 @@ BOOL _DIBDRV_PutLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, DWORD c; /* get foreground color */ + DWORD back = *(DWORD *)bmp->colorTable & 0x00ffffff; DWORD fore = *((DWORD *)bmp->colorTable + 1) & 0x00ffffff; - + /* put first partial byte, if any */ startx &= 0x07; mask = 0x80 >> startx; @@ -519,7 +549,11 @@ BOOL _DIBDRV_PutLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, while(startx--) { c = *dwBuf++ & 0x00ffffff; - if(c == 0x00ffffff || c == fore) + if(c == fore) + b |= mask; + else if(c == back) + b &= !mask; + else if(c == 0x00ffffff) b |= mask; else b &= !mask; @@ -536,7 +570,7 @@ BOOL _DIBDRV_PutLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, for(i = 0 ; i < 8 ; i++) { c = *dwBuf++ & 0x00ffffff; - if(c == 0x00ffffff || c == fore) + if(c == fore || (c == 0x00ffffff && c != back)) b |= mask; mask >>= 1; } @@ -551,7 +585,11 @@ BOOL _DIBDRV_PutLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, while(width--) { c = *dwBuf++ & 0x00ffffff; - if(c == 0x00ffffff || c == fore) + if(c == fore) + b |= mask; + else if(c == back) + b &= !mask; + else if(c == 0x00ffffff) b |= mask; else b &= !mask; diff --git a/dlls/winedib.drv/primitives_pixel.c b/dlls/winedib.drv/primitives_pixel.c index ca68cf16a46..78e68c7b422 100644 --- a/dlls/winedib.drv/primitives_pixel.c +++ b/dlls/winedib.drv/primitives_pixel.c @@ -25,24 +25,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(dibdrv); - /* ------------------------------------------------------------*/ /* BITFIELD HELPERS */ -static DWORD GetField32 (DWORD pixel, int shift, int len) +static inline DWORD GetField32 (DWORD pixel, int shift, int len) { pixel = pixel & (((1 << (len)) - 1) << shift); pixel = pixel << (32 - (shift + len)) >> 24; return pixel; } -static WORD GetField16 (WORD pixel, int shift, int len) -{ - FIXME("TODO\n"); - return 0; -} - - - /* ------------------------------------------------------------*/ /* PIXEL POINTER READING */ void *_DIBDRV_GetPixelPointer32(const DIBDRVBITMAP *dib, int x, int y) @@ -174,45 +165,50 @@ void _DIBDRV_SetPixel1(DIBDRVBITMAP *dib, int x, int y, DWORD and, DWORD xor) /* PIXEL READING */ DWORD _DIBDRV_GetPixel32_RGB(const DIBDRVBITMAP *dib, int x, int y) { - DWORD *ptr = dib->funcs->GetPixelPointer(dib, x, y); - return *ptr; + DWORD c = *(DWORD *)dib->funcs->GetPixelPointer(dib, x, y); + return + ((c & 0x000000ff) << 16) | + ((c & 0x0000ff00) ) | + ((c & 0x00ff0000) >> 16) | + ( c & 0xff000000 ); /* last one for alpha channel */ } DWORD _DIBDRV_GetPixel32_BITFIELDS(const DIBDRVBITMAP *dib, int x, int y) { DWORD *ptr = dib->funcs->GetPixelPointer(dib, x, y); - return GetField32(*ptr, dib->redShift, dib->redLen) << 16 | + return GetField32(*ptr, dib->redShift, dib->redLen) | GetField32(*ptr, dib->greenShift, dib->greenLen) << 8 | - GetField32(*ptr, dib->blueShift, dib->blueLen); + GetField32(*ptr, dib->blueShift, dib->blueLen) << 16; } DWORD _DIBDRV_GetPixel24(const DIBDRVBITMAP *dib, int x, int y) { BYTE *ptr = dib->funcs->GetPixelPointer(dib, x, y); - return (ptr[0] << 16) | (ptr[1] << 8) | ptr[2]; + return ((WORD)ptr[0] << 16) | ((WORD)ptr[1] << 8) | (WORD)ptr[2]; } DWORD _DIBDRV_GetPixel16_RGB(const DIBDRVBITMAP *dib, int x, int y) { - WORD *ptr = dib->funcs->GetPixelPointer(dib, x, y); - return ((*ptr & 0x7c00) << 9) | ((*ptr & 0x03e0) << 6) | ((*ptr & 0x001f) << 3); + WORD c = *(WORD *)dib->funcs->GetPixelPointer(dib, x, y); + /* 0RRR|RRGG|GGGB|BBBB */ + return ((c & 0x7c00) >> 7) | ((c & 0x03e0) << 6) | ((c & 0x001f) << 19); } DWORD _DIBDRV_GetPixel16_BITFIELDS(const DIBDRVBITMAP *dib, int x, int y) { - WORD *ptr = dib->funcs->GetPixelPointer(dib, x, y); + WORD c = *(WORD *)dib->funcs->GetPixelPointer(dib, x, y); - return GetField16(*ptr, dib->redShift, dib->redLen) << 16 | - GetField16(*ptr, dib->greenShift, dib->greenLen) << 8 | - GetField16(*ptr, dib->blueShift, dib->blueLen); + return (((c & dib->blueMask ) >> dib->blueShift ) << (24 - dib->blueLen )) | + (((c & dib->greenMask) >> dib->greenShift) << (16 - dib->greenLen)) | + (((c & dib->redMask ) >> dib->redShift ) << ( 8 - dib->redLen )); } DWORD _DIBDRV_GetPixel8(const DIBDRVBITMAP *dib, int x, int y) { BYTE *ptr = dib->funcs->GetPixelPointer(dib, x, y); RGBQUAD *color = dib->colorTable + *ptr; - return (color->rgbRed << 16) | (color->rgbGreen << 8) | color->rgbBlue; + return (color->rgbRed) | (color->rgbGreen << 8) | (color->rgbBlue << 16); } DWORD _DIBDRV_GetPixel4(const DIBDRVBITMAP *dib, int x, int y) @@ -226,7 +222,7 @@ DWORD _DIBDRV_GetPixel4(const DIBDRVBITMAP *dib, int x, int y) pix = *ptr >> 4; color = dib->colorTable + pix; - return (color->rgbRed << 16) | (color->rgbGreen << 8) | color->rgbBlue; + return (color->rgbRed) | (color->rgbGreen << 8) | (color->rgbBlue << 16); } DWORD _DIBDRV_GetPixel1(const DIBDRVBITMAP *dib, int x, int y) @@ -240,5 +236,5 @@ DWORD _DIBDRV_GetPixel1(const DIBDRVBITMAP *dib, int x, int y) pix &= 1; color = dib->colorTable + pix; - return (color->rgbRed << 16) | (color->rgbGreen << 8) | color->rgbBlue; + return (color->rgbRed) | (color->rgbGreen << 8) | (color->rgbBlue << 16); } -- 2.11.4.GIT