hmml_to_html.c: Correct colour lightness [#3]

This commit is contained in:
Matt Mascarenhas 2017-06-09 23:04:07 +01:00
parent 1389b4f414
commit a38ca2fd9e
2 changed files with 124 additions and 66 deletions

View File

@ -213,42 +213,23 @@ CopyStringToBufferHTMLSafe(buffer *Dest, char *String)
switch(*String) switch(*String)
{ {
case '<': case '<':
*Dest->Ptr++ = '&'; CopyStringToBuffer(Dest, "&lt;");
*Dest->Ptr++ = 'l';
*Dest->Ptr++ = 't';
*Dest->Ptr++ = ';';
String++; String++;
break; break;
case '>': case '>':
*Dest->Ptr++ = '&'; CopyStringToBuffer(Dest, "&gt;");
*Dest->Ptr++ = 'g';
*Dest->Ptr++ = 't';
*Dest->Ptr++ = ';';
String++; String++;
break; break;
case '&': case '&':
*Dest->Ptr++ = '&'; CopyStringToBuffer(Dest, "&amp;");
*Dest->Ptr++ = 'a';
*Dest->Ptr++ = 'm';
*Dest->Ptr++ = 'p';
*Dest->Ptr++ = ';';
String++; String++;
break; break;
case '\"': case '\"':
*Dest->Ptr++ = '&'; CopyStringToBuffer(Dest, "&quot;");
*Dest->Ptr++ = 'q';
*Dest->Ptr++ = 'u';
*Dest->Ptr++ = 'o';
*Dest->Ptr++ = 't';
*Dest->Ptr++ = ';';
String++; String++;
break; break;
case '\'': case '\'':
*Dest->Ptr++ = '&'; CopyStringToBuffer(Dest, "&#39;");
*Dest->Ptr++ = '#';
*Dest->Ptr++ = '3';
*Dest->Ptr++ = '9';
*Dest->Ptr++ = ';';
String++; String++;
break; break;
default: default:
@ -322,23 +303,23 @@ CharToColour(char Char)
return Colour; return Colour;
} }
char * hsl_colour *
StringToColourHash(buffer *Buffer, char *String) StringToColourHash(hsl_colour *Colour, char *String)
{ {
hsl_colour Colour = {0, 0, 26}; Colour->Hue = 0;
Colour->Saturation = 0;
Colour->Lightness = 26;
int i; int i;
for(i = 0; String[i]; ++i) for(i = 0; String[i]; ++i)
{ {
Colour.Hue += CharToColour(String[i]).Hue; Colour->Hue += CharToColour(String[i]).Hue;
Colour.Saturation += CharToColour(String[i]).Saturation; Colour->Saturation += CharToColour(String[i]).Saturation;
} }
Colour.Hue = Colour.Hue % 360; Colour->Hue = Colour->Hue % 360;
Colour.Saturation = Colour.Saturation % 26 + 74; Colour->Saturation = Colour->Saturation % 26 + 74;
Buffer->Ptr = Buffer->Location; return(Colour);
CopyStringToBuffer(Buffer, "hsl(%d, %d%%, %d%%)", Colour.Hue, Colour.Saturation, Colour.Lightness);
return(Buffer->Location);
} }
char * char *
@ -822,8 +803,10 @@ GenerateTopicColours(buffer *Colour, char *Topic)
++TopicsPtr; ++TopicsPtr;
} }
fprintf(TopicsFile, ".category.%s { border: 1px solid %s; background: %s; }\n", hsl_colour Colour;
SanitisePunctuation(Topic), StringToColourHash(Colour, Topic), StringToColourHash(Colour, Topic)); 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); fclose(TopicsFile);
free(TopicsBuffer); free(TopicsBuffer);
@ -1297,9 +1280,12 @@ TimecodeToSeconds(Anno->time));
} }
BuildFilter(TopicsArray, &UniqueTopics, MediaArray, &UniqueMedia, "authored"); BuildFilter(TopicsArray, &UniqueTopics, MediaArray, &UniqueMedia, "authored");
CopyStringToBuffer(&AnnotationClass, " authored"); CopyStringToBuffer(&AnnotationClass, " authored");
hsl_colour AuthorColour;
StringToColourHash(&AuthorColour, Anno->author);
CopyStringToBuffer(&Text, CopyStringToBuffer(&Text,
"<span class=\"author\" style=\"color: %s;\">%s</span> ", "<span class=\"author\" style=\"color: hsl(%d, %d%%, %d%%);\" data-hue=\"%d\" data-saturation=\"%d%%\">%s</span> ",
StringToColourHash(&Colour, Anno->author), AuthorColour.Hue, AuthorColour.Saturation, AuthorColour.Lightness,
AuthorColour.Hue, AuthorColour.Saturation,
Anno->author); Anno->author);
if(!HasMedium) if(!HasMedium)
{ {
@ -1320,24 +1306,30 @@ Anno->author);
: Anno->markers[MarkerIndex].marker; : Anno->markers[MarkerIndex].marker;
if(Anno->markers[MarkerIndex].type == HMML_MEMBER) if(Anno->markers[MarkerIndex].type == HMML_MEMBER)
{ {
hsl_colour MemberColour;
StringToColourHash(&MemberColour, Anno->markers[MarkerIndex].marker);
CopyStringToBuffer(&Text, CopyStringToBuffer(&Text,
// TODO(matt): Hoverbox // TODO(matt): Hoverbox
// We should get instructions on how to get this info in the config // We should get instructions on how to get this info in the config
"<a href=\"https://handmade.network/m/%s\" target=\"blank\" style=\"color: %s; text-decoration: none\">%.*s</a>", "<a class=\"member\" href=\"https://handmade.network/m/%s\" target=\"blank\" style=\"color: hsl(%d, %d%%, %d%%); text-decoration: none\" data-hue=\"%d\" data-saturation=\"%d%%\">%.*s</a>",
Anno->markers[MarkerIndex].marker, Anno->markers[MarkerIndex].marker,
StringToColourHash(&Colour, Anno->markers[MarkerIndex].marker), MemberColour.Hue, MemberColour.Saturation, MemberColour.Lightness,
MemberColour.Hue, MemberColour.Saturation,
StringLength(Readable), InPtr); StringLength(Readable), InPtr);
InPtr += StringLength(Readable); InPtr += StringLength(Readable);
++MarkerIndex; ++MarkerIndex;
} }
else if(Anno->markers[MarkerIndex].type == HMML_PROJECT) else if(Anno->markers[MarkerIndex].type == HMML_PROJECT)
{ {
hsl_colour ProjectColour;
StringToColourHash(&ProjectColour, Anno->markers[MarkerIndex].marker);
CopyStringToBuffer(&Text, CopyStringToBuffer(&Text,
// TODO(matt): Hoverbox // TODO(matt): Hoverbox
// We should get instructions on how to get this info in the config // We should get instructions on how to get this info in the config
"<a href=\"https://%s.handmade.network/\" target=\"blank\" style=\"color: %s; text-decoration: none\">%s</a>", "<a class=\"project\" href=\"https://%s.handmade.network/\" target=\"blank\" style=\"color: hsl(%d, %d%%, %d%%); text-decoration: none\" data-hue=\"%d\" data-saturation=\"%d%%\">%s</a>",
Anno->markers[MarkerIndex].marker, Anno->markers[MarkerIndex].marker,
StringToColourHash(&Colour, Anno->markers[MarkerIndex].marker), ProjectColour.Hue, ProjectColour.Saturation, ProjectColour.Lightness,
ProjectColour.Hue, ProjectColour.Saturation,
Readable); Readable);
InPtr += StringLength(Readable); InPtr += StringLength(Readable);
++MarkerIndex; ++MarkerIndex;
@ -1480,42 +1472,23 @@ AppendedIdentifier:
switch(*InPtr) switch(*InPtr)
{ {
case '<': case '<':
*Text.Ptr++ = '&'; CopyStringToBuffer(&Text, "&lt;");
*Text.Ptr++ = 'l';
*Text.Ptr++ = 't';
*Text.Ptr++ = ';';
InPtr++; InPtr++;
break; break;
case '>': case '>':
*Text.Ptr++ = '&'; CopyStringToBuffer(&Text, "&gt;");
*Text.Ptr++ = 'g';
*Text.Ptr++ = 't';
*Text.Ptr++ = ';';
InPtr++; InPtr++;
break; break;
case '&': case '&':
*Text.Ptr++ = '&'; CopyStringToBuffer(&Text, "&amp;");
*Text.Ptr++ = 'a';
*Text.Ptr++ = 'm';
*Text.Ptr++ = 'p';
*Text.Ptr++ = ';';
InPtr++; InPtr++;
break; break;
case '\"': case '\"':
*Text.Ptr++ = '&'; CopyStringToBuffer(&Text, "&quot;");
*Text.Ptr++ = 'q';
*Text.Ptr++ = 'u';
*Text.Ptr++ = 'o';
*Text.Ptr++ = 't';
*Text.Ptr++ = ';';
InPtr++; InPtr++;
break; break;
case '\'': case '\'':
*Text.Ptr++ = '&'; CopyStringToBuffer(&Text, "&#39;");
*Text.Ptr++ = '#';
*Text.Ptr++ = '3';
*Text.Ptr++ = '9';
*Text.Ptr++ = ';';
InPtr++; InPtr++;
break; break;
default: default:
@ -2271,6 +2244,17 @@ HMML.metadata.project);
" document.getElementById(\"focus-warn\").style.display = \"none\";\n" " document.getElementById(\"focus-warn\").style.display = \"none\";\n"
"});\n" "});\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"
" </script>\n"); " </script>\n");
//NOTE(matt): Here is where we do all our CopyBuffer() calls //NOTE(matt): Here is where we do all our CopyBuffer() calls

View File

@ -1105,3 +1105,77 @@ function handleMouseOverMenu(menu, eventType)
helpDocumentation.classList.toggle("visible"); 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%)");
}
}