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

Commit 75af3f3c authored by Chris Craik's avatar Chris Craik Committed by Android (Google) Code Review
Browse files

Merge "Add abort logging for huge scales and tessellation recursion depth"

parents b9607523 fe02b4b3
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -404,6 +404,9 @@ class GLES20Canvas extends HardwareCanvas {

    @Override
    public void scale(float sx, float sy) {
        // TODO: remove
        if (sx > 1000000 || sy > 1000000) throw new IllegalArgumentException("invalid scales passed " + sx + ", " + sy);

        nScale(mRenderer, sx, sy);
    }

+27 −11
Original line number Diff line number Diff line
@@ -57,17 +57,26 @@ namespace uirenderer {
#define ROUND_CAP_THRESH 0.25f
#define PI 3.1415926535897932f

// temporary error thresholds
#define ERROR_DEPTH 20
#define ERROR_SCALE 1e10
#define ERROR_SQR_INV_THRESH 1e-20

void PathTessellator::extractTessellationScales(const Matrix4& transform,
        float* scaleX, float* scaleY) {
    if (CC_LIKELY(transform.isPureTranslate())) {
        *scaleX = 1.0f;
        *scaleY = 1.0f;
    if (CC_UNLIKELY(!transform.isPureTranslate())) {
    } else {
        float m00 = transform.data[Matrix4::kScaleX];
        float m01 = transform.data[Matrix4::kSkewY];
        float m10 = transform.data[Matrix4::kSkewX];
        float m11 = transform.data[Matrix4::kScaleY];
        *scaleX = sqrt(m00 * m00 + m01 * m01);
        *scaleY = sqrt(m10 * m10 + m11 * m11);

        LOG_ALWAYS_FATAL_IF(*scaleX > ERROR_SCALE || *scaleY > ERROR_SCALE,
                "scales %e x %e too large for tessellation", *scaleX, *scaleY);
    }
}

@@ -92,10 +101,12 @@ struct PaintInfo {
public:
    PaintInfo(const SkPaint* paint, const mat4& transform) :
            style(paint->getStyle()), cap(paint->getStrokeCap()), isAA(paint->isAntiAlias()),
            inverseScaleX(1.0f), inverseScaleY(1.0f),
            halfStrokeWidth(paint->getStrokeWidth() * 0.5f), maxAlpha(1.0f) {
        // compute inverse scales
        if (CC_UNLIKELY(!transform.isPureTranslate())) {
        if (CC_LIKELY(transform.isPureTranslate())) {
            inverseScaleX = 1.0f;
            inverseScaleY = 1.0f;
        } else {
            float scaleX, scaleY;
            PathTessellator::extractTessellationScales(transform, &scaleX, &scaleY);
            inverseScaleX = (scaleX != 0) ? (1.0f / scaleX) : 1.0f;
@@ -922,6 +933,9 @@ bool PathTessellator::approximatePathOutlineVertices(const SkPath& path, bool fo
        Vector<Vertex>& outputVertices) {
    ATRACE_CALL();

    LOG_ALWAYS_FATAL_IF(sqrInvScaleX < ERROR_SQR_INV_THRESH || sqrInvScaleY < ERROR_SQR_INV_THRESH,
            "Invalid scale factors used for approx %e, %e", sqrInvScaleX, sqrInvScaleY);

    // TODO: to support joins other than sharp miter, join vertices should be labelled in the
    // perimeter, or resolved into more vertices. Reconsider forceClose-ing in that case.
    SkPath::Iter iter(path, forceClose);
@@ -975,14 +989,14 @@ bool PathTessellator::approximatePathOutlineVertices(const SkPath& path, bool fo
// Bezier approximation
///////////////////////////////////////////////////////////////////////////////

// Depth at which recursion is aborted
#define ABORT_DEPTH 20

void PathTessellator::recursiveCubicBezierVertices(
        float p1x, float p1y, float c1x, float c1y,
        float p2x, float p2y, float c2x, float c2y,
        float sqrInvScaleX, float sqrInvScaleY, float thresholdSquared,
        Vector<Vertex>& outputVertices, int depth) {
    LOG_ALWAYS_FATAL_IF(depth >= ERROR_DEPTH, "ERROR DEPTH exceeded: cubic approx, invscale %e x %e, vertcount %d",
            sqrInvScaleX, sqrInvScaleY, outputVertices.size());

    float dx = p2x - p1x;
    float dy = p2y - p1y;
    float d1 = fabs((c1x - p2x) * dy - (c1y - p2y) * dx);
@@ -990,8 +1004,7 @@ void PathTessellator::recursiveCubicBezierVertices(
    float d = d1 + d2;

    // multiplying by sqrInvScaleY/X equivalent to multiplying in dimensional scale factors

    if (depth >= ABORT_DEPTH || d * d < thresholdSquared * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
    if (d * d < thresholdSquared * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
        // below thresh, draw line by adding endpoint
        pushToVector(outputVertices, p2x, p2y);
    } else {
@@ -1029,11 +1042,14 @@ void PathTessellator::recursiveQuadraticBezierVertices(
        float cx, float cy,
        float sqrInvScaleX, float sqrInvScaleY, float thresholdSquared,
        Vector<Vertex>& outputVertices, int depth) {
    LOG_ALWAYS_FATAL_IF(depth >= ERROR_DEPTH, "ERROR_DEPTH exceeded: quadratic approx, invscale %e x %e, vertcount %d",
            sqrInvScaleX, sqrInvScaleY, outputVertices.size());

    float dx = bx - ax;
    float dy = by - ay;
    float d = (cx - bx) * dy - (cy - by) * dx;

    if (depth >= ABORT_DEPTH || d * d < thresholdSquared * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
    if (d * d < thresholdSquared * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
        // below thresh, draw line by adding endpoint
        pushToVector(outputVertices, bx, by);
    } else {
+3 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <vector>
#include <cutils/compiler.h>
#include <androidfw/ResourceTypes.h>
#include <utils/Log.h>

#include <SkCamera.h>
#include <SkMatrix.h>
@@ -282,6 +283,7 @@ public:
    }

    bool setScaleX(float scaleX) {
        LOG_ALWAYS_FATAL_IF(scaleX > 1000000, "invalid scaleX %e", scaleX);
        return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleX, scaleX);
    }

@@ -290,6 +292,7 @@ public:
    }

    bool setScaleY(float scaleY) {
        LOG_ALWAYS_FATAL_IF(scaleY > 1000000, "invalid scaleY %e", scaleY);
        return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleY, scaleY);
    }