1589708bf7c706348b763e8277004cb160b202bdbrileya@google.com/*
2589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * Copyright 2012 Google Inc.
3589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *
4589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * Use of this source code is governed by a BSD-style license that can be
5589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * found in the LICENSE file.
6589708bf7c706348b763e8277004cb160b202bdbrileya@google.com */
7589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
8589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#include "SkTwoPointConicalGradient.h"
9aa64fbfd349789f27b3cc35c1968d9dc0612cf8ecommit-bot@chromium.org#include "SkTwoPointConicalGradient_gpu.h"
10aa64fbfd349789f27b3cc35c1968d9dc0612cf8ecommit-bot@chromium.org
1187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgstruct TwoPtRadialContext {
1287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    const TwoPtRadial&  fRec;
1387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    float               fRelX, fRelY;
1487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    const float         fIncX, fIncY;
1587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    float               fB;
1687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    const float         fDB;
1787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
1887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkScalar fy,
1987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                       SkScalar dfx, SkScalar dfy);
2087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkFixed nextT();
2187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org};
2287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
23589708bf7c706348b763e8277004cb160b202bdbrileya@google.comstatic int valid_divide(float numer, float denom, float* ratio) {
24589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    SkASSERT(ratio);
25589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    if (0 == denom) {
26589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        return 0;
27589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    }
28589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    *ratio = numer / denom;
29589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    return 1;
30589708bf7c706348b763e8277004cb160b202bdbrileya@google.com}
31589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
32589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// Return the number of distinct real roots, and write them into roots[] in
33589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// ascending order
3444d83c1e81b0555efa94f78e2a53b862208cdd06commit-bot@chromium.orgstatic int find_quad_roots(float A, float B, float C, float roots[2], bool descendingOrder = false) {
35589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    SkASSERT(roots);
36fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
37589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    if (A == 0) {
38589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        return valid_divide(-C, B, roots);
39589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    }
40fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
41589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    float R = B*B - 4*A*C;
42589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    if (R < 0) {
43589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        return 0;
44589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    }
45589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    R = sk_float_sqrt(R);
46589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
47589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#if 1
48589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    float Q = B;
49589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    if (Q < 0) {
50589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        Q -= R;
51589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    } else {
52589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        Q += R;
53589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    }
54589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#else
55589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    // on 10.6 this was much slower than the above branch :(
56589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    float Q = B + copysignf(R, B);
57589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#endif
58589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    Q *= -0.5f;
59589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    if (0 == Q) {
60589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        roots[0] = 0;
61589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        return 1;
62589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    }
63589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
64589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    float r0 = Q / A;
65589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    float r1 = C / Q;
66589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    roots[0] = r0 < r1 ? r0 : r1;
67589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    roots[1] = r0 > r1 ? r0 : r1;
6844d83c1e81b0555efa94f78e2a53b862208cdd06commit-bot@chromium.org    if (descendingOrder) {
6944d83c1e81b0555efa94f78e2a53b862208cdd06commit-bot@chromium.org        SkTSwap(roots[0], roots[1]);
7044d83c1e81b0555efa94f78e2a53b862208cdd06commit-bot@chromium.org    }
71589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    return 2;
72589708bf7c706348b763e8277004cb160b202bdbrileya@google.com}
73589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
74589708bf7c706348b763e8277004cb160b202bdbrileya@google.comstatic float lerp(float x, float dx, float t) {
75589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    return x + t * dx;
76589708bf7c706348b763e8277004cb160b202bdbrileya@google.com}
77589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
78589708bf7c706348b763e8277004cb160b202bdbrileya@google.comstatic float sqr(float x) { return x * x; }
79589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
80589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid TwoPtRadial::init(const SkPoint& center0, SkScalar rad0,
8144d83c1e81b0555efa94f78e2a53b862208cdd06commit-bot@chromium.org                       const SkPoint& center1, SkScalar rad1,
8244d83c1e81b0555efa94f78e2a53b862208cdd06commit-bot@chromium.org                       bool flipped) {
83589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    fCenterX = SkScalarToFloat(center0.fX);
84589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    fCenterY = SkScalarToFloat(center0.fY);
85589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    fDCenterX = SkScalarToFloat(center1.fX) - fCenterX;
86589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    fDCenterY = SkScalarToFloat(center1.fY) - fCenterY;
87589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    fRadius = SkScalarToFloat(rad0);
88589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    fDRadius = SkScalarToFloat(rad1) - fRadius;
89589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
90589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    fA = sqr(fDCenterX) + sqr(fDCenterY) - sqr(fDRadius);
91589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    fRadius2 = sqr(fRadius);
92589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    fRDR = fRadius * fDRadius;
9344d83c1e81b0555efa94f78e2a53b862208cdd06commit-bot@chromium.org
9444d83c1e81b0555efa94f78e2a53b862208cdd06commit-bot@chromium.org    fFlipped = flipped;
95589708bf7c706348b763e8277004cb160b202bdbrileya@google.com}
96589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
9787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgTwoPtRadialContext::TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkScalar fy,
9887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                       SkScalar dfx, SkScalar dfy)
9987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    : fRec(rec)
10087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    , fRelX(SkScalarToFloat(fx) - rec.fCenterX)
10187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    , fRelY(SkScalarToFloat(fy) - rec.fCenterY)
10287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    , fIncX(SkScalarToFloat(dfx))
10387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    , fIncY(SkScalarToFloat(dfy))
10487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    , fB(-2 * (rec.fDCenterX * fRelX + rec.fDCenterY * fRelY + rec.fRDR))
10587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    , fDB(-2 * (rec.fDCenterX * fIncX + rec.fDCenterY * fIncY)) {}
10687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
10787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkFixed TwoPtRadialContext::nextT() {
108589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    float roots[2];
109fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
11087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    float C = sqr(fRelX) + sqr(fRelY) - fRec.fRadius2;
11187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    int countRoots = find_quad_roots(fRec.fA, fB, C, roots, fRec.fFlipped);
112589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
113589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    fRelX += fIncX;
114589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    fRelY += fIncY;
115589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    fB += fDB;
116589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
117589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    if (0 == countRoots) {
11887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        return TwoPtRadial::kDontDrawT;
119589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    }
120589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
121589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    // Prefer the bigger t value if both give a radius(t) > 0
122589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    // find_quad_roots returns the values sorted, so we start with the last
123589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    float t = roots[countRoots - 1];
12487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    float r = lerp(fRec.fRadius, fRec.fDRadius, t);
125589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    if (r <= 0) {
126589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        t = roots[0];   // might be the same as roots[countRoots-1]
12787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        r = lerp(fRec.fRadius, fRec.fDRadius, t);
128589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        if (r <= 0) {
12987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            return TwoPtRadial::kDontDrawT;
130589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        }
131589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    }
132589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    return SkFloatToFixed(t);
133589708bf7c706348b763e8277004cb160b202bdbrileya@google.com}
134589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
13587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgtypedef void (*TwoPointConicalProc)(TwoPtRadialContext* rec, SkPMColor* dstC,
13660040292be58ac553298209fb2e0684a4cb17dccreed@google.com                                    const SkPMColor* cache, int toggle, int count);
137589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
13887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgstatic void twopoint_clamp(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC,
13960040292be58ac553298209fb2e0684a4cb17dccreed@google.com                           const SkPMColor* SK_RESTRICT cache, int toggle,
14060040292be58ac553298209fb2e0684a4cb17dccreed@google.com                           int count) {
141589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    for (; count > 0; --count) {
142589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        SkFixed t = rec->nextT();
143589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        if (TwoPtRadial::DontDrawT(t)) {
144589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            *dstC++ = 0;
145589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        } else {
146589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            SkFixed index = SkClampMax(t, 0xFFFF);
147589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            SkASSERT(index <= 0xFFFF);
14860040292be58ac553298209fb2e0684a4cb17dccreed@google.com            *dstC++ = cache[toggle +
14960040292be58ac553298209fb2e0684a4cb17dccreed@google.com                            (index >> SkGradientShaderBase::kCache32Shift)];
150589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        }
15160040292be58ac553298209fb2e0684a4cb17dccreed@google.com        toggle = next_dither_toggle(toggle);
152589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    }
153589708bf7c706348b763e8277004cb160b202bdbrileya@google.com}
154589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
15587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgstatic void twopoint_repeat(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC,
15660040292be58ac553298209fb2e0684a4cb17dccreed@google.com                            const SkPMColor* SK_RESTRICT cache, int toggle,
15760040292be58ac553298209fb2e0684a4cb17dccreed@google.com                            int count) {
158589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    for (; count > 0; --count) {
159589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        SkFixed t = rec->nextT();
160589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        if (TwoPtRadial::DontDrawT(t)) {
161589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            *dstC++ = 0;
162589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        } else {
163589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            SkFixed index = repeat_tileproc(t);
164589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            SkASSERT(index <= 0xFFFF);
16560040292be58ac553298209fb2e0684a4cb17dccreed@google.com            *dstC++ = cache[toggle +
16660040292be58ac553298209fb2e0684a4cb17dccreed@google.com                            (index >> SkGradientShaderBase::kCache32Shift)];
167589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        }
16860040292be58ac553298209fb2e0684a4cb17dccreed@google.com        toggle = next_dither_toggle(toggle);
169589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    }
170589708bf7c706348b763e8277004cb160b202bdbrileya@google.com}
171589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
17287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgstatic void twopoint_mirror(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC,
17360040292be58ac553298209fb2e0684a4cb17dccreed@google.com                            const SkPMColor* SK_RESTRICT cache, int toggle,
17460040292be58ac553298209fb2e0684a4cb17dccreed@google.com                            int count) {
175589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    for (; count > 0; --count) {
176589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        SkFixed t = rec->nextT();
177589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        if (TwoPtRadial::DontDrawT(t)) {
178589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            *dstC++ = 0;
179589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        } else {
180589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            SkFixed index = mirror_tileproc(t);
181589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            SkASSERT(index <= 0xFFFF);
18260040292be58ac553298209fb2e0684a4cb17dccreed@google.com            *dstC++ = cache[toggle +
18360040292be58ac553298209fb2e0684a4cb17dccreed@google.com                            (index >> SkGradientShaderBase::kCache32Shift)];
184589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        }
18560040292be58ac553298209fb2e0684a4cb17dccreed@google.com        toggle = next_dither_toggle(toggle);
186589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    }
187589708bf7c706348b763e8277004cb160b202bdbrileya@google.com}
188589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
18998e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com/////////////////////////////////////////////////////////////////////
19098e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com
191589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSkTwoPointConicalGradient::SkTwoPointConicalGradient(
1923d3a860d0ba878adb905512a45c500a67532b0a3reed@google.com        const SkPoint& start, SkScalar startRadius,
1933d3a860d0ba878adb905512a45c500a67532b0a3reed@google.com        const SkPoint& end, SkScalar endRadius,
194addf2edf3da20f053daa3897cfe2c52d7369a7b1reed        bool flippedGrad, const Descriptor& desc)
195cc695fee81613dc92746c1c6bb27f45cfc6ce73emtklein    : SkGradientShaderBase(desc, SkMatrix::I())
196addf2edf3da20f053daa3897cfe2c52d7369a7b1reed    , fCenter1(start)
197addf2edf3da20f053daa3897cfe2c52d7369a7b1reed    , fCenter2(end)
198addf2edf3da20f053daa3897cfe2c52d7369a7b1reed    , fRadius1(startRadius)
199addf2edf3da20f053daa3897cfe2c52d7369a7b1reed    , fRadius2(endRadius)
200addf2edf3da20f053daa3897cfe2c52d7369a7b1reed    , fFlippedGrad(flippedGrad)
201addf2edf3da20f053daa3897cfe2c52d7369a7b1reed{
202589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    // this is degenerate, and should be caught by our caller
203589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    SkASSERT(fCenter1 != fCenter2 || fRadius1 != fRadius2);
204cc695fee81613dc92746c1c6bb27f45cfc6ce73emtklein    fRec.init(fCenter1, fRadius1, fCenter2, fRadius2, fFlippedGrad);
205589708bf7c706348b763e8277004cb160b202bdbrileya@google.com}
206589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
2073fbab82bd30158ccabc708a20419025923e08655commit-bot@chromium.orgbool SkTwoPointConicalGradient::isOpaque() const {
208cb6d97ca718c0335dde678bb64169f6de70b62d6robertphillips@google.com    // Because areas outside the cone are left untouched, we cannot treat the
209cb6d97ca718c0335dde678bb64169f6de70b62d6robertphillips@google.com    // shader as opaque even if the gradient itself is opaque.
210cb6d97ca718c0335dde678bb64169f6de70b62d6robertphillips@google.com    // TODO(junov): Compute whether the cone fills the plane crbug.com/222380
211cb6d97ca718c0335dde678bb64169f6de70b62d6robertphillips@google.com    return false;
2123fbab82bd30158ccabc708a20419025923e08655commit-bot@chromium.org}
2133fbab82bd30158ccabc708a20419025923e08655commit-bot@chromium.org
21487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgsize_t SkTwoPointConicalGradient::contextSize() const {
21587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    return sizeof(TwoPointConicalGradientContext);
21687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org}
21787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
218ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgSkShader::Context* SkTwoPointConicalGradient::onCreateContext(const ContextRec& rec,
219ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org                                                              void* storage) const {
220e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org    return SkNEW_PLACEMENT_ARGS(storage, TwoPointConicalGradientContext, (*this, rec));
22187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org}
22287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
22387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkTwoPointConicalGradient::TwoPointConicalGradientContext::TwoPointConicalGradientContext(
224e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org        const SkTwoPointConicalGradient& shader, const ContextRec& rec)
225e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org    : INHERITED(shader, rec)
22687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org{
22787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    // we don't have a span16 proc
22887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    fFlags &= ~kHasSpan16_Flag;
22987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
23087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    // in general, we might discard based on computed-radius, so clear
23187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    // this flag (todo: sometimes we can detect that we never discard...)
23287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    fFlags &= ~kOpaqueAlpha_Flag;
23387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org}
23487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
23587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkTwoPointConicalGradient::TwoPointConicalGradientContext::shadeSpan(
23687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        int x, int y, SkPMColor* dstCParam, int count) {
23787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    const SkTwoPointConicalGradient& twoPointConicalGradient =
23887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            static_cast<const SkTwoPointConicalGradient&>(fShader);
23987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
24060040292be58ac553298209fb2e0684a4cb17dccreed@google.com    int toggle = init_dither_toggle(x, y);
24160040292be58ac553298209fb2e0684a4cb17dccreed@google.com
242589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    SkASSERT(count > 0);
243fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
244589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    SkPMColor* SK_RESTRICT dstC = dstCParam;
245fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
246589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    SkMatrix::MapXYProc dstProc = fDstToIndexProc;
247100abf49e10544bc4f436bf1f38e6929779621f4bsalomon@google.com
24887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    const SkPMColor* SK_RESTRICT cache = fCache->getCache32();
249589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
25060040292be58ac553298209fb2e0684a4cb17dccreed@google.com    TwoPointConicalProc shadeProc = twopoint_repeat;
25187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    if (SkShader::kClamp_TileMode == twoPointConicalGradient.fTileMode) {
252589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        shadeProc = twopoint_clamp;
25387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    } else if (SkShader::kMirror_TileMode == twoPointConicalGradient.fTileMode) {
254589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        shadeProc = twopoint_mirror;
255589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    } else {
25687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        SkASSERT(SkShader::kRepeat_TileMode == twoPointConicalGradient.fTileMode);
257589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    }
258fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
259589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    if (fDstToIndexClass != kPerspective_MatrixClass) {
260589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        SkPoint srcPt;
261589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
262589708bf7c706348b763e8277004cb160b202bdbrileya@google.com                SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
263589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        SkScalar dx, fx = srcPt.fX;
264589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        SkScalar dy, fy = srcPt.fY;
265fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
266589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
267589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            SkFixed fixedX, fixedY;
268589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &fixedX, &fixedY);
269589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            dx = SkFixedToScalar(fixedX);
270589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            dy = SkFixedToScalar(fixedY);
271589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        } else {
272589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
273589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            dx = fDstToIndex.getScaleX();
274589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            dy = fDstToIndex.getSkewY();
275589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        }
276589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
27787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        TwoPtRadialContext rec(twoPointConicalGradient.fRec, fx, fy, dx, dy);
27887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        (*shadeProc)(&rec, dstC, cache, toggle, count);
279589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    } else {    // perspective case
280139a2359abdeedca1ff836aa24c1a6943d9274f8mike@reedtribe.org        SkScalar dstX = SkIntToScalar(x) + SK_ScalarHalf;
281139a2359abdeedca1ff836aa24c1a6943d9274f8mike@reedtribe.org        SkScalar dstY = SkIntToScalar(y) + SK_ScalarHalf;
282589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        for (; count > 0; --count) {
283589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            SkPoint srcPt;
284589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            dstProc(fDstToIndex, dstX, dstY, &srcPt);
28587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            TwoPtRadialContext rec(twoPointConicalGradient.fRec, srcPt.fX, srcPt.fY, 0, 0);
28687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            (*shadeProc)(&rec, dstC, cache, toggle, 1);
287139a2359abdeedca1ff836aa24c1a6943d9274f8mike@reedtribe.org
288139a2359abdeedca1ff836aa24c1a6943d9274f8mike@reedtribe.org            dstX += SK_Scalar1;
28960040292be58ac553298209fb2e0684a4cb17dccreed@google.com            toggle = next_dither_toggle(toggle);
290139a2359abdeedca1ff836aa24c1a6943d9274f8mike@reedtribe.org            dstC += 1;
291589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        }
292589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    }
293589708bf7c706348b763e8277004cb160b202bdbrileya@google.com}
294589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
295589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSkShader::BitmapType SkTwoPointConicalGradient::asABitmap(
296589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    SkBitmap* bitmap, SkMatrix* matrix, SkShader::TileMode* xy) const {
297589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    SkPoint diff = fCenter2 - fCenter1;
298589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    SkScalar diffLen = 0;
299589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
300589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    if (bitmap) {
3011c6d64b78b24083ee9fd7411dac8a4a7e2d03a3crileya@google.com        this->getGradientTableBitmap(bitmap);
302589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    }
303589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    if (matrix) {
304589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        diffLen = diff.length();
305589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    }
306589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    if (matrix) {
307589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        if (diffLen) {
308589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            SkScalar invDiffLen = SkScalarInvert(diffLen);
309589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            // rotate to align circle centers with the x-axis
310589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            matrix->setSinCos(-SkScalarMul(invDiffLen, diff.fY),
311589708bf7c706348b763e8277004cb160b202bdbrileya@google.com                              SkScalarMul(invDiffLen, diff.fX));
312589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        } else {
313589708bf7c706348b763e8277004cb160b202bdbrileya@google.com            matrix->reset();
314589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        }
315589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        matrix->preTranslate(-fCenter1.fX, -fCenter1.fY);
316589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    }
317589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    if (xy) {
318589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        xy[0] = fTileMode;
319589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        xy[1] = kClamp_TileMode;
320589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    }
321589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    return kTwoPointConical_BitmapType;
322589708bf7c706348b763e8277004cb160b202bdbrileya@google.com}
323589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
32444d83c1e81b0555efa94f78e2a53b862208cdd06commit-bot@chromium.org// Returns the original non-sorted version of the gradient
325589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSkShader::GradientType SkTwoPointConicalGradient::asAGradient(
326589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    GradientInfo* info) const {
327589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    if (info) {
32844d83c1e81b0555efa94f78e2a53b862208cdd06commit-bot@chromium.org        commonAsAGradient(info, fFlippedGrad);
329589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        info->fPoint[0] = fCenter1;
330589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        info->fPoint[1] = fCenter2;
331589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        info->fRadius[0] = fRadius1;
332589708bf7c706348b763e8277004cb160b202bdbrileya@google.com        info->fRadius[1] = fRadius2;
33344d83c1e81b0555efa94f78e2a53b862208cdd06commit-bot@chromium.org        if (fFlippedGrad) {
33444d83c1e81b0555efa94f78e2a53b862208cdd06commit-bot@chromium.org            SkTSwap(info->fPoint[0], info->fPoint[1]);
33544d83c1e81b0555efa94f78e2a53b862208cdd06commit-bot@chromium.org            SkTSwap(info->fRadius[0], info->fRadius[1]);
33644d83c1e81b0555efa94f78e2a53b862208cdd06commit-bot@chromium.org        }
337589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    }
338589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    return kConical_GradientType;
339589708bf7c706348b763e8277004cb160b202bdbrileya@google.com}
340589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
3419fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkTwoPointConicalGradient::CreateProc(SkReadBuffer& buffer) {
3429fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    DescriptorScope desc;
3439fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (!desc.unflatten(buffer)) {
3449fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        return NULL;
3459fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
3469fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkPoint c1 = buffer.readPoint();
3479fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkPoint c2 = buffer.readPoint();
3489fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkScalar r1 = buffer.readScalar();
3499fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkScalar r2 = buffer.readScalar();
3509fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
3519fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (buffer.readBool()) {    // flipped
3529fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        SkTSwap(c1, c2);
3539fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        SkTSwap(r1, r2);
3549fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
3559fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        SkColor* colors = desc.mutableColors();
3569fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        SkScalar* pos = desc.mutablePos();
3579fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        const int last = desc.fCount - 1;
3589fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        const int half = desc.fCount >> 1;
3599fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        for (int i = 0; i < half; ++i) {
3609fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed            SkTSwap(colors[i], colors[last - i]);
3619fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed            if (pos) {
3629fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                SkScalar tmp = pos[i];
3639fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                pos[i] = SK_Scalar1 - pos[last - i];
3649fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                pos[last - i] = SK_Scalar1 - tmp;
3659fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed            }
3669fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        }
3679fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        if (pos) {
3689fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed            if (desc.fCount & 1) {
3699fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                pos[half] = SK_Scalar1 - pos[half];
3709fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed            }
3719fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        }
3729fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
3739fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
3749fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return SkGradientShader::CreateTwoPointConical(c1, r1, c2, r2, desc.fColors, desc.fPos,
3759fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                   desc.fCount, desc.fTileMode, desc.fGradFlags,
3769fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                   desc.fLocalMatrix);
3779fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
378589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
3799fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedvoid SkTwoPointConicalGradient::flatten(SkWriteBuffer& buffer) const {
380589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    this->INHERITED::flatten(buffer);
381589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    buffer.writePoint(fCenter1);
382589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    buffer.writePoint(fCenter2);
383589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    buffer.writeScalar(fRadius1);
384589708bf7c706348b763e8277004cb160b202bdbrileya@google.com    buffer.writeScalar(fRadius2);
38544d83c1e81b0555efa94f78e2a53b862208cdd06commit-bot@chromium.org    buffer.writeBool(fFlippedGrad);
386589708bf7c706348b763e8277004cb160b202bdbrileya@google.com}
387589708bf7c706348b763e8277004cb160b202bdbrileya@google.com
388cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
389cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com
3909de5b514d38c5b36066bcdc14fba2f7e5196d372dandov#include "SkGr.h"
3919de5b514d38c5b36066bcdc14fba2f7e5196d372dandov
392b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkTwoPointConicalGradient::asFragmentProcessor(GrContext* context,
393b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                    const SkPaint& paint,
3945531d51ce7426bdae7563547326fcf0bf926a083joshualitt                                                    const SkMatrix& viewM,
395b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                    const SkMatrix* localMatrix,
396b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                    GrColor* paintColor,
397b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                    GrFragmentProcessor** fp)  const {
39849f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(context);
399f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com    SkASSERT(fPtsToUnit.isIdentity());
400dfdb7e5240276493077b7c6e1f3cc8b8a0e195babsalomon@google.com
401b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    *fp = Gr2PtConicalGradientEffect::Create(context, *this, fTileMode, localMatrix);
40283d081ae1d731b5039e99823620f5e287542ee39bsalomon    *paintColor = SkColor2GrColorJustAlpha(paint.getColor());
4039de5b514d38c5b36066bcdc14fba2f7e5196d372dandov    return true;
404d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com}
405d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com
406cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#else
407cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com
4085531d51ce7426bdae7563547326fcf0bf926a083joshualittbool SkTwoPointConicalGradient::asFragmentProcessor(GrContext*, const SkPaint&,
4095531d51ce7426bdae7563547326fcf0bf926a083joshualitt                                                    const SkMatrix&, const SkMatrix*,
410b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                    GrColor*, GrFragmentProcessor**)  const {
411cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com    SkDEBUGFAIL("Should not call in GPU-less build");
4129de5b514d38c5b36066bcdc14fba2f7e5196d372dandov    return false;
413cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com}
414cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com
415a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com#endif
41676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
4170f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
41876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.comvoid SkTwoPointConicalGradient::toString(SkString* str) const {
41976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->append("SkTwoPointConicalGradient: (");
42076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
42176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->append("center1: (");
42276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->appendScalar(fCenter1.fX);
42376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->append(", ");
42476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->appendScalar(fCenter1.fY);
42576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->append(") radius1: ");
42676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->appendScalar(fRadius1);
42776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->append(" ");
42876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
42976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->append("center2: (");
43076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->appendScalar(fCenter2.fX);
43176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->append(", ");
43276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->appendScalar(fCenter2.fY);
43376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->append(") radius2: ");
43476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->appendScalar(fRadius2);
43576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->append(" ");
43676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
43776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    this->INHERITED::toString(str);
43876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
43976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->append(")");
44076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com}
44176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#endif
442