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%)"); + } +}