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 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