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/T2ImageObj.cpp | |
download | t2win-37e364b2c6cc7487a1c888d256a73e5337bb7189.tar.gz t2win-37e364b2c6cc7487a1c888d256a73e5337bb7189.zip |
initial commit
Diffstat (limited to 'src/T2DLL/T2ImageObj.cpp')
-rw-r--r-- | src/T2DLL/T2ImageObj.cpp | 394 |
1 files changed, 394 insertions, 0 deletions
diff --git a/src/T2DLL/T2ImageObj.cpp b/src/T2DLL/T2ImageObj.cpp new file mode 100644 index 0000000..cea6308 --- /dev/null +++ b/src/T2DLL/T2ImageObj.cpp @@ -0,0 +1,394 @@ +#include "GlobalFunc.h" +#include "T2BitImage.h" +#include "T2ImageObj.h" + +T2ImageObj::T2ImageObj() { + mCount = 0; + mHandle = GlobalAlloc(GHND, 1); + mData = (ObjectData *) GlobalLock(mHandle); +} + +/*virtual*/ T2ImageObj::~T2ImageObj() { + GlobalUnlock(mHandle); + GlobalFree(mHandle); +} + +void T2ImageObj::AddObject(HINSTANCE instance, unsigned int resourceID, T2BitImage* image) { +#line 36 + _ASSERT(image); + + HRSRC rsrc = FindResource(instance, MAKEINTRESOURCE(resourceID), "OBJMAP"); + if (!rsrc) { + CString nameStr; + nameStr.Format("%d", resourceID); + + CString err = "T2ImageObj::AddObject ERROR : " + nameStr + " @" + GetModuleName(instance) + "\n"; + OutputDebugString(err); + } + +#line 45 + _ASSERT(rsrc); + + HGLOBAL h = LoadResource(instance, rsrc); +#line 47 + _ASSERT(h); + + void *resData = LockResource(h); + DWORD size = SizeofResource(instance, rsrc); + char *buffer = (char *) malloc(size); + memcpy(buffer, resData, size); + UnlockResource(h); + FreeResource(h); + + char *token = strtok(buffer, " \t\r\n\x1A"); + while (token) { + if (!_stricmp(token, "End")) + break; + + if (!_stricmp(token, "DefParts")) { + mCount++; + mHandle = GlobalReAlloc(mHandle, mCount * sizeof(ObjectData), GHND); + mData = (ObjectData *) GlobalLock(mHandle); + memset(&mData[mCount - 1], 0, sizeof(ObjectData)); + + mData[mCount - 1].image = image; + strcpy(mData[mCount - 1].name, ""); + mData[mCount - 1].id = 0; + mData[mCount - 1].pattern = -1; + mData[mCount - 1].grade = 0; + mData[mCount - 1].span = 0; + mData[mCount - 1].offset = -1; + } else if (!_stricmp(token, "Name")) { + strcpy(mData[mCount - 1].name, strtok(NULL, "\t\r\n\x1A")); + } else if (!_stricmp(token, "ID")) { + mData[mCount - 1].id = atoi(strtok(NULL, " \t\r\n\x1A")); + } else if (!_stricmp(token, "Pattern")) { + mData[mCount - 1].pattern = atoi(strtok(NULL, " \t\r\n\x1A")); + } else if (!_stricmp(token, "Grade")) { + mData[mCount - 1].grade = atoi(strtok(NULL, " \t\r\n\x1A")); + } else if (!_stricmp(token, "Span")) { + mData[mCount - 1].span = atoi(strtok(NULL, " \t\r\n\x1A")); + } else if (!_stricmp(token, "Offset")) { + mData[mCount - 1].offset = atoi(strtok(NULL, " \t\r\n\x1A")); + } else if (!_stricmp(token, "Roof")) { + if (!_stricmp(strtok(NULL, " \t\r\n\x1A"), "Yes")) + mData[mCount - 1].roof = true; + } else if (!_stricmp(token, "Floor")) { + if (!_stricmp(strtok(NULL, " \t\r\n\x1A"), "Yes")) + mData[mCount - 1].floor = true; + } else if (!_stricmp(token, "List")) { + // nothing + } else if (!_stricmp(token, "Loop")) { + mData[mCount - 1].subParts[mData[mCount - 1].subPartCount - 1].flags |= SPD_LOOP; + } else if (!_stricmp(token, "Transparent")) { + mData[mCount - 1].subParts[mData[mCount - 1].subPartCount - 1].flags |= SPD_TRANSPARENT; + } else if (!_stricmp(token, "Halftone")) { + mData[mCount - 1].subParts[mData[mCount - 1].subPartCount - 1].flags |= SPD_HALFTONE; + } else if (!_stricmp(token, "Rect")) { + mData[mCount - 1].subPartCount++; + mData[mCount - 1].subParts[mData[mCount - 1].subPartCount - 1].flags = SPD_RECT; + + char *argToken = strtok(NULL, " \t\r\n\x1A"); + char *arg = (char *) malloc(strlen(argToken) + 1); + strcpy(arg, argToken); + + char *p; + while ((p = strchr(arg, ','))) + *p = ' '; + + sscanf( + arg, + "%hd %hd %hd %hd", + &mData[mCount - 1].subParts[mData[mCount - 1].subPartCount - 1].left, + &mData[mCount - 1].subParts[mData[mCount - 1].subPartCount - 1].top, + &mData[mCount - 1].subParts[mData[mCount - 1].subPartCount - 1].right, + &mData[mCount - 1].subParts[mData[mCount - 1].subPartCount - 1].bottom + ); + + free(arg); + } else if (!_stricmp(token, "Parts")) { + char *argToken = strtok(NULL, " \t\r\n\x1A"); + if (argToken[0] != '#') { + int i; + for (i = 0; i < (mCount - 1); i++) { + if (!strcmp(mData[i].name, argToken)) { + mData[mCount - 1].subPartCount++; + mData[mCount - 1].subParts[mData[mCount - 1].subPartCount - 1].flags = SPD_PARTS_BY_NAME; + mData[mCount - 1].subParts[mData[mCount - 1].subPartCount - 1].partIndex = i; + break; + } + } + + if (i == (mCount - 1)) { + char buf[256]; + wsprintf(buf, "Undefined parts [%s]", argToken); + MessageBox(NULL, buf, "ERROR", MB_OK | MB_ICONWARNING | MB_TASKMODAL); + } + } else { + mData[mCount - 1].subPartCount++; + mData[mCount - 1].subParts[mData[mCount - 1].subPartCount - 1].flags = SPD_PARTS_BY_ID; + mData[mCount - 1].subParts[mData[mCount - 1].subPartCount - 1].objectID = atoi(&argToken[1]); + } + } else if (token[0] == '#') { + // nothing + } else { + char buf[256]; + wsprintf(buf, "Undefined token [%s]", token); + MessageBox(NULL, buf, "ERROR", MB_OK | MB_ICONWARNING | MB_TASKMODAL); + } + + token = strtok(NULL, " \t\r\n\x1A"); + } + + free(buffer); +} + +void T2ImageObj::AddObject(const char* name, int pattern, T2BitImage& image, const RECT* rect, BOOL transparent, BOOL halftoneMode) { + mCount++; + mHandle = GlobalReAlloc(mHandle, mCount * sizeof(ObjectData), GHND); + mData = (ObjectData *) GlobalLock(mHandle); + memset(&mData[mCount - 1], 0, sizeof(ObjectData)); + + mData[mCount - 1].image = ℑ + strcpy(mData[mCount - 1].name, name); + mData[mCount - 1].id = 0; + mData[mCount - 1].pattern = pattern; + mData[mCount - 1].grade = 0; + mData[mCount - 1].span = 0; + mData[mCount - 1].offset = -1; + mData[mCount - 1].subPartCount = 1; + mData[mCount - 1].subParts[0].flags = + SPD_RECT | + (transparent ? SPD_TRANSPARENT : 0) | + (halftoneMode ? SPD_HALFTONE : 0); + + if (rect) { + mData[mCount - 1].subParts[0].top = rect->top; + mData[mCount - 1].subParts[0].left = rect->left; + mData[mCount - 1].subParts[0].bottom = rect->bottom; + mData[mCount - 1].subParts[0].right = rect->right; + } else { + mData[mCount - 1].subParts[0].top = 0; + mData[mCount - 1].subParts[0].left = 0; + mData[mCount - 1].subParts[0].bottom = abs(image.mBitmap.header.biHeight); + mData[mCount - 1].subParts[0].right = abs(image.mBitmap.header.biWidth); + } +} + +void T2ImageObj::AddObject(int id, int pattern, T2BitImage& image, const RECT* rect, BOOL transparent, BOOL halftoneMode) { + mCount++; + mHandle = GlobalReAlloc(mHandle, mCount * sizeof(ObjectData), GHND); + mData = (ObjectData *) GlobalLock(mHandle); + memset(&mData[mCount - 1], 0, sizeof(ObjectData)); + + mData[mCount - 1].image = ℑ + strcpy(mData[mCount - 1].name, ""); + mData[mCount - 1].id = id; + mData[mCount - 1].pattern = pattern; + mData[mCount - 1].grade = 0; + mData[mCount - 1].span = 0; + mData[mCount - 1].offset = -1; + mData[mCount - 1].subPartCount = 1; + mData[mCount - 1].subParts[0].flags = + SPD_RECT | + (transparent ? SPD_TRANSPARENT : 0) | + (halftoneMode ? SPD_HALFTONE : 0); + + if (rect) { + mData[mCount - 1].subParts[0].top = rect->top; + mData[mCount - 1].subParts[0].left = rect->left; + mData[mCount - 1].subParts[0].bottom = rect->bottom; + mData[mCount - 1].subParts[0].right = rect->right; + } else { + mData[mCount - 1].subParts[0].top = 0; + mData[mCount - 1].subParts[0].left = 0; + mData[mCount - 1].subParts[0].bottom = abs(image.mBitmap.header.biHeight); + mData[mCount - 1].subParts[0].right = abs(image.mBitmap.header.biWidth); + } +} + +int T2ImageObj::FindObject(int id, int pattern, int grade, int span, int offset) { + ObjectData *obj = mData; + int index; + + for (index = 0; index < mCount; index++, obj++) { + if ( + (obj->id == id) && + (obj->pattern == pattern || obj->pattern == -1 || pattern == -1) && + (obj->grade == grade || obj->grade == 0 || grade == 0) && + (obj->span == span || obj->span == 0 || span == 0) && + (obj->offset == offset || obj->offset == 255 || offset == 255) + ) + break; + } + + if (index == mCount) + return -1; + else + return index; +} + +int T2ImageObj::FindObject(const char* name, int pattern, int grade, int span, int offset) { + ObjectData *obj = mData; + int index; + + for (index = 0; index < mCount; index++, obj++) { + if ( + !strcmp(obj->name, name) && + (obj->pattern == pattern || obj->pattern == -1 || pattern == -1) && + (obj->grade == grade || obj->grade == 0 || grade == 0) && + (obj->span == span || obj->span == 0 || span == 0) && + (obj->offset == offset || obj->offset == 255 || offset == 255) + ) + break; + } + + if (index == mCount) + return -1; + else + return index; +} + +void T2ImageObj::EnumParts(int index, int width, PARTSLIST* outParts, int* outCount) { +#line 272 + _ASSERT(index >= 0); + + int i = 0; + width = width * 8; + + while (width > 0 && i < mData[index].subPartCount) { + if (mData[index].subParts[i].flags & SPD_RECT) { + // Draw a piece of the image + outParts[*outCount].image = mData[index].image; + outParts[*outCount].rect.top = mData[index].subParts[i].top; + outParts[*outCount].rect.left = mData[index].subParts[i].left; + outParts[*outCount].rect.bottom = mData[index].subParts[i].bottom; + outParts[*outCount].rect.right = mData[index].subParts[i].right; + + if ((mData[index].subParts[i].flags & SPD_TRANSPARENT) == 0) + outParts[*outCount].transparent = false; + else + outParts[*outCount].transparent = true; + + if ((mData[index].subParts[i].flags & SPD_HALFTONE) == 0) + outParts[*outCount].halftoneMode = false; + else + outParts[*outCount].halftoneMode = true; + + width -= (outParts[*outCount].rect.right - outParts[*outCount].rect.left); + (*outCount)++; + } else if (mData[index].subParts[i].flags & SPD_PARTS_BY_NAME) { + // Include another part list + int prevCount = *outCount; + EnumParts(mData[index].subParts[i].partIndex, width, outParts, outCount); + for (; prevCount < *outCount; prevCount++) + width -= (outParts[prevCount].rect.right - outParts[prevCount].rect.left); + } else if (mData[index].subParts[i].flags & SPD_PARTS_BY_ID) { + // Search for an object and include its part list + int prevCount = *outCount; + EnumParts(FindObject(mData[index].subParts[i].objectID, -1, 0, 0, 255), width, outParts, outCount); + for (; prevCount < *outCount; prevCount++) + width -= (outParts[prevCount].rect.right - outParts[prevCount].rect.left); + } + + if (!(mData[index].subParts[i].flags & SPD_LOOP)) + i++; + } +} + +BOOL T2ImageObj::WithRoof(int index) { + return mData[index].roof; +} + +BOOL T2ImageObj::WithFloor(int index) { + return mData[index].floor; +} + +void T2ImageObj::DrawObject(T2BitImage* image, int index, RECT rect, int factor, int foreGndColor) { + DrawObject(image, index, rect, factor, false, foreGndColor); +} + +void T2ImageObj::DrawObject(CDC* dc, int index, RECT rect, int factor, int foreGndColor) { + DrawObject(dc, index, rect, factor, true, foreGndColor); +} + +void T2ImageObj::DrawObject(void* target, int index, RECT rect, int factor, BOOL targetIsDC, int foreGndColor) { +#line 338 + _ASSERT(index >= 0); + + static PARTSLIST parts[500]; + int width = rect.right - rect.left; + int num = 0; + EnumParts(index, width, parts, &num); + + if (num >= 500) + MessageBox(NULL, "Too many parts", "T2ImageObj::DrawObject", MB_OK | MB_ICONERROR | MB_TASKMODAL); + + for (int i = 0; i < num; i++) { + RECT srcRect = parts[i].rect; + RECT destRect = srcRect; + + if ((srcRect.right - srcRect.left) > ((destRect.right - destRect.left) << factor)) + srcRect.right = srcRect.left + ((destRect.right - destRect.left) << factor); + + if ((destRect.right - destRect.left) > ((srcRect.right - srcRect.left) >> factor)) + destRect.right = destRect.left + ((srcRect.right - srcRect.left) >> factor); + + if ((srcRect.bottom - srcRect.top) > ((destRect.bottom - destRect.top) << factor)) + srcRect.bottom = srcRect.top + ((destRect.bottom - destRect.top) << factor); + + if ((destRect.bottom - destRect.top) > ((srcRect.bottom - srcRect.top) >> factor)) + destRect.bottom = destRect.top + ((srcRect.bottom - srcRect.top) >> factor); + + if (parts[i].transparent) + parts[i].image->SetBackGndColor(0); + else + parts[i].image->SetBackGndColor(-1); + + if (parts[i].halftoneMode) + parts[i].image->SetHalftoneMode(true); + else + parts[i].image->SetHalftoneMode(false); + + parts[i].image->SetForeGndColor(foreGndColor); + if (targetIsDC) { + parts[i].image->CopyImage((CDC *) target, srcRect, destRect, false, NULL); + } else { + parts[i].image->CopyImage(*((T2BitImage *) target), srcRect, destRect, false, NULL); + } + parts[i].image->SetHalftoneMode(false); + + rect.left += (destRect.right - destRect.left); + } +} + +BOOL T2ImageObj::GetObjectSize(int index, SIZE* outSize) { +#line 383 + _ASSERT(index >= 0); + + PARTSLIST part; + int num = 0; + EnumParts(index, 1, &part, &num); + + if (num != 1) + return false; + + outSize->cx = part.rect.right - part.rect.left; + outSize->cy = part.rect.bottom - part.rect.top; + return true; +} + +T2BitImage* T2ImageObj::GetObjectImage(int index, RECT& outRect) { +#line 397 + _ASSERT(index >= 0); + + PARTSLIST part; + int num = 0; + EnumParts(index, 1, &part, &num); + + if (num != 1) + return NULL; + + outRect = part.rect; + return part.image; +} |