• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
insert(const AnimationValue * value)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 
GraphicsLayer(GraphicsLayerClient * client)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 
~GraphicsLayer()81 GraphicsLayer::~GraphicsLayer()
82 {
83     removeAllChildren();
84     removeFromParent();
85 }
86 
hasAncestor(GraphicsLayer * ancestor) const87 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 
setChildren(const Vector<GraphicsLayer * > & newChildren)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 
addChild(GraphicsLayer * childLayer)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 
addChildAtIndex(GraphicsLayer * childLayer,int index)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 
addChildBelow(GraphicsLayer * childLayer,GraphicsLayer * sibling)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 
addChildAbove(GraphicsLayer * childLayer,GraphicsLayer * sibling)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 
replaceChild(GraphicsLayer * oldChild,GraphicsLayer * newChild)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 
removeAllChildren()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 
removeFromParent()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 
setReplicatedByLayer(GraphicsLayer * layer)219 void GraphicsLayer::setReplicatedByLayer(GraphicsLayer* layer)
220 {
221     if (layer)
222         layer->setReplicatedLayer(this);
223 
224     m_replicaLayer = layer;
225 }
226 
setBackgroundColor(const Color & color)227 void GraphicsLayer::setBackgroundColor(const Color& color)
228 {
229     m_backgroundColor = color;
230     m_backgroundColorSet = true;
231 }
232 
clearBackgroundColor()233 void GraphicsLayer::clearBackgroundColor()
234 {
235     m_backgroundColor = Color();
236     m_backgroundColorSet = false;
237 }
238 
paintGraphicsLayerContents(GraphicsContext & context,const IntRect & clip)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 
suspendAnimations(double)245 void GraphicsLayer::suspendAnimations(double)
246 {
247 }
248 
resumeAnimations()249 void GraphicsLayer::resumeAnimations()
250 {
251 }
252 
updateDebugIndicators()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 
setZPosition(float position)270 void GraphicsLayer::setZPosition(float position)
271 {
272     m_zPosition = position;
273 }
274 
accumulatedOpacity() const275 float GraphicsLayer::accumulatedOpacity() const
276 {
277     if (!preserves3D())
278         return 1;
279 
280     return m_opacity * (parent() ? parent()->accumulatedOpacity() : 1);
281 }
282 
distributeOpacity(float accumulatedOpacity)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 
operationsAt(const KeyframeValueList & valueList,size_t index)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 
fetchTransformOperationList(const KeyframeValueList & valueList,TransformOperationList & list,bool & isValid,bool & hasBigRotation)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 
writeIndent(TextStream & ts,int indent)385 static void writeIndent(TextStream& ts, int indent)
386 {
387     for (int i = 0; i != indent; ++i)
388         ts << "  ";
389 }
390 
dumpLayer(TextStream & ts,int indent) const391 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 
dumpProperties(TextStream & ts,int indent) const401 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