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