diff options
author | David Schulz <david.schulz@qt.io> | 2018-08-14 06:55:56 +0200 |
---|---|---|
committer | David Schulz <david.schulz@qt.io> | 2018-08-14 09:25:44 +0000 |
commit | 493c5396ff1d1938b8614f42129355c37379a4ef (patch) | |
tree | 4e4a79a25f724ab8aceefe9f353f4383c7854d7e /src/plugins/texteditor/generichighlighter | |
parent | cfbc780a20af30f143286465c7c38135d87a5491 (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.cpp | 42 |
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()); |