WebCore/rendering/TransformState.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2009 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 COMPUTER, 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 COMPUTER, 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 "TransformState.h"
       
    28 
       
    29 namespace WebCore {
       
    30 
       
    31 void TransformState::move(int x, int y, TransformAccumulation accumulate)
       
    32 {
       
    33     if (m_accumulatingTransform && m_accumulatedTransform) {
       
    34         // If we're accumulating into an existing transform, apply the translation.
       
    35         if (m_direction == ApplyTransformDirection)
       
    36             m_accumulatedTransform->translateRight(x, y);
       
    37         else
       
    38             m_accumulatedTransform->translate(-x, -y);  // We're unapplying, so negate
       
    39         
       
    40         // Then flatten if necessary.
       
    41         if (accumulate == FlattenTransform)
       
    42             flatten();
       
    43     } else {
       
    44         // Just move the point and, optionally, the quad.
       
    45         m_lastPlanarPoint.move(x, y);
       
    46         if (m_mapQuad)
       
    47             m_lastPlanarQuad.move(x, y);
       
    48     }
       
    49     m_accumulatingTransform = accumulate == AccumulateTransform;
       
    50 }
       
    51 
       
    52 // FIXME: We transform AffineTransform to TransformationMatrix. This is rather inefficient.
       
    53 void TransformState::applyTransform(const AffineTransform& transformFromContainer, TransformAccumulation accumulate)
       
    54 {
       
    55     applyTransform(transformFromContainer.toTransformationMatrix(), accumulate);
       
    56 }
       
    57 
       
    58 void TransformState::applyTransform(const TransformationMatrix& transformFromContainer, TransformAccumulation accumulate)
       
    59 {
       
    60     // If we have an accumulated transform from last time, multiply in this transform
       
    61     if (m_accumulatedTransform) {
       
    62         if (m_direction == ApplyTransformDirection)
       
    63             m_accumulatedTransform->multiply(transformFromContainer);
       
    64         else
       
    65             m_accumulatedTransform->multLeft(transformFromContainer);
       
    66     } else if (accumulate == AccumulateTransform) {
       
    67         // Make one if we started to accumulate
       
    68         m_accumulatedTransform.set(new TransformationMatrix(transformFromContainer));
       
    69     }
       
    70     
       
    71     if (accumulate == FlattenTransform) {
       
    72         const TransformationMatrix* finalTransform = m_accumulatedTransform ? m_accumulatedTransform.get() : &transformFromContainer;
       
    73         flattenWithTransform(*finalTransform);
       
    74     }
       
    75     m_accumulatingTransform = accumulate == AccumulateTransform;
       
    76 }
       
    77 
       
    78 void TransformState::flatten()
       
    79 {
       
    80     if (!m_accumulatedTransform) {
       
    81         m_accumulatingTransform = false;
       
    82         return;
       
    83     }
       
    84     
       
    85     flattenWithTransform(*m_accumulatedTransform);
       
    86 }
       
    87 
       
    88 FloatPoint TransformState::mappedPoint() const
       
    89 {
       
    90     if (!m_accumulatedTransform)
       
    91         return m_lastPlanarPoint;
       
    92 
       
    93     if (m_direction == ApplyTransformDirection)
       
    94         return m_accumulatedTransform->mapPoint(m_lastPlanarPoint);
       
    95 
       
    96     return m_accumulatedTransform->inverse().projectPoint(m_lastPlanarPoint);
       
    97 }
       
    98 
       
    99 FloatQuad TransformState::mappedQuad() const
       
   100 {
       
   101     if (!m_accumulatedTransform)
       
   102         return m_lastPlanarQuad;
       
   103 
       
   104     if (m_direction == ApplyTransformDirection)
       
   105         return m_accumulatedTransform->mapQuad(m_lastPlanarQuad);
       
   106 
       
   107     return m_accumulatedTransform->inverse().projectQuad(m_lastPlanarQuad);
       
   108 }
       
   109 
       
   110 void TransformState::flattenWithTransform(const TransformationMatrix& t)
       
   111 {
       
   112     if (m_direction == ApplyTransformDirection) {
       
   113         m_lastPlanarPoint = t.mapPoint(m_lastPlanarPoint);
       
   114         if (m_mapQuad)
       
   115             m_lastPlanarQuad = t.mapQuad(m_lastPlanarQuad);
       
   116     } else {
       
   117         TransformationMatrix inverseTransform = t.inverse();
       
   118         m_lastPlanarPoint = inverseTransform.projectPoint(m_lastPlanarPoint);
       
   119         if (m_mapQuad)
       
   120             m_lastPlanarQuad = inverseTransform.projectQuad(m_lastPlanarQuad);
       
   121     }
       
   122 
       
   123     // We could throw away m_accumulatedTransform if we wanted to here, but that
       
   124     // would cause thrash when traversing hierarchies with alternating
       
   125     // preserve-3d and flat elements.
       
   126     if (m_accumulatedTransform)
       
   127         m_accumulatedTransform->makeIdentity();
       
   128     m_accumulatingTransform = false;
       
   129 }
       
   130 
       
   131 // HitTestingTransformState methods
       
   132 void HitTestingTransformState::translate(int x, int y, TransformAccumulation accumulate)
       
   133 {
       
   134     m_accumulatedTransform.translate(x, y);    
       
   135     if (accumulate == FlattenTransform)
       
   136         flattenWithTransform(m_accumulatedTransform);
       
   137 
       
   138     m_accumulatingTransform = accumulate == AccumulateTransform;
       
   139 }
       
   140 
       
   141 void HitTestingTransformState::applyTransform(const TransformationMatrix& transformFromContainer, TransformAccumulation accumulate)
       
   142 {
       
   143     m_accumulatedTransform.multLeft(transformFromContainer);    
       
   144     if (accumulate == FlattenTransform)
       
   145         flattenWithTransform(m_accumulatedTransform);
       
   146 
       
   147     m_accumulatingTransform = accumulate == AccumulateTransform;
       
   148 }
       
   149 
       
   150 void HitTestingTransformState::flatten()
       
   151 {
       
   152     flattenWithTransform(m_accumulatedTransform);
       
   153 }
       
   154 
       
   155 void HitTestingTransformState::flattenWithTransform(const TransformationMatrix& t)
       
   156 {
       
   157     TransformationMatrix inverseTransform = t.inverse();
       
   158     m_lastPlanarPoint = inverseTransform.projectPoint(m_lastPlanarPoint);
       
   159     m_lastPlanarQuad = inverseTransform.projectQuad(m_lastPlanarQuad);
       
   160 
       
   161     m_accumulatedTransform.makeIdentity();
       
   162     m_accumulatingTransform = false;
       
   163 }
       
   164 
       
   165 FloatPoint HitTestingTransformState::mappedPoint() const
       
   166 {
       
   167     return m_accumulatedTransform.inverse().projectPoint(m_lastPlanarPoint);
       
   168 }
       
   169 
       
   170 FloatQuad HitTestingTransformState::mappedQuad() const
       
   171 {
       
   172     return m_accumulatedTransform.inverse().projectQuad(m_lastPlanarQuad);
       
   173 }
       
   174 
       
   175 } // namespace WebCore