OSDN Git Service

Use isHighEndGfx to double textures
[android-x86/external-webkit.git] / Source / WebCore / platform / graphics / android / LayerAndroid.cpp
1 #include "config.h"
2 #include "LayerAndroid.h"
3
4 #if USE(ACCELERATED_COMPOSITING)
5
6 #include "AndroidAnimation.h"
7 #include "ClassTracker.h"
8 #include "DrawExtra.h"
9 #include "GLUtils.h"
10 #include "ImagesManager.h"
11 #include "MediaLayer.h"
12 #include "PaintedSurface.h"
13 #include "ParseCanvas.h"
14 #include "SkBitmapRef.h"
15 #include "SkBounder.h"
16 #include "SkDrawFilter.h"
17 #include "SkPaint.h"
18 #include "SkPicture.h"
19 #include "TilesManager.h"
20
21 #include <wtf/CurrentTime.h>
22 #include <math.h>
23
24 #define LAYER_DEBUG // Add diagonals for debugging
25 #undef LAYER_DEBUG
26
27 #include <cutils/log.h>
28 #include <wtf/text/CString.h>
29 #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "LayerAndroid", __VA_ARGS__)
30
31 #ifdef DEBUG
32
33 #undef XLOG
34 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "LayerAndroid", __VA_ARGS__)
35
36 #else
37
38 #undef XLOG
39 #define XLOG(...)
40
41 #endif // DEBUG
42
43 namespace WebCore {
44
45 static int gUniqueId;
46
47 class OpacityDrawFilter : public SkDrawFilter {
48 public:
49     OpacityDrawFilter(int opacity) : m_opacity(opacity) { }
50     virtual void filter(SkPaint* paint, Type)
51     {
52         paint->setAlpha(m_opacity);
53     }
54 private:
55     int m_opacity;
56 };
57
58 class HasTextBounder : public SkBounder {
59     virtual bool onIRect(const SkIRect& rect)
60     {
61         return false;
62     }
63 };
64
65 class HasTextCanvas : public SkCanvas {
66 public:
67     HasTextCanvas(SkBounder* bounder, SkPicture* picture)
68         : m_picture(picture)
69         , m_hasText(false)
70     {
71         setBounder(bounder);
72     }
73
74     void setHasText()
75     {
76         m_hasText = true;
77         m_picture->abortPlayback();
78     }
79
80     bool hasText()
81     {
82         return m_hasText;
83     }
84
85     virtual bool clipPath(const SkPath&, SkRegion::Op) {
86         return true;
87     }
88
89     virtual void commonDrawBitmap(const SkBitmap& bitmap,
90                                   const SkIRect* rect,
91                                   const SkMatrix&,
92                                   const SkPaint&) {}
93
94     virtual void drawPaint(const SkPaint& paint) {}
95     virtual void drawPath(const SkPath&, const SkPaint& paint) {}
96     virtual void drawPoints(PointMode, size_t,
97                             const SkPoint [], const SkPaint& paint) {}
98
99     virtual void drawRect(const SkRect& , const SkPaint& paint) {}
100     virtual void drawSprite(const SkBitmap& , int , int ,
101                             const SkPaint* paint = NULL) {}
102
103     virtual void drawText(const void*, size_t byteLength, SkScalar,
104                           SkScalar, const SkPaint& paint)
105     {
106         setHasText();
107     }
108
109     virtual void drawPosText(const void* , size_t byteLength,
110                              const SkPoint [], const SkPaint& paint)
111     {
112         setHasText();
113     }
114
115     virtual void drawPosTextH(const void*, size_t byteLength,
116                               const SkScalar [], SkScalar,
117                               const SkPaint& paint)
118     {
119         setHasText();
120     }
121
122     virtual void drawTextOnPath(const void*, size_t byteLength,
123                                 const SkPath&, const SkMatrix*,
124                                 const SkPaint& paint)
125     {
126         setHasText();
127     }
128
129     virtual void drawPicture(SkPicture& picture) {
130         SkCanvas::drawPicture(picture);
131     }
132
133 private:
134
135     SkPicture* m_picture;
136     bool m_hasText;
137 };
138
139 ///////////////////////////////////////////////////////////////////////////////
140
141 LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(),
142     m_haveClip(false),
143     m_isFixed(false),
144     m_isIframe(false),
145     m_backfaceVisibility(true),
146     m_visible(true),
147     m_preserves3D(false),
148     m_anchorPointZ(0),
149     m_recordingPicture(0),
150     m_uniqueId(++gUniqueId),
151     m_texture(0),
152     m_imageRef(0),
153     m_imageTexture(0),
154     m_pictureUsed(0),
155     m_scale(1),
156     m_lastComputeTextureSize(0),
157     m_owningLayer(owner),
158     m_type(LayerAndroid::WebCoreLayer),
159     m_hasText(true)
160 {
161     m_backgroundColor = 0;
162
163     m_preserves3D = false;
164     m_iframeOffset.set(0,0);
165     m_dirtyRegion.setEmpty();
166 #ifdef DEBUG_COUNT
167     ClassTracker::instance()->increment("LayerAndroid");
168     ClassTracker::instance()->add(this);
169 #endif
170 }
171
172 LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer),
173     m_haveClip(layer.m_haveClip),
174     m_isIframe(layer.m_isIframe),
175     m_uniqueId(layer.m_uniqueId),
176     m_texture(0),
177     m_imageTexture(0),
178     m_owningLayer(layer.m_owningLayer),
179     m_type(LayerAndroid::UILayer),
180     m_hasText(true)
181 {
182     m_isFixed = layer.m_isFixed;
183     m_imageRef = layer.m_imageRef;
184     if (m_imageRef)
185         ImagesManager::instance()->addImage(m_imageRef);
186     m_renderLayerPos = layer.m_renderLayerPos;
187     m_transform = layer.m_transform;
188     m_backfaceVisibility = layer.m_backfaceVisibility;
189     m_visible = layer.m_visible;
190     m_backgroundColor = layer.m_backgroundColor;
191
192     m_fixedLeft = layer.m_fixedLeft;
193     m_fixedTop = layer.m_fixedTop;
194     m_fixedRight = layer.m_fixedRight;
195     m_fixedBottom = layer.m_fixedBottom;
196     m_fixedMarginLeft = layer.m_fixedMarginLeft;
197     m_fixedMarginTop = layer.m_fixedMarginTop;
198     m_fixedMarginRight = layer.m_fixedMarginRight;
199     m_fixedMarginBottom = layer.m_fixedMarginBottom;
200     m_fixedRect = layer.m_fixedRect;
201     m_iframeOffset = layer.m_iframeOffset;
202     m_recordingPicture = layer.m_recordingPicture;
203     SkSafeRef(m_recordingPicture);
204
205     m_preserves3D = layer.m_preserves3D;
206     m_anchorPointZ = layer.m_anchorPointZ;
207     m_drawTransform = layer.m_drawTransform;
208     m_childrenTransform = layer.m_childrenTransform;
209     m_pictureUsed = layer.m_pictureUsed;
210     m_dirtyRegion = layer.m_dirtyRegion;
211     m_scale = layer.m_scale;
212     m_lastComputeTextureSize = 0;
213
214     for (int i = 0; i < layer.countChildren(); i++)
215         addChild(layer.getChild(i)->copy())->unref();
216
217     KeyframesMap::const_iterator end = layer.m_animations.end();
218     for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it) {
219         pair<String, int> key((it->second)->name(), (it->second)->type());
220         m_animations.add(key, (it->second)->copy());
221     }
222
223     m_hasText = layer.m_hasText;
224
225 #ifdef DEBUG_COUNT
226     ClassTracker::instance()->increment("LayerAndroid - recopy (UI?)");
227     ClassTracker::instance()->add(this);
228 #endif
229 }
230
231 void LayerAndroid::checkTextPresence()
232 {
233     if (m_recordingPicture) {
234         // Let's check if we have text or not. If we don't, we can limit
235         // ourselves to scale 1!
236         HasTextBounder hasTextBounder;
237         HasTextCanvas checker(&hasTextBounder, m_recordingPicture);
238         SkBitmap bitmap;
239         bitmap.setConfig(SkBitmap::kARGB_8888_Config,
240                          m_recordingPicture->width(),
241                          m_recordingPicture->height());
242         checker.setBitmapDevice(bitmap);
243         checker.drawPicture(*m_recordingPicture);
244         m_hasText = checker.hasText();
245     }
246 }
247
248 LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(),
249     m_haveClip(false),
250     m_isFixed(false),
251     m_isIframe(false),
252     m_recordingPicture(picture),
253     m_uniqueId(++gUniqueId),
254     m_texture(0),
255     m_imageRef(0),
256     m_imageTexture(0),
257     m_scale(1),
258     m_lastComputeTextureSize(0),
259     m_owningLayer(0),
260     m_type(LayerAndroid::NavCacheLayer),
261     m_hasText(true)
262 {
263     m_backgroundColor = 0;
264     SkSafeRef(m_recordingPicture);
265     m_iframeOffset.set(0,0);
266     m_dirtyRegion.setEmpty();
267 #ifdef DEBUG_COUNT
268     ClassTracker::instance()->increment("LayerAndroid - from picture");
269     ClassTracker::instance()->add(this);
270 #endif
271 }
272
273 LayerAndroid::~LayerAndroid()
274 {
275     if (m_imageTexture)
276         ImagesManager::instance()->removeImage(m_imageTexture->imageRef());
277     SkSafeUnref(m_recordingPicture);
278     m_animations.clear();
279 #ifdef DEBUG_COUNT
280     ClassTracker::instance()->remove(this);
281     if (m_type == LayerAndroid::WebCoreLayer)
282         ClassTracker::instance()->decrement("LayerAndroid");
283     else if (m_type == LayerAndroid::UILayer)
284         ClassTracker::instance()->decrement("LayerAndroid - recopy (UI)");
285     else if (m_type == LayerAndroid::NavCacheLayer)
286         ClassTracker::instance()->decrement("LayerAndroid - from picture");
287 #endif
288 }
289
290 static int gDebugNbAnims = 0;
291
292 bool LayerAndroid::evaluateAnimations()
293 {
294     double time = WTF::currentTime();
295     gDebugNbAnims = 0;
296     return evaluateAnimations(time);
297 }
298
299 bool LayerAndroid::hasAnimations() const
300 {
301     for (int i = 0; i < countChildren(); i++) {
302         if (getChild(i)->hasAnimations())
303             return true;
304     }
305     return !!m_animations.size();
306 }
307
308 bool LayerAndroid::evaluateAnimations(double time)
309 {
310     bool hasRunningAnimations = false;
311     for (int i = 0; i < countChildren(); i++) {
312         if (getChild(i)->evaluateAnimations(time))
313             hasRunningAnimations = true;
314     }
315
316     m_hasRunningAnimations = false;
317     int nbAnims = 0;
318     KeyframesMap::const_iterator end = m_animations.end();
319     for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
320         gDebugNbAnims++;
321         nbAnims++;
322         LayerAndroid* currentLayer = const_cast<LayerAndroid*>(this);
323         m_hasRunningAnimations |= (it->second)->evaluate(currentLayer, time);
324     }
325
326     return hasRunningAnimations || m_hasRunningAnimations;
327 }
328
329 void LayerAndroid::addDirtyArea()
330 {
331     IntSize layerSize(getSize().width(), getSize().height());
332
333     FloatRect area = TilesManager::instance()->shader()->rectInInvScreenCoord(m_drawTransform, layerSize);
334     FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(m_clippingRect);
335     FloatRect clip = TilesManager::instance()->shader()->convertScreenCoordToInvScreenCoord(clippingRect);
336
337     area.intersect(clip);
338     IntRect dirtyArea(area.x(), area.y(), area.width(), area.height());
339     m_state->addDirtyArea(dirtyArea);
340 }
341
342 void LayerAndroid::addAnimation(PassRefPtr<AndroidAnimation> prpAnim)
343 {
344     RefPtr<AndroidAnimation> anim = prpAnim;
345     pair<String, int> key(anim->name(), anim->type());
346     removeAnimationsForProperty(anim->type());
347     m_animations.add(key, anim);
348 }
349
350 void LayerAndroid::removeAnimationsForProperty(AnimatedPropertyID property)
351 {
352     KeyframesMap::const_iterator end = m_animations.end();
353     Vector<pair<String, int> > toDelete;
354     for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
355         if ((it->second)->type() == property)
356             toDelete.append(it->first);
357     }
358
359     for (unsigned int i = 0; i < toDelete.size(); i++)
360         m_animations.remove(toDelete[i]);
361 }
362
363 void LayerAndroid::removeAnimationsForKeyframes(const String& name)
364 {
365     KeyframesMap::const_iterator end = m_animations.end();
366     Vector<pair<String, int> > toDelete;
367     for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
368         if ((it->second)->name() == name)
369             toDelete.append(it->first);
370     }
371
372     for (unsigned int i = 0; i < toDelete.size(); i++)
373             m_animations.remove(toDelete[i]);
374 }
375
376 // We only use the bounding rect of the layer as mask...
377 // FIXME: use a real mask?
378 void LayerAndroid::setMaskLayer(LayerAndroid* layer)
379 {
380     if (layer)
381         m_haveClip = true;
382 }
383
384 void LayerAndroid::setBackgroundColor(SkColor color)
385 {
386     m_backgroundColor = color;
387 }
388
389 static int gDebugChildLevel;
390
391 FloatPoint LayerAndroid::translation() const
392 {
393     TransformationMatrix::DecomposedType tDecomp;
394     m_transform.decompose(tDecomp);
395     FloatPoint p(tDecomp.translateX, tDecomp.translateY);
396     return p;
397 }
398
399 SkRect LayerAndroid::bounds() const
400 {
401     SkRect rect;
402     bounds(&rect);
403     return rect;
404 }
405
406 void LayerAndroid::bounds(SkRect* rect) const
407 {
408     const SkPoint& pos = this->getPosition();
409     const SkSize& size = this->getSize();
410
411     // The returned rect has the translation applied
412     // FIXME: apply the full transform to the rect,
413     // and fix the text selection accordingly
414     FloatPoint p(pos.fX, pos.fY);
415     p = m_transform.mapPoint(p);
416     rect->fLeft = p.x();
417     rect->fTop = p.y();
418     rect->fRight = p.x() + size.width();
419     rect->fBottom = p.y() + size.height();
420 }
421
422 static bool boundsIsUnique(const SkTDArray<SkRect>& region,
423                            const SkRect& local)
424 {
425     for (int i = 0; i < region.count(); i++) {
426         if (region[i].contains(local))
427             return false;
428     }
429     return true;
430 }
431
432 void LayerAndroid::clipArea(SkTDArray<SkRect>* region) const
433 {
434     SkRect local;
435     local.set(0, 0, std::numeric_limits<float>::max(),
436         std::numeric_limits<float>::max());
437     clipInner(region, local);
438 }
439
440 void LayerAndroid::clipInner(SkTDArray<SkRect>* region,
441                              const SkRect& local) const
442 {
443     SkRect localBounds;
444     bounds(&localBounds);
445     localBounds.intersect(local);
446     if (localBounds.isEmpty())
447         return;
448     if (m_recordingPicture && boundsIsUnique(*region, localBounds))
449         *region->append() = localBounds;
450     for (int i = 0; i < countChildren(); i++)
451         getChild(i)->clipInner(region, m_haveClip ? localBounds : local);
452 }
453
454 class FindCheck : public SkBounder {
455 public:
456     FindCheck()
457         : m_drew(false)
458         , m_drewText(false)
459     {
460     }
461
462     bool drew() const { return m_drew; }
463     bool drewText() const { return m_drewText; }
464     void reset() { m_drew = m_drewText = false; }
465
466 protected:
467     virtual bool onIRect(const SkIRect& )
468     {
469         m_drew = true;
470         return false;
471     }
472
473     virtual bool onIRectGlyph(const SkIRect& , const SkBounder::GlyphRec& )
474     {
475         m_drew = m_drewText = true;
476         return false;
477     }
478
479     bool m_drew;
480     bool m_drewText;
481 };
482
483 class FindCanvas : public ParseCanvas {
484 public:
485     void draw(SkPicture* picture, SkScalar offsetX, SkScalar offsetY)
486     {
487         save();
488         translate(-offsetX, -offsetY);
489         picture->draw(this);
490         restore();
491     }
492 };
493
494 class LayerAndroid::FindState {
495 public:
496     static const int TOUCH_SLOP = 10;
497
498     FindState(int x, int y)
499         : m_x(x)
500         , m_y(y)
501         , m_bestX(x)
502         , m_bestY(y)
503         , m_best(0)
504     {
505         m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, TOUCH_SLOP * 2,
506              TOUCH_SLOP * 2);
507         m_checker.setBounder(&m_findCheck);
508         m_checker.setBitmapDevice(m_bitmap);
509     }
510
511     const LayerAndroid* best() const { return m_best; }
512     int bestX() const { return m_bestX; }
513     int bestY() const { return m_bestY; }
514
515     bool drew(SkPicture* picture, const SkRect& localBounds)
516     {
517         m_findCheck.reset();
518         SkScalar localX = SkIntToScalar(m_x - TOUCH_SLOP) - localBounds.fLeft;
519         SkScalar localY = SkIntToScalar(m_y - TOUCH_SLOP) - localBounds.fTop;
520         m_checker.draw(picture, localX, localY);
521         return m_findCheck.drew();
522     }
523
524     bool drewText() { return m_findCheck.drewText(); }
525
526     void setBest(const LayerAndroid* best, int x, int y)
527     {
528         m_best = best;
529         m_bestX = x;
530         m_bestY = y;
531     }
532     int x() const { return m_x; }
533     int y() const { return m_y; }
534
535     void setLocation(int x, int y)
536     {
537         m_x = x;
538         m_y = y;
539     }
540
541 protected:
542     int m_x;
543     int m_y;
544     int m_bestX;
545     int m_bestY;
546     const LayerAndroid* m_best;
547     FindCheck m_findCheck;
548     SkBitmap m_bitmap;
549     FindCanvas m_checker;
550 };
551
552 void LayerAndroid::findInner(LayerAndroid::FindState& state) const
553 {
554     int x = state.x();
555     int y = state.y();
556     SkRect localBounds;
557     bounds(&localBounds);
558     if (!localBounds.contains(x, y))
559         return;
560     // Move into local coordinates.
561     state.setLocation(x - localBounds.fLeft, y - localBounds.fTop);
562     for (int i = 0; i < countChildren(); i++)
563         getChild(i)->findInner(state);
564     // Move back into the parent coordinates.
565     int testX = state.x();
566     int testY = state.y();
567     state.setLocation(x + localBounds.fLeft, y + localBounds.fTop);
568     if (!m_recordingPicture)
569         return;
570     if (!contentIsScrollable() && !state.drew(m_recordingPicture, localBounds))
571         return;
572     state.setBest(this, testX, testY); // set last match (presumably on top)
573 }
574
575 const LayerAndroid* LayerAndroid::find(int* xPtr, int* yPtr, SkPicture* root) const
576 {
577     FindState state(*xPtr, *yPtr);
578     SkRect rootBounds;
579     rootBounds.setEmpty();
580     if (root && state.drew(root, rootBounds) && state.drewText())
581         return 0; // use the root picture only if it contains the text
582     findInner(state);
583     *xPtr = state.bestX();
584     *yPtr = state.bestY();
585     return state.best();
586 }
587
588 ///////////////////////////////////////////////////////////////////////////////
589
590 bool LayerAndroid::updateFixedLayersPositions(SkRect viewport, LayerAndroid* parentIframeLayer)
591 {
592     bool hasFixedElements = false;
593     XLOG("updating fixed positions, using viewport %fx%f - %fx%f",
594          viewport.fLeft, viewport.fTop,
595          viewport.width(), viewport.height());
596     // If this is an iframe, accumulate the offset from the parent with
597     // current position, and change the parent pointer.
598     if (m_isIframe) {
599         // If this is the top level, take the current position
600         SkPoint parentOffset;
601         parentOffset.set(0,0);
602         if (parentIframeLayer)
603             parentOffset = parentIframeLayer->getPosition();
604
605         m_iframeOffset = parentOffset + getPosition();
606
607         parentIframeLayer = this;
608     }
609
610     if (m_isFixed) {
611         hasFixedElements = true;
612         // So if this is a fixed layer inside a iframe, use the iframe offset
613         // and the iframe's size as the viewport and pass to the children
614         if (parentIframeLayer) {
615             viewport = SkRect::MakeXYWH(parentIframeLayer->m_iframeOffset.fX,
616                                  parentIframeLayer->m_iframeOffset.fY,
617                                  parentIframeLayer->getSize().width(),
618                                  parentIframeLayer->getSize().height());
619         }
620         float w = viewport.width();
621         float h = viewport.height();
622         float dx = viewport.fLeft;
623         float dy = viewport.fTop;
624         float x = dx;
625         float y = dy;
626
627         // It turns out that when it is 'auto', we should use the webkit value
628         // from the original render layer's X,Y, that will take care of alignment
629         // with the parent's layer and fix Margin etc.
630         if (!(m_fixedLeft.defined() || m_fixedRight.defined()))
631             x += m_renderLayerPos.x();
632         else if (m_fixedLeft.defined() || !m_fixedRight.defined())
633             x += m_fixedMarginLeft.calcFloatValue(w) + m_fixedLeft.calcFloatValue(w) - m_fixedRect.fLeft;
634         else
635             x += w - m_fixedMarginRight.calcFloatValue(w) - m_fixedRight.calcFloatValue(w) - m_fixedRect.fRight;
636
637         if (!(m_fixedTop.defined() || m_fixedBottom.defined()))
638             y += m_renderLayerPos.y();
639         else if (m_fixedTop.defined() || !m_fixedBottom.defined())
640             y += m_fixedMarginTop.calcFloatValue(h) + m_fixedTop.calcFloatValue(h) - m_fixedRect.fTop;
641         else
642             y += h - m_fixedMarginBottom.calcFloatValue(h) - m_fixedBottom.calcFloatValue(h) - m_fixedRect.fBottom;
643
644         this->setPosition(x, y);
645     }
646
647     int count = this->countChildren();
648     for (int i = 0; i < count; i++)
649         hasFixedElements |= this->getChild(i)->updateFixedLayersPositions(viewport, parentIframeLayer);
650
651     return hasFixedElements;
652 }
653
654 void LayerAndroid::updatePositions()
655 {
656     // apply the viewport to us
657     if (!m_isFixed) {
658         // turn our fields into a matrix.
659         //
660         // FIXME: this should happen in the caller, and we should remove these
661         // fields from our subclass
662         SkMatrix matrix;
663         GLUtils::toSkMatrix(matrix, m_transform);
664         this->setMatrix(matrix);
665     }
666
667     // now apply it to our children
668     int count = this->countChildren();
669     for (int i = 0; i < count; i++)
670         this->getChild(i)->updatePositions();
671 }
672
673 void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentMatrix,
674                                              const FloatRect& clipping, float opacity, float scale)
675 {
676     m_atomicSync.lock();
677     IntSize layerSize(getSize().width(), getSize().height());
678     FloatPoint anchorPoint(getAnchorPoint().fX, getAnchorPoint().fY);
679     FloatPoint position(getPosition().fX, getPosition().fY);
680     float centerOffsetX = (0.5f - anchorPoint.x()) * layerSize.width();
681     float centerOffsetY = (0.5f - anchorPoint.y()) * layerSize.height();
682     float originX = anchorPoint.x() * layerSize.width();
683     float originY = anchorPoint.y() * layerSize.height();
684     TransformationMatrix localMatrix;
685     if (!m_isFixed)
686         localMatrix = parentMatrix;
687     localMatrix.translate3d(originX + position.x(),
688                             originY + position.y(),
689                             anchorPointZ());
690     localMatrix.multiply(m_transform);
691     localMatrix.translate3d(-originX,
692                             -originY,
693                             -anchorPointZ());
694
695     m_atomicSync.unlock();
696     setDrawTransform(localMatrix);
697     if (m_drawTransform.isIdentityOrTranslation()) {
698         // adjust the translation coordinates of the draw transform matrix so
699         // that layers (defined in content coordinates) will align to display/view pixels
700         float desiredContentX = round(m_drawTransform.m41() * scale) / scale;
701         float desiredContentY = round(m_drawTransform.m42() * scale) / scale;
702         XLOG("fudging translation from %f, %f to %f, %f",
703              m_drawTransform.m41(), m_drawTransform.m42(),
704              desiredContentX, desiredContentY);
705         m_drawTransform.setM41(desiredContentX);
706         m_drawTransform.setM42(desiredContentY);
707     }
708
709     m_zValue = TilesManager::instance()->shader()->zValue(m_drawTransform, getSize().width(), getSize().height());
710
711     m_atomicSync.lock();
712     m_scale = scale;
713     m_atomicSync.unlock();
714
715     opacity *= getOpacity();
716     setDrawOpacity(opacity);
717
718     if (m_haveClip) {
719         // The clipping rect calculation and intersetion will be done in documents coordinates.
720         FloatRect rect(0, 0, layerSize.width(), layerSize.height());
721         FloatRect clip = m_drawTransform.mapRect(rect);
722         clip.intersect(clipping);
723         setDrawClip(clip);
724     } else {
725         setDrawClip(clipping);
726     }
727
728     if (!m_backfaceVisibility
729          && m_drawTransform.inverse().m33() < 0) {
730          setVisible(false);
731          return;
732     } else {
733          setVisible(true);
734     }
735
736     int count = this->countChildren();
737     if (!count)
738         return;
739
740     // Flatten to 2D if the layer doesn't preserve 3D.
741     if (!preserves3D()) {
742         localMatrix.setM13(0);
743         localMatrix.setM23(0);
744         localMatrix.setM31(0);
745         localMatrix.setM32(0);
746         localMatrix.setM33(1);
747         localMatrix.setM34(0);
748         localMatrix.setM43(0);
749     }
750
751     // now apply it to our children
752
753     if (!m_childrenTransform.isIdentity()) {
754         localMatrix.translate(getSize().width() * 0.5f, getSize().height() * 0.5f);
755         localMatrix.multiply(m_childrenTransform);
756         localMatrix.translate(-getSize().width() * 0.5f, -getSize().height() * 0.5f);
757     }
758     for (int i = 0; i < count; i++)
759         this->getChild(i)->updateGLPositionsAndScale(localMatrix, drawClip(), opacity, scale);
760 }
761
762 void LayerAndroid::setContentsImage(SkBitmapRef* img)
763 {
764     m_imageRef = img;
765     if (!img)
766         return;
767
768     ImagesManager::instance()->addImage(img);
769 }
770
771 bool LayerAndroid::needsTexture()
772 {
773     return m_imageRef || (prepareContext()
774         && m_recordingPicture->width() && m_recordingPicture->height());
775 }
776
777 void LayerAndroid::removeTexture(PaintedSurface* texture)
778 {
779     if (texture == m_texture)
780         m_texture = 0;
781 }
782
783 IntRect LayerAndroid::clippedRect() const
784 {
785     IntRect r(0, 0, getWidth(), getHeight());
786     IntRect tr = m_drawTransform.mapRect(r);
787     IntRect cr = TilesManager::instance()->shader()->clippedRectWithViewport(tr);
788     IntRect rect = m_drawTransform.inverse().mapRect(cr);
789     return rect;
790 }
791
792 int LayerAndroid::nbLayers()
793 {
794     int nb = 0;
795     int count = this->countChildren();
796     for (int i = 0; i < count; i++)
797         nb += this->getChild(i)->nbLayers();
798     return nb+1;
799 }
800
801 int LayerAndroid::nbTexturedLayers()
802 {
803     int nb = 0;
804     int count = this->countChildren();
805     for (int i = 0; i < count; i++)
806         nb += this->getChild(i)->nbTexturedLayers();
807     if (needsTexture())
808         nb++;
809     return nb;
810 }
811
812 void LayerAndroid::computeTexturesAmount(TexturesResult* result)
813 {
814     if (!result)
815         return;
816
817     int count = this->countChildren();
818     for (int i = 0; i < count; i++)
819         this->getChild(i)->computeTexturesAmount(result);
820     if (m_texture && m_visible)
821         m_texture->computeTexturesAmount(result);
822 }
823
824 void LayerAndroid::showLayer(int indent)
825 {
826     char spaces[256];
827     memset(spaces, 0, 256);
828     for (int i = 0; i < indent; i++)
829         spaces[i] = ' ';
830
831     if (!indent) {
832         XLOGC("\n\n--- LAYERS TREE ---");
833         IntRect documentViewport(TilesManager::instance()->shader()->documentViewport());
834         XLOGC("documentViewport(%d, %d, %d, %d)",
835               documentViewport.x(), documentViewport.y(),
836               documentViewport.width(), documentViewport.height());
837     }
838
839     IntRect r(0, 0, getWidth(), getHeight());
840     IntRect tr = m_drawTransform.mapRect(r);
841     IntRect visible = visibleArea();
842     IntRect clip(m_clippingRect.x(), m_clippingRect.y(),
843                  m_clippingRect.width(), m_clippingRect.height());
844     XLOGC("%s [%d:0x%x] - %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) "
845           "clip (%d, %d, %d, %d) %s prepareContext(%d), pic w: %d h: %d",
846           spaces, uniqueId(), m_owningLayer,
847           needsTexture() ? "needs a texture" : "no texture",
848           tr.x(), tr.y(), tr.width(), tr.height(),
849           visible.x(), visible.y(), visible.width(), visible.height(),
850           clip.x(), clip.y(), clip.width(), clip.height(),
851           contentIsScrollable() ? "SCROLLABLE" : "",
852           prepareContext(),
853           m_recordingPicture ? m_recordingPicture->width() : -1,
854           m_recordingPicture ? m_recordingPicture->height() : -1);
855
856     int count = this->countChildren();
857     for (int i = 0; i < count; i++)
858         this->getChild(i)->showLayer(indent + 1);
859 }
860
861 void LayerAndroid::swapTiles()
862 {
863     int count = this->countChildren();
864     for (int i = 0; i < count; i++)
865         this->getChild(i)->swapTiles();
866
867     if (m_texture)
868         m_texture->swapTiles();
869 }
870
871 void LayerAndroid::setIsDrawing(bool isDrawing)
872 {
873     int count = this->countChildren();
874     for (int i = 0; i < count; i++)
875         this->getChild(i)->setIsDrawing(isDrawing);
876
877     if (m_texture) {
878         m_texture->setDrawingLayer(isDrawing ? this : 0);
879         m_texture->clearPaintingLayer();
880     }
881 }
882
883 void LayerAndroid::setIsPainting(Layer* drawingTree)
884 {
885     XLOG("setting layer %p as painting, needs texture %d, drawing tree %p",
886          this, needsTexture(), drawingTree);
887     int count = this->countChildren();
888     for (int i = 0; i < count; i++)
889         this->getChild(i)->setIsPainting(drawingTree);
890
891     obtainTextureForPainting(static_cast<LayerAndroid*>(drawingTree));
892 }
893
894 void LayerAndroid::mergeInvalsInto(Layer* replacementTree)
895 {
896     int count = this->countChildren();
897     for (int i = 0; i < count; i++)
898         this->getChild(i)->mergeInvalsInto(replacementTree);
899
900     LayerAndroid* replacementLayer = static_cast<LayerAndroid*>(replacementTree)->findById(uniqueId());
901     if (replacementLayer)
902         replacementLayer->markAsDirty(m_dirtyRegion);
903 }
904
905 bool LayerAndroid::isReady()
906 {
907     int count = countChildren();
908     for (int i = 0; i < count; i++)
909         if (!getChild(i)->isReady())
910             return false;
911
912     if (m_texture)
913         return m_texture->isReady();
914     // TODO: image, check if uploaded?
915     return true;
916 }
917
918 bool LayerAndroid::updateWithTree(LayerAndroid* newTree)
919 {
920 // Disable fast update for now
921 #if (0)
922     bool needsRepaint = false;
923     int count = this->countChildren();
924     for (int i = 0; i < count; i++)
925         needsRepaint |= this->getChild(i)->updateWithTree(newTree);
926
927     if (newTree) {
928         LayerAndroid* newLayer = newTree->findById(uniqueId());
929         needsRepaint |= updateWithLayer(newLayer);
930     }
931     return needsRepaint;
932 #else
933     return true;
934 #endif
935 }
936
937 // Return true to indicate to WebViewCore that the updates
938 // are too complicated to be fully handled and we need a full
939 // call to webkit (e.g. handle repaints)
940 bool LayerAndroid::updateWithLayer(LayerAndroid* layer)
941 {
942     if (!layer)
943         return true;
944
945     android::AutoMutex lock(m_atomicSync);
946     m_position = layer->m_position;
947     m_anchorPoint = layer->m_anchorPoint;
948     m_size = layer->m_size;
949     m_opacity = layer->m_opacity;
950     m_transform = layer->m_transform;
951
952     if (m_imageRef != layer->m_imageRef)
953         m_visible = false;
954
955     if ((m_recordingPicture != layer->m_recordingPicture)
956         || (m_imageRef != layer->m_imageRef))
957         return true;
958
959     return false;
960 }
961
962 void LayerAndroid::obtainTextureForPainting(LayerAndroid* drawingTree)
963 {
964     if (!needsTexture())
965         return;
966
967     if (m_imageRef) {
968         if (!m_imageTexture) {
969             m_imageTexture = ImagesManager::instance()->getTextureForImage(m_imageRef);
970             m_dirtyRegion.setEmpty();
971         }
972         if (m_texture) {
973             m_texture->setDrawingLayer(0);
974             m_texture->clearPaintingLayer();
975             m_texture = 0;
976         }
977     } else {
978         if (drawingTree) {
979             LayerAndroid* drawingLayer = drawingTree->findById(uniqueId());
980             if (drawingLayer) {
981                 // if a previous tree had the same layer, paint with that painted surface
982                 m_texture = drawingLayer->m_texture;
983             }
984         }
985
986         if (!m_texture)
987             m_texture = new PaintedSurface();
988
989         // pass the invalidated regions to the PaintedSurface
990         m_texture->setPaintingLayer(this, m_dirtyRegion);
991         m_dirtyRegion.setEmpty();
992     }
993 }
994
995
996 static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b)
997 {
998     return a->zValue() > b->zValue();
999 }
1000
1001 // We call this in WebViewCore, when copying the tree of layers.
1002 // As we construct a new tree that will be passed on the UI,
1003 // we mark the webkit-side tree as having no more dirty region
1004 // (otherwise we would continuously have those dirty region UI-side)
1005 void LayerAndroid::clearDirtyRegion()
1006 {
1007     int count = this->countChildren();
1008     for (int i = 0; i < count; i++)
1009         this->getChild(i)->clearDirtyRegion();
1010
1011     m_dirtyRegion.setEmpty();
1012 }
1013
1014 void LayerAndroid::prepare()
1015 {
1016     XLOG("LA %p preparing, m_texture %p", this, m_texture);
1017
1018     int count = this->countChildren();
1019     if (count > 0) {
1020         Vector <LayerAndroid*> sublayers;
1021         for (int i = 0; i < count; i++)
1022             sublayers.append(this->getChild(i));
1023
1024         // now we sort for the transparency
1025         std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
1026
1027         // iterate in reverse so top layers get textures first
1028         for (int i = count-1; i >= 0; i--)
1029             sublayers[i]->prepare();
1030     }
1031
1032     if (m_texture)
1033         m_texture->prepare(m_state);
1034
1035     if (m_imageTexture)
1036         m_imageTexture->prepareGL();
1037 }
1038
1039 IntRect LayerAndroid::unclippedArea()
1040 {
1041     IntRect area;
1042     area.setX(0);
1043     area.setY(0);
1044     area.setWidth(getSize().width());
1045     area.setHeight(getSize().height());
1046     return area;
1047 }
1048
1049 IntRect LayerAndroid::visibleArea()
1050 {
1051     IntRect area = unclippedArea();
1052     // First, we get the transformed area of the layer,
1053     // in document coordinates
1054     IntRect rect = m_drawTransform.mapRect(area);
1055     int dx = rect.x();
1056     int dy = rect.y();
1057
1058     // Then we apply the clipping
1059     IntRect clip(m_clippingRect);
1060     rect.intersect(clip);
1061
1062     // Now clip with the viewport in documents coordinate
1063     IntRect documentViewport(TilesManager::instance()->shader()->documentViewport());
1064     rect.intersect(documentViewport);
1065
1066     // Finally, let's return the visible area, in layers coordinate
1067     rect.move(-dx, -dy);
1068     return rect;
1069 }
1070
1071 bool LayerAndroid::drawCanvas(SkCanvas* canvas)
1072 {
1073     if (!m_visible)
1074         return false;
1075
1076     bool askScreenUpdate = false;
1077
1078     {
1079         SkAutoCanvasRestore acr(canvas, true);
1080         SkRect r;
1081         r.set(m_clippingRect.x(), m_clippingRect.y(),
1082               m_clippingRect.x() + m_clippingRect.width(),
1083               m_clippingRect.y() + m_clippingRect.height());
1084         canvas->clipRect(r);
1085         SkMatrix matrix;
1086         GLUtils::toSkMatrix(matrix, m_drawTransform);
1087         SkMatrix canvasMatrix = canvas->getTotalMatrix();
1088         matrix.postConcat(canvasMatrix);
1089         canvas->setMatrix(matrix);
1090         SkRect layerRect;
1091         layerRect.fLeft = 0;
1092         layerRect.fTop = 0;
1093         layerRect.fRight = getWidth();
1094         layerRect.fBottom = getHeight();
1095         onDraw(canvas, m_drawOpacity);
1096     }
1097
1098     // When the layer is dirty, the UI thread should be notified to redraw.
1099     askScreenUpdate |= drawChildrenCanvas(canvas);
1100     m_atomicSync.lock();
1101     if (askScreenUpdate || m_hasRunningAnimations || m_drawTransform.hasPerspective())
1102         addDirtyArea();
1103
1104     m_atomicSync.unlock();
1105     return askScreenUpdate;
1106 }
1107
1108 bool LayerAndroid::drawGL()
1109 {
1110     FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(m_clippingRect);
1111     TilesManager::instance()->shader()->clip(clippingRect);
1112     if (!m_visible)
1113         return false;
1114
1115     bool askScreenUpdate = false;
1116
1117     if (m_texture)
1118         askScreenUpdate |= m_texture->draw();
1119
1120     if (m_imageTexture)
1121         m_imageTexture->drawGL(this);
1122
1123     // When the layer is dirty, the UI thread should be notified to redraw.
1124     askScreenUpdate |= drawChildrenGL();
1125     m_atomicSync.lock();
1126     if (askScreenUpdate || m_hasRunningAnimations || m_drawTransform.hasPerspective())
1127         addDirtyArea();
1128
1129     m_atomicSync.unlock();
1130     return askScreenUpdate;
1131 }
1132
1133 bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas)
1134 {
1135     bool askScreenUpdate = false;
1136     int count = this->countChildren();
1137     if (count > 0) {
1138         Vector <LayerAndroid*> sublayers;
1139         for (int i = 0; i < count; i++)
1140             sublayers.append(this->getChild(i));
1141
1142         // now we sort for the transparency
1143         std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
1144         for (int i = 0; i < count; i++) {
1145             LayerAndroid* layer = sublayers[i];
1146             askScreenUpdate |= layer->drawCanvas(canvas);
1147         }
1148     }
1149
1150     return askScreenUpdate;
1151 }
1152
1153 bool LayerAndroid::drawChildrenGL()
1154 {
1155     bool askScreenUpdate = false;
1156     int count = this->countChildren();
1157     if (count > 0) {
1158         Vector <LayerAndroid*> sublayers;
1159         for (int i = 0; i < count; i++)
1160             sublayers.append(this->getChild(i));
1161
1162         // now we sort for the transparency
1163         std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
1164         for (int i = 0; i < count; i++) {
1165             LayerAndroid* layer = sublayers[i];
1166             askScreenUpdate |= layer->drawGL();
1167         }
1168     }
1169
1170     return askScreenUpdate;
1171 }
1172
1173 void LayerAndroid::contentDraw(SkCanvas* canvas)
1174 {
1175     if (m_recordingPicture)
1176       canvas->drawPicture(*m_recordingPicture);
1177
1178     if (TilesManager::instance()->getShowVisualIndicator()) {
1179         float w = getSize().width();
1180         float h = getSize().height();
1181         SkPaint paint;
1182         paint.setARGB(128, 255, 0, 0);
1183         canvas->drawLine(0, 0, w, h, paint);
1184         canvas->drawLine(0, h, w, 0, paint);
1185         paint.setARGB(128, 0, 255, 0);
1186         canvas->drawLine(0, 0, 0, h, paint);
1187         canvas->drawLine(0, h, w, h, paint);
1188         canvas->drawLine(w, h, w, 0, paint);
1189         canvas->drawLine(w, 0, 0, 0, paint);
1190
1191         if (m_isFixed) {
1192           SkPaint paint;
1193           paint.setARGB(80, 255, 0, 0);
1194           canvas->drawRect(m_fixedRect, paint);
1195         }
1196     }
1197 }
1198
1199 void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity)
1200 {
1201     if (m_haveClip) {
1202         SkRect r;
1203         r.set(0, 0, getSize().width(), getSize().height());
1204         canvas->clipRect(r);
1205         return;
1206     }
1207
1208     if (!prepareContext())
1209         return;
1210
1211     // we just have this save/restore for opacity...
1212     SkAutoCanvasRestore restore(canvas, true);
1213
1214     int canvasOpacity = SkScalarRound(opacity * 255);
1215     if (canvasOpacity < 255)
1216         canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity));
1217
1218     if (m_imageRef) {
1219         if (!m_imageTexture) {
1220             m_imageTexture = ImagesManager::instance()->getTextureForImage(m_imageRef);
1221             m_dirtyRegion.setEmpty();
1222         }
1223         if (m_imageTexture) {
1224             SkRect dest;
1225             dest.set(0, 0, getSize().width(), getSize().height());
1226             m_imageTexture->drawCanvas(canvas, dest);
1227         }
1228     }
1229     contentDraw(canvas);
1230 }
1231
1232 SkPicture* LayerAndroid::recordContext()
1233 {
1234     if (prepareContext(true))
1235         return m_recordingPicture;
1236     return 0;
1237 }
1238
1239 bool LayerAndroid::prepareContext(bool force)
1240 {
1241     if (masksToBounds())
1242         return false;
1243
1244     if (force || !m_recordingPicture ||
1245         (m_recordingPicture &&
1246          ((m_recordingPicture->width() != (int) getSize().width()) ||
1247           (m_recordingPicture->height() != (int) getSize().height())))) {
1248         SkSafeUnref(m_recordingPicture);
1249         m_recordingPicture = new SkPicture();
1250     }
1251
1252     return m_recordingPicture;
1253 }
1254
1255 SkRect LayerAndroid::subtractLayers(const SkRect& visibleRect) const
1256 {
1257     SkRect result;
1258     if (m_recordingPicture) {
1259         // FIXME: This seems wrong. localToGlobal() applies the full local transform,
1260         // se surely we should operate globalMatrix on size(), not bounds() with
1261         // the position removed? Perhaps we never noticed the bug because most
1262         // layers don't use a local transform?
1263         // See http://b/5338388
1264         SkRect globalRect = bounds();
1265         globalRect.offset(-getPosition()); // localToGlobal adds in position
1266         SkMatrix globalMatrix;
1267         localToGlobal(&globalMatrix);
1268         globalMatrix.mapRect(&globalRect);
1269         SkIRect roundedGlobal;
1270         globalRect.round(&roundedGlobal);
1271         SkIRect iVisibleRect;
1272         visibleRect.round(&iVisibleRect);
1273         SkRegion visRegion(iVisibleRect);
1274         visRegion.op(roundedGlobal, SkRegion::kDifference_Op);
1275         result.set(visRegion.getBounds());
1276 #if DEBUG_NAV_UI
1277         SkDebugf("%s visibleRect=(%g,%g,r=%g,b=%g) globalRect=(%g,%g,r=%g,b=%g)"
1278             "result=(%g,%g,r=%g,b=%g)", __FUNCTION__,
1279             visibleRect.fLeft, visibleRect.fTop,
1280             visibleRect.fRight, visibleRect.fBottom,
1281             globalRect.fLeft, globalRect.fTop,
1282             globalRect.fRight, globalRect.fBottom,
1283             result.fLeft, result.fTop, result.fRight, result.fBottom);
1284 #endif
1285     } else
1286         result = visibleRect;
1287     for (int i = 0; i < countChildren(); i++)
1288         result = getChild(i)->subtractLayers(result);
1289     return result;
1290 }
1291
1292 // Debug tools : dump the layers tree in a file.
1293 // The format is simple:
1294 // properties have the form: key = value;
1295 // all statements are finished with a semi-colon.
1296 // value can be:
1297 // - int
1298 // - float
1299 // - array of elements
1300 // - composed type
1301 // a composed type enclose properties in { and }
1302 // an array enclose composed types in { }, separated with a comma.
1303 // exemple:
1304 // {
1305 //   x = 3;
1306 //   y = 4;
1307 //   value = {
1308 //     x = 3;
1309 //     y = 4;
1310 //   };
1311 //   anarray = [
1312 //     { x = 3; },
1313 //     { y = 4; }
1314 //   ];
1315 // }
1316
1317 void lwrite(FILE* file, const char* str)
1318 {
1319     fwrite(str, sizeof(char), strlen(str), file);
1320 }
1321
1322 void writeIndent(FILE* file, int indentLevel)
1323 {
1324     if (indentLevel)
1325         fprintf(file, "%*s", indentLevel*2, " ");
1326 }
1327
1328 void writeln(FILE* file, int indentLevel, const char* str)
1329 {
1330     writeIndent(file, indentLevel);
1331     lwrite(file, str);
1332     lwrite(file, "\n");
1333 }
1334
1335 void writeIntVal(FILE* file, int indentLevel, const char* str, int value)
1336 {
1337     writeIndent(file, indentLevel);
1338     fprintf(file, "%s = %d;\n", str, value);
1339 }
1340
1341 void writeHexVal(FILE* file, int indentLevel, const char* str, int value)
1342 {
1343     writeIndent(file, indentLevel);
1344     fprintf(file, "%s = %x;\n", str, value);
1345 }
1346
1347 void writeFloatVal(FILE* file, int indentLevel, const char* str, float value)
1348 {
1349     writeIndent(file, indentLevel);
1350     fprintf(file, "%s = %.3f;\n", str, value);
1351 }
1352
1353 void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point)
1354 {
1355     writeIndent(file, indentLevel);
1356     fprintf(file, "%s = { x = %.3f; y = %.3f; };\n", str, point.fX, point.fY);
1357 }
1358
1359 void writeSize(FILE* file, int indentLevel, const char* str, SkSize size)
1360 {
1361     writeIndent(file, indentLevel);
1362     fprintf(file, "%s = { w = %.3f; h = %.3f; };\n", str, size.width(), size.height());
1363 }
1364
1365 void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect)
1366 {
1367     writeIndent(file, indentLevel);
1368     fprintf(file, "%s = { x = %.3f; y = %.3f; w = %.3f; h = %.3f; };\n",
1369             str, rect.fLeft, rect.fTop, rect.width(), rect.height());
1370 }
1371
1372 void writeLength(FILE* file, int indentLevel, const char* str, SkLength length)
1373 {
1374     if (!length.defined())
1375         return;
1376     writeIndent(file, indentLevel);
1377     fprintf(file, "%s = { type = %d; value = %.2f; };\n", str, length.type, length.value);
1378 }
1379
1380 void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix)
1381 {
1382     writeIndent(file, indentLevel);
1383     fprintf(file, "%s = { (%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f),"
1384             "(%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f) };\n",
1385             str,
1386             matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(),
1387             matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(),
1388             matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(),
1389             matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44());
1390 }
1391
1392 void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const
1393 {
1394     writeln(file, indentLevel, "{");
1395
1396     writeHexVal(file, indentLevel + 1, "layer", (int)this);
1397     writeIntVal(file, indentLevel + 1, "layerId", m_uniqueId);
1398     writeIntVal(file, indentLevel + 1, "haveClip", m_haveClip);
1399     writeIntVal(file, indentLevel + 1, "isFixed", m_isFixed);
1400     writeIntVal(file, indentLevel + 1, "m_isIframe", m_isIframe);
1401     writePoint(file, indentLevel + 1, "m_iframeOffset", m_iframeOffset);
1402
1403     writeFloatVal(file, indentLevel + 1, "opacity", getOpacity());
1404     writeSize(file, indentLevel + 1, "size", getSize());
1405     writePoint(file, indentLevel + 1, "position", getPosition());
1406     writePoint(file, indentLevel + 1, "anchor", getAnchorPoint());
1407
1408     writeMatrix(file, indentLevel + 1, "drawMatrix", m_drawTransform);
1409     writeMatrix(file, indentLevel + 1, "transformMatrix", m_transform);
1410     writeRect(file, indentLevel + 1, "clippingRect", SkRect(m_clippingRect));
1411
1412     if (m_isFixed) {
1413         writeLength(file, indentLevel + 1, "fixedLeft", m_fixedLeft);
1414         writeLength(file, indentLevel + 1, "fixedTop", m_fixedTop);
1415         writeLength(file, indentLevel + 1, "fixedRight", m_fixedRight);
1416         writeLength(file, indentLevel + 1, "fixedBottom", m_fixedBottom);
1417         writeLength(file, indentLevel + 1, "fixedMarginLeft", m_fixedMarginLeft);
1418         writeLength(file, indentLevel + 1, "fixedMarginTop", m_fixedMarginTop);
1419         writeLength(file, indentLevel + 1, "fixedMarginRight", m_fixedMarginRight);
1420         writeLength(file, indentLevel + 1, "fixedMarginBottom", m_fixedMarginBottom);
1421         writeRect(file, indentLevel + 1, "fixedRect", m_fixedRect);
1422     }
1423
1424     if (m_recordingPicture) {
1425         writeIntVal(file, indentLevel + 1, "m_recordingPicture.width", m_recordingPicture->width());
1426         writeIntVal(file, indentLevel + 1, "m_recordingPicture.height", m_recordingPicture->height());
1427     }
1428
1429     if (countChildren()) {
1430         writeln(file, indentLevel + 1, "children = [");
1431         for (int i = 0; i < countChildren(); i++) {
1432             if (i > 0)
1433                 writeln(file, indentLevel + 1, ", ");
1434             getChild(i)->dumpLayers(file, indentLevel + 1);
1435         }
1436         writeln(file, indentLevel + 1, "];");
1437     }
1438     writeln(file, indentLevel, "}");
1439 }
1440
1441 void LayerAndroid::dumpToLog() const
1442 {
1443     FILE* file = fopen("/data/data/com.android.browser/layertmp", "w");
1444     dumpLayers(file, 0);
1445     fclose(file);
1446     file = fopen("/data/data/com.android.browser/layertmp", "r");
1447     char buffer[512];
1448     bzero(buffer, sizeof(buffer));
1449     while (fgets(buffer, sizeof(buffer), file))
1450         SkDebugf("%s", buffer);
1451     fclose(file);
1452 }
1453
1454 LayerAndroid* LayerAndroid::findById(int match)
1455 {
1456     if (m_uniqueId == match)
1457         return this;
1458     for (int i = 0; i < countChildren(); i++) {
1459         LayerAndroid* result = getChild(i)->findById(match);
1460         if (result)
1461             return result;
1462     }
1463     return 0;
1464 }
1465
1466 } // namespace WebCore
1467
1468 #endif // USE(ACCELERATED_COMPOSITING)