1 /* 2 * Copyright (C) 2008 Apple 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 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "WebKitCSSMatrix.h" 28 29 #include "CSSParser.h" 30 #include "CSSStyleSelector.h" 31 #include "CSSMutableStyleDeclaration.h" 32 #include "CSSPropertyNames.h" 33 #include "CSSValueKeywords.h" 34 #include "ExceptionCode.h" 35 #include <wtf/MathExtras.h> 36 37 namespace WebCore { 38 39 WebKitCSSMatrix::WebKitCSSMatrix(const TransformationMatrix& m) 40 : m_matrix(m) 41 { 42 } 43 44 WebKitCSSMatrix::WebKitCSSMatrix(const String& s, ExceptionCode& ec) 45 { 46 setMatrixValue(s, ec); 47 } 48 49 WebKitCSSMatrix::~WebKitCSSMatrix() 50 { 51 } 52 53 void WebKitCSSMatrix::setMatrixValue(const String& string, ExceptionCode& ec) 54 { 55 RefPtr<CSSMutableStyleDeclaration> styleDeclaration = CSSMutableStyleDeclaration::create(); 56 if (CSSParser::parseValue(styleDeclaration.get(), CSSPropertyWebkitTransform, string, true, true)) { 57 // Convert to TransformOperations. This can fail if a property 58 // requires style (i.e., param uses 'ems' or 'exs') 59 RefPtr<CSSValue> value = styleDeclaration->getPropertyCSSValue(CSSPropertyWebkitTransform); 60 61 // Check for a "none" or empty transform. In these cases we can use the default identity matrix. 62 if (!value || (value->isPrimitiveValue() && (static_cast<CSSPrimitiveValue*>(value.get()))->getIdent() == CSSValueNone)) 63 return; 64 65 TransformOperations operations; 66 if (!CSSStyleSelector::createTransformOperations(value.get(), 0, 0, operations)) { 67 ec = SYNTAX_ERR; 68 return; 69 } 70 71 // Convert transform operations to a TransformationMatrix. This can fail 72 // if a param has a percentage ('%') 73 TransformationMatrix t; 74 for (unsigned i = 0; i < operations.operations().size(); ++i) { 75 if (operations.operations()[i].get()->apply(t, IntSize(0, 0))) { 76 ec = SYNTAX_ERR; 77 return; 78 } 79 } 80 81 // set the matrix 82 m_matrix = t; 83 } else if (!string.isEmpty()) // There is something there but parsing failed 84 ec = SYNTAX_ERR; 85 } 86 87 // Perform a concatenation of the matrices (this * secondMatrix) 88 PassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::multiply(WebKitCSSMatrix* secondMatrix) const 89 { 90 if (!secondMatrix) 91 return 0; 92 93 return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).multiply(secondMatrix->m_matrix)); 94 } 95 96 PassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::inverse(ExceptionCode& ec) const 97 { 98 if (!m_matrix.isInvertible()) { 99 ec = NOT_SUPPORTED_ERR; 100 return 0; 101 } 102 103 return WebKitCSSMatrix::create(m_matrix.inverse()); 104 } 105 106 PassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::translate(double x, double y, double z) const 107 { 108 if (isnan(x)) 109 x = 0; 110 if (isnan(y)) 111 y = 0; 112 if (isnan(z)) 113 z = 0; 114 return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).translate3d(x, y, z)); 115 } 116 117 PassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::scale(double scaleX, double scaleY, double scaleZ) const 118 { 119 if (isnan(scaleX)) 120 scaleX = 1; 121 if (isnan(scaleY)) 122 scaleY = scaleX; 123 if (isnan(scaleZ)) 124 scaleZ = 1; 125 return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).scale3d(scaleX, scaleY, scaleZ)); 126 } 127 128 PassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::rotate(double rotX, double rotY, double rotZ) const 129 { 130 if (isnan(rotX)) 131 rotX = 0; 132 133 if (isnan(rotY) && isnan(rotZ)) { 134 rotZ = rotX; 135 rotX = 0; 136 rotY = 0; 137 } 138 139 if (isnan(rotY)) 140 rotY = 0; 141 if (isnan(rotZ)) 142 rotZ = 0; 143 return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).rotate3d(rotX, rotY, rotZ)); 144 } 145 146 PassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::rotateAxisAngle(double x, double y, double z, double angle) const 147 { 148 if (isnan(x)) 149 x = 0; 150 if (isnan(y)) 151 y = 0; 152 if (isnan(z)) 153 z = 0; 154 if (isnan(angle)) 155 angle = 0; 156 if (x == 0 && y == 0 && z == 0) 157 z = 1; 158 return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).rotate3d(x, y, z, angle)); 159 } 160 161 PassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::skewX(double angle) const 162 { 163 if (isnan(angle)) 164 angle = 0; 165 return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).skewX(angle)); 166 } 167 168 PassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::skewY(double angle) const 169 { 170 if (isnan(angle)) 171 angle = 0; 172 return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).skewY(angle)); 173 } 174 175 String WebKitCSSMatrix::toString() const 176 { 177 // FIXME - Need to ensure valid CSS floating point values (https://bugs.webkit.org/show_bug.cgi?id=20674) 178 if (m_matrix.isAffine()) 179 return String::format("matrix(%f, %f, %f, %f, %f, %f)", 180 m_matrix.a(), m_matrix.b(), m_matrix.c(), m_matrix.d(), m_matrix.e(), m_matrix.f()); 181 return String::format("matrix3d(%f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f)", 182 m_matrix.m11(), m_matrix.m12(), m_matrix.m13(), m_matrix.m14(), 183 m_matrix.m21(), m_matrix.m22(), m_matrix.m23(), m_matrix.m24(), 184 m_matrix.m31(), m_matrix.m32(), m_matrix.m33(), m_matrix.m34(), 185 m_matrix.m41(), m_matrix.m42(), m_matrix.m43(), m_matrix.m44()); 186 } 187 188 } // namespace WebCore 189