Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e392c81f authored by Derek Sollenberger's avatar Derek Sollenberger
Browse files

Pass the radius as a float deeper into HWUI allowing RS to generate more accurate blurs.

Also, when converting radius to an integer value snap to the appropriate integer boundaries.

bug: 10650594
Change-Id: Icca4bc17d88162bbcbc6035d4f81bd1d98a4de2d
parent 69b43b49
Loading
Loading
Loading
Loading
+13 −11
Original line number Diff line number Diff line
@@ -592,7 +592,7 @@ void FontRenderer::setFont(const SkPaint* paint, const mat4& matrix) {
}

FontRenderer::DropShadow FontRenderer::renderDropShadow(const SkPaint* paint, const char *text,
        uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius, const float* positions) {
        uint32_t startIndex, uint32_t len, int numGlyphs, float radius, const float* positions) {
    checkInit();

    DropShadow image;
@@ -613,8 +613,9 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(const SkPaint* paint, co
    Rect bounds;
    mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds, positions);

    uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * radius;
    uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * radius;
    uint32_t intRadius = Blur::convertRadiusToInt(radius);
    uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * intRadius;
    uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * intRadius;

    uint32_t maxSize = Caches::getInstance().maxTextureSize;
    if (paddedWidth > maxSize || paddedHeight > maxSize) {
@@ -635,8 +636,8 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(const SkPaint* paint, co

    memset(dataBuffer, 0, size);

    int penX = radius - bounds.left;
    int penY = radius - bounds.bottom;
    int penX = intRadius - bounds.left;
    int penY = intRadius - bounds.bottom;

    if ((bounds.right > bounds.left) && (bounds.top > bounds.bottom)) {
        // text has non-whitespace, so draw and blur to create the shadow
@@ -727,9 +728,10 @@ void FontRenderer::removeFont(const Font* font) {
    }
}

void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, int32_t radius) {
void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, float radius) {
    uint32_t intRadius = Blur::convertRadiusToInt(radius);
#ifdef ANDROID_ENABLE_RENDERSCRIPT
    if (width * height * radius >= RS_MIN_INPUT_CUTOFF) {
    if (width * height * intRadius >= RS_MIN_INPUT_CUTOFF) {
        uint8_t* outImage = (uint8_t*) memalign(RS_CPU_ALLOCATION_ALIGNMENT, width * height);

        if (mRs == 0) {
@@ -768,12 +770,12 @@ void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, int
    }
#endif

    float *gaussian = new float[2 * radius + 1];
    Blur::generateGaussianWeights(gaussian, radius);
    float *gaussian = new float[2 * intRadius + 1];
    Blur::generateGaussianWeights(gaussian, intRadius);

    uint8_t* scratch = new uint8_t[width * height];
    Blur::horizontal(gaussian, radius, *image, scratch, width, height);
    Blur::vertical(gaussian, radius, scratch, *image, width, height);
    Blur::horizontal(gaussian, intRadius, *image, scratch, width, height);
    Blur::vertical(gaussian, intRadius, scratch, *image, width, height);

    delete[] gaussian;
    delete[] scratch;
+2 −2
Original line number Diff line number Diff line
@@ -129,7 +129,7 @@ public:
    // After renderDropShadow returns, the called owns the memory in DropShadow.image
    // and is responsible for releasing it when it's done with it
    DropShadow renderDropShadow(const SkPaint* paint, const char *text, uint32_t startIndex,
            uint32_t len, int numGlyphs, uint32_t radius, const float* positions);
            uint32_t len, int numGlyphs, float radius, const float* positions);

    void setTextureFiltering(bool linearFiltering) {
        mLinearFiltering = linearFiltering;
@@ -218,7 +218,7 @@ private:
            int32_t width, int32_t height);

    // the input image handle may have its pointer replaced (to avoid copies)
    void blurImage(uint8_t** image, int32_t width, int32_t height, int32_t radius);
    void blurImage(uint8_t** image, int32_t width, int32_t height, float radius);
};

}; // namespace uirenderer
+12 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <math.h>

#include "Blur.h"
#include "MathUtils.h"

namespace android {
namespace uirenderer {
@@ -35,6 +36,17 @@ float Blur::convertSigmaToRadius(float sigma) {
    return sigma > 0.5f ? (sigma - 0.5f) / BLUR_SIGMA_SCALE : 0.0f;
}

// if the original radius was on an integer boundary and the resulting radius
// is within the conversion error tolerance then we attempt to snap to the
// original integer boundary.
uint32_t Blur::convertRadiusToInt(float radius) {
    const float radiusCeil  = ceilf(radius);
    if (MathUtils::areEqual(radiusCeil, radius)) {
        return radiusCeil;
    }
    return radius;
}

/**
 * HWUI has used a slightly different equation than Skia to generate the value
 * for sigma and to preserve compatibility we have kept that logic.
+5 −1
Original line number Diff line number Diff line
@@ -27,8 +27,12 @@ class Blur {
public:
    // If radius > 0, return the corresponding sigma, else return 0
    ANDROID_API static float convertRadiusToSigma(float radius);
    // If sigma > 0.6, return the corresponding radius, else return 0
    // If sigma > 0.5, return the corresponding radius, else return 0
    ANDROID_API static float convertSigmaToRadius(float sigma);
    // If the original radius was on an integer boundary then after the sigma to
    // radius conversion a small rounding error may be introduced. This function
    // accounts for that error and snaps to the appropriate integer boundary.
    static uint32_t convertRadiusToInt(float radius);

    static void generateGaussianWeights(float* weights, int32_t radius);
    static void horizontal(float* weights, int32_t radius, const uint8_t* source,