b7c5c0b890679a6ac50f4f6e60d94c5bd2f032eb
[WebKit-https.git] / Source / WebCore / platform / graphics / texmap / TextureMapperLayer.cpp
1 /*
2  Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
3
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  Library General Public License for more details.
13
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB.  If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21 #include "TextureMapperLayer.h"
22
23 #include "FloatQuad.h"
24 #include "Region.h"
25 #include <wtf/MathExtras.h>
26
27 #if USE(ACCELERATED_COMPOSITING)
28
29 namespace WebCore {
30
31 class TextureMapperPaintOptions {
32 public:
33     RefPtr<BitmapTexture> surface;
34     float opacity;
35     TransformationMatrix transform;
36     IntSize offset;
37     TextureMapper* textureMapper;
38     TextureMapperPaintOptions()
39         : opacity(1)
40         , textureMapper(0)
41     { }
42 };
43
44 const TextureMapperLayer* TextureMapperLayer::rootLayer() const
45 {
46     if (m_effectTarget)
47         return m_effectTarget->rootLayer();
48     if (m_parent)
49         return m_parent->rootLayer();
50     return this;
51 }
52
53 void TextureMapperLayer::computeTransformsRecursive()
54 {
55     if (m_state.size.isEmpty() && m_state.masksToBounds)
56         return;
57
58     // Compute transforms recursively on the way down to leafs.
59     TransformationMatrix parentTransform;
60     if (m_parent)
61         parentTransform = m_parent->m_currentTransform.combinedForChildren();
62     else if (m_effectTarget)
63         parentTransform = m_effectTarget->m_currentTransform.combined();
64     m_currentTransform.combineTransforms(parentTransform);
65
66     m_state.visible = m_state.backfaceVisibility || !m_currentTransform.combined().isBackFaceVisible();
67
68     if (m_parent && m_parent->m_state.preserves3D)
69         m_centerZ = m_currentTransform.combined().mapPoint(FloatPoint3D(m_state.size.width() / 2, m_state.size.height() / 2, 0)).z();
70
71     if (m_state.maskLayer)
72         m_state.maskLayer->computeTransformsRecursive();
73     if (m_state.replicaLayer)
74         m_state.replicaLayer->computeTransformsRecursive();
75     for (size_t i = 0; i < m_children.size(); ++i)
76         m_children[i]->computeTransformsRecursive();
77
78     // Reorder children if needed on the way back up.
79     if (m_state.preserves3D)
80         sortByZOrder(m_children);
81 }
82
83 void TextureMapperLayer::paint()
84 {
85     computeTransformsRecursive();
86
87     TextureMapperPaintOptions options;
88     options.textureMapper = m_textureMapper;
89     options.textureMapper->bindSurface(0);
90     paintRecursive(options);
91 }
92
93 static Color blendWithOpacity(const Color& color, float opacity)
94 {
95     RGBA32 rgba = color.rgb();
96     // See Color::getRGBA() to know how to extract alpha from color.
97     float alpha = alphaChannel(rgba) / 255.;
98     float effectiveAlpha = alpha * opacity;
99     return Color(colorWithOverrideAlpha(rgba, effectiveAlpha));
100 }
101
102 void TextureMapperLayer::paintSelf(const TextureMapperPaintOptions& options)
103 {
104     if (!m_state.visible || !m_state.contentsVisible)
105         return;
106
107     // We apply the following transform to compensate for painting into a surface, and then apply the offset so that the painting fits in the target rect.
108     TransformationMatrix transform;
109     transform.translate(options.offset.width(), options.offset.height());
110     transform.multiply(options.transform);
111     transform.multiply(m_currentTransform.combined());
112
113     if (m_state.solidColor.isValid() && !m_state.contentsRect.isEmpty()) {
114         options.textureMapper->drawSolidColor(m_state.contentsRect, transform, blendWithOpacity(m_state.solidColor, options.opacity));
115         if (m_state.showDebugBorders)
116             options.textureMapper->drawBorder(m_state.debugBorderColor, m_state.debugBorderWidth, layerRect(), transform);
117         return;
118     }
119
120     if (m_backingStore) {
121         ASSERT(m_state.drawsContent && m_state.contentsVisible && !m_state.size.isEmpty());
122         ASSERT(!layerRect().isEmpty());
123         m_backingStore->paintToTextureMapper(options.textureMapper, layerRect(), transform, options.opacity);
124         if (m_state.showDebugBorders)
125             m_backingStore->drawBorder(options.textureMapper, m_state.debugBorderColor, m_state.debugBorderWidth, layerRect(), transform);
126         // Only draw repaint count for the main backing store.
127         if (m_state.showRepaintCounter)
128             m_backingStore->drawRepaintCounter(options.textureMapper, m_state.repaintCount, m_state.debugBorderColor, layerRect(), transform);
129     }
130
131     if (m_contentsLayer) {
132         ASSERT(!layerRect().isEmpty());
133         m_contentsLayer->paintToTextureMapper(options.textureMapper, m_state.contentsRect, transform, options.opacity);
134         if (m_state.showDebugBorders)
135             m_contentsLayer->drawBorder(options.textureMapper, m_state.debugBorderColor, m_state.debugBorderWidth, m_state.contentsRect, transform);
136     }
137 }
138
139 int TextureMapperLayer::compareGraphicsLayersZValue(const void* a, const void* b)
140 {
141     TextureMapperLayer* const* layerA = static_cast<TextureMapperLayer* const*>(a);
142     TextureMapperLayer* const* layerB = static_cast<TextureMapperLayer* const*>(b);
143     return int(((*layerA)->m_centerZ - (*layerB)->m_centerZ) * 1000);
144 }
145
146 void TextureMapperLayer::sortByZOrder(Vector<TextureMapperLayer* >& array)
147 {
148     qsort(array.data(), array.size(), sizeof(TextureMapperLayer*), compareGraphicsLayersZValue);
149 }
150
151 void TextureMapperLayer::paintSelfAndChildren(const TextureMapperPaintOptions& options)
152 {
153     paintSelf(options);
154
155     if (m_children.isEmpty())
156         return;
157
158     bool shouldClip = m_state.masksToBounds && !m_state.preserves3D;
159     if (shouldClip) {
160         TransformationMatrix clipTransform;
161         clipTransform.translate(options.offset.width(), options.offset.height());
162         clipTransform.multiply(options.transform);
163         clipTransform.multiply(m_currentTransform.combined());
164         options.textureMapper->beginClip(clipTransform, layerRect());
165     }
166
167     for (size_t i = 0; i < m_children.size(); ++i)
168         m_children[i]->paintRecursive(options);
169
170     if (shouldClip)
171         options.textureMapper->endClip();
172 }
173
174 bool TextureMapperLayer::shouldBlend() const
175 {
176     if (m_state.preserves3D)
177         return false;
178
179 #if ENABLE(CSS_FILTERS)
180     if (m_currentFilters.size())
181         return true;
182 #endif
183     return m_currentOpacity < 1 || m_state.maskLayer || (m_state.replicaLayer && m_state.replicaLayer->m_state.maskLayer);
184 }
185
186 bool TextureMapperLayer::isVisible() const
187 {
188     if (m_state.size.isEmpty() && (m_state.masksToBounds || m_state.maskLayer || m_children.isEmpty()))
189         return false;
190     if (!m_state.visible && m_children.isEmpty())
191         return false;
192     if (!m_state.contentsVisible && m_children.isEmpty())
193         return false;
194     if (m_currentOpacity < 0.01)
195         return false;
196     return true;
197 }
198
199 void TextureMapperLayer::paintSelfAndChildrenWithReplica(const TextureMapperPaintOptions& options)
200 {
201     if (m_state.replicaLayer) {
202         TextureMapperPaintOptions replicaOptions(options);
203         replicaOptions.transform
204             .multiply(m_state.replicaLayer->m_currentTransform.combined())
205             .multiply(m_currentTransform.combined().inverse());
206         paintSelfAndChildren(replicaOptions);
207     }
208
209     paintSelfAndChildren(options);
210 }
211
212 void TextureMapperLayer::setAnimatedTransform(const TransformationMatrix& matrix)
213 {
214     m_currentTransform.setLocalTransform(matrix);
215 }
216
217 void TextureMapperLayer::setAnimatedOpacity(float opacity)
218 {
219     m_currentOpacity = opacity;
220 }
221
222 TransformationMatrix TextureMapperLayer::replicaTransform()
223 {
224     return TransformationMatrix(m_state.replicaLayer->m_currentTransform.combined()).multiply(m_currentTransform.combined().inverse());
225 }
226
227 #if ENABLE(CSS_FILTERS)
228 void TextureMapperLayer::setAnimatedFilters(const FilterOperations& filters)
229 {
230     m_currentFilters = filters;
231 }
232
233 static bool shouldKeepContentTexture(const FilterOperations& filters)
234 {
235     for (size_t i = 0; i < filters.size(); ++i) {
236         switch (filters.operations().at(i)->getOperationType()) {
237         // The drop-shadow filter requires the content texture, because it needs to composite it
238         // on top of the blurred shadow color.
239         case FilterOperation::DROP_SHADOW:
240             return true;
241         default:
242             break;
243         }
244     }
245
246     return false;
247 }
248
249 static PassRefPtr<BitmapTexture> applyFilters(const FilterOperations& filters, TextureMapper* textureMapper, BitmapTexture* source)
250 {
251     if (!filters.size())
252         return source;
253
254     RefPtr<BitmapTexture> filterSurface = shouldKeepContentTexture(filters) ? textureMapper->acquireTextureFromPool(source->size()) : source;
255     return filterSurface->applyFilters(textureMapper, *source, filters);
256 }
257 #endif
258
259 static void resolveOverlaps(Region newRegion, Region& overlapRegion, Region& nonOverlapRegion)
260 {
261     Region newOverlapRegion(newRegion);
262     newOverlapRegion.intersect(nonOverlapRegion);
263     nonOverlapRegion.subtract(newOverlapRegion);
264     overlapRegion.unite(newOverlapRegion);
265     newRegion.subtract(overlapRegion);
266     nonOverlapRegion.unite(newRegion);
267 }
268
269 void TextureMapperLayer::computeOverlapRegions(Region& overlapRegion, Region& nonOverlapRegion, ResolveSelfOverlapMode mode)
270 {
271     if (!m_state.visible || !m_state.contentsVisible)
272         return;
273
274     FloatRect boundingRect;
275     if (m_backingStore || m_state.masksToBounds || m_state.maskLayer || hasFilters())
276         boundingRect = layerRect();
277     else if (m_contentsLayer || m_state.solidColor.alpha())
278         boundingRect = m_state.contentsRect;
279
280 #if ENABLE(CSS_FILTERS)
281     if (m_currentFilters.hasOutsets()) {
282         FilterOutsets outsets = m_currentFilters.outsets();
283         IntRect unfilteredTargetRect(boundingRect);
284         boundingRect.move(std::max(0, -outsets.left()), std::max(0, -outsets.top()));
285         boundingRect.expand(outsets.left() + outsets.right(), outsets.top() + outsets.bottom());
286         boundingRect.unite(unfilteredTargetRect);
287     }
288 #endif
289
290     TransformationMatrix replicaMatrix;
291     if (m_state.replicaLayer) {
292         replicaMatrix = replicaTransform();
293         boundingRect.unite(replicaMatrix.mapRect(boundingRect));
294     }
295
296     boundingRect = m_currentTransform.combined().mapRect(boundingRect);
297
298     // Count all masks and filters as overlap layers.
299     if (hasFilters() || m_state.maskLayer || (m_state.replicaLayer && m_state.replicaLayer->m_state.maskLayer)) {
300         Region newOverlapRegion(enclosingIntRect(boundingRect));
301         nonOverlapRegion.subtract(newOverlapRegion);
302         overlapRegion.unite(newOverlapRegion);
303         return;
304     }
305
306     Region newOverlapRegion;
307     Region newNonOverlapRegion(enclosingIntRect(boundingRect));
308
309     if (!m_state.masksToBounds) {
310         for (size_t i = 0; i < m_children.size(); ++i) {
311             TextureMapperLayer* child = m_children[i];
312             child->computeOverlapRegions(newOverlapRegion, newNonOverlapRegion, ResolveSelfOverlapIfNeeded);
313         }
314     }
315
316     if (m_state.replicaLayer) {
317         newOverlapRegion.unite(replicaMatrix.mapRect(newOverlapRegion.bounds()));
318         Region replicaRegion(replicaMatrix.mapRect(newNonOverlapRegion.bounds()));
319         resolveOverlaps(replicaRegion, newOverlapRegion, newNonOverlapRegion);
320     }
321
322     if ((mode != ResolveSelfOverlapAlways) && shouldBlend()) {
323         newNonOverlapRegion.unite(newOverlapRegion);
324         newOverlapRegion = Region();
325     }
326
327     overlapRegion.unite(newOverlapRegion);
328     resolveOverlaps(newNonOverlapRegion, overlapRegion, nonOverlapRegion);
329 }
330
331 void TextureMapperLayer::paintUsingOverlapRegions(const TextureMapperPaintOptions& options)
332 {
333     Region overlapRegion;
334     Region nonOverlapRegion;
335     computeOverlapRegions(overlapRegion, nonOverlapRegion, ResolveSelfOverlapAlways);
336     if (overlapRegion.isEmpty()) {
337         paintSelfAndChildrenWithReplica(options);
338         return;
339     }
340
341     Vector<IntRect> rects;
342
343     nonOverlapRegion.translate(options.offset);
344     rects = nonOverlapRegion.rects();
345     for (size_t i = 0; i < rects.size(); ++i) {
346         options.textureMapper->beginClip(TransformationMatrix(), rects[i]);
347         paintSelfAndChildrenWithReplica(options);
348         options.textureMapper->endClip();
349     }
350
351     rects = overlapRegion.rects();
352     IntSize maxTextureSize = options.textureMapper->maxTextureSize();
353     IntRect rect;
354     for (size_t i = 0; i < rects.size(); ++i) {
355         rect = rects[i];
356         for (int x = rect.x(); x < rect.maxX(); x += maxTextureSize.width()) {
357             for (int y = rect.y(); y < rect.maxY(); y += maxTextureSize.height()) {
358                 IntRect tileRect(IntPoint(x, y), maxTextureSize);
359                 tileRect.intersect(rect);
360                 paintWithIntermediateSurface(options, tileRect);
361             }
362         }
363     }
364 }
365
366 void TextureMapperLayer::applyMask(const TextureMapperPaintOptions& options)
367 {
368     options.textureMapper->setMaskMode(true);
369     paintSelf(options);
370     options.textureMapper->setMaskMode(false);
371 }
372
373 PassRefPtr<BitmapTexture> TextureMapperLayer::paintIntoSurface(const TextureMapperPaintOptions& options, const IntSize& size)
374 {
375     RefPtr<BitmapTexture> surface = options.textureMapper->acquireTextureFromPool(size);
376     TextureMapperPaintOptions paintOptions(options);
377     paintOptions.surface = surface;
378     options.textureMapper->bindSurface(surface.get());
379     paintSelfAndChildren(paintOptions);
380     if (m_state.maskLayer)
381         m_state.maskLayer->applyMask(options);
382 #if ENABLE(CSS_FILTERS)
383     if (!m_currentFilters.isEmpty())
384         surface = applyFilters(m_currentFilters, options.textureMapper, surface.get());
385 #endif
386     options.textureMapper->bindSurface(surface.get());
387     return surface;
388 }
389
390 static void commitSurface(const TextureMapperPaintOptions& options, PassRefPtr<BitmapTexture> surface, const IntRect& rect, float opacity)
391 {
392     options.textureMapper->bindSurface(options.surface.get());
393     TransformationMatrix targetTransform;
394     targetTransform.translate(options.offset.width(), options.offset.height());
395     targetTransform.multiply(options.transform);
396     options.textureMapper->drawTexture(*surface.get(), rect, targetTransform, opacity);
397 }
398
399 void TextureMapperLayer::paintWithIntermediateSurface(const TextureMapperPaintOptions& options, const IntRect& rect)
400 {
401     RefPtr<BitmapTexture> replicaSurface;
402     RefPtr<BitmapTexture> mainSurface;
403     TextureMapperPaintOptions paintOptions(options);
404     paintOptions.offset = -IntSize(rect.x(), rect.y());
405     paintOptions.opacity = 1;
406     paintOptions.transform = TransformationMatrix();
407     if (m_state.replicaLayer) {
408         paintOptions.transform = replicaTransform();
409         replicaSurface = paintIntoSurface(paintOptions, rect.size());
410         paintOptions.transform = TransformationMatrix();
411         if (m_state.replicaLayer->m_state.maskLayer)
412             m_state.replicaLayer->m_state.maskLayer->applyMask(paintOptions);
413     }
414
415     if (replicaSurface && options.opacity == 1) {
416         commitSurface(options, replicaSurface, rect, 1);
417         replicaSurface.clear();
418     }
419
420     mainSurface = paintIntoSurface(paintOptions, rect.size());
421     if (replicaSurface) {
422         options.textureMapper->bindSurface(replicaSurface.get());
423         options.textureMapper->drawTexture(*mainSurface.get(), FloatRect(FloatPoint::zero(), rect.size()));
424         mainSurface = replicaSurface;
425     }
426
427     commitSurface(options, mainSurface, rect, options.opacity);
428 }
429
430 void TextureMapperLayer::paintRecursive(const TextureMapperPaintOptions& options)
431 {
432     if (!isVisible())
433         return;
434
435     TextureMapperPaintOptions paintOptions(options);
436     paintOptions.opacity *= m_currentOpacity;
437
438     if (!shouldBlend()) {
439         paintSelfAndChildrenWithReplica(paintOptions);
440         return;
441     }
442
443     paintUsingOverlapRegions(paintOptions);
444 }
445
446 TextureMapperLayer::~TextureMapperLayer()
447 {
448     for (int i = m_children.size() - 1; i >= 0; --i)
449         m_children[i]->m_parent = 0;
450
451     if (m_parent)
452         m_parent->m_children.remove(m_parent->m_children.find(this));
453 }
454
455 TextureMapper* TextureMapperLayer::textureMapper() const
456 {
457     return rootLayer()->m_textureMapper;
458 }
459
460 void TextureMapperLayer::setChildren(const Vector<TextureMapperLayer*>& newChildren)
461 {
462     removeAllChildren();
463     for (size_t i = 0; i < newChildren.size(); ++i)
464         addChild(newChildren[i]);
465 }
466
467 void TextureMapperLayer::addChild(TextureMapperLayer* childLayer)
468 {
469     ASSERT(childLayer != this);
470
471     if (childLayer->m_parent)
472         childLayer->removeFromParent();
473
474     childLayer->m_parent = this;
475     m_children.append(childLayer);
476 }
477
478 void TextureMapperLayer::removeFromParent()
479 {
480     if (m_parent) {
481         unsigned i;
482         for (i = 0; i < m_parent->m_children.size(); i++) {
483             if (this == m_parent->m_children[i]) {
484                 m_parent->m_children.remove(i);
485                 break;
486             }
487         }
488
489         m_parent = 0;
490     }
491 }
492
493 void TextureMapperLayer::removeAllChildren()
494 {
495     while (m_children.size()) {
496         TextureMapperLayer* curLayer = m_children[0];
497         ASSERT(curLayer->m_parent);
498         curLayer->removeFromParent();
499     }
500 }
501
502 void TextureMapperLayer::setMaskLayer(TextureMapperLayer* maskLayer)
503 {
504     if (maskLayer)
505         maskLayer->m_effectTarget = this;
506     m_state.maskLayer = maskLayer;
507 }
508
509 void TextureMapperLayer::setReplicaLayer(TextureMapperLayer* replicaLayer)
510 {
511     if (replicaLayer)
512         replicaLayer->m_effectTarget = this;
513     m_state.replicaLayer = replicaLayer;
514 }
515
516 void TextureMapperLayer::setPosition(const FloatPoint& position)
517 {
518     m_state.pos = position;
519     m_currentTransform.setPosition(adjustedPosition());
520 }
521
522 void TextureMapperLayer::setSize(const FloatSize& size)
523 {
524     m_state.size = size;
525     m_currentTransform.setSize(size);
526 }
527
528 void TextureMapperLayer::setAnchorPoint(const FloatPoint3D& anchorPoint)
529 {
530     m_state.anchorPoint = anchorPoint;
531     m_currentTransform.setAnchorPoint(anchorPoint);
532 }
533
534 void TextureMapperLayer::setPreserves3D(bool preserves3D)
535 {
536     m_state.preserves3D = preserves3D;
537     m_currentTransform.setFlattening(!preserves3D);
538 }
539
540 void TextureMapperLayer::setTransform(const TransformationMatrix& transform)
541 {
542     m_state.transform = transform;
543     m_currentTransform.setLocalTransform(transform);
544 }
545
546 void TextureMapperLayer::setChildrenTransform(const TransformationMatrix& childrenTransform)
547 {
548     m_state.childrenTransform = childrenTransform;
549     m_currentTransform.setChildrenTransform(childrenTransform);
550 }
551
552 void TextureMapperLayer::setContentsRect(const IntRect& contentsRect)
553 {
554     m_state.contentsRect = contentsRect;
555 }
556
557 void TextureMapperLayer::setMasksToBounds(bool masksToBounds)
558 {
559     m_state.masksToBounds = masksToBounds;
560 }
561
562 void TextureMapperLayer::setDrawsContent(bool drawsContent)
563 {
564     m_state.drawsContent = drawsContent;
565 }
566
567 void TextureMapperLayer::setContentsVisible(bool contentsVisible)
568 {
569     m_state.contentsVisible = contentsVisible;
570 }
571
572 void TextureMapperLayer::setContentsOpaque(bool contentsOpaque)
573 {
574     m_state.contentsOpaque = contentsOpaque;
575 }
576
577 void TextureMapperLayer::setBackfaceVisibility(bool backfaceVisibility)
578 {
579     m_state.backfaceVisibility = backfaceVisibility;
580 }
581
582 void TextureMapperLayer::setOpacity(float opacity)
583 {
584     m_state.opacity = opacity;
585 }
586
587 void TextureMapperLayer::setSolidColor(const Color& color)
588 {
589     m_state.solidColor = color;
590 }
591
592 #if ENABLE(CSS_FILTERS)
593 void TextureMapperLayer::setFilters(const FilterOperations& filters)
594 {
595     m_state.filters = filters;
596 }
597 #endif
598
599 void TextureMapperLayer::setDebugVisuals(bool showDebugBorders, const Color& debugBorderColor, float debugBorderWidth, bool showRepaintCounter)
600 {
601     m_state.showDebugBorders = showDebugBorders;
602     m_state.debugBorderColor = debugBorderColor;
603     m_state.debugBorderWidth = debugBorderWidth;
604     m_state.showRepaintCounter = showRepaintCounter;
605 }
606
607 void TextureMapperLayer::setRepaintCount(int repaintCount)
608 {
609     m_state.repaintCount = repaintCount;
610 }
611
612 void TextureMapperLayer::setContentsLayer(TextureMapperPlatformLayer* platformLayer)
613 {
614     m_contentsLayer = platformLayer;
615 }
616
617 void TextureMapperLayer::setAnimations(const GraphicsLayerAnimations& animations)
618 {
619     m_animations = animations;
620 }
621
622 void TextureMapperLayer::setFixedToViewport(bool fixedToViewport)
623 {
624     m_fixedToViewport = fixedToViewport;
625 }
626
627 void TextureMapperLayer::setBackingStore(PassRefPtr<TextureMapperBackingStore> backingStore)
628 {
629     m_backingStore = backingStore;
630 }
631
632 bool TextureMapperLayer::descendantsOrSelfHaveRunningAnimations() const
633 {
634     if (m_animations.hasRunningAnimations())
635         return true;
636
637     for (size_t i = 0; i < m_children.size(); ++i) {
638         if (m_children[i]->descendantsOrSelfHaveRunningAnimations())
639             return true;
640     }
641
642     return false;
643 }
644
645 void TextureMapperLayer::applyAnimationsRecursively()
646 {
647     syncAnimations();
648     for (size_t i = 0; i < m_children.size(); ++i)
649         m_children[i]->applyAnimationsRecursively();
650 }
651
652 void TextureMapperLayer::syncAnimations()
653 {
654     m_animations.apply(this);
655     if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyWebkitTransform))
656         m_currentTransform.setLocalTransform(m_state.transform);
657     if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyOpacity))
658         m_currentOpacity = m_state.opacity;
659
660 #if ENABLE(CSS_FILTERS)
661     if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyWebkitFilter))
662         m_currentFilters = m_state.filters;
663 #endif
664 }
665
666 bool TextureMapperLayer::isAncestorFixedToViewport() const
667 {
668     for (TextureMapperLayer* parent = m_parent; parent; parent = parent->m_parent) {
669         if (parent->m_fixedToViewport)
670             return true;
671     }
672
673     return false;
674 }
675
676 void TextureMapperLayer::setScrollPositionDeltaIfNeeded(const FloatSize& delta)
677 {
678     // delta is the difference between the scroll offset in the ui process and the scroll offset
679     // in the web process. We add this delta to the position of fixed layers, to make
680     // sure that they do not move while scrolling. We need to reset this delta to fixed layers
681     // that have an ancestor which is also a fixed layer, because the delta will be added to the ancestor.
682     if (isAncestorFixedToViewport())
683         m_scrollPositionDelta = FloatSize();
684     else
685         m_scrollPositionDelta = delta;
686     m_currentTransform.setPosition(adjustedPosition());
687 }
688
689 template<class HitTestCondition> TextureMapperLayer* TextureMapperLayer::hitTest(const FloatPoint& point, HitTestCondition condition)
690 {
691     if (!m_state.visible || !m_state.contentsVisible)
692         return 0;
693
694     TextureMapperLayer* result = 0;
695     for (int i = m_children.size() - 1; !result && i >= 0; --i)
696         result = m_children[i]->hitTest(point, condition);
697
698     if (result)
699         return result;
700
701     return condition(this, point) ? this : 0;
702 }
703
704 bool TextureMapperLayer::scrollableLayerHitTestCondition(TextureMapperLayer* layer, const FloatPoint& point)
705 {
706     // scrolling layer's m_parent->m_parent, the parent of the scrolling layes, is the one that defines the
707     // rectangle to be used for hit testing.
708     if (!layer->isScrollable() || !layer->m_parent || !layer->m_parent->m_parent)
709         return false;
710
711     TextureMapperLayer* parentLayer = layer->m_parent->m_parent;
712     FloatRect rect = parentLayer->layerRect();
713     return parentLayer->m_currentTransform.combined().mapQuad(rect).containsPoint(point);
714 }
715
716 TextureMapperLayer* TextureMapperLayer::findScrollableContentsLayerAt(const FloatPoint& point)
717 {
718     return hitTest(point, &TextureMapperLayer::scrollableLayerHitTestCondition);
719 }
720
721 FloatSize TextureMapperLayer::mapScrollOffset(const FloatSize& offset)
722 {
723     double zeroX, zeroY, offsetX, offsetY;
724     TransformationMatrix transform = m_currentTransform.combined().inverse();
725     transform.map(0, 0, zeroX, zeroY);
726     transform.map(offset.width(), offset.height(), offsetX, offsetY);
727     return FloatSize(offsetX - zeroX, offsetY - zeroY);
728 }
729
730 void TextureMapperLayer::commitScrollOffset(const FloatSize& offset)
731 {
732     FloatSize fullOffset = m_accumulatedScrollOffsetFractionalPart + offset;
733
734     int intWidth = round(fullOffset.width());
735     int intHeight = round(fullOffset.height());
736
737     // m_accumulatedScrollOffsetFractionalPart holds the fractional part of the user scroll offset that
738     // has not yet been synced with the web process because the web process expects an IntSize.
739     m_accumulatedScrollOffsetFractionalPart = FloatSize(fullOffset.width() - intWidth, fullOffset.height() - intHeight);
740
741     m_scrollClient->commitScrollOffset(m_id, IntSize(intWidth, intHeight));
742 }
743
744 void TextureMapperLayer::scrollBy(const FloatSize& offset)
745 {
746     if (!isScrollable() || !m_scrollClient || offset.isZero())
747         return;
748
749     FloatSize scrollOffset = mapScrollOffset(offset);
750     m_userScrollOffset += scrollOffset;
751
752     m_currentTransform.setPosition(adjustedPosition());
753     commitScrollOffset(scrollOffset);
754 }
755
756 void TextureMapperLayer::didCommitScrollOffset(const IntSize& offset)
757 {
758     m_userScrollOffset = FloatSize(m_userScrollOffset.width() - offset.width(), m_userScrollOffset.height() - offset.height());
759     m_currentTransform.setPosition(adjustedPosition());
760 }
761
762 }
763 #endif