Bug 1697240 - Refactor ScrollbarDrawingMac to not depend on a DrawTarget. r=mstange

Just return a simplified set of operations (basically rects to fill and the
thumb, which is a bit more complicated but not all that much).

Differential Revision: https://phabricator.services.mozilla.com/D107688
This commit is contained in:
Emilio Cobos Álvarez 2021-03-10 16:43:58 +00:00
Родитель 3b800c74bc
Коммит 47716bef8d
4 изменённых файлов: 149 добавлений и 80 удалений

Просмотреть файл

@ -6,7 +6,6 @@
#include "ScrollbarDrawingMac.h"
#include "mozilla/gfx/Helpers.h"
#include "mozilla/gfx/PathHelpers.h"
#include "mozilla/RelativeLuminanceUtils.h"
#include "nsLayoutUtils.h"
#include "nsIFrame.h"
@ -127,8 +126,12 @@ ScrollbarParams ScrollbarDrawingMac::ComputeScrollbarParams(
return params;
}
void ScrollbarDrawingMac::DrawScrollbarThumb(DrawTarget& aDT, const Rect& aRect,
const ScrollbarParams& aParams) {
auto ScrollbarDrawingMac::GetThumbRect(const Rect& aRect,
const ScrollbarParams& aParams,
float aScale) -> ThumbRect {
// This matches the sizing checks in GetMinimumWidgetSize etc.
aScale = aScale >= 2.0f ? 2.0f : 1.0f;
// Compute the thumb thickness. This varies based on aParams.small,
// aParams.overlay and aParams.rolledOver. non-overlay: 6 / 8, overlay
// non-hovered: 5 / 7, overlay hovered: 9 / 11
@ -139,11 +142,13 @@ void ScrollbarDrawingMac::DrawScrollbarThumb(DrawTarget& aDT, const Rect& aRect,
thickness += 4.0f;
}
}
thickness *= aScale;
// Compute the thumb rect.
float outerSpacing = (aParams.overlay || aParams.small) ? 1.0f : 2.0f;
const float outerSpacing =
((aParams.overlay || aParams.small) ? 1.0f : 2.0f) * aScale;
Rect thumbRect = aRect;
thumbRect.Deflate(1.0f);
thumbRect.Deflate(1.0f * aScale);
if (aParams.horizontal) {
float bottomEdge = thumbRect.YMost() - outerSpacing;
thumbRect.SetBoxY(bottomEdge - thickness, bottomEdge);
@ -171,29 +176,20 @@ void ScrollbarDrawingMac::DrawScrollbarThumb(DrawTarget& aDT, const Rect& aRect,
}
}
// Fill the thumb shape with the color.
float cornerRadius =
(aParams.horizontal ? thumbRect.Height() : thumbRect.Width()) / 2.0f;
aDT.FillRoundedRect(RoundedRect(thumbRect, RectCornerRadii(cornerRadius)),
ColorPattern(ToDeviceColor(faceColor)));
nscolor strokeColor = 0;
float strokeOutset = 0.0f;
float strokeWidth = 0.0f;
// Overlay scrollbars have an additional stroke around the fill.
if (aParams.overlay) {
float strokeOutset = aParams.onDarkBackground ? 0.3f : 0.5f;
float strokeWidth = aParams.onDarkBackground ? 0.6f : 0.8f;
nscolor strokeColor = aParams.onDarkBackground ? NS_RGBA(0, 0, 0, 48)
: NS_RGBA(255, 255, 255, 48);
Rect thumbStrokeRect = thumbRect;
thumbStrokeRect.Inflate(strokeOutset);
float strokeRadius = (aParams.horizontal ? thumbStrokeRect.Height()
: thumbStrokeRect.Width()) /
2.0f;
strokeOutset = (aParams.onDarkBackground ? 0.3f : 0.5f) * aScale;
strokeWidth = (aParams.onDarkBackground ? 0.6f : 0.8f) * aScale;
RefPtr<Path> path = MakePathForRoundedRect(aDT, thumbStrokeRect,
RectCornerRadii(strokeRadius));
aDT.Stroke(path, ColorPattern(ToDeviceColor(strokeColor)),
StrokeOptions(strokeWidth));
strokeColor = aParams.onDarkBackground ? NS_RGBA(0, 0, 0, 48)
: NS_RGBA(255, 255, 255, 48);
}
return {thumbRect, faceColor, strokeColor, strokeWidth, strokeOutset};
}
struct ScrollbarTrackDecorationColors {
@ -224,13 +220,18 @@ static ScrollbarTrackDecorationColors ComputeScrollbarTrackDecorationColors(
return result;
}
void ScrollbarDrawingMac::DrawScrollbarTrack(DrawTarget& aDT, const Rect& aRect,
const ScrollbarParams& aParams) {
bool ScrollbarDrawingMac::GetScrollbarTrackRects(const Rect& aRect,
const ScrollbarParams& aParams,
float aScale,
ScrollbarTrackRects& aRects) {
if (aParams.overlay && !aParams.rolledOver) {
// Non-hovered overlay scrollbars don't have a track. Draw nothing.
return;
return false;
}
// This matches the sizing checks in GetMinimumWidgetSize etc.
aScale = aScale >= 2.0f ? 2.0f : 1.0f;
nscolor trackColor;
if (aParams.custom) {
trackColor = aParams.trackColor;
@ -253,16 +254,17 @@ void ScrollbarDrawingMac::DrawScrollbarTrack(DrawTarget& aDT, const Rect& aRect,
nscolor color;
float thickness;
} segments[] = {
{colors.mInnerColor, 1.0f},
{colors.mShadowColor, 1.0f},
{trackColor, thickness - 3.0f},
{colors.mOuterColor, 1.0f},
{colors.mInnerColor, 1.0f * aScale},
{colors.mShadowColor, 1.0f * aScale},
{trackColor, thickness - 3.0f * aScale},
{colors.mOuterColor, 1.0f * aScale},
};
// Iterate over the segments "from inside to outside" and fill each segment.
// For horizontal scrollbars, iterate top to bottom.
// For vertical scrollbars, iterate left to right or right to left based on
// aParams.rtl.
auto current = aRects.begin();
float accumulatedThickness = 0.0f;
for (const auto& segment : segments) {
Rect segmentRect = aRect;
@ -279,18 +281,25 @@ void ScrollbarDrawingMac::DrawScrollbarTrack(DrawTarget& aDT, const Rect& aRect,
aRect.X() + endThickness);
}
}
aDT.FillRect(segmentRect, ColorPattern(ToDeviceColor(segment.color)));
accumulatedThickness = endThickness;
*current++ = {segmentRect, segment.color};
}
return true;
}
void ScrollbarDrawingMac::DrawScrollCorner(DrawTarget& aDT, const Rect& aRect,
const ScrollbarParams& aParams) {
bool ScrollbarDrawingMac::GetScrollCornerRects(const Rect& aRect,
const ScrollbarParams& aParams,
float aScale,
ScrollCornerRects& aRects) {
if (aParams.overlay && !aParams.rolledOver) {
// Non-hovered overlay scrollbars don't have a corner. Draw nothing.
return;
return false;
}
// This matches the sizing checks in GetMinimumWidgetSize etc.
aScale = aScale >= 2.0f ? 2.0f : 1.0f;
// Draw the following scroll corner.
//
// Output: Rectangles:
@ -316,22 +325,29 @@ void ScrollbarDrawingMac::DrawScrollCorner(DrawTarget& aDT, const Rect& aRect,
nscolor color;
Rect relativeRect;
} pieces[] = {
{colors.mInnerColor, {0.0f, 0.0f, 1.0f, 1.0f}},
{colors.mShadowColor, {1.0f, 0.0f, 1.0f, 1.0f}},
{colors.mShadowColor, {0.0f, 1.0f, 2.0f, 1.0f}},
{trackColor, {2.0f, 0.0f, width - 3.0f, 2.0f}},
{trackColor, {0.0f, 2.0f, width - 1.0f, height - 3.0f}},
{colors.mOuterColor, {width - 1.0f, 0.0f, 1.0f, height - 1.0f}},
{colors.mOuterColor, {0.0f, height - 1.0f, width, 1.0f}},
{colors.mInnerColor, {0.0f, 0.0f, 1.0f * aScale, 1.0f * aScale}},
{colors.mShadowColor,
{1.0f * aScale, 0.0f, 1.0f * aScale, 1.0f * aScale}},
{colors.mShadowColor,
{0.0f, 1.0f * aScale, 2.0f * aScale, 1.0f * aScale}},
{trackColor, {2.0f * aScale, 0.0f, width - 3.0f * aScale, 2.0f * aScale}},
{trackColor,
{0.0f, 2.0f * aScale, width - 1.0f * aScale, height - 3.0f * aScale}},
{colors.mOuterColor,
{width - 1.0f * aScale, 0.0f, 1.0f * aScale, height - 1.0f * aScale}},
{colors.mOuterColor,
{0.0f, height - 1.0f * aScale, width, 1.0f * aScale}},
};
auto current = aRects.begin();
for (const auto& piece : pieces) {
Rect pieceRect = piece.relativeRect + aRect.TopLeft();
if (aParams.rtl) {
pieceRect.x = aRect.XMost() - piece.relativeRect.XMost();
}
aDT.FillRect(pieceRect, ColorPattern(ToDeviceColor(piece.color)));
*current++ = {pieceRect, piece.color};
}
return true;
}
} // namespace widget

Просмотреть файл

@ -10,6 +10,7 @@
#include "nsColor.h"
#include "nsITheme.h"
#include "Units.h"
#include "mozilla/Array.h"
namespace mozilla {
namespace gfx {
@ -33,6 +34,11 @@ struct ScrollbarParams {
class ScrollbarDrawingMac final {
public:
struct FillRect {
gfx::Rect mRect;
nscolor mColor;
};
static CSSIntCoord GetScrollbarSize(StyleScrollbarWidth, bool aOverlay);
static LayoutDeviceIntCoord GetScrollbarSize(StyleScrollbarWidth,
@ -43,12 +49,28 @@ class ScrollbarDrawingMac final {
static ScrollbarParams ComputeScrollbarParams(nsIFrame* aFrame,
const ComputedStyle& aStyle,
bool aIsHorizontal);
static void DrawScrollbarThumb(gfx::DrawTarget& aDT, const gfx::Rect& aRect,
const ScrollbarParams& aParams);
static void DrawScrollbarTrack(gfx::DrawTarget& aDT, const gfx::Rect& aRect,
const ScrollbarParams& aParams);
static void DrawScrollCorner(gfx::DrawTarget& aDT, const gfx::Rect& aRect,
const ScrollbarParams& aParams);
// The caller can draw this rectangle with rounded corners as appropriate.
struct ThumbRect {
gfx::Rect mRect;
nscolor mFillColor;
nscolor mStrokeColor;
float mStrokeWidth;
float mStrokeOutset;
};
static ThumbRect GetThumbRect(const gfx::Rect& aRect,
const ScrollbarParams& aParams, float aScale);
using ScrollbarTrackRects = Array<FillRect, 4>;
static bool GetScrollbarTrackRects(const gfx::Rect& aRect,
const ScrollbarParams& aParams,
float aScale, ScrollbarTrackRects&);
using ScrollCornerRects = Array<FillRect, 7>;
static bool GetScrollCornerRects(const gfx::Rect& aRect,
const ScrollbarParams& aParams,
float aScale, ScrollCornerRects&);
};
} // namespace widget

Просмотреть файл

@ -75,15 +75,25 @@ bool nsNativeBasicThemeCocoa::PaintScrollbarThumb(
DPIRatio aDpiRatio) {
ScrollbarParams params =
ScrollbarDrawingMac::ComputeScrollbarParams(aFrame, aStyle, aHorizontal);
auto rect = aRect.ToUnknownRect();
if (aDpiRatio.scale >= 2.0f) {
mozilla::gfx::AutoRestoreTransform autoRestoreTransform(&aDrawTarget);
aDrawTarget.SetTransform(aDrawTarget.GetTransform().PreScale(2.0f, 2.0f));
rect.Scale(1.0f / 2.0f);
ScrollbarDrawingMac::DrawScrollbarThumb(aDrawTarget, rect, params);
} else {
ScrollbarDrawingMac::DrawScrollbarThumb(aDrawTarget, rect, params);
auto thumb = ScrollbarDrawingMac::GetThumbRect(aRect.ToUnknownRect(), params,
aDpiRatio.scale);
auto thumbRect = LayoutDeviceRect::FromUnknownRect(thumb.mRect);
LayoutDeviceCoord radius =
(params.horizontal ? thumbRect.Height() : thumbRect.Width()) / 2.0f;
PaintRoundedRectWithRadius(
aDrawTarget, thumbRect, thumbRect, sRGBColor::FromABGR(thumb.mFillColor),
sRGBColor::White(0.0f), 0.0f, radius / aDpiRatio, aDpiRatio);
if (!thumb.mStrokeColor) {
return true;
}
// Paint the stroke if needed.
thumbRect.Inflate(thumb.mStrokeOutset + thumb.mStrokeWidth);
radius = (params.horizontal ? thumbRect.Height() : thumbRect.Width()) / 2.0f;
PaintRoundedRectWithRadius(aDrawTarget, thumbRect,
sRGBColor::White(0.0f),
sRGBColor::FromABGR(thumb.mStrokeColor),
thumb.mStrokeWidth, radius / aDpiRatio, aDpiRatio);
return true;
}
@ -93,14 +103,13 @@ bool nsNativeBasicThemeCocoa::PaintScrollbarTrack(
const EventStates& aDocumentState, DPIRatio aDpiRatio) {
ScrollbarParams params =
ScrollbarDrawingMac::ComputeScrollbarParams(aFrame, aStyle, aHorizontal);
auto rect = aRect.ToUnknownRect();
if (aDpiRatio.scale >= 2.0f) {
mozilla::gfx::AutoRestoreTransform autoRestoreTransform(&aDrawTarget);
aDrawTarget.SetTransform(aDrawTarget.GetTransform().PreScale(2.0f, 2.0f));
rect.Scale(1.0f / 2.0f);
ScrollbarDrawingMac::DrawScrollbarTrack(aDrawTarget, rect, params);
} else {
ScrollbarDrawingMac::DrawScrollbarTrack(aDrawTarget, rect, params);
ScrollbarDrawingMac::ScrollbarTrackRects rects;
if (ScrollbarDrawingMac::GetScrollbarTrackRects(aRect.ToUnknownRect(), params,
aDpiRatio.scale, rects)) {
for (const auto& rect : rects) {
FillRect(aDrawTarget, LayoutDeviceRect::FromUnknownRect(rect.mRect),
sRGBColor::FromABGR(rect.mColor));
}
}
return true;
}
@ -111,15 +120,13 @@ bool nsNativeBasicThemeCocoa::PaintScrollCorner(
DPIRatio aDpiRatio) {
ScrollbarParams params =
ScrollbarDrawingMac::ComputeScrollbarParams(aFrame, aStyle, false);
if (aDpiRatio.scale >= 2.0f) {
mozilla::gfx::AutoRestoreTransform autoRestoreTransform(&aDrawTarget);
aDrawTarget.SetTransform(aDrawTarget.GetTransform().PreScale(2.0f, 2.0f));
auto rect = aRect.ToUnknownRect();
rect.Scale(1 / 2.0f);
ScrollbarDrawingMac::DrawScrollCorner(aDrawTarget, rect, params);
} else {
auto rect = aRect.ToUnknownRect();
ScrollbarDrawingMac::DrawScrollCorner(aDrawTarget, rect, params);
ScrollbarDrawingMac::ScrollCornerRects rects;
if (ScrollbarDrawingMac::GetScrollCornerRects(aRect.ToUnknownRect(), params,
aDpiRatio.scale, rects)) {
for (const auto& rect : rects) {
FillRect(aDrawTarget, LayoutDeviceRect::FromUnknownRect(rect.mRect),
sRGBColor::FromABGR(rect.mColor));
}
}
return true;
}

Просмотреть файл

@ -7,6 +7,7 @@
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/Helpers.h"
#include "mozilla/gfx/PathHelpers.h"
#include "nsChildView.h"
#include "nsDeviceContext.h"
#include "nsLayoutUtils.h"
@ -2815,9 +2816,6 @@ void nsNativeThemeCocoa::RenderWidget(const WidgetInfo& aWidgetInfo, DrawTarget&
AutoRestoreTransform autoRestoreTransform(&aDrawTarget);
gfx::Rect dirtyRect = aDirtyRect;
gfx::Rect widgetRect = aWidgetRect;
dirtyRect.Scale(1.0f / aScale);
widgetRect.Scale(1.0f / aScale);
aDrawTarget.SetTransform(aDrawTarget.GetTransform().PreScale(aScale, aScale));
const Widget widget = aWidgetInfo.Widget();
@ -2826,25 +2824,51 @@ void nsNativeThemeCocoa::RenderWidget(const WidgetInfo& aWidgetInfo, DrawTarget&
switch (widget) {
case Widget::eColorFill: {
sRGBColor color = aWidgetInfo.Params<sRGBColor>();
aDrawTarget.FillRect(widgetRect, ColorPattern(ToDeviceColor(color)));
aDrawTarget.FillRect(aWidgetRect, ColorPattern(ToDeviceColor(color)));
break;
}
case Widget::eScrollbarThumb: {
ScrollbarParams params = aWidgetInfo.Params<ScrollbarParams>();
ScrollbarDrawingMac::DrawScrollbarThumb(aDrawTarget, widgetRect, params);
auto thumb = ScrollbarDrawingMac::GetThumbRect(aWidgetRect, params, aScale);
float cornerRadius = (params.horizontal ? thumb.mRect.Height() : thumb.mRect.Width()) / 2.0f;
aDrawTarget.FillRoundedRect(RoundedRect(thumb.mRect, RectCornerRadii(cornerRadius)),
ColorPattern(ToDeviceColor(thumb.mFillColor)));
if (thumb.mStrokeColor) {
auto strokeRect = thumb.mRect;
strokeRect.Inflate(thumb.mStrokeOutset);
float strokeRadius = (params.horizontal ? strokeRect.Height() : strokeRect.Width()) / 2.0f;
RefPtr<Path> path =
MakePathForRoundedRect(aDrawTarget, strokeRect, RectCornerRadii(strokeRadius));
aDrawTarget.Stroke(path, ColorPattern(ToDeviceColor(thumb.mStrokeColor)),
StrokeOptions(thumb.mStrokeWidth));
}
break;
}
case Widget::eScrollbarTrack: {
ScrollbarParams params = aWidgetInfo.Params<ScrollbarParams>();
ScrollbarDrawingMac::DrawScrollbarTrack(aDrawTarget, widgetRect, params);
ScrollbarDrawingMac::ScrollbarTrackRects rects;
if (ScrollbarDrawingMac::GetScrollbarTrackRects(aWidgetRect, params, aScale, rects)) {
for (const auto& rect : rects) {
aDrawTarget.FillRect(rect.mRect, ColorPattern(ToDeviceColor(rect.mColor)));
}
}
break;
}
case Widget::eScrollCorner: {
ScrollbarParams params = aWidgetInfo.Params<ScrollbarParams>();
ScrollbarDrawingMac::DrawScrollCorner(aDrawTarget, widgetRect, params);
ScrollbarDrawingMac::ScrollCornerRects rects;
if (ScrollbarDrawingMac::GetScrollCornerRects(aWidgetRect, params, aScale, rects)) {
for (const auto& rect : rects) {
aDrawTarget.FillRect(rect.mRect, ColorPattern(ToDeviceColor(rect.mColor)));
}
}
break;
}
default: {
gfx::Rect widgetRect = aWidgetRect;
dirtyRect.Scale(1.0f / aScale);
widgetRect.Scale(1.0f / aScale);
// The remaining widgets require a CGContext.
CGRect macRect =
CGRectMake(widgetRect.X(), widgetRect.Y(), widgetRect.Width(), widgetRect.Height());