summaryrefslogtreecommitdiffstats
path: root/layout/generic/nsTextPaintStyle.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /layout/generic/nsTextPaintStyle.cpp
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'layout/generic/nsTextPaintStyle.cpp')
-rw-r--r--layout/generic/nsTextPaintStyle.cpp580
1 files changed, 580 insertions, 0 deletions
diff --git a/layout/generic/nsTextPaintStyle.cpp b/layout/generic/nsTextPaintStyle.cpp
new file mode 100644
index 0000000000..0eff737602
--- /dev/null
+++ b/layout/generic/nsTextPaintStyle.cpp
@@ -0,0 +1,580 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsTextPaintStyle.h"
+
+#include "nsCSSColorUtils.h"
+#include "nsCSSRendering.h"
+#include "nsFrameSelection.h"
+#include "nsLayoutUtils.h"
+#include "nsTextFrame.h"
+#include "nsStyleConsts.h"
+
+#include "mozilla/LookAndFeel.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+static nscolor EnsureDifferentColors(nscolor colorA, nscolor colorB) {
+ if (colorA == colorB) {
+ nscolor res;
+ res = NS_RGB(NS_GET_R(colorA) ^ 0xff, NS_GET_G(colorA) ^ 0xff,
+ NS_GET_B(colorA) ^ 0xff);
+ return res;
+ }
+ return colorA;
+}
+
+nsTextPaintStyle::nsTextPaintStyle(nsTextFrame* aFrame)
+ : mFrame(aFrame),
+ mPresContext(aFrame->PresContext()),
+ mInitCommonColors(false),
+ mInitSelectionColorsAndShadow(false),
+ mResolveColors(true),
+ mSelectionTextColor(NS_RGBA(0, 0, 0, 0)),
+ mSelectionBGColor(NS_RGBA(0, 0, 0, 0)),
+ mSufficientContrast(0),
+ mFrameBackgroundColor(NS_RGBA(0, 0, 0, 0)),
+ mSystemFieldForegroundColor(NS_RGBA(0, 0, 0, 0)),
+ mSystemFieldBackgroundColor(NS_RGBA(0, 0, 0, 0)) {}
+
+bool nsTextPaintStyle::EnsureSufficientContrast(nscolor* aForeColor,
+ nscolor* aBackColor) {
+ InitCommonColors();
+
+ const bool sameAsForeground = *aForeColor == NS_SAME_AS_FOREGROUND_COLOR;
+ if (sameAsForeground) {
+ *aForeColor = GetTextColor();
+ }
+
+ // If the combination of selection background color and frame background color
+ // has sufficient contrast, don't exchange the selection colors.
+ //
+ // Note we use a different threshold here: mSufficientContrast is for contrast
+ // between text and background colors, but since we're diffing two
+ // backgrounds, we don't need that much contrast. We match the heuristic from
+ // NS_SUFFICIENT_LUMINOSITY_DIFFERENCE_BG and use 20% of mSufficientContrast.
+ const int32_t minLuminosityDifferenceForBackground = mSufficientContrast / 5;
+ const int32_t backLuminosityDifference =
+ NS_LUMINOSITY_DIFFERENCE(*aBackColor, mFrameBackgroundColor);
+ if (backLuminosityDifference >= minLuminosityDifferenceForBackground) {
+ return false;
+ }
+
+ // Otherwise, we should use the higher-contrast color for the selection
+ // background color.
+ //
+ // For NS_SAME_AS_FOREGROUND_COLOR we only do this if the background is
+ // totally indistinguishable, that is, if the luminosity difference is 0.
+ if (sameAsForeground && backLuminosityDifference) {
+ return false;
+ }
+
+ int32_t foreLuminosityDifference =
+ NS_LUMINOSITY_DIFFERENCE(*aForeColor, mFrameBackgroundColor);
+ if (backLuminosityDifference < foreLuminosityDifference) {
+ std::swap(*aForeColor, *aBackColor);
+ // Ensure foreground color is opaque to guarantee contrast.
+ *aForeColor = NS_RGB(NS_GET_R(*aForeColor), NS_GET_G(*aForeColor),
+ NS_GET_B(*aForeColor));
+ return true;
+ }
+ return false;
+}
+
+nscolor nsTextPaintStyle::GetTextColor() {
+ if (mFrame->IsInSVGTextSubtree()) {
+ if (!mResolveColors) {
+ return NS_SAME_AS_FOREGROUND_COLOR;
+ }
+
+ const nsStyleSVG* style = mFrame->StyleSVG();
+ switch (style->mFill.kind.tag) {
+ case StyleSVGPaintKind::Tag::None:
+ return NS_RGBA(0, 0, 0, 0);
+ case StyleSVGPaintKind::Tag::Color:
+ return nsLayoutUtils::GetColor(mFrame, &nsStyleSVG::mFill);
+ default:
+ NS_ERROR("cannot resolve SVG paint to nscolor");
+ return NS_RGBA(0, 0, 0, 255);
+ }
+ }
+
+ return nsLayoutUtils::GetColor(mFrame, &nsStyleText::mWebkitTextFillColor);
+}
+
+bool nsTextPaintStyle::GetSelectionColors(nscolor* aForeColor,
+ nscolor* aBackColor) {
+ NS_ASSERTION(aForeColor, "aForeColor is null");
+ NS_ASSERTION(aBackColor, "aBackColor is null");
+
+ if (!InitSelectionColorsAndShadow()) {
+ return false;
+ }
+
+ *aForeColor = mSelectionTextColor;
+ *aBackColor = mSelectionBGColor;
+ return true;
+}
+
+void nsTextPaintStyle::GetHighlightColors(nscolor* aForeColor,
+ nscolor* aBackColor) {
+ NS_ASSERTION(aForeColor, "aForeColor is null");
+ NS_ASSERTION(aBackColor, "aBackColor is null");
+
+ const nsFrameSelection* frameSelection = mFrame->GetConstFrameSelection();
+ const Selection* selection =
+ frameSelection->GetSelection(SelectionType::eFind);
+ const SelectionCustomColors* customColors = nullptr;
+ if (selection) {
+ customColors = selection->GetCustomColors();
+ }
+
+ if (!customColors) {
+ nscolor backColor = LookAndFeel::Color(
+ LookAndFeel::ColorID::TextHighlightBackground, mFrame);
+ nscolor foreColor = LookAndFeel::Color(
+ LookAndFeel::ColorID::TextHighlightForeground, mFrame);
+ EnsureSufficientContrast(&foreColor, &backColor);
+ *aForeColor = foreColor;
+ *aBackColor = backColor;
+ return;
+ }
+
+ if (customColors->mForegroundColor && customColors->mBackgroundColor) {
+ nscolor foreColor = *customColors->mForegroundColor;
+ nscolor backColor = *customColors->mBackgroundColor;
+
+ if (EnsureSufficientContrast(&foreColor, &backColor) &&
+ customColors->mAltForegroundColor &&
+ customColors->mAltBackgroundColor) {
+ foreColor = *customColors->mAltForegroundColor;
+ backColor = *customColors->mAltBackgroundColor;
+ }
+
+ *aForeColor = foreColor;
+ *aBackColor = backColor;
+ return;
+ }
+
+ InitCommonColors();
+
+ if (customColors->mBackgroundColor) {
+ // !mForegroundColor means "currentColor"; the current color of the text.
+ nscolor foreColor = GetTextColor();
+ nscolor backColor = *customColors->mBackgroundColor;
+
+ int32_t luminosityDifference =
+ NS_LUMINOSITY_DIFFERENCE(foreColor, backColor);
+
+ if (mSufficientContrast > luminosityDifference &&
+ customColors->mAltBackgroundColor) {
+ int32_t altLuminosityDifference = NS_LUMINOSITY_DIFFERENCE(
+ foreColor, *customColors->mAltBackgroundColor);
+
+ if (luminosityDifference < altLuminosityDifference) {
+ backColor = *customColors->mAltBackgroundColor;
+ }
+ }
+
+ *aForeColor = foreColor;
+ *aBackColor = backColor;
+ return;
+ }
+
+ if (customColors->mForegroundColor) {
+ nscolor foreColor = *customColors->mForegroundColor;
+ // !mBackgroundColor means "transparent"; the current color of the
+ // background.
+
+ int32_t luminosityDifference =
+ NS_LUMINOSITY_DIFFERENCE(foreColor, mFrameBackgroundColor);
+
+ if (mSufficientContrast > luminosityDifference &&
+ customColors->mAltForegroundColor) {
+ int32_t altLuminosityDifference = NS_LUMINOSITY_DIFFERENCE(
+ *customColors->mForegroundColor, mFrameBackgroundColor);
+
+ if (luminosityDifference < altLuminosityDifference) {
+ foreColor = *customColors->mAltForegroundColor;
+ }
+ }
+
+ *aForeColor = foreColor;
+ *aBackColor = NS_TRANSPARENT;
+ return;
+ }
+
+ // There are neither mForegroundColor nor mBackgroundColor.
+ *aForeColor = GetTextColor();
+ *aBackColor = NS_TRANSPARENT;
+}
+
+bool nsTextPaintStyle::GetCustomHighlightTextColor(nsAtom* aHighlightName,
+ nscolor* aForeColor) {
+ NS_ASSERTION(aForeColor, "aForeColor is null");
+
+ // non-existing highlights will be stored as `aHighlightName->nullptr`,
+ // so subsequent calls only need a hashtable lookup and don't have
+ // to enter the style engine.
+ RefPtr<ComputedStyle> highlightStyle =
+ mCustomHighlightPseudoStyles.LookupOrInsertWith(
+ aHighlightName, [this, &aHighlightName] {
+ return mFrame->ComputeHighlightSelectionStyle(aHighlightName);
+ });
+ if (!highlightStyle) {
+ // highlight `aHighlightName` doesn't exist or has no style rules.
+ return false;
+ }
+
+ *aForeColor = highlightStyle->GetVisitedDependentColor(
+ &nsStyleText::mWebkitTextFillColor);
+
+ return highlightStyle->HasAuthorSpecifiedTextColor();
+}
+
+bool nsTextPaintStyle::GetCustomHighlightBackgroundColor(nsAtom* aHighlightName,
+ nscolor* aBackColor) {
+ NS_ASSERTION(aBackColor, "aBackColor is null");
+ // non-existing highlights will be stored as `aHighlightName->nullptr`,
+ // so subsequent calls only need a hashtable lookup and don't have
+ // to enter the style engine.
+ RefPtr<ComputedStyle> highlightStyle =
+ mCustomHighlightPseudoStyles.LookupOrInsertWith(
+ aHighlightName, [this, &aHighlightName] {
+ return mFrame->ComputeHighlightSelectionStyle(aHighlightName);
+ });
+ if (!highlightStyle) {
+ // highlight `aHighlightName` doesn't exist or has no style rules.
+ return false;
+ }
+
+ *aBackColor = highlightStyle->GetVisitedDependentColor(
+ &nsStyleBackground::mBackgroundColor);
+ return NS_GET_A(*aBackColor) != 0;
+}
+
+void nsTextPaintStyle::GetURLSecondaryColor(nscolor* aForeColor) {
+ NS_ASSERTION(aForeColor, "aForeColor is null");
+
+ const nscolor textColor = GetTextColor();
+ *aForeColor = NS_RGBA(NS_GET_R(textColor), NS_GET_G(textColor),
+ NS_GET_B(textColor), 127);
+}
+
+void nsTextPaintStyle::GetIMESelectionColors(SelectionStyleIndex aIndex,
+ nscolor* aForeColor,
+ nscolor* aBackColor) {
+ NS_ASSERTION(aForeColor, "aForeColor is null");
+ NS_ASSERTION(aBackColor, "aBackColor is null");
+
+ nsSelectionStyle* selectionStyle = SelectionStyle(aIndex);
+ *aForeColor = selectionStyle->mTextColor;
+ *aBackColor = selectionStyle->mBGColor;
+}
+
+bool nsTextPaintStyle::GetSelectionUnderlineForPaint(
+ SelectionStyleIndex aIndex, nscolor* aLineColor, float* aRelativeSize,
+ StyleTextDecorationStyle* aStyle) {
+ NS_ASSERTION(aLineColor, "aLineColor is null");
+ NS_ASSERTION(aRelativeSize, "aRelativeSize is null");
+
+ nsSelectionStyle* selectionStyle = SelectionStyle(aIndex);
+ if (selectionStyle->mUnderlineStyle == StyleTextDecorationStyle::None ||
+ selectionStyle->mUnderlineColor == NS_TRANSPARENT ||
+ selectionStyle->mUnderlineRelativeSize <= 0.0f)
+ return false;
+
+ *aLineColor = selectionStyle->mUnderlineColor;
+ *aRelativeSize = selectionStyle->mUnderlineRelativeSize;
+ *aStyle = selectionStyle->mUnderlineStyle;
+ return true;
+}
+
+void nsTextPaintStyle::InitCommonColors() {
+ if (mInitCommonColors) {
+ return;
+ }
+
+ auto bgColor = nsCSSRendering::FindEffectiveBackgroundColor(mFrame);
+ mFrameBackgroundColor = bgColor.mColor;
+
+ mSystemFieldForegroundColor =
+ LookAndFeel::Color(LookAndFeel::ColorID::Fieldtext, mFrame);
+ mSystemFieldBackgroundColor =
+ LookAndFeel::Color(LookAndFeel::ColorID::Field, mFrame);
+
+ if (bgColor.mIsThemed) {
+ // Assume a native widget has sufficient contrast always
+ mSufficientContrast = 0;
+ mInitCommonColors = true;
+ return;
+ }
+
+ nscolor defaultWindowBackgroundColor =
+ LookAndFeel::Color(LookAndFeel::ColorID::Window, mFrame);
+ nscolor selectionTextColor =
+ LookAndFeel::Color(LookAndFeel::ColorID::Highlighttext, mFrame);
+ nscolor selectionBGColor =
+ LookAndFeel::Color(LookAndFeel::ColorID::Highlight, mFrame);
+
+ mSufficientContrast = std::min(
+ std::min(NS_SUFFICIENT_LUMINOSITY_DIFFERENCE,
+ NS_LUMINOSITY_DIFFERENCE(selectionTextColor, selectionBGColor)),
+ NS_LUMINOSITY_DIFFERENCE(defaultWindowBackgroundColor, selectionBGColor));
+
+ mInitCommonColors = true;
+}
+
+nscolor nsTextPaintStyle::GetSystemFieldForegroundColor() {
+ InitCommonColors();
+ return mSystemFieldForegroundColor;
+}
+
+nscolor nsTextPaintStyle::GetSystemFieldBackgroundColor() {
+ InitCommonColors();
+ return mSystemFieldBackgroundColor;
+}
+
+bool nsTextPaintStyle::InitSelectionColorsAndShadow() {
+ if (mInitSelectionColorsAndShadow) {
+ return true;
+ }
+
+ int16_t selectionFlags;
+ const int16_t selectionStatus = mFrame->GetSelectionStatus(&selectionFlags);
+ if (!(selectionFlags & nsISelectionDisplay::DISPLAY_TEXT) ||
+ selectionStatus < nsISelectionController::SELECTION_ON) {
+ // Not displaying the normal selection.
+ // We're not caching this fact, so every call to GetSelectionColors
+ // will come through here. We could avoid this, but it's not really worth
+ // it.
+ return false;
+ }
+
+ mInitSelectionColorsAndShadow = true;
+
+ // Use ::selection pseudo class if applicable.
+ if (RefPtr<ComputedStyle> style =
+ mFrame->ComputeSelectionStyle(selectionStatus)) {
+ mSelectionBGColor =
+ style->GetVisitedDependentColor(&nsStyleBackground::mBackgroundColor);
+ mSelectionTextColor =
+ style->GetVisitedDependentColor(&nsStyleText::mWebkitTextFillColor);
+ mSelectionPseudoStyle = std::move(style);
+ return true;
+ }
+
+ mSelectionTextColor =
+ LookAndFeel::Color(LookAndFeel::ColorID::Highlighttext, mFrame);
+
+ nscolor selectionBGColor =
+ LookAndFeel::Color(LookAndFeel::ColorID::Highlight, mFrame);
+
+ switch (selectionStatus) {
+ case nsISelectionController::SELECTION_ATTENTION: {
+ mSelectionTextColor = LookAndFeel::Color(
+ LookAndFeel::ColorID::TextSelectAttentionForeground, mFrame);
+ mSelectionBGColor = LookAndFeel::Color(
+ LookAndFeel::ColorID::TextSelectAttentionBackground, mFrame);
+ mSelectionBGColor =
+ EnsureDifferentColors(mSelectionBGColor, selectionBGColor);
+ break;
+ }
+ case nsISelectionController::SELECTION_ON: {
+ mSelectionBGColor = selectionBGColor;
+ break;
+ }
+ default: {
+ mSelectionBGColor = LookAndFeel::Color(
+ LookAndFeel::ColorID::TextSelectDisabledBackground, mFrame);
+ mSelectionBGColor =
+ EnsureDifferentColors(mSelectionBGColor, selectionBGColor);
+ break;
+ }
+ }
+
+ if (mResolveColors) {
+ EnsureSufficientContrast(&mSelectionTextColor, &mSelectionBGColor);
+ }
+ return true;
+}
+
+nsTextPaintStyle::nsSelectionStyle* nsTextPaintStyle::SelectionStyle(
+ SelectionStyleIndex aIndex) {
+ Maybe<nsSelectionStyle>& selectionStyle = mSelectionStyle[aIndex];
+ if (!selectionStyle) {
+ selectionStyle.emplace(InitSelectionStyle(aIndex));
+ }
+ return selectionStyle.ptr();
+}
+
+struct StyleIDs {
+ LookAndFeel::ColorID mForeground, mBackground, mLine;
+ LookAndFeel::IntID mLineStyle;
+ LookAndFeel::FloatID mLineRelativeSize;
+};
+EnumeratedArray<nsTextPaintStyle::SelectionStyleIndex,
+ nsTextPaintStyle::SelectionStyleIndex::Count, StyleIDs>
+ SelectionStyleIDs = {
+ StyleIDs{LookAndFeel::ColorID::IMERawInputForeground,
+ LookAndFeel::ColorID::IMERawInputBackground,
+ LookAndFeel::ColorID::IMERawInputUnderline,
+ LookAndFeel::IntID::IMERawInputUnderlineStyle,
+ LookAndFeel::FloatID::IMEUnderlineRelativeSize},
+ StyleIDs{LookAndFeel::ColorID::IMESelectedRawTextForeground,
+ LookAndFeel::ColorID::IMESelectedRawTextBackground,
+ LookAndFeel::ColorID::IMESelectedRawTextUnderline,
+ LookAndFeel::IntID::IMESelectedRawTextUnderlineStyle,
+ LookAndFeel::FloatID::IMEUnderlineRelativeSize},
+ StyleIDs{LookAndFeel::ColorID::IMEConvertedTextForeground,
+ LookAndFeel::ColorID::IMEConvertedTextBackground,
+ LookAndFeel::ColorID::IMEConvertedTextUnderline,
+ LookAndFeel::IntID::IMEConvertedTextUnderlineStyle,
+ LookAndFeel::FloatID::IMEUnderlineRelativeSize},
+ StyleIDs{LookAndFeel::ColorID::IMESelectedConvertedTextForeground,
+ LookAndFeel::ColorID::IMESelectedConvertedTextBackground,
+ LookAndFeel::ColorID::IMESelectedConvertedTextUnderline,
+ LookAndFeel::IntID::IMESelectedConvertedTextUnderline,
+ LookAndFeel::FloatID::IMEUnderlineRelativeSize},
+ StyleIDs{LookAndFeel::ColorID::End, LookAndFeel::ColorID::End,
+ LookAndFeel::ColorID::SpellCheckerUnderline,
+ LookAndFeel::IntID::SpellCheckerUnderlineStyle,
+ LookAndFeel::FloatID::SpellCheckerUnderlineRelativeSize}};
+
+nsTextPaintStyle::nsSelectionStyle nsTextPaintStyle::InitSelectionStyle(
+ SelectionStyleIndex aIndex) {
+ const StyleIDs& styleIDs = SelectionStyleIDs[aIndex];
+
+ nscolor foreColor, backColor;
+ if (styleIDs.mForeground == LookAndFeel::ColorID::End) {
+ foreColor = NS_SAME_AS_FOREGROUND_COLOR;
+ } else {
+ foreColor = LookAndFeel::Color(styleIDs.mForeground, mFrame);
+ }
+ if (styleIDs.mBackground == LookAndFeel::ColorID::End) {
+ backColor = NS_TRANSPARENT;
+ } else {
+ backColor = LookAndFeel::Color(styleIDs.mBackground, mFrame);
+ }
+
+ // Convert special color to actual color
+ NS_ASSERTION(foreColor != NS_TRANSPARENT,
+ "foreColor cannot be NS_TRANSPARENT");
+ NS_ASSERTION(backColor != NS_SAME_AS_FOREGROUND_COLOR,
+ "backColor cannot be NS_SAME_AS_FOREGROUND_COLOR");
+ NS_ASSERTION(backColor != NS_40PERCENT_FOREGROUND_COLOR,
+ "backColor cannot be NS_40PERCENT_FOREGROUND_COLOR");
+
+ if (mResolveColors) {
+ foreColor = GetResolvedForeColor(foreColor, GetTextColor(), backColor);
+
+ if (NS_GET_A(backColor) > 0) {
+ EnsureSufficientContrast(&foreColor, &backColor);
+ }
+ }
+
+ nscolor lineColor;
+ float relativeSize;
+ StyleTextDecorationStyle lineStyle;
+ GetSelectionUnderline(mFrame, aIndex, &lineColor, &relativeSize, &lineStyle);
+
+ if (mResolveColors) {
+ lineColor = GetResolvedForeColor(lineColor, foreColor, backColor);
+ }
+
+ return nsSelectionStyle{foreColor, backColor, lineColor, lineStyle,
+ relativeSize};
+}
+
+/* static */
+bool nsTextPaintStyle::GetSelectionUnderline(nsIFrame* aFrame,
+ SelectionStyleIndex aIndex,
+ nscolor* aLineColor,
+ float* aRelativeSize,
+ StyleTextDecorationStyle* aStyle) {
+ NS_ASSERTION(aFrame, "aFrame is null");
+ NS_ASSERTION(aRelativeSize, "aRelativeSize is null");
+ NS_ASSERTION(aStyle, "aStyle is null");
+
+ const StyleIDs& styleIDs = SelectionStyleIDs[aIndex];
+
+ nscolor color = LookAndFeel::Color(styleIDs.mLine, aFrame);
+ const int32_t lineStyle = LookAndFeel::GetInt(styleIDs.mLineStyle);
+ auto style = static_cast<StyleTextDecorationStyle>(lineStyle);
+ if (lineStyle > static_cast<int32_t>(StyleTextDecorationStyle::Sentinel)) {
+ NS_ERROR("Invalid underline style value is specified");
+ style = StyleTextDecorationStyle::Solid;
+ }
+ float size = LookAndFeel::GetFloat(styleIDs.mLineRelativeSize);
+
+ NS_ASSERTION(size, "selection underline relative size must be larger than 0");
+
+ if (aLineColor) {
+ *aLineColor = color;
+ }
+ *aRelativeSize = size;
+ *aStyle = style;
+
+ return style != StyleTextDecorationStyle::None && color != NS_TRANSPARENT &&
+ size > 0.0f;
+}
+
+bool nsTextPaintStyle::GetSelectionShadow(
+ Span<const StyleSimpleShadow>* aShadows) {
+ if (!InitSelectionColorsAndShadow()) {
+ return false;
+ }
+
+ if (mSelectionPseudoStyle) {
+ *aShadows = mSelectionPseudoStyle->StyleText()->mTextShadow.AsSpan();
+ return true;
+ }
+
+ return false;
+}
+
+inline nscolor Get40PercentColor(nscolor aForeColor, nscolor aBackColor) {
+ nscolor foreColor = NS_RGBA(NS_GET_R(aForeColor), NS_GET_G(aForeColor),
+ NS_GET_B(aForeColor), (uint8_t)(255 * 0.4f));
+ // Don't use true alpha color for readability.
+ return NS_ComposeColors(aBackColor, foreColor);
+}
+
+nscolor nsTextPaintStyle::GetResolvedForeColor(nscolor aColor,
+ nscolor aDefaultForeColor,
+ nscolor aBackColor) {
+ if (aColor == NS_SAME_AS_FOREGROUND_COLOR) {
+ return aDefaultForeColor;
+ }
+
+ if (aColor != NS_40PERCENT_FOREGROUND_COLOR) {
+ return aColor;
+ }
+
+ // Get actual background color
+ nscolor actualBGColor = aBackColor;
+ if (actualBGColor == NS_TRANSPARENT) {
+ InitCommonColors();
+ actualBGColor = mFrameBackgroundColor;
+ }
+ return Get40PercentColor(aDefaultForeColor, actualBGColor);
+}
+
+nscolor nsTextPaintStyle::GetWebkitTextStrokeColor() {
+ if (mFrame->IsInSVGTextSubtree()) {
+ return 0;
+ }
+ return mFrame->StyleText()->mWebkitTextStrokeColor.CalcColor(mFrame);
+}
+
+float nsTextPaintStyle::GetWebkitTextStrokeWidth() {
+ if (mFrame->IsInSVGTextSubtree()) {
+ return 0.0f;
+ }
+ nscoord coord = mFrame->StyleText()->mWebkitTextStrokeWidth;
+ return mFrame->PresContext()->AppUnitsToFloatDevPixels(coord);
+}