From 75c11e7822208a054b94d2c6e2c99298419b316f Mon Sep 17 00:00:00 2001 From: Meep-Eep Date: Sun, 29 Nov 2009 23:32:02 +0000 Subject: [PATCH] Added 'COLOR' resource type. git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3370 8092fc87-c524-0410-9efc-e669fe64eaf9 --- sc2/ChangeLog | 1 + sc2/src/libs/gfxlib.h | 7 +- sc2/src/libs/reslib.h | 6 ++ sc2/src/libs/resource/resinit.c | 186 +++++++++++++++++++++++++++++++- 4 files changed, 197 insertions(+), 3 deletions(-) diff --git a/sc2/ChangeLog b/sc2/ChangeLog index aa825e7ad..4e315e6e0 100644 --- a/sc2/ChangeLog +++ b/sc2/ChangeLog @@ -1,4 +1,5 @@ Changes towards version 0.7: +- Added 'COLOR' resource type - SvdB - All graphics operations use 24-bits colors at the game level too now, instead of 16 bits colors. - SvdB - Cross-platform safemode (ignores uqm.cfg, bug #946) - Michael diff --git a/sc2/src/libs/gfxlib.h b/sc2/src/libs/gfxlib.h index fe0c04c83..954435736 100644 --- a/sc2/src/libs/gfxlib.h +++ b/sc2/src/libs/gfxlib.h @@ -20,6 +20,9 @@ #define _GFXLIB_H #include "libs/compiler.h" + +typedef struct Color Color; + #include "libs/reslib.h" typedef struct context_desc CONTEXT_DESC; @@ -39,12 +42,12 @@ typedef UWORD TIME_VALUE; typedef SWORD COORD; -typedef struct Color { +struct Color { BYTE r; BYTE g; BYTE b; BYTE a; // Currently unused -} Color; +}; static inline bool sameColor(Color c1, Color c2) diff --git a/sc2/src/libs/reslib.h b/sc2/src/libs/reslib.h index c184c1b66..ee1ff701c 100644 --- a/sc2/src/libs/reslib.h +++ b/sc2/src/libs/reslib.h @@ -79,6 +79,8 @@ void *GetResourceData (uio_Stream *fp, DWORD length); BOOLEAN FreeResourceData (void *); #include "strlib.h" +#include "gfxlib.h" + // For Color typedef STRING_TABLE DIRENTRY_REF; typedef STRING DIRENTRY; @@ -114,6 +116,10 @@ BOOLEAN res_IsBoolean (const char *key); BOOLEAN res_GetBoolean (const char *key); void res_PutBoolean (const char *key, BOOLEAN value); +BOOLEAN res_IsColor (const char *key); +Color res_GetColor (const char *key); +void res_PutColor (const char *key, Color value); + BOOLEAN res_Remove (const char *key); #endif /* _RESLIB_H */ diff --git a/sc2/src/libs/resource/resinit.c b/sc2/src/libs/resource/resinit.c index fee9cd29e..754c01137 100644 --- a/sc2/src/libs/resource/resinit.c +++ b/sc2/src/libs/resource/resinit.c @@ -160,6 +160,128 @@ DescriptorToBoolean (const char *descriptor, RESOURCE_DATA *resdata) } } +static inline size_t +skipWhiteSpace (const char *start) +{ + const char *ptr = start; + while (isspace (*ptr)) + ptr++; + return (ptr - start); +} + +// On success, resdata->num will be filled with a 32-bits RGBA value. +static void +DescriptorToColor (const char *descriptor, RESOURCE_DATA *resdata) +{ + int bytesParsed; + int componentBits; + int maxComponentValue; + size_t componentCount; + size_t compI;; + int comps[4]; + // One element for each of r, g, b, a. + + descriptor += skipWhiteSpace (descriptor); + +#if 0 + // Can't use this; '#' starts a comment. + if (*descriptor == '#') + { + // "#rrggbb" + int i; + DWORD value = 0; + + descriptor++; + for (i = 0; i < 6; i++) + { + BYTE nibbleValue; + if (*descriptor >= '0' && *descriptor <= '9') + nibbleValue = *descriptor - '0'; + else if (*descriptor >= 'a' && *descriptor <= 'f') + nibbleValue = 0xa + *descriptor - 'a'; + else if (*descriptor >= 'A' && *descriptor <= 'F') + nibbleValue = 0xa + *descriptor - 'A'; + else + goto fail; + + value = (value * 16) + nibbleValue; + descriptor++; + } + + descriptor += skipWhiteSpace (descriptor); + + if (*descriptor != '\0') + log_add (log_Warning, "Junk after color resource string."); + + resdata->num = (value << 8) | 0xff; + return; + } +#endif + + // Color is of the form "rgb(r, g, b)", "rgba(r, g, b, a)", + // or "rgb15(r, g, b)". + + if (sscanf (descriptor, "rgb ( %i , %i , %i ) %n", + &comps[0], &comps[1], &comps[2], &bytesParsed) >= 3) + { + componentBits = 8; + componentCount = 3; + comps[3] = 0xff; + } + else if (sscanf (descriptor, "rgba ( %i , %i , %i , %i ) %n", + &comps[0], &comps[1], &comps[2], &comps[3], &bytesParsed) >= 4) + { + componentBits = 8; + componentCount = 4; + } + else if (sscanf (descriptor, "rgb15 ( %i , %i , %i ) %n", + &comps[0], &comps[1], &comps[2], &bytesParsed) >= 3) + { + componentBits = 5; + componentCount = 3; + comps[3] = 0xff; + } + else + goto fail; + + if (descriptor[bytesParsed] != '\0') + log_add (log_Warning, "Junk after color resource string."); + + maxComponentValue = (1 << componentBits) - 1; + + // Check the range of the components. + for (compI = 0; compI < componentCount; compI++) + { + if (comps[compI] < 0) + { + comps[compI] = 0; + log_add (log_Warning, "Color component value too small; " + "value clipped."); + } + + if (comps[compI] > (long) maxComponentValue) + { + comps[compI] = maxComponentValue; + log_add (log_Warning, "Color component value too large; " + "value clipped."); + } + } + + if (componentBits == 5) + resdata->num = ((CC5TO8 (comps[0]) << 24) | + (CC5TO8 (comps[1]) << 16) | (CC5TO8 (comps[2]) << 8) | + comps[3]); + else + resdata->num = ((comps[0] << 24) | (comps[1] << 16) | + (comps[2] << 8) | comps[3]); + + return; + +fail: + log_add (log_Error, "Invalid color description string for resource.\n"); + resdata->num = 0x00000000; +} + static void RawDescriptor (RESOURCE_DATA *resdata, char *buf, unsigned int size) { @@ -179,6 +301,25 @@ BooleanToString (RESOURCE_DATA *resdata, char *buf, unsigned int size) snprintf (buf, size, "%s", resdata->num ? "true" : "false"); } +static void +ColorToString (RESOURCE_DATA *resdata, char *buf, unsigned int size) +{ + if ((resdata->num & 0xff) == 0xff) + { + // Opaque color, save as "rgb". + snprintf (buf, size, "rgb(0x%02x, 0x%02x, 0x%02x)", + (resdata->num >> 24), (resdata->num >> 16) & 0xff, + (resdata->num >> 8) & 0xff); + } + else + { + // (Partially) transparent color, save as "rgba". + snprintf (buf, size, "rgba(0x%02x, 0x%02x, 0x%02x, 0x%02x)", + (resdata->num >> 24), (resdata->num >> 16) & 0xff, + (resdata->num >> 8) & 0xff, resdata->num & 0xff); + } +} + static RESOURCE_INDEX curResourceIndex; void @@ -201,7 +342,9 @@ InitResourceSystem (void) InstallResTypeVectors ("UNKNOWNRES", UseDescriptorAsRes, NULL, NULL); InstallResTypeVectors ("STRING", UseDescriptorAsRes, NULL, RawDescriptor); InstallResTypeVectors ("INT32", DescriptorToInt, NULL, IntToString); - InstallResTypeVectors ("BOOLEAN", DescriptorToBoolean, NULL, BooleanToString); + InstallResTypeVectors ("BOOLEAN", DescriptorToBoolean, NULL, + BooleanToString); + InstallResTypeVectors ("COLOR", DescriptorToColor, NULL, ColorToString); InstallGraphicResTypes (); InstallStringTableResType (); InstallAudioResTypes (); @@ -436,6 +579,47 @@ res_PutBoolean (const char *key, BOOLEAN value) desc->resdata.num = value; } +BOOLEAN +res_IsColor (const char *key) +{ + RESOURCE_INDEX idx = _get_current_index_header (); + ResourceDesc *desc = lookupResourceDesc (idx, key); + return desc && !strcmp(desc->vtable->resType, "COLOR"); +} + +Color +res_GetColor (const char *key) +{ + RESOURCE_INDEX idx = _get_current_index_header (); + ResourceDesc *desc = lookupResourceDesc (idx, key); + DWORD num; + if (!desc || strcmp(desc->vtable->resType, "COLOR")) + { + // TODO: Better error handling + return buildColorRgba (0, 0, 0, 0); + } + + num = desc->resdata.num; + return buildColorRgba (num >> 24, (num >> 16) & 0xff, + (desc->resdata.num >> 8) & 0xff, num & 0xff); +} + +void +res_PutColor (const char *key, Color value) +{ + RESOURCE_INDEX idx = _get_current_index_header (); + ResourceDesc *desc = lookupResourceDesc (idx, key); + if (!desc || strcmp(desc->vtable->resType, "COLOR")) + { + /* TODO: This is kind of roundabout. We can do better by refactoring + * newResourceDesc */ + process_resource_desc(key, "COLOR:#000000"); + desc = lookupResourceDesc (idx, key); + } + desc->resdata.num = + (value.r << 24) | (value.g << 16) | (value.b << 8) | value.a; +} + BOOLEAN res_HasKey (const char *key) {