예제 #1
0
// https://code.google.com/p/chromium/issues/detail?id=448299
// Giant (inverse) matrix causes overflow when converting/computing using 32.32
// Before the fix, we would assert (and then crash).
static void test_big_grad(skiatest::Reporter* reporter) {
    const SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
    const SkPoint pts[] = {{ 15, 14.7112684f }, { 0.709064007f, 12.6108112f }};
    SkPaint paint;
    paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp));

    SkBitmap bm;
    bm.allocN32Pixels(2000, 1);
    SkCanvas c(bm);

    const SkScalar affine[] = {
        1.06608627e-06f, 4.26434525e-07f, 6.2855f, 2.6611f, 273.4393f, 244.0046f
    };
    SkMatrix matrix;
    matrix.setAffine(affine);
    c.concat(matrix);

    c.drawPaint(paint);
}
// This test case including path coords and matrix taken from crbug.com/627443.
// Because of inaccuracies in large floating point values this causes the
// the path renderer to attempt to add a path DF to its atlas that is larger
// than the plot size which used to crash rather than fail gracefully.
static void test_far_from_origin(GrDrawContext* drawContext, GrPathRenderer* pr,
                                 GrResourceProvider* rp) {
    SkPath path;
    path.lineTo(49.0255089839f, 0.473541f);
    static constexpr SkScalar mvals[] = {14.0348252854f, 2.13026182736f,
                                         13.6122547187f, 118.309922702f,
                                         1912337682.09f, 2105391889.87f};
    SkMatrix matrix;
    matrix.setAffine(mvals);
    SkMatrix inverse;
    SkAssertResult(matrix.invert(&inverse));
    path.transform(inverse);

    SkStrokeRec rec(SkStrokeRec::kFill_InitStyle);
    rec.setStrokeStyle(1.f);
    rec.setStrokeParams(SkPaint::kRound_Cap, SkPaint::kRound_Join, 1.f);
    GrStyle style(rec, nullptr);

    GrShape shape(path, style);
    shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, 1.f);

    GrPaint paint;
    paint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode));

    GrNoClip noClip;
    GrPathRenderer::DrawPathArgs args;
    args.fPaint = &paint;
    args.fUserStencilSettings = &GrUserStencilSettings::kUnused;
    args.fDrawContext = drawContext;
    args.fClip = &noClip;
    args.fResourceProvider = rp;
    args.fViewMatrix = &matrix;
    args.fShape = &shape;
    args.fAntiAlias = true;
    args.fGammaCorrect = false;
    args.fColor = 0x0;
    pr->drawPath(args);
}
예제 #3
0
GrDrawVerticesOp::GrDrawVerticesOp(const Helper::MakeArgs& helperArgs, GrColor color,
                                   sk_sp<SkVertices> vertices, const SkVertices::Bone bones[],
                                   int boneCount, GrPrimitiveType primitiveType, GrAAType aaType,
                                   sk_sp<GrColorSpaceXform> colorSpaceXform,
                                   const SkMatrix& viewMatrix)
        : INHERITED(ClassID())
        , fHelper(helperArgs, aaType)
        , fPrimitiveType(primitiveType)
        , fColorSpaceXform(std::move(colorSpaceXform)) {
    SkASSERT(vertices);

    fVertexCount = vertices->vertexCount();
    fIndexCount = vertices->indexCount();
    fColorArrayType = vertices->hasColors() ? ColorArrayType::kSkColor
                                            : ColorArrayType::kPremulGrColor;

    Mesh& mesh = fMeshes.push_back();
    mesh.fColor = color;
    mesh.fViewMatrix = viewMatrix;
    mesh.fVertices = std::move(vertices);
    mesh.fIgnoreTexCoords = false;
    mesh.fIgnoreColors = false;
    mesh.fIgnoreBones = false;

    if (mesh.fVertices->hasBones() && bones) {
        // Perform the transformations on the CPU instead of the GPU.
        mesh.fVertices = mesh.fVertices->applyBones(bones, boneCount);
    } else {
        if (bones && boneCount > 1) {
            // NOTE: This should never be used. All bone transforms are being done on the CPU
            // instead of the GPU.

            // Copy the bone data.
            fBones.assign(bones, bones + boneCount);
        }
    }

    fFlags = 0;
    if (mesh.hasPerVertexColors()) {
        fFlags |= kRequiresPerVertexColors_Flag;
    }
    if (mesh.hasExplicitLocalCoords()) {
        fFlags |= kAnyMeshHasExplicitLocalCoords_Flag;
    }
    if (mesh.hasBones()) {
        fFlags |= kHasBones_Flag;
    }

    // Special case for meshes with a world transform but no bone weights.
    // These will be considered normal vertices draws without bones.
    if (!mesh.fVertices->hasBones() && boneCount == 1) {
        SkMatrix worldTransform;
        worldTransform.setAffine(bones[0].values);
        mesh.fViewMatrix.preConcat(worldTransform);
    }

    IsZeroArea zeroArea;
    if (GrIsPrimTypeLines(primitiveType) || GrPrimitiveType::kPoints == primitiveType) {
        zeroArea = IsZeroArea::kYes;
    } else {
        zeroArea = IsZeroArea::kNo;
    }

    if (this->hasBones()) {
        // We don't know the bounds if there are deformations involved, so attempt to calculate
        // the maximum possible.
        SkRect bounds = SkRect::MakeEmpty();
        const SkRect originalBounds = bones[0].mapRect(mesh.fVertices->bounds());
        for (int i = 1; i < boneCount; i++) {
            const SkVertices::Bone& matrix = bones[i];
            bounds.join(matrix.mapRect(originalBounds));
        }

        this->setTransformedBounds(bounds,
                                   mesh.fViewMatrix,
                                   HasAABloat::kNo,
                                   zeroArea);
    } else {
        this->setTransformedBounds(mesh.fVertices->bounds(),
                                   mesh.fViewMatrix,
                                   HasAABloat::kNo,
                                   zeroArea);
    }
}