1635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project/* 2635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Copyright (C) 2008 Apple Inc. All Rights Reserved. 3635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 4635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Redistribution and use in source and binary forms, with or without 5635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * modification, are permitted provided that the following conditions 6635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * are met: 7635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 8635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * notice, this list of conditions and the following disclaimer. 9635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 10635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 11635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * documentation and/or other materials provided with the distribution. 12635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 13635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project */ 25635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 26635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "config.h" 278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "WebKitCSSMatrix.h" 28635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 29635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "CSSParser.h" 30635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "CSSStyleSelector.h" 31635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "CSSMutableStyleDeclaration.h" 32635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "CSSPropertyNames.h" 3365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include "CSSValueKeywords.h" 34635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "ExceptionCode.h" 358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include <wtf/MathExtras.h> 36635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 37635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectnamespace WebCore { 38635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 39635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectWebKitCSSMatrix::WebKitCSSMatrix(const TransformationMatrix& m) 406b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner : m_matrix(m) 41635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 42635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 43635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 44635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectWebKitCSSMatrix::WebKitCSSMatrix(const String& s, ExceptionCode& ec) 45635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 46635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project setMatrixValue(s, ec); 47635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 48635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 49635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectWebKitCSSMatrix::~WebKitCSSMatrix() 50635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 51635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 52635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 53635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid WebKitCSSMatrix::setMatrixValue(const String& string, ExceptionCode& ec) 54635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 55635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project RefPtr<CSSMutableStyleDeclaration> styleDeclaration = CSSMutableStyleDeclaration::create(); 562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (CSSParser::parseValue(styleDeclaration.get(), CSSPropertyWebkitTransform, string, true, true)) { 57635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Convert to TransformOperations. This can fail if a property 58635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // requires style (i.e., param uses 'ems' or 'exs') 5965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch RefPtr<CSSValue> value = styleDeclaration->getPropertyCSSValue(CSSPropertyWebkitTransform); 6065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 6165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch // Check for a "none" or empty transform. In these cases we can use the default identity matrix. 6265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if (!value || (value->isPrimitiveValue() && (static_cast<CSSPrimitiveValue*>(value.get()))->getIdent() == CSSValueNone)) 6365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch return; 6465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 65635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project TransformOperations operations; 6665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if (!CSSStyleSelector::createTransformOperations(value.get(), 0, 0, operations)) { 67635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ec = SYNTAX_ERR; 68635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return; 69635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 70635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 71635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Convert transform operations to a TransformationMatrix. This can fail 72635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // if a param has a percentage ('%') 73635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project TransformationMatrix t; 74635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (unsigned i = 0; i < operations.operations().size(); ++i) { 75635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (operations.operations()[i].get()->apply(t, IntSize(0, 0))) { 76635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ec = SYNTAX_ERR; 77635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return; 78635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 79635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 80635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 81635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // set the matrix 82635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_matrix = t; 83635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else if (!string.isEmpty()) // There is something there but parsing failed 84635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ec = SYNTAX_ERR; 85635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 86635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 8721939df44de1705786c545cd1bf519d47250322dBen Murdoch// Perform a concatenation of the matrices (this * secondMatrix) 888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianPassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::multiply(WebKitCSSMatrix* secondMatrix) const 89635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (!secondMatrix) 918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return 0; 928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).multiply(secondMatrix->m_matrix)); 94635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 95635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianPassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::inverse(ExceptionCode& ec) const 97635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 98635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!m_matrix.isInvertible()) { 99635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ec = NOT_SUPPORTED_ERR; 100635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 101635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 102635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 103635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return WebKitCSSMatrix::create(m_matrix.inverse()); 104635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 105635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianPassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::translate(double x, double y, double z) const 107635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 108635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (isnan(x)) 1098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian x = 0; 110635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (isnan(y)) 1118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian y = 0; 1128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (isnan(z)) 1138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian z = 0; 1148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).translate3d(x, y, z)); 115635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 116635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianPassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::scale(double scaleX, double scaleY, double scaleZ) const 118635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 119635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (isnan(scaleX)) 1208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian scaleX = 1; 121635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (isnan(scaleY)) 1228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian scaleY = scaleX; 1238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (isnan(scaleZ)) 1248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian scaleZ = 1; 1258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).scale3d(scaleX, scaleY, scaleZ)); 126635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 127635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianPassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::rotate(double rotX, double rotY, double rotZ) const 129635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (isnan(rotX)) 1318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian rotX = 0; 1328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (isnan(rotY) && isnan(rotZ)) { 1348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian rotZ = rotX; 1358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian rotX = 0; 1368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian rotY = 0; 1378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 1388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (isnan(rotY)) 1408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian rotY = 0; 1418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (isnan(rotZ)) 1428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian rotZ = 0; 1438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).rotate3d(rotX, rotY, rotZ)); 144635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 145635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianPassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::rotateAxisAngle(double x, double y, double z, double angle) const 1478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 1488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (isnan(x)) 1498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian x = 0; 1508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (isnan(y)) 1518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian y = 0; 1528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (isnan(z)) 1538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian z = 0; 1548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (isnan(angle)) 1558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian angle = 0; 1568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (x == 0 && y == 0 && z == 0) 1578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian z = 1; 1588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).rotate3d(x, y, z, angle)); 1598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 1608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 161cad810f21b803229eb11403f9209855525a25d57Steve BlockPassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::skewX(double angle) const 162cad810f21b803229eb11403f9209855525a25d57Steve Block{ 163cad810f21b803229eb11403f9209855525a25d57Steve Block if (isnan(angle)) 164cad810f21b803229eb11403f9209855525a25d57Steve Block angle = 0; 165cad810f21b803229eb11403f9209855525a25d57Steve Block return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).skewX(angle)); 166cad810f21b803229eb11403f9209855525a25d57Steve Block} 167cad810f21b803229eb11403f9209855525a25d57Steve Block 168cad810f21b803229eb11403f9209855525a25d57Steve BlockPassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::skewY(double angle) const 169cad810f21b803229eb11403f9209855525a25d57Steve Block{ 170cad810f21b803229eb11403f9209855525a25d57Steve Block if (isnan(angle)) 171cad810f21b803229eb11403f9209855525a25d57Steve Block angle = 0; 172cad810f21b803229eb11403f9209855525a25d57Steve Block return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).skewY(angle)); 173cad810f21b803229eb11403f9209855525a25d57Steve Block} 1748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 1758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianString WebKitCSSMatrix::toString() const 176635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian // FIXME - Need to ensure valid CSS floating point values (https://bugs.webkit.org/show_bug.cgi?id=20674) 1788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (m_matrix.isAffine()) 1798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return String::format("matrix(%f, %f, %f, %f, %f, %f)", 1808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix.a(), m_matrix.b(), m_matrix.c(), m_matrix.d(), m_matrix.e(), m_matrix.f()); 1818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return String::format("matrix3d(%f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f)", 1828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix.m11(), m_matrix.m12(), m_matrix.m13(), m_matrix.m14(), 1838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix.m21(), m_matrix.m22(), m_matrix.m23(), m_matrix.m24(), 1848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix.m31(), m_matrix.m32(), m_matrix.m33(), m_matrix.m34(), 1858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_matrix.m41(), m_matrix.m42(), m_matrix.m43(), m_matrix.m44()); 186635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 187635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 188635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} // namespace WebCore 189