mirror of
https://github.com/dgis/emu48android
synced 2024-12-26 09:58:49 +01:00
Support the transparency in the KML Global Color.
This commit is contained in:
parent
577091db9e
commit
fe3d8c4da0
3 changed files with 274 additions and 143 deletions
|
@ -96,6 +96,134 @@ VOID CopyItemsToClipboard(HWND hWnd) // save selected Listbox Items to Clipboar
|
|||
return;
|
||||
}
|
||||
|
||||
#define WIDTHBYTES(bits) ((((bits) + 31) / 32) * 4)
|
||||
|
||||
static BOOL AbsColorCmp(DWORD dwColor1,DWORD dwColor2,DWORD dwTol)
|
||||
{
|
||||
DWORD dwDiff;
|
||||
|
||||
dwDiff = (DWORD) abs((INT) (dwColor1 & 0xFF) - (INT) (dwColor2 & 0xFF));
|
||||
dwColor1 >>= 8;
|
||||
dwColor2 >>= 8;
|
||||
dwDiff += (DWORD) abs((INT) (dwColor1 & 0xFF) - (INT) (dwColor2 & 0xFF));
|
||||
dwColor1 >>= 8;
|
||||
dwColor2 >>= 8;
|
||||
dwDiff += (DWORD) abs((INT) (dwColor1 & 0xFF) - (INT) (dwColor2 & 0xFF));
|
||||
|
||||
return dwDiff > dwTol; // FALSE = colors match
|
||||
}
|
||||
|
||||
static BOOL LabColorCmp(DWORD dwColor1,DWORD dwColor2,DWORD dwTol)
|
||||
{
|
||||
DWORD dwDiff;
|
||||
INT nDiffCol;
|
||||
|
||||
nDiffCol = (INT) (dwColor1 & 0xFF) - (INT) (dwColor2 & 0xFF);
|
||||
dwDiff = (DWORD) (nDiffCol * nDiffCol);
|
||||
dwColor1 >>= 8;
|
||||
dwColor2 >>= 8;
|
||||
nDiffCol = (INT) (dwColor1 & 0xFF) - (INT) (dwColor2 & 0xFF);
|
||||
dwDiff += (DWORD) (nDiffCol * nDiffCol);
|
||||
dwColor1 >>= 8;
|
||||
dwColor2 >>= 8;
|
||||
nDiffCol = (INT) (dwColor1 & 0xFF) - (INT) (dwColor2 & 0xFF);
|
||||
dwDiff += (DWORD) (nDiffCol * nDiffCol);
|
||||
dwTol *= dwTol;
|
||||
|
||||
return dwDiff > dwTol; // FALSE = colors match
|
||||
}
|
||||
|
||||
static DWORD EncodeColorBits(DWORD dwColorVal,DWORD dwMask)
|
||||
{
|
||||
#define MAXBIT 32
|
||||
UINT uLshift = MAXBIT;
|
||||
UINT uRshift = 8;
|
||||
DWORD dwBitMask = dwMask;
|
||||
|
||||
dwColorVal &= 0xFF; // the color component using the lowest 8 bit
|
||||
|
||||
// position of highest bit
|
||||
while ((dwBitMask & (1<<(MAXBIT-1))) == 0 && uLshift > 0)
|
||||
{
|
||||
dwBitMask <<= 1; // next bit
|
||||
--uLshift; // next position
|
||||
}
|
||||
|
||||
if (uLshift > 24) // avoid overflow on 32bit mask
|
||||
{
|
||||
uLshift -= uRshift; // normalize left shift
|
||||
uRshift = 0;
|
||||
}
|
||||
|
||||
return ((dwColorVal << uLshift) >> uRshift) & dwMask;
|
||||
#undef MAXBIT
|
||||
}
|
||||
|
||||
extern JavaVM *java_machine;
|
||||
extern jobject bitmapMainScreen;
|
||||
extern AndroidBitmapInfo androidBitmapInfo;
|
||||
|
||||
static void MakeBitmapTransparent(HBITMAP hBmp,COLORREF color,DWORD dwTol) {
|
||||
|
||||
BOOL (*fnColorCmp)(DWORD dwColor1,DWORD dwColor2,DWORD dwTol);
|
||||
if (dwTol >= 1000) { // use CIE L*a*b compare
|
||||
fnColorCmp = LabColorCmp;
|
||||
dwTol -= 1000; // remove L*a*b compare selector
|
||||
} else { // use Abs summation compare
|
||||
fnColorCmp = AbsColorCmp;
|
||||
}
|
||||
|
||||
JNIEnv * jniEnv = NULL;
|
||||
jint ret;
|
||||
|
||||
BOOL needDetach = FALSE;
|
||||
ret = (*java_machine)->GetEnv(java_machine, (void **) &jniEnv, JNI_VERSION_1_6);
|
||||
if (ret == JNI_EDETACHED) {
|
||||
// GetEnv: not attached
|
||||
ret = (*java_machine)->AttachCurrentThread(java_machine, &jniEnv, NULL);
|
||||
if (ret == JNI_OK) {
|
||||
needDetach = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
int destinationWidth = androidBitmapInfo.width;
|
||||
int destinationHeight = androidBitmapInfo.height;
|
||||
int destinationBitCount = 32;
|
||||
int destinationStride = androidBitmapInfo.stride;
|
||||
void * pixelsDestination = NULL;
|
||||
if ((ret = AndroidBitmap_lockPixels(jniEnv, bitmapMainScreen, &pixelsDestination)) < 0) {
|
||||
LOGD("AndroidBitmap_lockPixels() failed ! error=%d", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
LPBYTE pbyBits = pixelsDestination;
|
||||
|
||||
// convert COLORREF to RGBQUAD color
|
||||
DWORD dwRed = 0x00FF0000;
|
||||
DWORD dwGreen = 0x0000FF00;
|
||||
DWORD dwBlue = 0x000000FF;
|
||||
|
||||
color = EncodeColorBits((color >> 16), dwBlue)
|
||||
| EncodeColorBits((color >> 8), dwGreen)
|
||||
| EncodeColorBits((color >> 0), dwRed);
|
||||
|
||||
DWORD dwBpp = (DWORD) (destinationBitCount >> 3);
|
||||
LPBYTE pbyColor = pbyBits + (destinationHeight - 1) * destinationStride;
|
||||
|
||||
for (LONG y = 0; y < destinationHeight; ++y) {
|
||||
LPBYTE pbyLineStart = pbyColor;
|
||||
for (LONG x = 0; x < destinationWidth; ++x) {
|
||||
if(!fnColorCmp(*(LPDWORD)pbyColor,color,dwTol))
|
||||
*(LPDWORD)pbyColor = 0x00000000;
|
||||
pbyColor += dwBpp;
|
||||
}
|
||||
pbyColor = pbyLineStart - destinationStride;
|
||||
}
|
||||
|
||||
if(jniEnv && (ret = AndroidBitmap_unlockPixels(jniEnv, bitmapMainScreen)) < 0)
|
||||
LOGD("AndroidBitmap_unlockPixels() failed ! error=%d", ret);
|
||||
}
|
||||
|
||||
//
|
||||
// WM_PAINT
|
||||
//
|
||||
|
@ -127,6 +255,9 @@ static LRESULT OnPaint(HWND hWindow)
|
|||
Paint.rcPaint.right-Paint.rcPaint.left, Paint.rcPaint.bottom-Paint.rcPaint.top,
|
||||
hMainDC, rcMainPaint.left, rcMainPaint.top, SRCCOPY);
|
||||
|
||||
if (dwTColor != (DWORD) -1) // prepare background bitmap with transparency
|
||||
MakeBitmapTransparent((HBITMAP)GetCurrentObject(hPaintDC, OBJ_BITMAP), dwTColor, dwTColorTol);
|
||||
|
||||
// CdB for HP: add apples display stuff
|
||||
SetWindowOrgEx(hPaintDC, nBackgroundX, nBackgroundY, NULL);
|
||||
|
||||
|
|
|
@ -2026,163 +2026,163 @@ void StretchBltInternal(int xDest, int yDest, int wDest, int hDest,
|
|||
int dst_maxy = yDest + hDest;
|
||||
|
||||
if(xDest < 0) {
|
||||
wDest += xDest;
|
||||
xDest = 0;
|
||||
}
|
||||
wDest += xDest;
|
||||
xDest = 0;
|
||||
}
|
||||
if(yDest < 0) {
|
||||
hDest += yDest;
|
||||
yDest = 0;
|
||||
}
|
||||
hDest += yDest;
|
||||
yDest = 0;
|
||||
}
|
||||
if(dst_maxx > destinationWidth)
|
||||
dst_maxx = destinationWidth;
|
||||
dst_maxx = destinationWidth;
|
||||
if(dst_maxy > destinationHeight)
|
||||
dst_maxy = destinationHeight;
|
||||
dst_maxy = destinationHeight;
|
||||
|
||||
for (int y = yDest; y < dst_maxy; y++) {
|
||||
int src_cury = ySrc + (y - yDest) * hSrc / hDest;
|
||||
if(!reverseHeight)
|
||||
src_cury = sourceHeight - 1 - src_cury;
|
||||
if (src_cury < 0 || src_cury >= sourceHeight)
|
||||
int src_cury = ySrc + (y - yDest) * hSrc / hDest;
|
||||
if(!reverseHeight)
|
||||
src_cury = sourceHeight - 1 - src_cury;
|
||||
if (src_cury < 0 || src_cury >= sourceHeight)
|
||||
continue;
|
||||
BYTE parity = (BYTE) xSrc;
|
||||
for (int x = xDest; x < dst_maxx; x++, parity++) {
|
||||
int src_curx = xSrc + (x - xDest) * wSrc / wDest;
|
||||
if (src_curx < 0 || src_curx >= sourceWidth)
|
||||
continue;
|
||||
BYTE parity = (BYTE) xSrc;
|
||||
for (int x = xDest; x < dst_maxx; x++, parity++) {
|
||||
int src_curx = xSrc + (x - xDest) * wSrc / wDest;
|
||||
if (src_curx < 0 || src_curx >= sourceWidth)
|
||||
continue;
|
||||
|
||||
BYTE * sourcePixelBase = pixelsSource + sourceStride * src_cury;
|
||||
BYTE * destinationPixelBase = pixelsDestination + destinationStride * y;
|
||||
BYTE * sourcePixelBase = pixelsSource + sourceStride * src_cury;
|
||||
BYTE * destinationPixelBase = pixelsDestination + destinationStride * y;
|
||||
|
||||
COLORREF sourceColor = 0xFF000000;
|
||||
BYTE * sourceColorPointer = (BYTE *) &sourceColor;
|
||||
COLORREF sourceColor = 0xFF000000;
|
||||
BYTE * sourceColorPointer = (BYTE *) &sourceColor;
|
||||
|
||||
switch (sourceBitCount) {
|
||||
case 1: {
|
||||
//TODO https://devblogs.microsoft.com/oldnewthing/?p=29013
|
||||
// When blitting from a monochrome DC to a color DC,
|
||||
// the color black in the source turns into the destination’s text color,
|
||||
// and the color white in the source turns into the destination’s background
|
||||
// color.
|
||||
BYTE * sourcePixel = sourcePixelBase + ((UINT)src_curx >> (UINT)3);
|
||||
UINT bitNumber = (UINT) (src_curx % 8);
|
||||
if(*sourcePixel & ((UINT)1 << bitNumber)) {
|
||||
// Monochrome 1=White
|
||||
sourceColorPointer[0] = 255;
|
||||
sourceColorPointer[1] = 255;
|
||||
sourceColorPointer[2] = 255;
|
||||
} else {
|
||||
// Monochrome 0=Black
|
||||
sourceColorPointer[0] = 0;
|
||||
sourceColorPointer[1] = 0;
|
||||
sourceColorPointer[2] = 0;
|
||||
}
|
||||
sourceColorPointer[3] = 255;
|
||||
break;
|
||||
switch (sourceBitCount) {
|
||||
case 1: {
|
||||
//TODO https://devblogs.microsoft.com/oldnewthing/?p=29013
|
||||
// When blitting from a monochrome DC to a color DC,
|
||||
// the color black in the source turns into the destination’s text color,
|
||||
// and the color white in the source turns into the destination’s background
|
||||
// color.
|
||||
BYTE * sourcePixel = sourcePixelBase + ((UINT)src_curx >> (UINT)3);
|
||||
UINT bitNumber = (UINT) (src_curx % 8);
|
||||
if(*sourcePixel & ((UINT)1 << bitNumber)) {
|
||||
// Monochrome 1=White
|
||||
sourceColorPointer[0] = 255;
|
||||
sourceColorPointer[1] = 255;
|
||||
sourceColorPointer[2] = 255;
|
||||
} else {
|
||||
// Monochrome 0=Black
|
||||
sourceColorPointer[0] = 0;
|
||||
sourceColorPointer[1] = 0;
|
||||
sourceColorPointer[2] = 0;
|
||||
}
|
||||
case 4: {
|
||||
int currentXBytes = ((sourceBitCount >> (UINT)2) * src_curx) >> (UINT)1;
|
||||
BYTE * sourcePixel = sourcePixelBase + currentXBytes;
|
||||
BYTE colorIndex = (parity & (BYTE)0x1 ? sourcePixel[0] & (BYTE)0x0F : sourcePixel[0] >> (UINT)4);
|
||||
if (palPalEntry) {
|
||||
sourceColorPointer[0] = palPalEntry[colorIndex].peBlue;
|
||||
sourceColorPointer[1] = palPalEntry[colorIndex].peGreen;
|
||||
sourceColorPointer[2] = palPalEntry[colorIndex].peRed;
|
||||
sourceColorPointer[3] = 255;
|
||||
} else {
|
||||
sourceColorPointer[0] = colorIndex;
|
||||
sourceColorPointer[1] = colorIndex;
|
||||
sourceColorPointer[2] = colorIndex;
|
||||
sourceColorPointer[3] = 255;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
BYTE * sourcePixel = sourcePixelBase + src_curx;
|
||||
BYTE colorIndex = sourcePixel[0];
|
||||
if (palPalEntry) {
|
||||
sourceColorPointer[0] = palPalEntry[colorIndex].peBlue;
|
||||
sourceColorPointer[1] = palPalEntry[colorIndex].peGreen;
|
||||
sourceColorPointer[2] = palPalEntry[colorIndex].peRed;
|
||||
sourceColorPointer[3] = 255;
|
||||
} else {
|
||||
sourceColorPointer[0] = colorIndex;
|
||||
sourceColorPointer[1] = colorIndex;
|
||||
sourceColorPointer[2] = colorIndex;
|
||||
sourceColorPointer[3] = 255;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 24: {
|
||||
BYTE * sourcePixel = sourcePixelBase + 3 * src_curx;
|
||||
sourceColorPointer[0] = sourcePixel[2];
|
||||
sourceColorPointer[1] = sourcePixel[1];
|
||||
sourceColorPointer[2] = sourcePixel[0];
|
||||
sourceColorPointer[3] = 255;
|
||||
break;
|
||||
}
|
||||
case 32: {
|
||||
BYTE *sourcePixel = sourcePixelBase + 4 * src_curx;
|
||||
memcpy(sourceColorPointer, sourcePixel, 4);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
sourceColorPointer[3] = 255;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (destinationBitCount) {
|
||||
case 1: {
|
||||
//TODO https://devblogs.microsoft.com/oldnewthing/?p=29013
|
||||
// If you blit from a color DC to a monochrome DC,
|
||||
// then all pixels in the source that are equal to the background color
|
||||
// will turn white, and all other pixels will turn black.
|
||||
// In other words, GDI considers a monochrome bitmap to be
|
||||
// black pixels on a white background.
|
||||
BYTE * destinationPixel = destinationPixelBase + (x >> 3);
|
||||
UINT bitNumber = x % 8;
|
||||
if(backgroundColor == sourceColor) {
|
||||
*destinationPixel |= (1 << bitNumber); // 1 White
|
||||
} else {
|
||||
*destinationPixel &= ~(1 << bitNumber); // 0 Black
|
||||
}
|
||||
break;
|
||||
case 4: {
|
||||
int currentXBytes = ((sourceBitCount >> (UINT)2) * src_curx) >> (UINT)1;
|
||||
BYTE * sourcePixel = sourcePixelBase + currentXBytes;
|
||||
BYTE colorIndex = (parity & (BYTE)0x1 ? sourcePixel[0] & (BYTE)0x0F : sourcePixel[0] >> (UINT)4);
|
||||
if (palPalEntry) {
|
||||
sourceColorPointer[0] = palPalEntry[colorIndex].peBlue;
|
||||
sourceColorPointer[1] = palPalEntry[colorIndex].peGreen;
|
||||
sourceColorPointer[2] = palPalEntry[colorIndex].peRed;
|
||||
sourceColorPointer[3] = 255;
|
||||
} else {
|
||||
sourceColorPointer[0] = colorIndex;
|
||||
sourceColorPointer[1] = colorIndex;
|
||||
sourceColorPointer[2] = colorIndex;
|
||||
sourceColorPointer[3] = 255;
|
||||
}
|
||||
case 4: {
|
||||
//TODO
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
//TODO
|
||||
break;
|
||||
}
|
||||
case 24: {
|
||||
BYTE * destinationPixel = destinationPixelBase + 3 * x;
|
||||
destinationPixel[0] = sourceColorPointer[0];
|
||||
destinationPixel[1] = sourceColorPointer[1];
|
||||
destinationPixel[2] = sourceColorPointer[2];
|
||||
break;
|
||||
}
|
||||
case 32: {
|
||||
BYTE * destinationPixel = destinationPixelBase + 4 * x;
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/gdi/ternary-raster-operations
|
||||
// http://www.qnx.com/developers/docs/6.4.1/gf/dev_guide/api/gf_context_set_rop.html
|
||||
if (rop == ROP_PDSPxax) { // P ^ (D & (S ^ P))
|
||||
UINT destination = *((UINT *) destinationPixel);
|
||||
*((UINT *)destinationPixel) = (brushColor ^ (destination & (sourceColor ^ brushColor))) | 0xFF000000;
|
||||
} else if (rop == ROP_PSDPxax) { // P ^ (S & (D ^ P))
|
||||
UINT destination = *((UINT *) destinationPixel);
|
||||
*((UINT *)destinationPixel) = (brushColor ^ (sourceColor & (destination ^ brushColor))) | 0xFF000000;
|
||||
} else if (rop == SRCAND) { // dest = source AND dest
|
||||
UINT destination = *((UINT *) destinationPixel);
|
||||
*((UINT *)destinationPixel) = (sourceColor & destination) | 0xFF000000;
|
||||
} else
|
||||
*((UINT *)destinationPixel) = sourceColor;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
BYTE * sourcePixel = sourcePixelBase + src_curx;
|
||||
BYTE colorIndex = sourcePixel[0];
|
||||
if (palPalEntry) {
|
||||
sourceColorPointer[0] = palPalEntry[colorIndex].peBlue;
|
||||
sourceColorPointer[1] = palPalEntry[colorIndex].peGreen;
|
||||
sourceColorPointer[2] = palPalEntry[colorIndex].peRed;
|
||||
sourceColorPointer[3] = 255;
|
||||
} else {
|
||||
sourceColorPointer[0] = colorIndex;
|
||||
sourceColorPointer[1] = colorIndex;
|
||||
sourceColorPointer[2] = colorIndex;
|
||||
sourceColorPointer[3] = 255;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 24: {
|
||||
BYTE * sourcePixel = sourcePixelBase + 3 * src_curx;
|
||||
sourceColorPointer[0] = sourcePixel[2];
|
||||
sourceColorPointer[1] = sourcePixel[1];
|
||||
sourceColorPointer[2] = sourcePixel[0];
|
||||
sourceColorPointer[3] = 255;
|
||||
break;
|
||||
}
|
||||
case 32: {
|
||||
BYTE *sourcePixel = sourcePixelBase + 4 * src_curx;
|
||||
memcpy(sourceColorPointer, sourcePixel, 4);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (destinationBitCount) {
|
||||
case 1: {
|
||||
//TODO https://devblogs.microsoft.com/oldnewthing/?p=29013
|
||||
// If you blit from a color DC to a monochrome DC,
|
||||
// then all pixels in the source that are equal to the background color
|
||||
// will turn white, and all other pixels will turn black.
|
||||
// In other words, GDI considers a monochrome bitmap to be
|
||||
// black pixels on a white background.
|
||||
BYTE * destinationPixel = destinationPixelBase + (x >> 3);
|
||||
UINT bitNumber = x % 8;
|
||||
if(backgroundColor == sourceColor) {
|
||||
*destinationPixel |= (1 << bitNumber); // 1 White
|
||||
} else {
|
||||
*destinationPixel &= ~(1 << bitNumber); // 0 Black
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
//TODO
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
//TODO
|
||||
break;
|
||||
}
|
||||
case 24: {
|
||||
BYTE * destinationPixel = destinationPixelBase + 3 * x;
|
||||
destinationPixel[0] = sourceColorPointer[0];
|
||||
destinationPixel[1] = sourceColorPointer[1];
|
||||
destinationPixel[2] = sourceColorPointer[2];
|
||||
break;
|
||||
}
|
||||
case 32: {
|
||||
BYTE * destinationPixel = destinationPixelBase + 4 * x;
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/gdi/ternary-raster-operations
|
||||
// http://www.qnx.com/developers/docs/6.4.1/gf/dev_guide/api/gf_context_set_rop.html
|
||||
if (rop == ROP_PDSPxax) { // P ^ (D & (S ^ P))
|
||||
UINT destination = *((UINT *) destinationPixel);
|
||||
*((UINT *)destinationPixel) = (brushColor ^ (destination & (sourceColor ^ brushColor))) | 0xFF000000;
|
||||
} else if (rop == ROP_PSDPxax) { // P ^ (S & (D ^ P))
|
||||
UINT destination = *((UINT *) destinationPixel);
|
||||
*((UINT *)destinationPixel) = (brushColor ^ (sourceColor & (destination ^ brushColor))) | 0xFF000000;
|
||||
} else if (rop == SRCAND) { // dest = source AND dest
|
||||
UINT destination = *((UINT *) destinationPixel);
|
||||
*((UINT *)destinationPixel) = (sourceColor & destination) | 0xFF000000;
|
||||
} else
|
||||
*((UINT *)destinationPixel) = sourceColor;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT SetDIBColorTable(HDC hdc, UINT iStart, UINT cEntries, CONST RGBQUAD *prgbq) {
|
||||
|
|
|
@ -7,7 +7,7 @@ buildscript {
|
|||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.1'
|
||||
classpath 'com.android.tools.build:gradle:3.5.2'
|
||||
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
|
Loading…
Reference in a new issue