summaryrefslogtreecommitdiff
path: root/src/T2DLL/T2ImageObj.cpp
diff options
context:
space:
mode:
authorAsh Wolf <ninji@wuffs.org>2023-06-14 00:50:34 +0100
committerAsh Wolf <ninji@wuffs.org>2023-06-14 00:50:34 +0100
commit37e364b2c6cc7487a1c888d256a73e5337bb7189 (patch)
treeeaf6e857382eef16c2dd940eb4125536fbe068bd /src/T2DLL/T2ImageObj.cpp
downloadt2win-37e364b2c6cc7487a1c888d256a73e5337bb7189.tar.gz
t2win-37e364b2c6cc7487a1c888d256a73e5337bb7189.zip
initial commit
Diffstat (limited to 'src/T2DLL/T2ImageObj.cpp')
-rw-r--r--src/T2DLL/T2ImageObj.cpp394
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 = &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 = &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;
+}