[Texmap] Implementation for pattern compositing
[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::computePatternTransformIfNeeded()
103 {
104     if (!m_patternTransformDirty)
105         return;
106
107     m_patternTransformDirty = false;
108     m_patternTransform =
109         TransformationMatrix::rectToRect(FloatRect(FloatPoint::zero(), m_state.contentsTileSize), m_state.contentsRect)
110         .multiply(TransformationMatrix().translate(m_state.contentsTilePhase.x() / m_state.contentsRect.width(), m_state.contentsTilePhase.y() / m_state.contentsRect.height()));
111 }
112
113 void TextureMapperLayer::paintSelf(const TextureMapperPaintOptions& options)
114 {
115     if (!m_state.visible || !m_state.contentsVisible)
116         return;
117
118     // 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.
119     TransformationMatrix transform;
120     transform.translate(options.offset.width(), options.offset.height());
121     transform.multiply(options.transform);
122     transform.multiply(m_currentTransform.combined());
123
124     if (m_state.solidColor.isValid() && !m_state.contentsRect.isEmpty() && m_state.solidColor.alpha()) {
125         options.textureMapper->drawSolidColor(m_state.contentsRect, transform, blendWithOpacity(m_state.solidColor, options.opacity));
126         if (m_state.showDebugBorders)
127             options.textureMapper->drawBorder(m_state.debugBorderColor, m_state.debugBorderWidth, layerRect(), transform);
128         return;
129     }
130
131     options.textureMapper->setWrapMode(TextureMapper::StretchWrap);
132     options.textureMapper->setPatternTransform(TransformationMatrix());
133
134     if (!m_state.contentsTileSize.isEmpty()) {
135         computePatternTransformIfNeeded();
136         options.textureMapper->setWrapMode(TextureMapper::RepeatWrap);
137         options.textureMapper->setPatternTransform(m_patternTransform);
138     }
139
140     if (m_backingStore) {
141         ASSERT(m_state.drawsContent && m_state.contentsVisible && !m_state.size.isEmpty());
142         FloatRect targetRect = m_state.shouldMapBackingStoreToContentsRect ? m_state.contentsRect : layerRect();
143         ASSERT(!targetRect.isEmpty());
144         m_backingStore->paintToTextureMapper(options.textureMapper, targetRect, transform, options.opacity);
145         if (m_state.showDebugBorders)
146             m_backingStore->drawBorder(options.textureMapper, m_state.debugBorderColor, m_state.debugBorderWidth, targetRect, transform);
147         // Only draw repaint count for the main backing store.
148         if (m_state.showRepaintCounter)
149             m_backingStore->drawRepaintCounter(options.textureMapper, m_state.repaintCount, m_state.debugBorderColor, targetRect, transform);
150     }
151
152     if (!m_contentsLayer)
153         return;
154
155     ASSERT(!layerRect().isEmpty());
156     m_contentsLayer->paintToTextureMapper(options.textureMapper, m_state.contentsRect, transform, options.opacity);
157     if (m_state.showDebugBorders)
158         m_contentsLayer->drawBorder(options.textureMapper, m_state.debugBorderColor, m_state.debugBorderWidth, m_state.contentsRect, transform);
159 }
160
161 int TextureMapperLayer::compareGraphicsLayersZValue(const void* a, const void* b)
162 {
163     TextureMapperLayer* const* layerA = static_cast<TextureMapperLayer* const*>(a);
164     TextureMapperLayer* const* layerB = static_cast<TextureMapperLayer* const*>(b);
165     return int(((*layerA)->m_centerZ - (*layerB)->m_centerZ) * 1000);
166 }
167
168 void TextureMapperLayer::sortByZOrder(Vector<TextureMapperLayer* >& array)
169 {
170     qsort(array.data(), array.size(), sizeof(TextureMapperLayer*), compareGraphicsLayersZValue);
171 }
172
173 void TextureMapperLayer::paintSelfAndChildren(const TextureMapperPaintOptions& options)
174 {
175     paintSelf(options);
176
177     if (m_children.isEmpty())
178         return;
179
180     bool shouldClip = m_state.masksToBounds && !m_state.preserves3D;
181     if (shouldClip) {
182         TransformationMatrix clipTransform;
183         clipTransform.translate(options.offset.width(), options.offset.height());
184         clipTransform.multiply(options.transform);
185         clipTransform.multiply(m_currentTransform.combined());
186         options.textureMapper->beginClip(clipTransform, layerRect());
187     }
188
189     for (size_t i = 0; i < m_children.size(); ++i)
190         m_children[i]->paintRecursive(options);
191
192     if (shouldClip)
193         options.textureMapper->endClip();
194 }
195
196 bool TextureMapperLayer::shouldBlend() const
197 {
198     if (m_state.preserves3D)
199         return false;
200
201 #if ENABLE(CSS_FILTERS)
202     if (m_currentFilters.size())
203         return true;
204 #endif
205     return m_currentOpacity < 1 || m_state.maskLayer || (m_state.replicaLayer && m_state.replicaLayer->m_state.maskLayer);
206 }
207
208 bool TextureMapperLayer::isVisible() const
209 {
210     if (m_state.size.isEmpty() && (m_state.masksToBounds || m_state.maskLayer || m_children.isEmpty()))
211         return false;
212     if (!m_state.visible && m_children.isEmpty())
213         return false;
214     if (!m_state.contentsVisible && m_children.isEmpty())
215         return false;
216     if (m_currentOpacity < 0.01)
217         return false;
218     return true;
219 }
220
221 void TextureMapperLayer::paintSelfAndChildrenWithReplica(const TextureMapperPaintOptions& options)
222 {
223     if (m_state.replicaLayer) {
224         TextureMapperPaintOptions replicaOptions(options);
225         replicaOptions.transform
226             .multiply(m_state.replicaLayer->m_currentTransform.combined())
227             .multiply(m_currentTransform.combined().inverse());
228         paintSelfAndChildren(replicaOptions);
229     }
230
231     paintSelfAndChildren(options);
232 }
233
234 void TextureMapperLayer::setAnimatedTransform(const TransformationMatrix& matrix)
235 {
236     m_currentTransform.setLocalTransform(matrix);
237 }
238
239 void TextureMapperLayer::setAnimatedOpacity(float opacity)
240 {
241     m_currentOpacity = opacity;
242 }
243
244 TransformationMatrix TextureMapperLayer::replicaTransform()
245 {
246     return TransformationMatrix(m_state.replicaLayer->m_currentTransform.combined()).multiply(m_currentTransform.combined().inverse());
247 }
248
249 #if ENABLE(CSS_FILTERS)
250 void TextureMapperLayer::setAnimatedFilters(const FilterOperations& filters)
251 {
252     m_currentFilters = filters;
253 }
254
255 static bool shouldKeepContentTexture(const FilterOperations& filters)
256 {
257     for (size_t i = 0; i < filters.size(); ++i) {
258         switch (filters.operations().at(i)->getOperationType()) {
259         // The drop-shadow filter requires the content texture, because it needs to composite it
260         // on top of the blurred shadow color.
261         case FilterOperation::DROP_SHADOW:
262             return true;
263         default:
264             break;
265         }
266     }
267
268     return false;
269 }
270
271 static PassRefPtr<BitmapTexture> applyFilters(const FilterOperations& filters, TextureMapper* textureMapper, BitmapTexture* source)
272 {
273     if (!filters.size())
274         return source;
275
276     RefPtr<BitmapTexture> filterSurface = shouldKeepContentTexture(filters) ? textureMapper->acquireTextureFromPool(source->size()) : source;
277     return filterSurface->applyFilters(textureMapper, *source, filters);
278 }
279 #endif
280
281 static void resolveOverlaps(Region newRegion, Region& overlapRegion, Region& nonOverlapRegion)
282 {
283     Region newOverlapRegion(newRegion);
284     newOverlapRegion.intersect(nonOverlapRegion);
285     nonOverlapRegion.subtract(newOverlapRegion);
286     overlapRegion.unite(newOverlapRegion);
287     newRegion.subtract(overlapRegion);
288     nonOverlapRegion.unite(newRegion);
289 }
290
291 void TextureMapperLayer::computeOverlapRegions(Region& overlapRegion, Region& nonOverlapRegion, ResolveSelfOverlapMode mode)
292 {
293     if (!m_state.visible || !m_state.contentsVisible)
294         return;
295
296     FloatRect boundingRect;
297     if (m_backingStore || m_state.masksToBounds || m_state.maskLayer || hasFilters())
298         boundingRect = layerRect();
299     else if (m_contentsLayer || m_state.solidColor.alpha())
300         boundingRect = m_state.contentsRect;
301
302 #if ENABLE(CSS_FILTERS)
303     if (m_currentFilters.hasOutsets()) {
304         FilterOutsets outsets = m_currentFilters.outsets();
305         IntRect unfilteredTargetRect(boundingRect);
306         boundingRect.move(std::max(0, -outsets.left()), std::max(0, -outsets.top()));
307         boundingRect.expand(outsets.left() + outsets.right(), outsets.top() + outsets.bottom());
308         boundingRect.unite(unfilteredTargetRect);
309     }
310 #endif
311
312     TransformationMatrix replicaMatrix;
313     if (m_state.replicaLayer) {
314         replicaMatrix = replicaTransform();
315         boundingRect.unite(replicaMatrix.mapRect(boundingRect));
316     }
317
318     boundingRect = m_currentTransform.combined().mapRect(boundingRect);
319
320     // Count all masks and filters as overlap layers.
321     if (hasFilters() || m_state.maskLayer || (m_state.replicaLayer && m_state.replicaLayer->m_state.maskLayer)) {
322         Region newOverlapRegion(enclosingIntRect(boundingRect));
323         nonOverlapRegion.subtract(newOverlapRegion);
324         overlapRegion.unite(newOverlapRegion);
325         return;
326     }
327
328     Region newOverlapRegion;
329     Region newNonOverlapRegion(enclosingIntRect(boundingRect));
330
331     if (!m_state.masksToBounds) {
332         for (size_t i = 0; i < m_children.size(); ++i) {
333             TextureMapperLayer* child = m_children[i];
334             child->computeOverlapRegions(newOverlapRegion, newNonOverlapRegion, ResolveSelfOverlapIfNeeded);
335         }
336     }
337
338     if (m_state.replicaLayer) {
339         newOverlapRegion.unite(replicaMatrix.mapRect(newOverlapRegion.bounds()));
340         Region replicaRegion(replicaMatrix.mapRect(newNonOverlapRegion.bounds()));
341         resolveOverlaps(replicaRegion, newOverlapRegion, newNonOverlapRegion);
342     }
343
344     if ((mode != ResolveSelfOverlapAlways) && shouldBlend()) {
345         newNonOverlapRegion.unite(newOverlapRegion);
346         newOverlapRegion = Region();
347     }
348
349     overlapRegion.unite(newOverlapRegion);
350     resolveOverlaps(newNonOverlapRegion, overlapRegion, nonOverlapRegion);
351 }
352
353 void TextureMapperLayer::paintUsingOverlapRegions(const TextureMapperPaintOptions& options)
354 {
355     Region overlapRegion;
356     Region nonOverlapRegion;
357     computeOverlapRegions(overlapRegion, nonOverlapRegion, ResolveSelfOverlapAlways);
358     if (overlapRegion.isEmpty()) {
359         paintSelfAndChildrenWithReplica(options);
360         return;
361     }
362
363     Vector<IntRect> rects;
364
365     nonOverlapRegion.translate(options.offset);
366     rects = nonOverlapRegion.rects();
367     for (size_t i = 0; i < rects.size(); ++i) {
368         options.textureMapper->beginClip(TransformationMatrix(), rects[i]);
369         paintSelfAndChildrenWithReplica(options);
370         options.textureMapper->endClip();
371     }
372
373     rects = overlapRegion.rects();
374     IntSize maxTextureSize = options.textureMapper->maxTextureSize();
375     IntRect rect;
376     for (size_t i = 0; i < rects.size(); ++i) {
377         rect = rects[i];
378         for (int x = rect.x(); x < rect.maxX(); x += maxTextureSize.width()) {
379             for (int y = rect.y(); y < rect.maxY(); y += maxTextureSize.height()) {
380                 IntRect tileRect(IntPoint(x, y), maxTextureSize);
381                 tileRect.intersect(rect);
382                 paintWithIntermediateSurface(options, tileRect);
383             }
384         }
385     }
386 }
387
388 void TextureMapperLayer::applyMask(const TextureMapperPaintOptions& options)
389 {
390     options.textureMapper->setMaskMode(true);
391     paintSelf(options);
392     options.textureMapper->setMaskMode(false);
393 }
394
395 PassRefPtr<BitmapTexture> TextureMapperLayer::paintIntoSurface(const TextureMapperPaintOptions& options, const IntSize& size)
396 {
397     RefPtr<BitmapTexture> surface = options.textureMapper->acquireTextureFromPool(size);
398     TextureMapperPaintOptions paintOptions(options);
399     paintOptions.surface = surface;
400     options.textureMapper->bindSurface(surface.get());
401     paintSelfAndChildren(paintOptions);
402     if (m_state.maskLayer)
403         m_state.maskLayer->applyMask(options);
404 #if ENABLE(CSS_FILTERS)
405     if (!m_currentFilters.isEmpty())
406         surface = applyFilters(m_currentFilters, options.textureMapper, surface.get());
407 #endif
408     options.textureMapper->bindSurface(surface.get());
409     return surface;
410 }
411
412 static void commitSurface(const TextureMapperPaintOptions& options, PassRefPtr<BitmapTexture> surface, const IntRect& rect, float opacity)
413 {
414     options.textureMapper->bindSurface(options.surface.get());
415     TransformationMatrix targetTransform;
416     targetTransform.translate(options.offset.width(), options.offset.height());
417     targetTransform.multiply(options.transform);
418     options.textureMapper->drawTexture(*surface.get(), rect, targetTransform, opacity);
419 }
420
421 void TextureMapperLayer::paintWithIntermediateSurface(const TextureMapperPaintOptions& options, const IntRect& rect)
422 {
423     RefPtr<BitmapTexture> replicaSurface;
424     RefPtr<BitmapTexture> mainSurface;
425     TextureMapperPaintOptions paintOptions(options);
426     paintOptions.offset = -IntSize(rect.x(), rect.y());
427     paintOptions.opacity = 1;
428     paintOptions.transform = TransformationMatrix();
429     if (m_state.replicaLayer) {
430         paintOptions.transform = replicaTransform();
431         replicaSurface = paintIntoSurface(paintOptions, rect.size());
432         paintOptions.transform = TransformationMatrix();
433         if (m_state.replicaLayer->m_state.maskLayer)
434             m_state.replicaLayer->m_state.maskLayer->applyMask(paintOptions);
435     }
436
437     if (replicaSurface && options.opacity == 1) {
438         commitSurface(options, replicaSurface, rect, 1);
439         replicaSurface.clear();
440     }
441
442     mainSurface = paintIntoSurface(paintOptions, rect.size());
443     if (replicaSurface) {
444         options.textureMapper->bindSurface(replicaSurface.get());
445         options.textureMapper->drawTexture(*mainSurface.get(), FloatRect(FloatPoint::zero(), rect.size()));
446         mainSurface = replicaSurface;
447     }
448
449     commitSurface(options, mainSurface, rect, options.opacity);
450 }
451
452 void TextureMapperLayer::paintRecursive(const TextureMapperPaintOptions& options)
453 {
454     if (!isVisible())
455         return;
456
457     TextureMapperPaintOptions paintOptions(options);
458     paintOptions.opacity *= m_currentOpacity;
459
460     if (!shouldBlend()) {
461         paintSelfAndChildrenWithReplica(paintOptions);
462         return;
463     }
464
465     paintUsingOverlapRegions(paintOptions);
466 }
467
468 TextureMapperLayer::~TextureMapperLayer()
469 {
470     for (int i = m_children.size() - 1; i >= 0; --i)
471         m_children[i]->m_parent = 0;
472
473     if (m_parent)
474         m_parent->m_children.remove(m_parent->m_children.find(this));
475 }
476
477 TextureMapper* TextureMapperLayer::textureMapper() const
478 {
479     return rootLayer()->m_textureMapper;
480 }
481
482 void TextureMapperLayer::setChildren(const Vector<TextureMapperLayer*>& newChildren)
483 {
484     removeAllChildren();
485     for (size_t i = 0; i < newChildren.size(); ++i)
486         addChild(newChildren[i]);
487 }
488
489 void TextureMapperLayer::addChild(TextureMapperLayer* childLayer)
490 {
491     ASSERT(childLayer != this);
492
493     if (childLayer->m_parent)
494         childLayer->removeFromParent();
495
496     childLayer->m_parent = this;
497     m_children.append(childLayer);
498 }
499
500 void TextureMapperLayer::removeFromParent()
501 {
502     if (m_parent) {
503         unsigned i;
504         for (i = 0; i < m_parent->m_children.size(); i++) {
505             if (this == m_parent->m_children[i]) {
506                 m_parent->m_children.remove(i);
507                 break;
508             }
509         }
510
511         m_parent = 0;
512     }
513 }
514
515 void TextureMapperLayer::removeAllChildren()
516 {
517     while (m_children.size()) {
518         TextureMapperLayer* curLayer = m_children[0];
519         ASSERT(curLayer->m_parent);
520         curLayer->removeFromParent();
521     }
522 }
523
524 void TextureMapperLayer::setMaskLayer(TextureMapperLayer* maskLayer)
525 {
526     if (maskLayer)
527         maskLayer->m_effectTarget = this;
528     m_state.maskLayer = maskLayer;
529 }
530
531 void TextureMapperLayer::setReplicaLayer(TextureMapperLayer* replicaLayer)
532 {
533     if (replicaLayer)
534         replicaLayer->m_effectTarget = this;
535     m_state.replicaLayer = replicaLayer;
536 }
537
538 void TextureMapperLayer::setPosition(const FloatPoint& position)
539 {
540     m_state.pos = position;
541     m_currentTransform.setPosition(adjustedPosition());
542 }
543
544 void TextureMapperLayer::setSize(const FloatSize& size)
545 {
546     m_state.size = size;
547     m_currentTransform.setSize(size);
548 }
549
550 void TextureMapperLayer::setAnchorPoint(const FloatPoint3D& anchorPoint)
551 {
552     m_state.anchorPoint = anchorPoint;
553     m_currentTransform.setAnchorPoint(anchorPoint);
554 }
555
556 void TextureMapperLayer::setPreserves3D(bool preserves3D)
557 {
558     m_state.preserves3D = preserves3D;
559     m_currentTransform.setFlattening(!preserves3D);
560 }
561
562 void TextureMapperLayer::setTransform(const TransformationMatrix& transform)
563 {
564     m_state.transform = transform;
565     m_currentTransform.setLocalTransform(transform);
566 }
567
568 void TextureMapperLayer::setChildrenTransform(const TransformationMatrix& childrenTransform)
569 {
570     m_state.childrenTransform = childrenTransform;
571     m_currentTransform.setChildrenTransform(childrenTransform);
572 }
573
574 void TextureMapperLayer::setContentsRect(const IntRect& contentsRect)
575 {
576     if (contentsRect == m_state.contentsRect)
577         return;
578     m_state.contentsRect = contentsRect;
579     m_patternTransformDirty = true;
580 }
581
582 void TextureMapperLayer::setContentsTileSize(const IntSize& size)
583 {
584     if (size == m_state.contentsTileSize)
585         return;
586     m_state.contentsTileSize = size;
587     m_patternTransformDirty = true;
588 }
589
590 void TextureMapperLayer::setContentsTilePhase(const IntPoint& phase)
591 {
592     if (phase == m_state.contentsTilePhase)
593         return;
594     m_state.contentsTilePhase = phase;
595     m_patternTransformDirty = true;
596 }
597
598 void TextureMapperLayer::setMasksToBounds(bool masksToBounds)
599 {
600     m_state.masksToBounds = masksToBounds;
601 }
602
603 void TextureMapperLayer::setDrawsContent(bool drawsContent)
604 {
605     m_state.drawsContent = drawsContent;
606 }
607
608 void TextureMapperLayer::setContentsVisible(bool contentsVisible)
609 {
610     m_state.contentsVisible = contentsVisible;
611 }
612
613 void TextureMapperLayer::setContentsOpaque(bool contentsOpaque)
614 {
615     m_state.contentsOpaque = contentsOpaque;
616 }
617
618 void TextureMapperLayer::setBackfaceVisibility(bool backfaceVisibility)
619 {
620     m_state.backfaceVisibility = backfaceVisibility;
621 }
622
623 void TextureMapperLayer::setOpacity(float opacity)
624 {
625     m_state.opacity = opacity;
626 }
627
628 void TextureMapperLayer::setSolidColor(const Color& color)
629 {
630     m_state.solidColor = color;
631 }
632
633 #if ENABLE(CSS_FILTERS)
634 void TextureMapperLayer::setFilters(const FilterOperations& filters)
635 {
636     m_state.filters = filters;
637 }
638 #endif
639
640 void TextureMapperLayer::setDebugVisuals(bool showDebugBorders, const Color& debugBorderColor, float debugBorderWidth, bool showRepaintCounter)
641 {
642     m_state.showDebugBorders = showDebugBorders;
643     m_state.debugBorderColor = debugBorderColor;
644     m_state.debugBorderWidth = debugBorderWidth;
645     m_state.showRepaintCounter = showRepaintCounter;
646 }
647
648 void TextureMapperLayer::setRepaintCount(int repaintCount)
649 {
650     m_state.repaintCount = repaintCount;
651 }
652
653 void TextureMapperLayer::setContentsLayer(TextureMapperPlatformLayer* platformLayer)
654 {
655     m_contentsLayer = platformLayer;
656 }
657
658 void TextureMapperLayer::setAnimations(const GraphicsLayerAnimations& animations)
659 {
660     m_animations = animations;
661 }
662
663 void TextureMapperLayer::setFixedToViewport(bool fixedToViewport)
664 {
665     m_fixedToViewport = fixedToViewport;
666 }
667
668 void TextureMapperLayer::setBackingStore(PassRefPtr<TextureMapperBackingStore> backingStore)
669 {
670     m_backingStore = backingStore;
671 }
672
673 bool TextureMapperLayer::descendantsOrSelfHaveRunningAnimations() const
674 {
675     if (m_animations.hasRunningAnimations())
676         return true;
677
678     for (size_t i = 0; i < m_children.size(); ++i) {
679         if (m_children[i]->descendantsOrSelfHaveRunningAnimations())
680             return true;
681     }
682
683     return false;
684 }
685
686 void TextureMapperLayer::applyAnimationsRecursively()
687 {
688     syncAnimations();
689     for (size_t i = 0; i < m_children.size(); ++i)
690         m_children[i]->applyAnimationsRecursively();
691 }
692
693 void TextureMapperLayer::syncAnimations()
694 {
695     m_animations.apply(this);
696     if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyWebkitTransform))
697         m_currentTransform.setLocalTransform(m_state.transform);
698     if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyOpacity))
699         m_currentOpacity = m_state.opacity;
700
701 #if ENABLE(CSS_FILTERS)
702     if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyWebkitFilter))
703         m_currentFilters = m_state.filters;
704 #endif
705 }
706
707 bool TextureMapperLayer::isAncestorFixedToViewport() const
708 {
709     for (TextureMapperLayer* parent = m_parent; parent; parent = parent->m_parent) {
710         if (parent->m_fixedToViewport)
711             return true;
712     }
713
714     return false;
715 }
716
717 void TextureMapperLayer::setScrollPositionDeltaIfNeeded(const FloatSize& delta)
718 {
719     // delta is the difference between the scroll offset in the ui process and the scroll offset
720     // in the web process. We add this delta to the position of fixed layers, to make
721     // sure that they do not move while scrolling. We need to reset this delta to fixed layers
722     // that have an ancestor which is also a fixed layer, because the delta will be added to the ancestor.
723     if (isAncestorFixedToViewport())
724         m_scrollPositionDelta = FloatSize();
725     else
726         m_scrollPositionDelta = delta;
727     m_currentTransform.setPosition(adjustedPosition());
728 }
729
730 template<class HitTestCondition> TextureMapperLayer* TextureMapperLayer::hitTest(const FloatPoint& point, HitTestCondition condition)
731 {
732     if (!m_state.visible || !m_state.contentsVisible)
733         return 0;
734
735     TextureMapperLayer* result = 0;
736     for (int i = m_children.size() - 1; !result && i >= 0; --i)
737         result = m_children[i]->hitTest(point, condition);
738
739     if (result)
740         return result;
741
742     return condition(this, point) ? this : 0;
743 }
744
745 bool TextureMapperLayer::scrollableLayerHitTestCondition(TextureMapperLayer* layer, const FloatPoint& point)
746 {
747     // scrolling layer's m_parent->m_parent, the parent of the scrolling layes, is the one that defines the
748     // rectangle to be used for hit testing.
749     if (!layer->isScrollable() || !layer->m_parent || !layer->m_parent->m_parent)
750         return false;
751
752     TextureMapperLayer* parentLayer = layer->m_parent->m_parent;
753     FloatRect rect = parentLayer->layerRect();
754     return parentLayer->m_currentTransform.combined().mapQuad(rect).containsPoint(point);
755 }
756
757 TextureMapperLayer* TextureMapperLayer::findScrollableContentsLayerAt(const FloatPoint& point)
758 {
759     return hitTest(point, &TextureMapperLayer::scrollableLayerHitTestCondition);
760 }
761
762 FloatSize TextureMapperLayer::mapScrollOffset(const FloatSize& offset)
763 {
764     double zeroX, zeroY, offsetX, offsetY;
765     TransformationMatrix transform = m_currentTransform.combined().inverse();
766     transform.map(0, 0, zeroX, zeroY);
767     transform.map(offset.width(), offset.height(), offsetX, offsetY);
768     return FloatSize(offsetX - zeroX, offsetY - zeroY);
769 }
770
771 void TextureMapperLayer::commitScrollOffset(const FloatSize& offset)
772 {
773     FloatSize fullOffset = m_accumulatedScrollOffsetFractionalPart + offset;
774
775     int intWidth = round(fullOffset.width());
776     int intHeight = round(fullOffset.height());
777
778     // m_accumulatedScrollOffsetFractionalPart holds the fractional part of the user scroll offset that
779     // has not yet been synced with the web process because the web process expects an IntSize.
780     m_accumulatedScrollOffsetFractionalPart = FloatSize(fullOffset.width() - intWidth, fullOffset.height() - intHeight);
781
782     m_scrollClient->commitScrollOffset(m_id, IntSize(intWidth, intHeight));
783 }
784
785 void TextureMapperLayer::scrollBy(const FloatSize& offset)
786 {
787     if (!isScrollable() || !m_scrollClient || offset.isZero())
788         return;
789
790     FloatSize scrollOffset = mapScrollOffset(offset);
791     m_userScrollOffset += scrollOffset;
792
793     m_currentTransform.setPosition(adjustedPosition());
794     commitScrollOffset(scrollOffset);
795 }
796
797 void TextureMapperLayer::didCommitScrollOffset(const IntSize& offset)
798 {
799     m_userScrollOffset = FloatSize(m_userScrollOffset.width() - offset.width(), m_userScrollOffset.height() - offset.height());
800     m_currentTransform.setPosition(adjustedPosition());
801 }
802
803 }
804 #endif