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