GUI: Fix hard shadow under HiDPI rendering (#4908)

This commit is contained in:
su-xingyu 2023-04-15 02:04:16 +02:00 committed by GitHub
parent 1bab29825a
commit c577b1d616
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 40 additions and 12 deletions

View file

@ -52,6 +52,7 @@ void VectorRenderer::drawStep(const Common::Rect &area, const Common::Rect &clip
setStrokeWidth(step.stroke); setStrokeWidth(step.stroke);
setFillMode((FillMode)step.fillMode); setFillMode((FillMode)step.fillMode);
setClippingRect(applyStepClippingRect(area, clip, step)); setClippingRect(applyStepClippingRect(area, clip, step));
setShadowIntensity(step.shadowIntensity);
_dynamicData = extra; _dynamicData = extra;

View file

@ -92,6 +92,8 @@ struct DrawStep {
uint32 scale; /**< scale of all the coordinates in FIXED POINT with 16 bits mantissa */ uint32 scale; /**< scale of all the coordinates in FIXED POINT with 16 bits mantissa */
uint32 shadowIntensity; /**< interval for drawing shadows in FIXED POINT with 16 bits mantissa */
GUI::ThemeEngine::AutoScaleMode autoscale; /**< scale alphaimage if present */ GUI::ThemeEngine::AutoScaleMode autoscale; /**< scale alphaimage if present */
DrawStep() { DrawStep() {
@ -107,6 +109,7 @@ struct DrawStep {
shadowFillMode = 0; shadowFillMode = 0;
extraData = 0; extraData = 0;
scale = 0; scale = 0;
shadowIntensity = 1 << 16;
autoscale = GUI::ThemeEngine::kAutoScaleNone; autoscale = GUI::ThemeEngine::kAutoScaleNone;
} }
}; };
@ -375,6 +378,18 @@ public:
_gradientFactor = factor; _gradientFactor = factor;
} }
/**
* Sets the pixel interval for drawing shadows
*
* @param shadowIntensity interval for drawing shadows
*/
virtual void setShadowIntensity(uint32 shadowIntensity) {
if (shadowIntensity > 0)
_shadowIntensity = shadowIntensity;
else
warning("setShadowIntensity(): zero intensity");
}
/** /**
* Sets the clipping rectangle to be used by draw calls. * Sets the clipping rectangle to be used by draw calls.
* *
@ -544,6 +559,7 @@ protected:
uint32 _dynamicData; /**< Dynamic data from the GUI Theme that modifies the drawing of the current shape */ uint32 _dynamicData; /**< Dynamic data from the GUI Theme that modifies the drawing of the current shape */
int _gradientFactor; /**< Multiplication factor of the active gradient */ int _gradientFactor; /**< Multiplication factor of the active gradient */
uint32 _shadowIntensity; /**< Intensity of the shadow */
}; };
/** @} */ /** @} */
} // End of namespace Graphics } // End of namespace Graphics

View file

@ -1286,9 +1286,9 @@ drawRoundedSquare(int x, int y, int r, int w, int h) {
&& y + h + Base::_shadowOffset + 1 < Base::_activeSurface->h && y + h + Base::_shadowOffset + 1 < Base::_activeSurface->h
&& h > (Base::_shadowOffset + 1) * 2) { && h > (Base::_shadowOffset + 1) * 2) {
if (useOriginal) { if (useOriginal) {
drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset); drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset, Base::_shadowIntensity);
} else { } else {
drawRoundedSquareShadowClip(x, y, r, w, h, Base::_shadowOffset); drawRoundedSquareShadowClip(x, y, r, w, h, Base::_shadowOffset, Base::_shadowIntensity);
} }
} }
@ -3666,7 +3666,7 @@ drawSquareShadowClip(int x, int y, int w, int h, int offset) {
template<typename PixelType> template<typename PixelType>
void VectorRendererSpec<PixelType>:: void VectorRendererSpec<PixelType>::
drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) { drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset, uint32 shadowIntensity) {
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
// "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme) // "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
@ -3686,7 +3686,9 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
// Soft shadows are constructed by drawing increasingly // Soft shadows are constructed by drawing increasingly
// darker and smaller rectangles on top of each other. // darker and smaller rectangles on top of each other.
for (int i = offset; i >= 0; i--) { uint32 targetOffset = (uint32)offset << 16;
int curOffset = 0;
for (uint32 i = shadowIntensity; i <= targetOffset; i += shadowIntensity) {
int f, ddF_x, ddF_y; int f, ddF_x, ddF_y;
int x, y, px, py; int x, y, px, py;
@ -3747,7 +3749,8 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
} }
// Make shadow smaller each iteration // Make shadow smaller each iteration
shadowRect.grow(-1); shadowRect.grow(curOffset - (i >> 16));
curOffset = i >> 16;
if (_shadowFillMode == kShadowExponential) if (_shadowFillMode == kShadowExponential)
// Multiply with expfactor // Multiply with expfactor
@ -3757,7 +3760,7 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
template<typename PixelType> template<typename PixelType>
void VectorRendererSpec<PixelType>:: void VectorRendererSpec<PixelType>::
drawRoundedSquareShadowClip(int x1, int y1, int r, int w, int h, int offset) { drawRoundedSquareShadowClip(int x1, int y1, int r, int w, int h, int offset, uint32 shadowIntensity) {
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
// "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme) // "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
@ -3777,7 +3780,13 @@ drawRoundedSquareShadowClip(int x1, int y1, int r, int w, int h, int offset) {
// Soft shadows are constructed by drawing increasingly // Soft shadows are constructed by drawing increasingly
// darker and smaller rectangles on top of each other. // darker and smaller rectangles on top of each other.
for (int i = offset; i >= 0; i--) {
// HACK: shadowIntensity is tailed with 16-bits mantissa. We also represent the
// offset as a 16.16 fixed point number here as termination condition to simplify
// looping logic.
uint32 targetOffset = (uint32)offset << 16;
int curOffset = 0;
for (uint32 i = shadowIntensity; i <= targetOffset; i += shadowIntensity) {
int f, ddF_x, ddF_y; int f, ddF_x, ddF_y;
int x, y, px, py; int x, y, px, py;
@ -3840,7 +3849,8 @@ drawRoundedSquareShadowClip(int x1, int y1, int r, int w, int h, int offset) {
} }
// Make shadow smaller each iteration // Make shadow smaller each iteration
shadowRect.grow(-1); shadowRect.grow(curOffset - (i >> 16));
curOffset = i >> 16;
if (_shadowFillMode == kShadowExponential) if (_shadowFillMode == kShadowExponential)
// Multiply with expfactor // Multiply with expfactor

View file

@ -258,8 +258,8 @@ protected:
*/ */
virtual void drawSquareShadow(int x, int y, int w, int h, int offset); virtual void drawSquareShadow(int x, int y, int w, int h, int offset);
virtual void drawSquareShadowClip(int x, int y, int w, int h, int offset); virtual void drawSquareShadowClip(int x, int y, int w, int h, int offset);
virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int offset); virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int offset, uint32 shadowIntensity);
virtual void drawRoundedSquareShadowClip(int x, int y, int r, int w, int h, int offset); virtual void drawRoundedSquareShadowClip(int x, int y, int r, int w, int h, int offset, uint32 shadowIntensity);
/** /**
* Calculates the color gradient on a given point. * Calculates the color gradient on a given point.
@ -380,8 +380,8 @@ protected:
virtual void drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m); virtual void drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m);
virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int offset) { virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int offset, uint32 shadowIntensity) {
Base::drawRoundedSquareShadow(x, y, r, w, h, offset); Base::drawRoundedSquareShadow(x, y, r, w, h, offset, shadowIntensity);
} }
virtual void drawTabAlg(int x, int y, int w, int h, int r, virtual void drawTabAlg(int x, int y, int w, int h, int r,

View file

@ -161,6 +161,7 @@ Graphics::DrawStep *ThemeParser::defaultDrawStep() {
step->fillMode = Graphics::VectorRenderer::kFillDisabled; step->fillMode = Graphics::VectorRenderer::kFillDisabled;
step->scale = (1 << 16); step->scale = (1 << 16);
step->radius = 0xFF; step->radius = 0xFF;
step->shadowIntensity = SCALEVALUE((1 << 16));
return step; return step;
} }