diff --git a/src/Client/AsyncDownloader.c b/src/Client/AsyncDownloader.c index 1e0540755..35beefb6d 100644 --- a/src/Client/AsyncDownloader.c +++ b/src/Client/AsyncDownloader.c @@ -21,7 +21,7 @@ typedef struct AsyncRequestList_ { AsyncRequest DefaultRequests[10]; } AsyncRequestList; -void AsyncRequestList_Append(AsyncRequestList* list, AsyncRequest* item); +/*void AsyncRequestList_Append(AsyncRequestList* list, AsyncRequest* item); void AsyncRequestList_Prepend(AsyncRequestList* list, AsyncRequest* item); void AsyncRequestList_RemoveAt(AsyncRequestList* list, UInt32 i); @@ -268,8 +268,8 @@ void AsyncDownloader_Init(void) { Int32 index = FindRequest(&id, &older); if (index >= 0) { - /* very rare case - priority item was inserted, then inserted again (so put before first item), */ - /* and both items got downloaded before an external function removed them from the queue */ + // very rare case - priority item was inserted, then inserted again (so put before first item), + // and both items got downloaded before an external function removed them from the queue if (older.TimeAdded > request.TimeAdded) { AsyncRequest tmp = older; older = *request; *request = tmp; } @@ -282,7 +282,6 @@ void AsyncDownloader_Init(void) { } Platform_MutexUnlock(async_processedMutex); } - /* object DownloadContent(Request request, HttpWebResponse response) { if (request.Type == RequestType.Bitmap) { MemoryStream data = DownloadBytes(response); diff --git a/src/Client/Drawer2D.c b/src/Client/Drawer2D.c index c0b0c97bf..5f01116ae 100644 --- a/src/Client/Drawer2D.c +++ b/src/Client/Drawer2D.c @@ -129,7 +129,7 @@ Int32 Drawer2D_FontHeight(FontDesc* font, bool useShadow) { Texture Drawer2D_MakeTextTexture(DrawTextArgs* args, Int32 windowX, Int32 windowY) { Size2D size = Drawer2D_MeasureText(args); - if (size.Width == 0.0f && size.Height == 0.0f) { + if (size.Width == 0 && size.Height == 0) { return Texture_FromOrigin(NULL, windowX, windowY, 0, 0, 1.0f, 1.0f); } @@ -343,7 +343,6 @@ void Drawer2D_DrawBitmapText(DrawTextArgs* args, Int32 x, Int32 y) { } Size2D Drawer2D_MeasureBitmapText(DrawTextArgs* args) { - if (Drawer2D_IsEmptyText(&args->Text)) return Size2D_Empty; Int32 textHeight = Drawer2D_AdjTextSize(args->Font.Size); Size2D total = { 0, Drawer2D_CellSize(textHeight) }; Int32 point = Math_Floor(args->Font.Size); @@ -367,18 +366,65 @@ Size2D Drawer2D_MeasureBitmapText(DrawTextArgs* args) { return total; } -void Drawer2D_DrawText(DrawTextArgs* args, Int32 x, Int32 y) { - if (Drawer2D_UseBitmappedChat) { - Drawer2D_DrawBitmapText(args, x, y); - } else { - Platform_DrawText(args, x, y); +Int32 Drawer2D_NextPart(Int32 i, STRING_REF String* value, STRING_TRANSIENT String* part, UInt8* nextCol) { + Int32 length = 0, start = i; + for (; i < value->length; i++) { + if (value->buffer[i] == '&' && Drawer2D_ValidColCodeAt(value, i + 1)) break; + length++; } + + *part = String_UNSAFE_Substring(value, start, length); + i += 2; /* skip over colour code */ + + if (i <= value->length) *nextCol = value->buffer[i - 1]; + return i; +} + +void Drawer2D_DrawText(DrawTextArgs* args, Int32 x, Int32 y) { + if (Drawer2D_IsEmptyText(&args->Text)) return; + if (Drawer2D_UseBitmappedChat) { Drawer2D_DrawBitmapText(args, x, y); return; } + + String value = args->Text; + UInt8 nextCol = 'f'; + Int32 i = 0; + + while (i < value.length) { + UInt8 colCode = nextCol; + i = Drawer2D_NextPart(i, &value, &args->Text, &nextCol); + PackedCol col = Drawer2D_Cols[colCode]; + + if (args->UseShadow) { + PackedCol black = PACKEDCOL_BLACK; + PackedCol backCol = Drawer2D_BlackTextShadows ? black : PackedCol_Scale(col, 0.25f); + Platform_DrawText(args, x + DRAWER2D_OFFSET, y + DRAWER2D_OFFSET, backCol); + } + + Platform_DrawText(args, x, y, col); + x += Platform_MeasureText(args).Width; + } + args->Text = value; } Size2D Drawer2D_MeasureText(DrawTextArgs* args) { - if (Drawer2D_UseBitmappedChat) { - return Drawer2D_MeasureBitmapText(args); - } else { - return Platform_MeasureText(args); + if (Drawer2D_IsEmptyText(&args->Text)) return Size2D_Empty; + if (Drawer2D_UseBitmappedChat) return Drawer2D_MeasureBitmapText(args); + + String value = args->Text; + UInt8 nextCol = 'f'; + Int32 i = 0; + Size2D size = { 0, 0 }; + + while (i < value.length) { + UInt8 col = nextCol; + i = Drawer2D_NextPart(i, &value, &args->Text, &nextCol); + + Size2D partSize = Platform_MeasureText(args); + size.Width += partSize.Width; + size.Height = max(size.Height, partSize.Height); } + + /* TODO: Is this font shadow offet right? */ + if (args->UseShadow) { size.Width += DRAWER2D_OFFSET; size.Height += DRAWER2D_OFFSET; } + args->Text = value; + return size; } \ No newline at end of file diff --git a/src/Client/Drawer2D.h b/src/Client/Drawer2D.h index 9be5d7977..ec8fcde18 100644 --- a/src/Client/Drawer2D.h +++ b/src/Client/Drawer2D.h @@ -18,7 +18,7 @@ bool Drawer2D_UseBitmappedChat; /* Whether the shadows behind text (that uses shadows) is fully black. */ bool Drawer2D_BlackTextShadows; PackedCol Drawer2D_Cols[DRAWER2D_MAX_COLS]; -#define DRAWER2D_OFFSET 1.3f +#define DRAWER2D_OFFSET 1 void Drawer2D_Init(void); void Drawer2D_Free(void); diff --git a/src/Client/Game.c b/src/Client/Game.c index ede7a2315..89063b3df 100644 --- a/src/Client/Game.c +++ b/src/Client/Game.c @@ -768,6 +768,19 @@ void Audio_PlayDigSound(UInt8 type) { } void Audio_PlayStepSound(UInt8 type) { } /* TODO: needed for async downloading */ +IGameComponent AsyncDownloader_MakeComponent(void) { return IGameComponent_MakeEmpty(); } +void AsyncDownloader_GetSkin(STRING_PURE String* id, STRING_PURE String* skinName) { } +void AsyncDownloader_GetData(STRING_PURE String* url, bool priority, STRING_PURE String* id) { } +void AsyncDownloader_GetImage(STRING_PURE String* url, bool priority, STRING_PURE String* id) { } +void AsyncDownloader_GetString(STRING_PURE String* url, bool priority, STRING_PURE String* id) { } +void AsyncDownloader_GetContentLength(STRING_PURE String* url, bool priority, STRING_PURE String* id) { } +void AsyncDownloader_PostString(STRING_PURE String* url, bool priority, STRING_PURE String* id, STRING_PURE String* contents) { } +void AsyncDownloader_GetDataEx(STRING_PURE String* url, bool priority, STRING_PURE String* id, DateTime* lastModified, STRING_PURE String* etag) { } +void AsyncDownloader_GetImageEx(STRING_PURE String* url, bool priority, STRING_PURE String* id, DateTime* lastModified, STRING_PURE String* etag) { } + +bool AsyncDownloader_Get(STRING_PURE String* id, AsyncRequest* item) { return false; } +bool AsyncDownloader_GetCurrent(AsyncRequest* request, Int32* progress) { return false; } +void AsyncDownloader_PurgeOldEntriesTask(ScheduledTask* task) { } DateTime DateTime_FromTotalMs(Int64 ms) { DateTime time; return time; } void Bitmap_EncodePng(Bitmap* bmp, Stream* stream) { } diff --git a/src/Client/Platform.h b/src/Client/Platform.h index c7c20406f..4b881b628 100644 --- a/src/Client/Platform.h +++ b/src/Client/Platform.h @@ -2,6 +2,7 @@ #define CC_PLATFORM_H #include "Utils.h" #include "2DStructs.h" +#include "PackedCol.h" /* Abstracts platform specific memory management, I/O, etc. Copyright 2017 ClassicalSharp | Licensed under BSD-3 */ @@ -75,7 +76,7 @@ void Platform_FreeFont(FontDesc* desc); void Platform_SetBitmap(Bitmap* bmp); void Platform_ReleaseBitmap(void); Size2D Platform_MeasureText(DrawTextArgs* args); -void Platform_DrawText(DrawTextArgs* args, Int32 x, Int32 y); +void Platform_DrawText(DrawTextArgs* args, Int32 x, Int32 y, PackedCol col); void Platform_SocketCreate(void** socket); ReturnCode Platform_SocketConnect(void* socket, STRING_PURE String* ip, Int32 port); diff --git a/src/Client/WinPlatform.c b/src/Client/WinPlatform.c index 8c44fbd72..3f7e14fcf 100644 --- a/src/Client/WinPlatform.c +++ b/src/Client/WinPlatform.c @@ -30,6 +30,10 @@ void Platform_Init(void) { hdc = CreateCompatibleDC(NULL); if (hdc == NULL) ErrorHandler_Fail("Failed to get screen DC"); + SetTextColor(hdc, 0x00FFFFFF); + SetBkColor(hdc, 0x00000000); + SetBkMode(hdc, OPAQUE); + stopwatch_highResolution = QueryPerformanceFrequency(&stopwatch_freq); WSADATA wsaData; @@ -399,15 +403,28 @@ void Platform_FreeFont(FontDesc* desc) { bool bmpAssociated; HBITMAP hbmp; Bitmap* bmp; +void* hbmp_bits; void Platform_AssociateBitmap(void) { if (bmpAssociated) return; bmpAssociated = true; - /* TODO: Should we be using CreateDIBitmap here? */ - hbmp = CreateBitmap(bmp->Width, bmp->Height, 1, 32, bmp->Scan0); + BITMAPINFO bmi; + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = bmp->Width; + bmi.bmiHeader.biHeight = bmp->Height; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = Bitmap_DataSize(bmp->Width, bmp->Height); + + hbmp = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &hbmp_bits, NULL, 0x0); if (hbmp == NULL) ErrorHandler_Fail("Creating bitmap handle failed"); if (!SelectObject(hdc, hbmp)) ErrorHandler_Fail("Selecting bitmap handle"); + + String font = String_FromConst("Arial"); + FontDesc desc; Platform_MakeFont(&desc, &font, 12, FONT_STYLE_NORMAL); + String text = String_FromConst("TEST"); } void Platform_SetBitmap(Bitmap* bmpNew) { @@ -415,8 +432,16 @@ void Platform_SetBitmap(Bitmap* bmpNew) { bmp = bmpNew; } +void Platform_DrawBufferedText(void) { + /* draw text and stuff */ + //Platform_MemCpy(bmp->Scan0, hbmp_bits, Bitmap_DataSize(bmp->Width, bmp->Height)); + //BITMAP bmp = { 0 }; + //./ReturnCode result = GetObjectA(hbmp, sizeof(BITMAP), &bmp); +} + void Platform_ReleaseBitmap(void) { if (bmpAssociated) { + Platform_DrawBufferedText(); if (!DeleteObject(hbmp)) ErrorHandler_Fail("Deleting bitmap handle failed"); hbmp = NULL; } @@ -425,28 +450,69 @@ void Platform_ReleaseBitmap(void) { bmp = NULL; } -/* TODO: Associate Font with device */ -/* TODO: Add shadow offset for drawing */ +/* TODO: not ssociate font with device so much */ Size2D Platform_MeasureText(DrawTextArgs* args) { - HDC hDC = GetDC(NULL); RECT r = { 0 }; - HGDIOBJ oldFont = SelectObject(hDC, args->Font.Handle); - DrawTextA(hDC, args->Text.buffer, args->Text.length, + HGDIOBJ oldFont = SelectObject(hdc, args->Font.Handle); + DrawTextA(hdc, args->Text.buffer, args->Text.length, &r, DT_CALCRECT | DT_NOPREFIX | DT_SINGLELINE | DT_NOCLIP); - SelectObject(hDC, oldFont); + SelectObject(hdc, oldFont); return Size2D_Make(r.right, r.bottom); } -void Platform_DrawText(DrawTextArgs* args, Int32 x, Int32 y) { - HDC hDC = GetDC(NULL); - RECT r = { 0 }; +/* TODO: not allocate so much */ +/* TODO: check return codes and stuff */ +/* TODO: make text prettier.. somehow? */ +/* TODO: Do we need to / 255 instead of >> 8 ? */ +/* TODO: Don't use DrawTextA, bit slow */ +/* TODO: Code page 437 - so probably need to use W variants of functions */ +void Platform_DrawText(DrawTextArgs* args, Int32 x, Int32 y, PackedCol col) { + String* text = &args->Text; + HGDIOBJ oldFont = (HFONT)SelectObject(hdc, (HFONT)args->Font.Handle); + RECT area = { 0 }; + DrawTextA(hdc, text->buffer, text->length, &area, DT_CALCRECT); - HGDIOBJ oldFont = SelectObject(hDC, args->Font.Handle); - DrawTextA(hDC, args->Text.buffer, args->Text.length, - &r, DT_NOPREFIX | DT_SINGLELINE | DT_NOCLIP); - SelectObject(hDC, oldFont); + void* bits = NULL; + BITMAPINFO bmi = { 0 }; + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = bmp->Width; + bmi.bmiHeader.biHeight = -bmp->Height; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = BI_RGB; + + HBITMAP dib = CreateDIBSection(hdc, &bmi, 0, &bits, NULL, 0); + HGDIOBJ oldBmp = (HBITMAP)SelectObject(hdc, dib); + DrawTextA(hdc, text->buffer, text->length, &area, DT_NOPREFIX | DT_SINGLELINE | DT_NOCLIP); + + Int32 xx, yy; + for (yy = 0; yy < area.bottom; yy++) { + UInt8* src = (UInt8*)bits + yy * (bmp->Width * 4); + UInt8* dst = (UInt8*)Bitmap_GetRow(bmp, y + yy); dst += x * BITMAP_SIZEOF_PIXEL; + + for (xx = 0; xx < area.right; xx++) { + UInt8 intensity = *src, invIntensity = UInt8_MaxValue - intensity; + dst[0] = ((col.B * intensity) >> 8) + ((dst[0] * invIntensity) >> 8); + dst[1] = ((col.G * intensity) >> 8) + ((dst[1] * invIntensity) >> 8); + dst[2] = ((col.R * intensity) >> 8) + ((dst[2] * invIntensity) >> 8); + dst[3] = intensity + ((dst[3] * invIntensity) >> 8); + src += BITMAP_SIZEOF_PIXEL; dst += BITMAP_SIZEOF_PIXEL; + } + } + + SelectObject(hdc, oldBmp); + SelectObject(hdc, oldFont); + DeleteObject(dib); + + //RECT r = { 0 }; + //Platform_AssociateBitmap(); + + //HGDIOBJ oldFont = SelectObject(hdc, args->Font.Handle); + //DrawTextA(hdc, args->Text.buffer, args->Text.length, + // &r, DT_NOPREFIX | DT_SINGLELINE | DT_NOCLIP); + //SelectObject(hdc, oldFont); }