|
|
|
@@ -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)
|
|
|
|
|
{
|
|
|
|
|