Home | History | Annotate | Download | only in graphics
      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 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 
     28 #if USE(ACCELERATED_COMPOSITING)
     29 
     30 #include "GraphicsLayer.h"
     31 
     32 #include "FloatPoint.h"
     33 #include "RotateTransformOperation.h"
     34 #include "TextStream.h"
     35 
     36 namespace WebCore {
     37 
     38 void KeyframeValueList::insert(const AnimationValue* value)
     39 {
     40     for (size_t i = 0; i < m_values.size(); ++i) {
     41         const AnimationValue* curValue = m_values[i];
     42         if (curValue->keyTime() == value->keyTime()) {
     43             ASSERT_NOT_REACHED();
     44             // insert after
     45             m_values.insert(i + 1, value);
     46             return;
     47         }
     48         if (curValue->keyTime() > value->keyTime()) {
     49             // insert before
     50             m_values.insert(i, value);
     51             return;
     52         }
     53     }
     54 
     55     m_values.append(value);
     56 }
     57 
     58 GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client)
     59     : m_client(client)
     60     , m_anchorPoint(0.5f, 0.5f, 0)
     61     , m_opacity(1)
     62     , m_zPosition(0)
     63     , m_backgroundColorSet(false)
     64     , m_contentsOpaque(false)
     65     , m_preserves3D(false)
     66     , m_backfaceVisibility(true)
     67     , m_usingTiledLayer(false)
     68     , m_masksToBounds(false)
     69     , m_drawsContent(false)
     70     , m_paintingPhase(GraphicsLayerPaintAll)
     71     , m_geometryOrientation(CompositingCoordinatesTopDown)
     72     , m_contentsOrientation(CompositingCoordinatesTopDown)
     73     , m_parent(0)
     74     , m_maskLayer(0)
     75     , m_replicaLayer(0)
     76     , m_replicatedLayer(0)
     77     , m_repaintCount(0)
     78 {
     79 }
     80 
     81 GraphicsLayer::~GraphicsLayer()
     82 {
     83     removeAllChildren();
     84     removeFromParent();
     85 }
     86 
     87 bool GraphicsLayer::hasAncestor(GraphicsLayer* ancestor) const
     88 {
     89     for (GraphicsLayer* curr = parent(); curr; curr = curr->parent()) {
     90         if (curr == ancestor)
     91             return true;
     92     }
     93 
     94     return false;
     95 }
     96 
     97 bool GraphicsLayer::setChildren(const Vector<GraphicsLayer*>& newChildren)
     98 {
     99     // If the contents of the arrays are the same, nothing to do.
    100     if (newChildren == m_children)
    101         return false;
    102 
    103     removeAllChildren();
    104 
    105     size_t listSize = newChildren.size();
    106     for (size_t i = 0; i < listSize; ++i)
    107         addChild(newChildren[i]);
    108 
    109     return true;
    110 }
    111 
    112 void GraphicsLayer::addChild(GraphicsLayer* childLayer)
    113 {
    114     ASSERT(childLayer != this);
    115 
    116     if (childLayer->parent())
    117         childLayer->removeFromParent();
    118 
    119     childLayer->setParent(this);
    120     m_children.append(childLayer);
    121 }
    122 
    123 void GraphicsLayer::addChildAtIndex(GraphicsLayer* childLayer, int index)
    124 {
    125     ASSERT(childLayer != this);
    126 
    127     if (childLayer->parent())
    128         childLayer->removeFromParent();
    129 
    130     childLayer->setParent(this);
    131     m_children.insert(index, childLayer);
    132 }
    133 
    134 void GraphicsLayer::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
    135 {
    136     ASSERT(childLayer != this);
    137     childLayer->removeFromParent();
    138 
    139     bool found = false;
    140     for (unsigned i = 0; i < m_children.size(); i++) {
    141         if (sibling == m_children[i]) {
    142             m_children.insert(i, childLayer);
    143             found = true;
    144             break;
    145         }
    146     }
    147 
    148     childLayer->setParent(this);
    149 
    150     if (!found)
    151         m_children.append(childLayer);
    152 }
    153 
    154 void GraphicsLayer::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
    155 {
    156     childLayer->removeFromParent();
    157     ASSERT(childLayer != this);
    158 
    159     bool found = false;
    160     for (unsigned i = 0; i < m_children.size(); i++) {
    161         if (sibling == m_children[i]) {
    162             m_children.insert(i+1, childLayer);
    163             found = true;
    164             break;
    165         }
    166     }
    167 
    168     childLayer->setParent(this);
    169 
    170     if (!found)
    171         m_children.append(childLayer);
    172 }
    173 
    174 bool GraphicsLayer::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
    175 {
    176     ASSERT(!newChild->parent());
    177     bool found = false;
    178     for (unsigned i = 0; i < m_children.size(); i++) {
    179         if (oldChild == m_children[i]) {
    180             m_children[i] = newChild;
    181             found = true;
    182             break;
    183         }
    184     }
    185     if (found) {
    186         oldChild->setParent(0);
    187 
    188         newChild->removeFromParent();
    189         newChild->setParent(this);
    190         return true;
    191     }
    192     return false;
    193 }
    194 
    195 void GraphicsLayer::removeAllChildren()
    196 {
    197     while (m_children.size()) {
    198         GraphicsLayer* curLayer = m_children[0];
    199         ASSERT(curLayer->parent());
    200         curLayer->removeFromParent();
    201     }
    202 }
    203 
    204 void GraphicsLayer::removeFromParent()
    205 {
    206     if (m_parent) {
    207         unsigned i;
    208         for (i = 0; i < m_parent->m_children.size(); i++) {
    209             if (this == m_parent->m_children[i]) {
    210                 m_parent->m_children.remove(i);
    211                 break;
    212             }
    213         }
    214 
    215         setParent(0);
    216     }
    217 }
    218 
    219 void GraphicsLayer::setReplicatedByLayer(GraphicsLayer* layer)
    220 {
    221     if (layer)
    222         layer->setReplicatedLayer(this);
    223 
    224     m_replicaLayer = layer;
    225 }
    226 
    227 void GraphicsLayer::setBackgroundColor(const Color& color)
    228 {
    229     m_backgroundColor = color;
    230     m_backgroundColorSet = true;
    231 }
    232 
    233 void GraphicsLayer::clearBackgroundColor()
    234 {
    235     m_backgroundColor = Color();
    236     m_backgroundColorSet = false;
    237 }
    238 
    239 void GraphicsLayer::paintGraphicsLayerContents(GraphicsContext& context, const IntRect& clip)
    240 {
    241     if (m_client)
    242         m_client->paintContents(this, context, m_paintingPhase, clip);
    243 }
    244 
    245 void GraphicsLayer::suspendAnimations(double)
    246 {
    247 }
    248 
    249 void GraphicsLayer::resumeAnimations()
    250 {
    251 }
    252 
    253 void GraphicsLayer::updateDebugIndicators()
    254 {
    255     if (GraphicsLayer::showDebugBorders()) {
    256         if (drawsContent()) {
    257             if (m_usingTiledLayer)
    258                 setDebugBorder(Color(0, 255, 0, 204), 2.0f);    // tiled layer: green
    259             else
    260                 setDebugBorder(Color(255, 0, 0, 204), 2.0f);    // normal layer: red
    261         } else if (masksToBounds()) {
    262             setDebugBorder(Color(128, 255, 255, 178), 2.0f);    // masking layer: pale blue
    263             if (GraphicsLayer::showDebugBorders())
    264                 setDebugBackgroundColor(Color(128, 255, 255, 52));
    265         } else
    266             setDebugBorder(Color(255, 255, 0, 204), 2.0f);      // container: yellow
    267     }
    268 }
    269 
    270 void GraphicsLayer::setZPosition(float position)
    271 {
    272     m_zPosition = position;
    273 }
    274 
    275 float GraphicsLayer::accumulatedOpacity() const
    276 {
    277     if (!preserves3D())
    278         return 1;
    279 
    280     return m_opacity * (parent() ? parent()->accumulatedOpacity() : 1);
    281 }
    282 
    283 void GraphicsLayer::distributeOpacity(float accumulatedOpacity)
    284 {
    285     // If this is a transform layer we need to distribute our opacity to all our children
    286 
    287     // Incoming accumulatedOpacity is the contribution from our parent(s). We mutiply this by our own
    288     // opacity to get the total contribution
    289     accumulatedOpacity *= m_opacity;
    290 
    291     setOpacityInternal(accumulatedOpacity);
    292 
    293     if (preserves3D()) {
    294         size_t numChildren = children().size();
    295         for (size_t i = 0; i < numChildren; ++i)
    296             children()[i]->distributeOpacity(accumulatedOpacity);
    297     }
    298 }
    299 
    300 // An "invalid" list is one whose functions don't match, and therefore has to be animated as a Matrix
    301 // The hasBigRotation flag will always return false if isValid is false. Otherwise hasBigRotation is
    302 // true if the rotation between any two keyframes is >= 180 degrees.
    303 
    304 static inline const TransformOperations* operationsAt(const KeyframeValueList& valueList, size_t index)
    305 {
    306     return static_cast<const TransformAnimationValue*>(valueList.at(index))->value();
    307 }
    308 
    309 void GraphicsLayer::fetchTransformOperationList(const KeyframeValueList& valueList, TransformOperationList& list, bool& isValid, bool& hasBigRotation)
    310 {
    311     ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
    312 
    313     list.clear();
    314     isValid = false;
    315     hasBigRotation = false;
    316 
    317     if (valueList.size() < 2)
    318         return;
    319 
    320     // Empty transforms match anything, so find the first non-empty entry as the reference.
    321     size_t firstIndex = 0;
    322     for ( ; firstIndex < valueList.size(); ++firstIndex) {
    323         if (operationsAt(valueList, firstIndex)->operations().size() > 0)
    324             break;
    325     }
    326 
    327     if (firstIndex >= valueList.size())
    328         return;
    329 
    330     const TransformOperations* firstVal = operationsAt(valueList, firstIndex);
    331 
    332     // See if the keyframes are valid.
    333     for (size_t i = firstIndex + 1; i < valueList.size(); ++i) {
    334         const TransformOperations* val = operationsAt(valueList, i);
    335 
    336         // a null transform matches anything
    337         if (val->operations().isEmpty())
    338             continue;
    339 
    340         if (firstVal->operations().size() != val->operations().size())
    341             return;
    342 
    343         for (size_t j = 0; j < firstVal->operations().size(); ++j) {
    344             if (!firstVal->operations().at(j)->isSameType(*val->operations().at(j)))
    345                 return;
    346         }
    347     }
    348 
    349     // Keyframes are valid, fill in the list.
    350     isValid = true;
    351 
    352     double lastRotAngle = 0.0;
    353     double maxRotAngle = -1.0;
    354 
    355     list.resize(firstVal->operations().size());
    356     for (size_t j = 0; j < firstVal->operations().size(); ++j) {
    357         TransformOperation::OperationType type = firstVal->operations().at(j)->getOperationType();
    358         list[j] = type;
    359 
    360         // if this is a rotation entry, we need to see if any angle differences are >= 180 deg
    361         if (type == TransformOperation::ROTATE_X ||
    362             type == TransformOperation::ROTATE_Y ||
    363             type == TransformOperation::ROTATE_Z ||
    364             type == TransformOperation::ROTATE_3D) {
    365             lastRotAngle = static_cast<RotateTransformOperation*>(firstVal->operations().at(j).get())->angle();
    366 
    367             if (maxRotAngle < 0)
    368                 maxRotAngle = fabs(lastRotAngle);
    369 
    370             for (size_t i = firstIndex + 1; i < valueList.size(); ++i) {
    371                 const TransformOperations* val = operationsAt(valueList, i);
    372                 double rotAngle = val->operations().isEmpty() ? 0 : (static_cast<RotateTransformOperation*>(val->operations().at(j).get())->angle());
    373                 double diffAngle = fabs(rotAngle - lastRotAngle);
    374                 if (diffAngle > maxRotAngle)
    375                     maxRotAngle = diffAngle;
    376                 lastRotAngle = rotAngle;
    377             }
    378         }
    379     }
    380 
    381     hasBigRotation = maxRotAngle >= 180.0;
    382 }
    383 
    384 
    385 static void writeIndent(TextStream& ts, int indent)
    386 {
    387     for (int i = 0; i != indent; ++i)
    388         ts << "  ";
    389 }
    390 
    391 void GraphicsLayer::dumpLayer(TextStream& ts, int indent) const
    392 {
    393     writeIndent(ts, indent);
    394     ts << "(" << "GraphicsLayer" << " " << static_cast<void*>(const_cast<GraphicsLayer*>(this));
    395     ts << " \"" << m_name << "\"\n";
    396     dumpProperties(ts, indent);
    397     writeIndent(ts, indent);
    398     ts << ")\n";
    399 }
    400 
    401 void GraphicsLayer::dumpProperties(TextStream& ts, int indent) const
    402 {
    403     writeIndent(ts, indent + 1);
    404     ts << "(position " << m_position.x() << " " << m_position.y() << ")\n";
    405 
    406     writeIndent(ts, indent + 1);
    407     ts << "(anchor " << m_anchorPoint.x() << " " << m_anchorPoint.y() << ")\n";
    408 
    409     writeIndent(ts, indent + 1);
    410     ts << "(bounds " << m_size.width() << " " << m_size.height() << ")\n";
    411 
    412     writeIndent(ts, indent + 1);
    413     ts << "(opacity " << m_opacity << ")\n";
    414 
    415     writeIndent(ts, indent + 1);
    416     ts << "(usingTiledLayer " << m_usingTiledLayer << ")\n";
    417 
    418     writeIndent(ts, indent + 1);
    419     ts << "(m_preserves3D " << m_preserves3D << ")\n";
    420 
    421     writeIndent(ts, indent + 1);
    422     ts << "(drawsContent " << m_drawsContent << ")\n";
    423 
    424     writeIndent(ts, indent + 1);
    425     ts << "(m_backfaceVisibility " << (m_backfaceVisibility ? "visible" : "hidden") << ")\n";
    426 
    427     writeIndent(ts, indent + 1);
    428     ts << "(client ";
    429     if (m_client)
    430         ts << static_cast<void*>(m_client);
    431     else
    432         ts << "none";
    433     ts << ")\n";
    434 
    435     writeIndent(ts, indent + 1);
    436     ts << "(backgroundColor ";
    437     if (!m_backgroundColorSet)
    438         ts << "none";
    439     else
    440         ts << m_backgroundColor.name();
    441     ts << ")\n";
    442 
    443     writeIndent(ts, indent + 1);
    444     ts << "(transform ";
    445     if (m_transform.isIdentity())
    446         ts << "identity";
    447     else {
    448         ts << "[" << m_transform.m11() << " " << m_transform.m12() << " " << m_transform.m13() << " " << m_transform.m14() << "] ";
    449         ts << "[" << m_transform.m21() << " " << m_transform.m22() << " " << m_transform.m23() << " " << m_transform.m24() << "] ";
    450         ts << "[" << m_transform.m31() << " " << m_transform.m32() << " " << m_transform.m33() << " " << m_transform.m34() << "] ";
    451         ts << "[" << m_transform.m41() << " " << m_transform.m42() << " " << m_transform.m43() << " " << m_transform.m44() << "]";
    452     }
    453     ts << ")\n";
    454 
    455     writeIndent(ts, indent + 1);
    456     ts << "(childrenTransform ";
    457     if (m_childrenTransform.isIdentity())
    458         ts << "identity";
    459     else {
    460         ts << "[" << m_childrenTransform.m11() << " " << m_childrenTransform.m12() << " " << m_childrenTransform.m13() << " " << m_childrenTransform.m14() << "] ";
    461         ts << "[" << m_childrenTransform.m21() << " " << m_childrenTransform.m22() << " " << m_childrenTransform.m23() << " " << m_childrenTransform.m24() << "] ";
    462         ts << "[" << m_childrenTransform.m31() << " " << m_childrenTransform.m32() << " " << m_childrenTransform.m33() << " " << m_childrenTransform.m34() << "] ";
    463         ts << "[" << m_childrenTransform.m41() << " " << m_childrenTransform.m42() << " " << m_childrenTransform.m43() << " " << m_childrenTransform.m44() << "]";
    464     }
    465     ts << ")\n";
    466 
    467     if (m_replicaLayer) {
    468         writeIndent(ts, indent + 1);
    469         ts << "(replica layer " << m_replicaLayer << ")\n";
    470         m_replicaLayer->dumpLayer(ts, indent+2);
    471     }
    472 
    473     if (m_replicatedLayer) {
    474         writeIndent(ts, indent + 1);
    475         ts << "(replicated layer " << m_replicatedLayer << ")\n";
    476     }
    477 
    478     if (m_children.size()) {
    479         writeIndent(ts, indent + 1);
    480         ts << "(children " << m_children.size() << "\n";
    481 
    482         unsigned i;
    483         for (i = 0; i < m_children.size(); i++)
    484             m_children[i]->dumpLayer(ts, indent+2);
    485         writeIndent(ts, indent + 1);
    486         ts << ")\n";
    487     }
    488 }
    489 
    490 } // namespace WebCore
    491 
    492 #endif // USE(ACCELERATED_COMPOSITING)
    493