static SkString sweepCode(const SkShader::GradientInfo& info) {
    SkString function("{exch atan 360 div\n");
    tileModeCode(info.fTileMode, &function);
    gradientFunctionCode(info, &function);
    function.append("}");
    return function;
}
static SkString linearCode(const SkShader::GradientInfo& info) {
    SkString function("{pop\n");  // Just ditch the y value.
    tileModeCode(info.fTileMode, &function);
    gradientFunctionCode(info, &function);
    function.append("}");
    return function;
}
Exemple #3
0
static void sweepCode(const SkShader::GradientInfo& info,
                          const SkMatrix& perspectiveRemover,
                          SkDynamicMemoryWStream* function) {
    function->writeText("{exch atan 360 div\n");
    tileModeCode((SkTileMode)info.fTileMode, function);
    gradient_function_code(info, function);
    function->writeText("}");
}
Exemple #4
0
static SkString linearCode(const SkShader::GradientInfo& info,
                           const SkMatrix& perspectiveRemover) {
    SkString function("{");

    function.append(apply_perspective_to_coordinates(perspectiveRemover));

    function.append("pop\n");  // Just ditch the y value.
    tileModeCode(info.fTileMode, &function);
    gradientFunctionCode(info, &function);
    function.append("}");
    return function;
}
Exemple #5
0
static void linearCode(const SkShader::GradientInfo& info,
                       const SkMatrix& perspectiveRemover,
                       SkDynamicMemoryWStream* function) {
    function->writeText("{");

    apply_perspective_to_coordinates(perspectiveRemover, function);

    function->writeText("pop\n");  // Just ditch the y value.
    tileModeCode((SkTileMode)info.fTileMode, function);
    gradient_function_code(info, function);
    function->writeText("}");
}
static SkString radialCode(const SkShader::GradientInfo& info) {
    SkString function("{");
    // Find the distance from the origin.
    function.append("dup "      // x y y
                    "mul "      // x y^2
                    "exch "     // y^2 x
                    "dup "      // y^2 x x
                    "mul "      // y^2 x^2
                    "add "      // y^2+x^2
                    "sqrt\n");  // sqrt(y^2+x^2)

    tileModeCode(info.fTileMode, &function);
    gradientFunctionCode(info, &function);
    function.append("}");
    return function;
}
Exemple #7
0
/* The math here is all based on the description in Two_Point_Radial_Gradient,
   with one simplification, the coordinate space has been scaled so that
   Dr = 1.  This means we don't need to scale the entire equation by 1/Dr^2.
 */
static SkString twoPointRadialCode(const SkShader::GradientInfo& info,
                                   const SkMatrix& perspectiveRemover) {
    SkScalar dx = info.fPoint[0].fX - info.fPoint[1].fX;
    SkScalar dy = info.fPoint[0].fY - info.fPoint[1].fY;
    SkScalar sr = info.fRadius[0];
    SkScalar a = SkScalarMul(dx, dx) + SkScalarMul(dy, dy) - SK_Scalar1;
    bool posRoot = info.fRadius[1] > info.fRadius[0];

    // We start with a stack of (x y), copy it and then consume one copy in
    // order to calculate b and the other to calculate c.
    SkString function("{");

    function.append(apply_perspective_to_coordinates(perspectiveRemover));

    function.append("2 copy ");

    // Calculate -b and b^2.
    function.appendScalar(dy);
    function.append(" mul exch ");
    function.appendScalar(dx);
    function.append(" mul add ");
    function.appendScalar(sr);
    function.append(" sub 2 mul neg dup dup mul\n");

    // Calculate c
    function.append("4 2 roll dup mul exch dup mul add ");
    function.appendScalar(SkScalarMul(sr, sr));
    function.append(" sub\n");

    // Calculate the determinate
    function.appendScalar(SkScalarMul(SkIntToScalar(4), a));
    function.append(" mul sub abs sqrt\n");

    // And then the final value of t.
    if (posRoot) {
        function.append("sub ");
    } else {
        function.append("add ");
    }
    function.appendScalar(SkScalarMul(SkIntToScalar(2), a));
    function.append(" div\n");

    tileModeCode(info.fTileMode, &function);
    gradientFunctionCode(info, &function);
    function.append("}");
    return function;
}
Exemple #8
0
static SkString radialCode(const SkShader::GradientInfo& info,
                           const SkMatrix& perspectiveRemover) {
    SkString function("{");

    function.append(apply_perspective_to_coordinates(perspectiveRemover));

    // Find the distance from the origin.
    function.append("dup "      // x y y
                    "mul "      // x y^2
                    "exch "     // y^2 x
                    "dup "      // y^2 x x
                    "mul "      // y^2 x^2
                    "add "      // y^2+x^2
                    "sqrt\n");  // sqrt(y^2+x^2)

    tileModeCode(info.fTileMode, &function);
    gradientFunctionCode(info, &function);
    function.append("}");
    return function;
}
Exemple #9
0
static void radialCode(const SkShader::GradientInfo& info,
                       const SkMatrix& perspectiveRemover,
                       SkDynamicMemoryWStream* function) {
    function->writeText("{");

    apply_perspective_to_coordinates(perspectiveRemover, function);

    // Find the distance from the origin.
    function->writeText("dup "      // x y y
                    "mul "      // x y^2
                    "exch "     // y^2 x
                    "dup "      // y^2 x x
                    "mul "      // y^2 x^2
                    "add "      // y^2+x^2
                    "sqrt\n");  // sqrt(y^2+x^2)

    tileModeCode((SkTileMode)info.fTileMode, function);
    gradient_function_code(info, function);
    function->writeText("}");
}
Exemple #10
0
/* Conical gradient shader, based on the Canvas spec for radial gradients
   See: http://www.w3.org/TR/2dcontext/#dom-context-2d-createradialgradient
 */
static SkString twoPointConicalCode(const SkShader::GradientInfo& info,
                                    const SkMatrix& perspectiveRemover) {
    SkScalar dx = info.fPoint[1].fX - info.fPoint[0].fX;
    SkScalar dy = info.fPoint[1].fY - info.fPoint[0].fY;
    SkScalar r0 = info.fRadius[0];
    SkScalar dr = info.fRadius[1] - info.fRadius[0];
    SkScalar a = SkScalarMul(dx, dx) + SkScalarMul(dy, dy) -
                 SkScalarMul(dr, dr);

    // First compute t, if the pixel falls outside the cone, then we'll end
    // with 'false' on the stack, otherwise we'll push 'true' with t below it

    // We start with a stack of (x y), copy it and then consume one copy in
    // order to calculate b and the other to calculate c.
    SkString function("{");

    function.append(apply_perspective_to_coordinates(perspectiveRemover));

    function.append("2 copy ");

    // Calculate b and b^2; b = -2 * (y * dy + x * dx + r0 * dr).
    function.appendScalar(dy);
    function.append(" mul exch ");
    function.appendScalar(dx);
    function.append(" mul add ");
    function.appendScalar(SkScalarMul(r0, dr));
    function.append(" add -2 mul dup dup mul\n");

    // c = x^2 + y^2 + radius0^2
    function.append("4 2 roll dup mul exch dup mul add ");
    function.appendScalar(SkScalarMul(r0, r0));
    function.append(" sub dup 4 1 roll\n");

    // Contents of the stack at this point: c, b, b^2, c

    // if a = 0, then we collapse to a simpler linear case
    if (a == 0) {

        // t = -c/b
        function.append("pop pop div neg dup ");

        // compute radius(t)
        function.appendScalar(dr);
        function.append(" mul ");
        function.appendScalar(r0);
        function.append(" add\n");

        // if r(t) < 0, then it's outside the cone
        function.append("0 lt {pop false} {true} ifelse\n");

    } else {

        // quadratic case: the Canvas spec wants the largest
        // root t for which radius(t) > 0

        // compute the discriminant (b^2 - 4ac)
        function.appendScalar(SkScalarMul(SkIntToScalar(4), a));
        function.append(" mul sub dup\n");

        // if d >= 0, proceed
        function.append("0 ge {\n");

        // an intermediate value we'll use to compute the roots:
        // q = -0.5 * (b +/- sqrt(d))
        function.append("sqrt exch dup 0 lt {exch -1 mul} if");
        function.append(" add -0.5 mul dup\n");

        // first root = q / a
        function.appendScalar(a);
        function.append(" div\n");

        // second root = c / q
        function.append("3 1 roll div\n");

        // put the larger root on top of the stack
        function.append("2 copy gt {exch} if\n");

        // compute radius(t) for larger root
        function.append("dup ");
        function.appendScalar(dr);
        function.append(" mul ");
        function.appendScalar(r0);
        function.append(" add\n");

        // if r(t) > 0, we have our t, pop off the smaller root and we're done
        function.append(" 0 gt {exch pop true}\n");

        // otherwise, throw out the larger one and try the smaller root
        function.append("{pop dup\n");
        function.appendScalar(dr);
        function.append(" mul ");
        function.appendScalar(r0);
        function.append(" add\n");

        // if r(t) < 0, push false, otherwise the smaller root is our t
        function.append("0 le {pop false} {true} ifelse\n");
        function.append("} ifelse\n");

        // d < 0, clear the stack and push false
        function.append("} {pop pop pop false} ifelse\n");
    }

    // if the pixel is in the cone, proceed to compute a color
    function.append("{");
    tileModeCode(info.fTileMode, &function);
    gradientFunctionCode(info, &function);

    // otherwise, just write black
    function.append("} {0 0 0} ifelse }");

    return function;
}