• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 
28 #if ENABLE(ACCELERATED_2D_CANVAS)
29 
30 #include "LoopBlinnTextureCoords.h"
31 
32 #include <math.h>
33 #include <wtf/Assertions.h>
34 
35 namespace WebCore {
36 
compute(const LoopBlinnClassifier::Result & classification,LoopBlinnConstants::FillSide sideToFill)37 LoopBlinnTextureCoords::Result LoopBlinnTextureCoords::compute(const LoopBlinnClassifier::Result& classification, LoopBlinnConstants::FillSide sideToFill)
38 {
39     // Loop and Blinn's formulation states that the right side of the
40     // curve is defined to be the inside (filled region), but for some
41     // reason it looks like with the default orientation parameters we
42     // are filling the left side of the curve. Regardless, because we
43     // can receive arbitrarily oriented curves as input, we might have
44     // to reverse the orientation of the cubic texture coordinates even
45     // in cases where the paper doesn't say it is necessary.
46     bool reverseOrientation = false;
47     static const float OneThird = 1.0f / 3.0f;
48     static const float TwoThirds = 2.0f / 3.0f;
49     LoopBlinnClassifier::CurveType curveType = classification.curveType;
50 
51     LoopBlinnTextureCoords::Result result;
52 
53     switch (curveType) {
54     case LoopBlinnClassifier::kSerpentine: {
55         float t1 = sqrtf(9.0f * classification.d2 * classification.d2 - 12 * classification.d1 * classification.d3);
56         float ls = 3.0f * classification.d2 - t1;
57         float lt = 6.0f * classification.d1;
58         float ms = 3.0f * classification.d2 + t1;
59         float mt = lt;
60         float ltMinusLs = lt - ls;
61         float mtMinusMs = mt - ms;
62         result.klmCoordinates[0] = FloatPoint3D(ls * ms,
63                                                 ls * ls * ls,
64                                                 ms * ms * ms);
65         result.klmCoordinates[1] = FloatPoint3D(OneThird * (3.0f * ls * ms - ls * mt - lt * ms),
66                                                 ls * ls * (ls - lt),
67                                                 ms * ms * (ms - mt));
68         result.klmCoordinates[2] = FloatPoint3D(OneThird * (lt * (mt - 2.0f * ms) + ls * (3.0f * ms - 2.0f * mt)),
69                                                 ltMinusLs * ltMinusLs * ls,
70                                                 mtMinusMs * mtMinusMs * ms);
71         result.klmCoordinates[3] = FloatPoint3D(ltMinusLs * mtMinusMs,
72                                                 -(ltMinusLs * ltMinusLs * ltMinusLs),
73                                                 -(mtMinusMs * mtMinusMs * mtMinusMs));
74         if (classification.d1 < 0.0f)
75             reverseOrientation = true;
76         break;
77     }
78 
79     case LoopBlinnClassifier::kLoop: {
80         float t1 = sqrtf(4.0f * classification.d1 * classification.d3 - 3.0f * classification.d2 * classification.d2);
81         float ls = classification.d2 - t1;
82         float lt = 2.0f * classification.d1;
83         float ms = classification.d2 + t1;
84         float mt = lt;
85 
86         // Figure out whether there is a rendering artifact requiring
87         // the curve to be subdivided by the caller.
88         float ql = ls / lt;
89         float qm = ms / mt;
90         if (0.0f < ql && ql < 1.0f) {
91             result.hasRenderingArtifact = true;
92             result.subdivisionParameterValue = ql;
93             return result;
94         }
95 
96         if (0.0f < qm && qm < 1.0f) {
97             result.hasRenderingArtifact = true;
98             result.subdivisionParameterValue = qm;
99             return result;
100         }
101 
102         float ltMinusLs = lt - ls;
103         float mtMinusMs = mt - ms;
104         result.klmCoordinates[0] = FloatPoint3D(ls * ms,
105                                                 ls * ls * ms,
106                                                 ls * ms * ms);
107         result.klmCoordinates[1] = FloatPoint3D(OneThird * (-ls * mt - lt * ms + 3.0f * ls * ms),
108                                                 -OneThird * ls * (ls * (mt - 3.0f * ms) + 2.0f * lt * ms),
109                                                 -OneThird * ms * (ls * (2.0f * mt - 3.0f * ms) + lt * ms));
110         result.klmCoordinates[2] = FloatPoint3D(OneThird * (lt * (mt - 2.0f * ms) + ls * (3.0f * ms - 2.0f * mt)),
111                                                 OneThird * (lt - ls) * (ls * (2.0f * mt - 3.0f * ms) + lt * ms),
112                                                 OneThird * (mt - ms) * (ls * (mt - 3.0f * ms) + 2.0f * lt * ms));
113         result.klmCoordinates[3] = FloatPoint3D(ltMinusLs * mtMinusMs,
114                                                 -(ltMinusLs * ltMinusLs) * mtMinusMs,
115                                                 -ltMinusLs * mtMinusMs * mtMinusMs);
116         reverseOrientation = ((classification.d1 > 0.0f && result.klmCoordinates[0].x() < 0.0f)
117                            || (classification.d1 < 0.0f && result.klmCoordinates[0].x() > 0.0f));
118         break;
119     }
120 
121     case LoopBlinnClassifier::kCusp: {
122         float ls = classification.d3;
123         float lt = 3.0f * classification.d2;
124         float lsMinusLt = ls - lt;
125         result.klmCoordinates[0] = FloatPoint3D(ls,
126                                                 ls * ls * ls,
127                                                 1.0f);
128         result.klmCoordinates[1] = FloatPoint3D(ls - OneThird * lt,
129                                                 ls * ls * lsMinusLt,
130                                                 1.0f);
131         result.klmCoordinates[2] = FloatPoint3D(ls - TwoThirds * lt,
132                                                 lsMinusLt * lsMinusLt * ls,
133                                                 1.0f);
134         result.klmCoordinates[3] = FloatPoint3D(lsMinusLt,
135                                                 lsMinusLt * lsMinusLt * lsMinusLt,
136                                                 1.0f);
137         break;
138     }
139 
140     case LoopBlinnClassifier::kQuadratic: {
141         result.klmCoordinates[0] = FloatPoint3D(0, 0, 0);
142         result.klmCoordinates[1] = FloatPoint3D(OneThird, 0, OneThird);
143         result.klmCoordinates[2] = FloatPoint3D(TwoThirds, OneThird, TwoThirds);
144         result.klmCoordinates[3] = FloatPoint3D(1, 1, 1);
145         if (classification.d3 < 0)
146             reverseOrientation = true;
147         break;
148     }
149 
150     case LoopBlinnClassifier::kLine:
151     case LoopBlinnClassifier::kPoint:
152         result.isLineOrPoint = true;
153         break;
154 
155     default:
156         ASSERT_NOT_REACHED();
157         break;
158     }
159 
160     if (sideToFill == LoopBlinnConstants::RightSide)
161         reverseOrientation = !reverseOrientation;
162 
163     if (reverseOrientation) {
164         for (int i = 0; i < 4; ++i) {
165             result.klmCoordinates[i].setX(-result.klmCoordinates[i].x());
166             result.klmCoordinates[i].setY(-result.klmCoordinates[i].y());
167         }
168     }
169 
170     return result;
171 }
172 
173 } // namespace WebCore
174 
175 #endif
176