aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/texteditor/generichighlighter
diff options
context:
space:
mode:
authorDavid Schulz <david.schulz@qt.io>2018-08-14 06:55:56 +0200
committerDavid Schulz <david.schulz@qt.io>2018-08-14 09:25:44 +0000
commit493c5396ff1d1938b8614f42129355c37379a4ef (patch)
tree4e4a79a25f724ab8aceefe9f353f4383c7854d7e /src/plugins/texteditor/generichighlighter
parentcfbc780a20af30f143286465c7c38135d87a5491 (diff)
GenericHighlighter: check text color against background
The kate syntax highlighter format allows to directly assign a color for a specific item. This could result in a bad contrast ratio between text and background. Check the contrast ratio according to W3C Recommendation and apply if it exceeds the minimum contrast ratio for large text. (https://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast- contrast) Task-number: QTCREATORBUG-20919 Change-Id: If5a5d09224446df72f31027cd30e50088179d6d7 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Diffstat (limited to 'src/plugins/texteditor/generichighlighter')
-rw-r--r--src/plugins/texteditor/generichighlighter/highlighter.cpp42
1 files changed, 41 insertions, 1 deletions
diff --git a/src/plugins/texteditor/generichighlighter/highlighter.cpp b/src/plugins/texteditor/generichighlighter/highlighter.cpp
index fd875eae28..055f390261 100644
--- a/src/plugins/texteditor/generichighlighter/highlighter.cpp
+++ b/src/plugins/texteditor/generichighlighter/highlighter.cpp
@@ -498,6 +498,43 @@ void Highlighter::handleContextChange(const QString &contextName,
changeContext(contextName, definition, setCurrent);
}
+
+static double luminance(const QColor &color)
+{
+ // calculate the luminance based on
+ // https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
+ auto val = [](const double &colorVal) {
+ return colorVal < 0.03928 ? colorVal / 12.92 : std::pow((colorVal + 0.055) / 1.055, 2.4);
+ };
+
+ static QHash<QRgb, double> cache;
+ QHash<QRgb, double>::iterator it = cache.find(color.rgb());
+ if (it == cache.end()) {
+ it = cache.insert(color.rgb(), 0.2126 * val(color.redF())
+ + 0.7152 * val(color.greenF())
+ + 0.0722 * val(color.blueF()));
+ }
+ return it.value();
+}
+
+static float contrastRatio(const QColor &color1, const QColor &color2)
+{
+ // calculate the contrast ratio based on
+ // https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
+ auto contrast = (luminance(color1) + 0.05) / (luminance(color2) + 0.05);
+ if (contrast < 1)
+ return 1 / contrast;
+ return contrast;
+}
+
+
+static bool isReadableOn(const QColor &background, const QColor &foreground)
+{
+ // following the W3C Recommendation on contrast for large Text
+ // https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
+ return contrastRatio(background, foreground) > 3;
+}
+
void Highlighter::applyFormat(int offset,
int count,
const QString &itemDataName,
@@ -526,7 +563,10 @@ void Highlighter::applyFormat(int offset,
// strategy). This is because the highlighter does not really know on which
// definition(s) it is working. Since not many item data specify customizations I
// think this approach would fit better. If there are other ideas...
- if (itemData->color().isValid())
+ QBrush bg = format.background();
+ if (bg.style() == Qt::NoBrush)
+ bg = formatForCategory(C_TEXT).background();
+ if (itemData->color().isValid() && isReadableOn(bg.color(), itemData->color()))
format.setForeground(itemData->color());
if (itemData->isItalicSpecified())
format.setFontItalic(itemData->isItalic());