diff --git a/hmml_to_html/hmml_to_html.c b/hmml_to_html/hmml_to_html.c
index c07f841..487e710 100644
--- a/hmml_to_html/hmml_to_html.c
+++ b/hmml_to_html/hmml_to_html.c
@@ -213,42 +213,23 @@ CopyStringToBufferHTMLSafe(buffer *Dest, char *String)
switch(*String)
{
case '<':
- *Dest->Ptr++ = '&';
- *Dest->Ptr++ = 'l';
- *Dest->Ptr++ = 't';
- *Dest->Ptr++ = ';';
+ CopyStringToBuffer(Dest, "<");
String++;
break;
case '>':
- *Dest->Ptr++ = '&';
- *Dest->Ptr++ = 'g';
- *Dest->Ptr++ = 't';
- *Dest->Ptr++ = ';';
+ CopyStringToBuffer(Dest, ">");
String++;
break;
case '&':
- *Dest->Ptr++ = '&';
- *Dest->Ptr++ = 'a';
- *Dest->Ptr++ = 'm';
- *Dest->Ptr++ = 'p';
- *Dest->Ptr++ = ';';
+ CopyStringToBuffer(Dest, "&");
String++;
break;
case '\"':
- *Dest->Ptr++ = '&';
- *Dest->Ptr++ = 'q';
- *Dest->Ptr++ = 'u';
- *Dest->Ptr++ = 'o';
- *Dest->Ptr++ = 't';
- *Dest->Ptr++ = ';';
+ CopyStringToBuffer(Dest, """);
String++;
break;
case '\'':
- *Dest->Ptr++ = '&';
- *Dest->Ptr++ = '#';
- *Dest->Ptr++ = '3';
- *Dest->Ptr++ = '9';
- *Dest->Ptr++ = ';';
+ CopyStringToBuffer(Dest, "'");
String++;
break;
default:
@@ -322,23 +303,23 @@ CharToColour(char Char)
return Colour;
}
-char *
-StringToColourHash(buffer *Buffer, char *String)
+hsl_colour *
+StringToColourHash(hsl_colour *Colour, char *String)
{
- hsl_colour Colour = {0, 0, 26};
+ Colour->Hue = 0;
+ Colour->Saturation = 0;
+ Colour->Lightness = 26;
int i;
for(i = 0; String[i]; ++i)
{
- Colour.Hue += CharToColour(String[i]).Hue;
- Colour.Saturation += CharToColour(String[i]).Saturation;
+ Colour->Hue += CharToColour(String[i]).Hue;
+ Colour->Saturation += CharToColour(String[i]).Saturation;
}
- Colour.Hue = Colour.Hue % 360;
- Colour.Saturation = Colour.Saturation % 26 + 74;
- Buffer->Ptr = Buffer->Location;
- CopyStringToBuffer(Buffer, "hsl(%d, %d%%, %d%%)", Colour.Hue, Colour.Saturation, Colour.Lightness);
- return(Buffer->Location);
+ Colour->Hue = Colour->Hue % 360;
+ Colour->Saturation = Colour->Saturation % 26 + 74;
+ return(Colour);
}
char *
@@ -822,8 +803,10 @@ GenerateTopicColours(buffer *Colour, char *Topic)
++TopicsPtr;
}
- fprintf(TopicsFile, ".category.%s { border: 1px solid %s; background: %s; }\n",
- SanitisePunctuation(Topic), StringToColourHash(Colour, Topic), StringToColourHash(Colour, Topic));
+ hsl_colour Colour;
+ StringToColourHash(&Colour, Topic);
+ fprintf(TopicsFile, ".category.%s { border: 1px solid hsl(%d, %d%%, %d%%); background: hsl(%d, %d%%, %d%%); }\n",
+ SanitisePunctuation(Topic), Colour.Hue, Colour.Saturation, Colour.Lightness, Colour.Hue, Colour.Saturation, Colour.Lightness);
fclose(TopicsFile);
free(TopicsBuffer);
@@ -1297,9 +1280,12 @@ TimecodeToSeconds(Anno->time));
}
BuildFilter(TopicsArray, &UniqueTopics, MediaArray, &UniqueMedia, "authored");
CopyStringToBuffer(&AnnotationClass, " authored");
+ hsl_colour AuthorColour;
+ StringToColourHash(&AuthorColour, Anno->author);
CopyStringToBuffer(&Text,
-"%s ",
-StringToColourHash(&Colour, Anno->author),
+"%s ",
+AuthorColour.Hue, AuthorColour.Saturation, AuthorColour.Lightness,
+AuthorColour.Hue, AuthorColour.Saturation,
Anno->author);
if(!HasMedium)
{
@@ -1320,24 +1306,30 @@ Anno->author);
: Anno->markers[MarkerIndex].marker;
if(Anno->markers[MarkerIndex].type == HMML_MEMBER)
{
+ hsl_colour MemberColour;
+ StringToColourHash(&MemberColour, Anno->markers[MarkerIndex].marker);
CopyStringToBuffer(&Text,
// TODO(matt): Hoverbox
// We should get instructions on how to get this info in the config
-"%.*s",
+"%.*s",
Anno->markers[MarkerIndex].marker,
-StringToColourHash(&Colour, Anno->markers[MarkerIndex].marker),
+MemberColour.Hue, MemberColour.Saturation, MemberColour.Lightness,
+MemberColour.Hue, MemberColour.Saturation,
StringLength(Readable), InPtr);
InPtr += StringLength(Readable);
++MarkerIndex;
}
else if(Anno->markers[MarkerIndex].type == HMML_PROJECT)
{
+ hsl_colour ProjectColour;
+ StringToColourHash(&ProjectColour, Anno->markers[MarkerIndex].marker);
CopyStringToBuffer(&Text,
// TODO(matt): Hoverbox
// We should get instructions on how to get this info in the config
-"%s",
+"%s",
Anno->markers[MarkerIndex].marker,
-StringToColourHash(&Colour, Anno->markers[MarkerIndex].marker),
+ProjectColour.Hue, ProjectColour.Saturation, ProjectColour.Lightness,
+ProjectColour.Hue, ProjectColour.Saturation,
Readable);
InPtr += StringLength(Readable);
++MarkerIndex;
@@ -1480,42 +1472,23 @@ AppendedIdentifier:
switch(*InPtr)
{
case '<':
- *Text.Ptr++ = '&';
- *Text.Ptr++ = 'l';
- *Text.Ptr++ = 't';
- *Text.Ptr++ = ';';
+ CopyStringToBuffer(&Text, "<");
InPtr++;
break;
case '>':
- *Text.Ptr++ = '&';
- *Text.Ptr++ = 'g';
- *Text.Ptr++ = 't';
- *Text.Ptr++ = ';';
+ CopyStringToBuffer(&Text, ">");
InPtr++;
break;
case '&':
- *Text.Ptr++ = '&';
- *Text.Ptr++ = 'a';
- *Text.Ptr++ = 'm';
- *Text.Ptr++ = 'p';
- *Text.Ptr++ = ';';
+ CopyStringToBuffer(&Text, "&");
InPtr++;
break;
case '\"':
- *Text.Ptr++ = '&';
- *Text.Ptr++ = 'q';
- *Text.Ptr++ = 'u';
- *Text.Ptr++ = 'o';
- *Text.Ptr++ = 't';
- *Text.Ptr++ = ';';
+ CopyStringToBuffer(&Text, """);
InPtr++;
break;
case '\'':
- *Text.Ptr++ = '&';
- *Text.Ptr++ = '#';
- *Text.Ptr++ = '3';
- *Text.Ptr++ = '9';
- *Text.Ptr++ = ';';
+ CopyStringToBuffer(&Text, "'");
InPtr++;
break;
default:
@@ -2271,6 +2244,17 @@ HMML.metadata.project);
" document.getElementById(\"focus-warn\").style.display = \"none\";\n"
"});\n"
"\n"
+"var colouredItems = document.querySelectorAll(\".author, .member, .project\");\n"
+"for(i = 0; i < colouredItems.length; ++i)\n"
+"{\n"
+" setTextLightness(colouredItems[i]);\n"
+"}\n"
+"\n"
+"var topicDots = document.querySelectorAll(\".category\");\n"
+"for(var i = 0; i < topicDots.length; ++i)\n"
+"{\n"
+" setDotLightness(topicDots[i]);\n"
+"}\n"
" \n");
//NOTE(matt): Here is where we do all our CopyBuffer() calls
diff --git a/hmml_to_html/player.js b/hmml_to_html/player.js
index 1a2df19..ed0e787 100644
--- a/hmml_to_html/player.js
+++ b/hmml_to_html/player.js
@@ -1105,3 +1105,77 @@ function handleMouseOverMenu(menu, eventType)
helpDocumentation.classList.toggle("visible");
}
}
+
+function RGBtoHSL(colour)
+{
+ var rgb = colour.slice(4, -1).split(", ");
+ var red = rgb[0];
+ var green = rgb[1];
+ var blue = rgb[2];
+ var min = Math.min(red, green, blue);
+ var max = Math.max(red, green, blue);
+ var chroma = max - min;
+ var hue = 0;
+ if(max == red)
+ {
+ hue = ((green - blue) / chroma) % 6;
+ }
+ else if(max == green)
+ {
+ hue = ((blue - red) / chroma) + 2;
+ }
+ else if(max == blue)
+ {
+ hue = ((red - green) / chroma) + 4;
+ }
+
+ var saturation = chroma / 255 * 100;
+ hue = (hue * 60) < 0 ? 360 + (hue * 60) : (hue * 60);
+
+ return [hue, saturation]
+}
+
+function getBackgroundBrightness(element) {
+ var colour = getComputedStyle(element).getPropertyValue("background-color");
+ var depth = 0;
+ while(colour == "transparent" && depth <= 4)
+ {
+ element = element.parentNode;
+ colour = getComputedStyle(element).getPropertyValue("background-color");
+ ++depth;
+ }
+ var rgb = colour.slice(4, -1).split(", ");
+ return Math.sqrt(rgb[0] * rgb[0] * .241 +
+ rgb[1] * rgb[1] * .691 +
+ rgb[2] * rgb[2] * .068);
+}
+
+function setTextLightness(textElement)
+{
+ var textHue = textElement.getAttribute("data-hue");
+ var textSaturation = textElement.getAttribute("data-saturation");
+ if(getBackgroundBrightness(textElement.parentNode) < 127)
+ {
+ textElement.style.color = ("hsl(" + textHue + ", " + textSaturation + ", 76%)");
+ }
+ else
+ {
+ textElement.style.color = ("hsl(" + textHue + ", " + textSaturation + ", 24%)");
+ }
+}
+
+function setDotLightness(topicDot)
+{
+ var Hue = RGBtoHSL(getComputedStyle(topicDot).getPropertyValue("background-color"))[0];
+ var Saturation = RGBtoHSL(getComputedStyle(topicDot).getPropertyValue("background-color"))[1];
+ if(getBackgroundBrightness(topicDot.parentNode) < 127)
+ {
+ topicDot.style.backgroundColor = ("hsl(" + Hue + ", " + Saturation + "%, 76%)");
+ topicDot.style.borderColor = ("hsl(" + Hue + ", " + Saturation + "%, 76%)");
+ }
+ else
+ {
+ topicDot.style.backgroundColor = ("hsl(" + Hue + ", " + Saturation + "%, 24%)");
+ topicDot.style.borderColor = ("hsl(" + Hue + ", " + Saturation + "%, 24%)");
+ }
+}