diff options
author | Ash Wolf <ninji@wuffs.org> | 2023-06-14 00:50:34 +0100 |
---|---|---|
committer | Ash Wolf <ninji@wuffs.org> | 2023-06-14 00:50:34 +0100 |
commit | 37e364b2c6cc7487a1c888d256a73e5337bb7189 (patch) | |
tree | eaf6e857382eef16c2dd940eb4125536fbe068bd /src/T2DLL/T2BitImage.cpp | |
download | t2win-37e364b2c6cc7487a1c888d256a73e5337bb7189.tar.gz t2win-37e364b2c6cc7487a1c888d256a73e5337bb7189.zip |
initial commit
Diffstat (limited to '')
-rw-r--r-- | src/T2DLL/T2BitImage.cpp | 1228 |
1 files changed, 1228 insertions, 0 deletions
diff --git a/src/T2DLL/T2BitImage.cpp b/src/T2DLL/T2BitImage.cpp new file mode 100644 index 0000000..ea00253 --- /dev/null +++ b/src/T2DLL/T2BitImage.cpp @@ -0,0 +1,1228 @@ +#include "GlobalFunc.h" +#include "T2BitImage.h" + +#define ALIGN_ROW_SIZE(s) ((((s) + 3) / 4) * 4) + +T2BitImage::T2BitImage(const char* path, unsigned int id, BOOL flip) { + mMemHandle = NULL; + + SUBPLUGINFSENTRY fsEntry; + CFile *file = OpenSubPluginFS(path, id, 0, &fsEntry); + if (!file) { + CString idStr; + idStr.Format("%d", id); + + CString err = "T2BitImage::T2BitImage ERROR : " + idStr + " @" + path + "\n"; + OutputDebugString(err); + throw 0; + } + + void *data = malloc(fsEntry.spfse_mC); + file->Read(data, fsEntry.spfse_mC); + SetupBitmap((BITMAPINFO *) data, flip); + free(data); + + file->Close(); + delete file; +} + +T2BitImage::T2BitImage(HINSTANCE instance, unsigned int id, BOOL flip) { + mMemHandle = NULL; + + HRSRC rsrc = FindResource(instance, MAKEINTRESOURCE(id), MAKEINTRESOURCE(2)); + if (!rsrc) { + CString idStr; + idStr.Format("%d", id); + + CString err = "T2BitImage::T2BitImage ERROR : " + idStr + " @" + GetModuleName(instance) + "\n"; + OutputDebugString(err); + throw 0; + } + + HGLOBAL h = LoadResource(instance, rsrc); + void *data = LockResource(h); + SetupBitmap((BITMAPINFO *) data, flip); + UnlockResource(h); + FreeResource(rsrc); +} + +void T2BitImage::SetupBitmap(BITMAPINFO* info, BOOL flip) { + mBitmap.header = info->bmiHeader; + + int colorCount = 256; + if (mBitmap.header.biClrUsed != 0) + colorCount = mBitmap.header.biClrUsed; + + int dataSize = ALIGN_ROW_SIZE(mBitmap.header.biWidth) * mBitmap.header.biHeight; + mMemHandle = GlobalAlloc(GHND, dataSize); + mData = (unsigned char *) GlobalLock(mMemHandle); + + for (int i = 0; i < colorCount; i++) + mBitmap.palette[i] = i; + + memcpy(mData, info->bmiColors + colorCount, dataSize); + + if (flip) { + int rowSize = ALIGN_ROW_SIZE(mBitmap.header.biWidth); + void *tmp = malloc(rowSize); + for (int y = 0; y < mBitmap.header.biHeight / 2; y++) { + int otherY = mBitmap.header.biHeight - y - 1; + memcpy(tmp, mData + y * rowSize, rowSize); + memcpy(mData + y * rowSize, mData + otherY * rowSize, rowSize); + memcpy(mData + otherY * rowSize, tmp, rowSize); + } + free(tmp); + } + + mBackGndColor = -1; + mForeGndColor = -1; + mOrigin.x = 0; + mOrigin.y = 0; + mHalftoneMode = false; + SetClipRect(NULL); +} + +T2BitImage::T2BitImage(const RECT& rect) { + int w = rect.right - rect.left; + int h = rect.bottom - rect.top; + + memset(&mBitmap.header, 0, sizeof(mBitmap.header)); + mBitmap.header.biSize = sizeof(mBitmap.header); + mBitmap.header.biWidth = w; + mBitmap.header.biHeight = h; + mBitmap.header.biPlanes = 1; + mBitmap.header.biBitCount = 8; + mBitmap.header.biSizeImage = ALIGN_ROW_SIZE(w) * h; + mBitmap.header.biClrUsed = 256; + + for (int i = 0; i < 256; i++) + mBitmap.palette[i] = i; + + mMemHandle = GlobalAlloc(GHND, mBitmap.header.biSizeImage); + mData = (unsigned char *) GlobalLock(mMemHandle); + + mBackGndColor = -1; + mForeGndColor = -1; + mOrigin.x = 0; + mOrigin.y = 0; + mHalftoneMode = false; + SetClipRect(NULL); +} + +/*virtual*/ T2BitImage::~T2BitImage() { + if (mMemHandle) { + GlobalUnlock(mMemHandle); + GlobalFree(mMemHandle); + } +} + +BOOL T2BitImage::BeginDrawing() { + return true; +} + +void T2BitImage::EndDrawing() { +} + +void T2BitImage::CopyImage(T2BitImage& destImg, const RECT& inSrc, const RECT& inDest, int, CRgn* rgn) { + RECT src; + src.top = inSrc.top; + src.left = inSrc.left; + src.bottom = inSrc.bottom; + src.right = inSrc.right; + OffsetRect(&src, -mOrigin.x, -mOrigin.y); + + RECT dest; + dest.top = inDest.top; + dest.left = inDest.left; + dest.bottom = inDest.bottom; + dest.right = inDest.right; + OffsetRect(&dest, -destImg.mOrigin.x, -destImg.mOrigin.y); + + RECT clipSrc = mClipRect; + OffsetRect(&clipSrc, -mOrigin.x, -mOrigin.y); + + RECT clipDest = destImg.mClipRect; + OffsetRect(&clipDest, -destImg.mOrigin.x, -destImg.mOrigin.y); + + int align; + + if ((dest.bottom - dest.top) == ((src.bottom - src.top) * 4)) { + align = 1; // Y scale /4 + } else if ((dest.bottom - dest.top) == ((src.bottom - src.top) * 2)) { + align = 2; // Y scale /2 + } else if ((dest.bottom - dest.top) == (src.bottom - src.top)) { + align = 4; // No scaling + } else if (((dest.bottom - dest.top) * 2) == (src.bottom - src.top)) { + align = 8; // Y scale *2 + } else if (((dest.bottom - dest.top) * 4) == (src.bottom - src.top)) { + align = 16; // Y scale *4 + } else { + CString err; + err.Format("不正な拡大縮小率\nSrc(%d,%d),Dest(%d,%d)", dest.top, dest.bottom, src.top, src.bottom); +#line 183 + __Rep0(__FILE__, __LINE__, err); + } + + if ( + ((src.right - src.left) != (((dest.right - dest.left) * align) / 4)) || + ((src.bottom - src.top) != (((dest.bottom - dest.top) * align) / 4)) + ) { + CString err; + err.Format("不正な拡大縮小率\nSrc(%d,%d),Dest(%d,%d)", dest.top, dest.bottom, src.top, src.bottom); +#line 190 + __Rep0(__FILE__, __LINE__, err); + } + + RECT rect2; + + int srcX = src.left; + int srcY = src.top; + rect2.top = 0; + rect2.left = 0; + rect2.bottom = mBitmap.header.biHeight; + rect2.right = mBitmap.header.biWidth; + + if (!IntersectRect(&src, &rect2, &src)) + return; + if (mHasClipRect && !IntersectRect(&src, &clipSrc, &src)) + return; + + int destX = dest.left; + int destY = dest.top; + rect2.top = 0; + rect2.left = 0; + rect2.bottom = destImg.mBitmap.header.biHeight; + rect2.right = destImg.mBitmap.header.biWidth; + + if (!IntersectRect(&dest, &rect2, &dest)) + return; + if (destImg.mHasClipRect && !IntersectRect(&dest, &clipDest, &dest)) + return; + + OffsetRect(&src, -srcX, -srcY); + OffsetRect(&dest, -destX, -destY); + + dest.right = (dest.right * align) / 4; + dest.bottom = (dest.bottom * align) / 4; + dest.left = (dest.left * align) / 4; + dest.top = (dest.top * align) / 4; + + if (!IntersectRect(&dest, &src, &dest)) + return; + + src = dest; + + dest.right = (dest.right * 4) / align; + dest.bottom = (dest.bottom * 4) / align; + dest.left = (dest.left * 4) / align; + dest.top = (dest.top * 4) / align; + + OffsetRect(&src, srcX, srcY); + OffsetRect(&dest, destX, destY); + + int width = dest.right - dest.left; + int height = dest.bottom - dest.top; + + int destRowSize = ALIGN_ROW_SIZE(destImg.mBitmap.header.biWidth); + int srcRowSize = ALIGN_ROW_SIZE(mBitmap.header.biWidth); + + unsigned char *destP = destImg.mData + dest.top * destRowSize + dest.left; + unsigned char *srcP = mData + src.top * srcRowSize + src.left; + + int foreGndColor = mForeGndColor; + int backGndColor = mBackGndColor; + BOOL halftoneMode = mHalftoneMode; + + int xAdjust = 0; + if (dest.left < 0) { + xAdjust = -dest.left; + destP += xAdjust; + width -= xAdjust; + } + + int yAdjust = 0; + if (dest.top < 0) { + yAdjust = -dest.top; + destP += destRowSize * yAdjust; + height -= yAdjust; + } + +#define INC_SRC_ROW \ + __asm mov eax, srcP \ + __asm add eax, srcRowSize \ + __asm mov srcP, eax + +#define INC_SRC_ROW_2 \ + __asm mov eax, srcP \ + __asm add eax, srcRowSize \ + __asm add eax, srcRowSize \ + __asm mov srcP, eax + +#define INC_SRC_ROW_4 \ + __asm mov eax, srcP \ + __asm mov ebx, srcRowSize \ + __asm add eax, ebx \ + __asm add eax, ebx \ + __asm add eax, ebx \ + __asm add eax, ebx \ + __asm mov srcP, eax + +#define INC_DEST_ROW \ + __asm mov eax, destP \ + __asm add eax, destRowSize \ + __asm mov destP, eax + + if (!halftoneMode && foreGndColor == -1 && backGndColor == -1) { + // Simple drawing + if (align == 2) { +#ifdef _MSC_VER + __asm { + mov ecx, height + simple2_rowLoop: + or ecx, ecx + jle simple2_end + mov esi, srcP + mov edi, destP + mov edx, width + mov eax, xAdjust + or eax, eax + jnz simple2_midXAdjust + simple2_loopXAdjust: + or edx, edx + jle simple2_afterXAdjust + mov al, [esi] + mov [edi], al + inc edi + dec edx + or edx, edx + jle simple2_afterXAdjust + simple2_midXAdjust: + mov al, [esi] + mov [edi], al + inc esi + inc edi + dec edx + jmp simple2_loopXAdjust + simple2_afterXAdjust: + mov eax, yAdjust + inc eax + mov yAdjust, eax + and eax, 1 + jnz simple2_skipRowInc + INC_SRC_ROW + simple2_skipRowInc: + INC_DEST_ROW + dec ecx + jmp simple2_rowLoop + simple2_end: + } +#endif + } else if (align == 4) { + // No Y scaling at all + if ((width % 8) == 0) { +#ifdef _MSC_VER + __asm { + mov ecx, height + simple4a_outerLoop: + or ecx, ecx + jle simple4a_end + mov esi, srcP + mov edi, destP + mov edx, width + shr edx, 3 + simple4a_innerLoop: + or edx, edx + jle simple4a_rowDone + ; copy an 8-byte chunk + mov eax, [esi] + mov [edi], eax + mov eax, [esi+4] + mov [edi+4], eax + add esi, 8 + add edi, 8 + dec edx + jmp simple4a_innerLoop + simple4a_rowDone: + INC_SRC_ROW + INC_DEST_ROW + dec ecx + jmp simple4a_outerLoop + simple4a_end: + } +#endif + } else { +#ifdef _MSC_VER + __asm { + mov ecx, height + simple4b_outerLoop: + or ecx, ecx + jle simple4b_end + mov esi, srcP + mov edi, destP + mov edx, width + simple4b_innerLoop: + or edx, edx + jle simple4b_rowDone + cmp edx, 4 + jc simple4b_byteCopy + mov eax, [esi] + mov [edi], eax + add esi, 4 + add edi, 4 + sub edx, 4 + jmp simple4b_innerLoop + simple4b_byteCopy: + mov al, [esi] + mov [edi], al + inc esi + inc edi + dec edx + jmp simple4b_innerLoop + simple4b_rowDone: + INC_SRC_ROW + INC_DEST_ROW + dec ecx + jmp simple4b_outerLoop + simple4b_end: + } +#endif + } + } else if (align == 8) { +#ifdef _MSC_VER + __asm { + mov ecx, height + simple8_outerLoop: + or ecx, ecx + jle simple8_end + mov esi, srcP + mov edi, destP + mov edx, width + simple8_innerLoop: + or edx, edx + jle simple8_rowDone + mov al, [esi] + mov [edi], al + add esi, 4 + inc edi + dec edx + jmp simple8_innerLoop + simple8_rowDone: + INC_SRC_ROW_2 + INC_DEST_ROW + dec ecx + jmp simple8_outerLoop + simple8_end: + } +#endif + } else if (align == 16) { +#ifdef _MSC_VER + __asm { + mov ecx, height + simple16_outerLoop: + or ecx, ecx + jle simple16_end + mov esi, srcP + mov edi, destP + mov edx, width + simple16_innerLoop: + or edx, edx + jle simple16_rowDone + mov al, [esi] + mov [edi], al + add esi, 4 + inc edi + dec edx + jmp simple16_innerLoop + simple16_rowDone: + INC_SRC_ROW_4 + INC_DEST_ROW + dec ecx + jmp simple16_outerLoop + simple16_end: + } +#endif + } + return; + } + + if (!halftoneMode && foreGndColor == -1 && backGndColor != -1) { + // Drawing with a background colour only + if (align == 4) { +#ifdef _MSC_VER + __asm { + mov ecx, height + bgc4_outerLoop: + or ecx, ecx + jle bgc4_end + mov esi, srcP + mov edi, destP + mov ah, byte ptr [backGndColor] + mov edx, width + bgc4_innerLoop: + or edx, edx + jle bgc4_rowDone + mov al, [esi] + cmp al, ah + jz bgc4_skipPixel + mov [edi], al + bgc4_skipPixel: + inc esi + inc edi + dec edx + jmp bgc4_innerLoop + bgc4_rowDone: + INC_SRC_ROW + INC_DEST_ROW + dec ecx + jmp bgc4_outerLoop + bgc4_end: + } +#endif + } else if (align == 8) { +#ifdef _MSC_VER + __asm { + mov ecx, height + bgc8_outerLoop: + or ecx, ecx + jle bgc8_end + mov esi, srcP + mov edi, destP + mov ah, byte ptr [backGndColor] + mov edx, width + bgc8_innerLoop: + or edx, edx + jle bgc8_rowDone + mov al, [esi] + cmp al, ah + jz bgc8_skipPixel + mov [edi], al + bgc8_skipPixel: + add esi, 2 + inc edi + dec edx + jmp bgc8_innerLoop + bgc8_rowDone: + INC_SRC_ROW_2 + INC_DEST_ROW + dec ecx + jmp bgc8_outerLoop + bgc8_end: + } +#endif + } else if (align == 16) { +#ifdef _MSC_VER + __asm { + mov ecx, height + bgc16_outerLoop: + or ecx, ecx + jle bgc16_end + mov esi, srcP + mov edi, destP + mov ah, byte ptr [backGndColor] + mov edx, width + bgc16_innerLoop: + or edx, edx + jle bgc16_rowDone + mov al, [esi] + cmp al, ah + jz bgc16_skipPixel + mov [edi], al + bgc16_skipPixel: + add esi, 4 + inc edi + dec edx + jmp bgc16_innerLoop + bgc16_rowDone: + INC_SRC_ROW_4 + INC_DEST_ROW + dec ecx + jmp bgc16_outerLoop + bgc16_end: + } +#endif + } + return; + } + + if (halftoneMode && foreGndColor == -1 && backGndColor == -1) { + // Simple drawing in halftone mode + if (align == 4) { +#ifdef _MSC_VER + __asm { + mov ecx, height + ht4_outerLoop: + or ecx, ecx + jle ht4_end + mov esi, srcP + mov edi, destP + mov edx, width + mov ebx, ecx + ht4_innerLoop: + or edx, edx + jle ht4_rowDone + test ebx, 1 + jz ht4_skipPixel + mov al, [esi] + mov [edi], al + ht4_skipPixel: + inc esi + inc edi + dec edx + inc ebx + jmp ht4_innerLoop + ht4_rowDone: + INC_SRC_ROW + INC_DEST_ROW + dec ecx + jmp ht4_outerLoop + ht4_end: + } +#endif + } else if (align == 8) { +#ifdef _MSC_VER + __asm { + mov ecx, height + ht8_outerLoop: + or ecx, ecx + jle ht8_end + mov esi, srcP + mov edi, destP + mov edx, width + mov ebx, ecx + ht8_innerLoop: + or edx, edx + jle ht8_rowDone + test ebx, 1 + jz ht8_skipPixel + mov al, [esi] + mov [edi], al + ht8_skipPixel: + add esi, 2 + inc edi + dec edx + inc ebx + jmp ht8_innerLoop + ht8_rowDone: + INC_SRC_ROW_2 + INC_DEST_ROW + dec ecx + jmp ht8_outerLoop + ht8_end: + } +#endif + } else if (align == 16) { +#ifdef _MSC_VER + __asm { + mov ecx, height + ht16_outerLoop: + or ecx, ecx + jle ht16_end + mov esi, srcP + mov edi, destP + mov edx, width + mov ebx, ecx + ht16_innerLoop: + or edx, edx + jle ht16_rowDone + test ebx, 1 + jz ht16_skipPixel + mov al, [esi] + mov [edi], al + ht16_skipPixel: + add esi, 4 + inc edi + dec edx + inc ebx + jmp ht16_innerLoop + ht16_rowDone: + INC_SRC_ROW_4 + INC_DEST_ROW + dec ecx + jmp ht16_outerLoop + ht16_end: + } +#endif + } + return; + } + + if (halftoneMode && foreGndColor == -1 && backGndColor != -1) { + // Drawing with a background colour in halftone mode + if (align == 4) { +#ifdef _MSC_VER + __asm { + mov ecx, height + htBg4_outerLoop: + or ecx, ecx + jle htBg4_end + mov esi, srcP + mov edi, destP + mov ah, byte ptr [backGndColor] + mov edx, width + mov ebx, ecx + htBg4_innerLoop: + or edx, edx + jle htBg4_rowDone + test ebx, 1 + jz htBg4_skipPixel + mov al, [esi] + cmp al, ah + jz htBg4_skipPixel + mov [edi], al + htBg4_skipPixel: + inc esi + inc edi + dec edx + inc ebx + jmp htBg4_innerLoop + htBg4_rowDone: + INC_SRC_ROW + INC_DEST_ROW + dec ecx + jmp htBg4_outerLoop + htBg4_end: + } +#endif + } else if (align == 8) { +#ifdef _MSC_VER + __asm { + mov ecx, height + htBg8_outerLoop: + or ecx, ecx + jle htBg8_end + mov esi, srcP + mov edi, destP + mov ah, byte ptr [backGndColor] + mov edx, width + mov ebx, ecx + htBg8_innerLoop: + or edx, edx + jle htBg8_rowDone + test ebx, 1 + jz htBg8_skipPixel + mov al, [esi] + cmp al, ah + jz htBg8_skipPixel + mov [edi], al + htBg8_skipPixel: + add esi, 2 + inc edi + dec edx + inc ebx + jmp htBg8_innerLoop + htBg8_rowDone: + INC_SRC_ROW_2 + INC_DEST_ROW + dec ecx + jmp htBg8_outerLoop + htBg8_end: + } +#endif + } else if (align == 16) { +#ifdef _MSC_VER + __asm { + mov ecx, height + htBg16_outerLoop: + or ecx, ecx + jle htBg16_end + mov esi, srcP + mov edi, destP + mov ah, byte ptr [backGndColor] + mov edx, width + mov ebx, ecx + htBg16_innerLoop: + or edx, edx + jle htBg16_rowDone + test ebx, 1 + jz htBg16_skipPixel + mov al, [esi] + cmp al, ah + jz htBg16_skipPixel + mov [edi], al + htBg16_skipPixel: + add esi, 4 + inc edi + dec edx + inc ebx + jmp htBg16_innerLoop + htBg16_rowDone: + INC_SRC_ROW_4 + INC_DEST_ROW + dec ecx + jmp htBg16_outerLoop + htBg16_end: + } +#endif + } + return; + } + + if (!halftoneMode && foreGndColor != -1 && backGndColor != -1) { + // Drawing with a foreground and background colour + if (align == 4) { +#ifdef _MSC_VER + __asm { + mov ecx, height + fgBg4_outerLoop: + or ecx, ecx + jle fgBg4_end + mov esi, srcP + mov edi, destP + mov bh, byte ptr [foreGndColor] + mov bl, byte ptr [backGndColor] + mov edx, width + fgBg4_innerLoop: + or edx, edx + jle fgBg4_rowDone + mov al, [esi] + cmp al, bl + jz fgBg4_skipPixel + mov [edi], bh + fgBg4_skipPixel: + inc esi + inc edi + dec edx + jmp fgBg4_innerLoop + fgBg4_rowDone: + INC_SRC_ROW + INC_DEST_ROW + dec ecx + jmp fgBg4_outerLoop + fgBg4_end: + } +#endif + } else if (align == 8) { +#ifdef _MSC_VER + __asm { + mov ecx, height + fgBg8_outerLoop: + or ecx, ecx + jle fgBg8_end + mov esi, srcP + mov edi, destP + mov bh, byte ptr [foreGndColor] + mov bl, byte ptr [backGndColor] + mov edx, width + fgBg8_innerLoop: + or edx, edx + jle fgBg8_rowDone + mov al, [esi] + cmp al, bl + jz fgBg8_skipPixel + mov [edi], bh + fgBg8_skipPixel: + add esi, 2 + inc edi + dec edx + jmp fgBg8_innerLoop + fgBg8_rowDone: + INC_SRC_ROW_2 + INC_DEST_ROW + dec ecx + jmp fgBg8_outerLoop + fgBg8_end: + } +#endif + } else if (align == 16) { +#ifdef _MSC_VER + __asm { + mov ecx, height + fgBg16_outerLoop: + or ecx, ecx + jle fgBg16_end + mov esi, srcP + mov edi, destP + mov bh, byte ptr [foreGndColor] + mov bl, byte ptr [backGndColor] + mov edx, width + fgBg16_innerLoop: + or edx, edx + jle fgBg16_rowDone + mov al, [esi] + cmp al, bl + jz fgBg16_skipPixel + mov [edi], bh + fgBg16_skipPixel: + add esi, 4 + inc edi + dec edx + jmp fgBg16_innerLoop + fgBg16_rowDone: + INC_SRC_ROW_4 + INC_DEST_ROW + dec ecx + jmp fgBg16_outerLoop + fgBg16_end: + } +#endif + } + return; + } + + _CrtDbgBreak(); +} + +void T2BitImage::CopyImage(CDC* dc, const RECT& inSrc, const RECT& inDest, int, CRgn*) { + RECT src; + src.top = inSrc.top; + src.left = inSrc.left; + src.bottom = inSrc.bottom; + src.right = inSrc.right; + OffsetRect(&src, -mOrigin.x, -mOrigin.y); + + RECT dest; + dest.top = inDest.top; + dest.left = inDest.left; + dest.bottom = inDest.bottom; + dest.right = inDest.right; + + if ((src.right - src.left) != (dest.right - dest.left) || + (src.top - src.bottom) != (dest.top - dest.bottom)) + return; + + int diffX = src.left - dest.left; + int diffY = src.top - dest.top; + + RECT tmp; + tmp.top = 0; + tmp.left = 0; + tmp.right = mBitmap.header.biWidth; + tmp.bottom = mBitmap.header.biHeight; + + if (tmp.top > tmp.bottom) { + int save = tmp.top; + tmp.top = tmp.bottom; + tmp.bottom = save; + } + + if (src.top > src.bottom) { + int save = src.top; + src.top = src.bottom; + src.bottom = save; + } + + if (!IntersectRect(&src, &tmp, &src)) + return; + + OffsetRect(&dest, diffX, diffY); + if (!IntersectRect(&dest, &dest, &src)) + return; + OffsetRect(&dest, -diffX, -diffY); + + Bitmap bmp = mBitmap; + bmp.header.biHeight = -bmp.header.biHeight; + + SetDIBitsToDevice( + dc->m_hDC, + dest.left, + dest.top, + src.right - src.left, + src.bottom - src.top, + src.left, + abs(bmp.header.biHeight) - src.bottom, + 0, + -bmp.header.biHeight, + mData, + (BITMAPINFO *) &bmp, + 1 + ); +} + +void T2BitImage::Clear(int c) { + memset(mData, c, ALIGN_ROW_SIZE(mBitmap.header.biWidth) * abs(mBitmap.header.biHeight)); +} + +void T2BitImage::SetBackGndColor(int c) { + mBackGndColor = c; +} + +void T2BitImage::SetForeGndColor(int c) { + mForeGndColor = c; +} + +void T2BitImage::SetOrigin(int x, int y) { + mOrigin.x = x; + mOrigin.y = y; +} + +void T2BitImage::SetClipRect(RECT* rect) { + if (!rect) { + SetRect(&mClipRect, 0, 0, mBitmap.header.biWidth, mBitmap.header.biHeight); + mHasClipRect = false; + } else { + mClipRect = *rect; + mHasClipRect = true; + } +} + +void T2BitImage::SetHalftoneMode(BOOL m) { + mHalftoneMode = m; +} + +void T2BitImage::DrawFocusRect(RECT rect) { + DrawFocusRect2(rect); + InsetRect(&rect, 1, 1); + DrawFocusRect2(rect); +} + +void T2BitImage::DrawFocusRect2(RECT rect) { + OffsetRect(&rect, -mOrigin.x, -mOrigin.y); + + RECT bitmapRect; + SetRect(&bitmapRect, 0, 0, mBitmap.header.biWidth, mBitmap.header.biHeight); + + IntersectRect(&rect, &rect, &bitmapRect); + + if (rect.top >= 0) + DrawFocusLine(rect.left, rect.top, rect.right, rect.top); + if (rect.right < mBitmap.header.biWidth) + DrawFocusLine(rect.right - 1, rect.top, rect.right - 1, rect.bottom); + if (rect.bottom < mBitmap.header.biHeight) + DrawFocusLine(rect.left, rect.bottom - 1, rect.right, rect.bottom - 1); + if (rect.left >= 0) + DrawFocusLine(rect.left, rect.top, rect.left, rect.bottom); +} + +void T2BitImage::DrawFocusLine(int x1, int y1, int x2, int y2) { + if (x1 > x2) { + int tmp = x1; + x1 = x2; + x2 = tmp; + } else if (y1 > y2) { + int tmp = y1; + y1 = y2; + y2 = tmp; + } + + int rowSize = ALIGN_ROW_SIZE(mBitmap.header.biWidth); + int counter = 0; + unsigned char *p = mData + y1 * rowSize + x1; + + if (x1 == x2) { + for (int y = y1; y < y2; y++) { + *p = (counter >= 3) ? 254 : 253; + p += rowSize; + counter++; + if (counter == 6) + counter = 0; + } + } else if (y1 == y2) { + for (int x = x1; x < x2; x++) { + *p = (counter >= 3) ? 254 : 253; + p++; + counter++; + if (counter == 6) + counter = 0; + } + } else { + _CrtDbgBreak(); + } +} + +void T2BitImage::FillMesh(RECT rect, int c) { + OffsetRect(&rect, -mOrigin.x, -mOrigin.y); + + RECT bitmapRect; + SetRect(&bitmapRect, 0, 0, mBitmap.header.biWidth, mBitmap.header.biHeight); + + if (mHasClipRect) { + RECT clipRect = mClipRect; + OffsetRect(&clipRect, -mOrigin.x, -mOrigin.y); + IntersectRect(&bitmapRect, &bitmapRect, &clipRect); + } + + IntersectRect(&rect, &rect, &bitmapRect); + if (!IsRectEmpty(&rect)) { + unsigned char parity = rect.left + rect.top; + int rowSize = ALIGN_ROW_SIZE(mBitmap.header.biWidth); + unsigned char *p = mData + rect.top * rowSize + rect.left; + int width = rect.right - rect.left; + int height = rect.bottom - rect.top; + unsigned char cByte = c; + + if (width > 0 && height > 0) { +#ifdef _MSC_VER + __asm { + mov al, cByte + mov ebx, p + mov ecx, height + rowLoop: + mov ah, parity + mov edi, ebx + mov edx, width + pixelLoop: + test ah, 1 + jz skip + mov [edi], al + skip: + inc edi + inc ah + dec edx + jnz pixelLoop + add ebx, rowSize + mov ah, parity + inc ah + mov parity, ah + dec ecx + jnz rowLoop + } +#endif + } + } +} + +void T2BitImage::FillRect(RECT rect, int c) { + OffsetRect(&rect, -mOrigin.x, -mOrigin.y); + + RECT bitmapRect; + SetRect(&bitmapRect, 0, 0, mBitmap.header.biWidth, mBitmap.header.biHeight); + + if (mHasClipRect) { + RECT clipRect = mClipRect; + OffsetRect(&clipRect, -mOrigin.x, -mOrigin.y); + IntersectRect(&bitmapRect, &bitmapRect, &clipRect); + } + + IntersectRect(&rect, &rect, &bitmapRect); + if (!IsRectEmpty(&rect)) { + int rowSize = ALIGN_ROW_SIZE(mBitmap.header.biWidth); + unsigned char *p = mData + rect.top * rowSize + rect.left; + int width = rect.right - rect.left; + int height = rect.bottom - rect.top; + unsigned char cByte = c; + + if (width > 0 && height > 0) { +#ifdef _MSC_VER + __asm { + mov al, cByte + mov ebx, p + mov ecx, height + rowLoop: + mov edi, ebx + mov edx, width + pixelLoop: + mov [edi], al + inc edi + dec edx + jnz pixelLoop + add ebx, rowSize + dec ecx + jnz rowLoop + } +#endif + } + } +} + +int T2BitImage::GetPixel(int x, int y) { + x -= mOrigin.x; + y -= mOrigin.y; + + if (x < 0 || x >= mBitmap.header.biWidth || y < 0 || y >= mBitmap.header.biHeight) + return -1; + + int rowSize = ALIGN_ROW_SIZE(mBitmap.header.biWidth); + return mData[y * rowSize + x]; +} + +int T2BitImage::GetPixel(const POINT& pt) { + return GetPixel(pt.x, pt.y); +} + +/*virtual*/ BOOL T2BitImage::IsExist() { + return mMemHandle != NULL; +} + +void T2BitImage::DrawFrameRect(RECT rect, int c) { + OffsetRect(&rect, -mOrigin.x, -mOrigin.y); + + RECT bitmapRect; + SetRect(&bitmapRect, 0, 0, mBitmap.header.biWidth, mBitmap.header.biHeight); + + if (mHasClipRect) { + RECT clipRect = mClipRect; + OffsetRect(&clipRect, -mOrigin.x, -mOrigin.y); + IntersectRect(&bitmapRect, &bitmapRect, &clipRect); + } + + RECT frameRect; + IntersectRect(&frameRect, &rect, &bitmapRect); + if (!IsRectEmpty(&frameRect)) { + if (frameRect.top == rect.top) + DrawFrameLine(frameRect.left, frameRect.top, frameRect.right, frameRect.top, c); + if (frameRect.left == rect.left) + DrawFrameLine(frameRect.left, frameRect.top, frameRect.left, frameRect.bottom, c); + if (frameRect.bottom == rect.bottom) + DrawFrameLine(frameRect.left, frameRect.bottom - 1, frameRect.right, frameRect.bottom - 1, c); + if (frameRect.right == rect.right) + DrawFrameLine(frameRect.right - 1, frameRect.top, frameRect.right - 1, frameRect.bottom, c); + } +} + +void T2BitImage::DrawFrameLine(int x1, int y1, int x2, int y2, int c) { + if (x1 == x2) { + if (y1 != y2) { + if (y2 < y1) { + int tmp = y1; + y1 = y2; + y2 = tmp; + } + + int rowSize = ALIGN_ROW_SIZE(mBitmap.header.biWidth); + unsigned char *p = mData + y1 * rowSize + x1; + int count = y2 - y1; + unsigned char cByte = c; +#ifdef _MSC_VER + __asm { + mov ecx, count + mov edi, p + mov al, cByte + mov edx, rowSize + pixelLoop: + mov [edi], al + add edi, edx + dec ecx + jnz pixelLoop + } +#else + do { + *p = cByte; + p += rowSize; + } while (--count != 0); +#endif + } + } else if (y1 == y2) { + if (x1 != x2) { + if (x2 < x1) { + int tmp = x1; + x1 = x2; + x2 = tmp; + } + + int rowSize = ALIGN_ROW_SIZE(mBitmap.header.biWidth); + unsigned char *p = mData + y1 * rowSize + x1; + int count = x2 - x1; + unsigned char cByte = c; +#ifdef _MSC_VER + __asm { + mov ecx, count + mov edi, p + mov al, cByte + pixelLoop2: + mov [edi], al + inc edi + dec ecx + jnz pixelLoop2 + } +#else + do { + *p = cByte; + p++; + } while (--count != 0); +#endif + } + } else { +#line 1457 + _ASSERT(0); + } +} |