• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "config.h"
2 #include "LayerAndroid.h"
3 
4 #if USE(ACCELERATED_COMPOSITING)
5 
6 #include "AndroidAnimation.h"
7 #include "DrawExtra.h"
8 #include "SkCanvas.h"
9 #include "SkDrawFilter.h"
10 #include "SkPaint.h"
11 #include "SkPicture.h"
12 #include <wtf/CurrentTime.h>
13 
14 #define LAYER_DEBUG // Add diagonals for debugging
15 #undef LAYER_DEBUG
16 
17 namespace WebCore {
18 
19 static int gDebugLayerAndroidInstances;
20 static int gUniqueId;
21 
instancesCount()22 inline int LayerAndroid::instancesCount()
23 {
24     return gDebugLayerAndroidInstances;
25 }
26 
27 class OpacityDrawFilter : public SkDrawFilter {
28  public:
OpacityDrawFilter(int opacity)29     OpacityDrawFilter(int opacity) : m_opacity(opacity) { }
filter(SkCanvas * canvas,SkPaint * paint,Type)30     virtual bool filter(SkCanvas* canvas, SkPaint* paint, Type)
31     {
32         m_previousOpacity = paint->getAlpha();
33         paint->setAlpha(m_opacity);
34         return true;
35     }
restore(SkCanvas * canvas,SkPaint * paint,Type)36     virtual void restore(SkCanvas* canvas, SkPaint* paint, Type)
37     {
38         paint->setAlpha(m_previousOpacity);
39     }
40  private:
41     int m_opacity;
42     int m_previousOpacity;
43 };
44 
45 ///////////////////////////////////////////////////////////////////////////////
46 
LayerAndroid(bool isRootLayer)47 LayerAndroid::LayerAndroid(bool isRootLayer) : SkLayer(),
48     m_isRootLayer(isRootLayer),
49     m_haveClip(false),
50     m_doRotation(false),
51     m_isFixed(false),
52     m_recordingPicture(0),
53     m_extra(0),
54     m_uniqueId(++gUniqueId)
55 {
56     m_angleTransform = 0;
57     m_translation.set(0, 0);
58     m_scale.set(1, 1);
59     m_backgroundColor = 0;
60 
61     gDebugLayerAndroidInstances++;
62 }
63 
LayerAndroid(const LayerAndroid & layer)64 LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer),
65     m_isRootLayer(layer.m_isRootLayer),
66     m_haveClip(layer.m_haveClip),
67     m_extra(0), // deliberately not copied
68     m_uniqueId(layer.m_uniqueId)
69 {
70     m_doRotation = layer.m_doRotation;
71     m_isFixed = layer.m_isFixed;
72 
73     m_angleTransform = layer.m_angleTransform;
74     m_translation = layer.m_translation;
75     m_scale = layer.m_scale;
76     m_backgroundColor = layer.m_backgroundColor;
77 
78     m_fixedLeft = layer.m_fixedLeft;
79     m_fixedTop = layer.m_fixedTop;
80     m_fixedRight = layer.m_fixedRight;
81     m_fixedBottom = layer.m_fixedBottom;
82     m_fixedMarginLeft = layer.m_fixedMarginLeft;
83     m_fixedMarginTop = layer.m_fixedMarginTop;
84     m_fixedMarginRight = layer.m_fixedMarginRight;
85     m_fixedMarginBottom = layer.m_fixedMarginBottom;
86     m_fixedOffset = layer.m_fixedOffset;
87     m_fixedWidth = layer.m_fixedWidth;
88     m_fixedHeight = layer.m_fixedHeight;
89 
90     m_recordingPicture = layer.m_recordingPicture;
91     SkSafeRef(m_recordingPicture);
92 
93     for (int i = 0; i < layer.countChildren(); i++)
94         addChild(new LayerAndroid(*layer.getChild(i)))->unref();
95 
96     KeyframesMap::const_iterator end = layer.m_animations.end();
97     for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it)
98         m_animations.add((it->second)->name(), (it->second)->copy());
99 
100     gDebugLayerAndroidInstances++;
101 }
102 
LayerAndroid(SkPicture * picture)103 LayerAndroid::LayerAndroid(SkPicture* picture) : SkLayer(),
104     m_isRootLayer(true),
105     m_haveClip(false),
106     m_doRotation(false),
107     m_isFixed(false),
108     m_recordingPicture(picture),
109     m_extra(0),
110     m_uniqueId(-1)
111 {
112     m_angleTransform = 0;
113     m_translation.set(0, 0);
114     m_scale.set(1, 1);
115     m_backgroundColor = 0;
116     SkSafeRef(m_recordingPicture);
117     gDebugLayerAndroidInstances++;
118 }
119 
~LayerAndroid()120 LayerAndroid::~LayerAndroid()
121 {
122     removeChildren();
123     m_recordingPicture->safeUnref();
124     m_animations.clear();
125     gDebugLayerAndroidInstances--;
126 }
127 
128 static int gDebugNbAnims = 0;
129 
evaluateAnimations() const130 bool LayerAndroid::evaluateAnimations() const
131 {
132     double time = WTF::currentTime();
133     gDebugNbAnims = 0;
134     return evaluateAnimations(time);
135 }
136 
hasAnimations() const137 bool LayerAndroid::hasAnimations() const
138 {
139     for (int i = 0; i < countChildren(); i++) {
140         if (getChild(i)->hasAnimations())
141             return true;
142     }
143     return !!m_animations.size();
144 }
145 
evaluateAnimations(double time) const146 bool LayerAndroid::evaluateAnimations(double time) const
147 {
148     bool hasRunningAnimations = false;
149     for (int i = 0; i < countChildren(); i++) {
150         if (getChild(i)->evaluateAnimations(time))
151             hasRunningAnimations = true;
152     }
153     KeyframesMap::const_iterator end = m_animations.end();
154     for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
155         gDebugNbAnims++;
156         LayerAndroid* currentLayer = const_cast<LayerAndroid*>(this);
157         if ((it->second)->evaluate(currentLayer, time)) {
158             hasRunningAnimations = true;
159         }
160     }
161 
162     return hasRunningAnimations;
163 }
164 
addAnimation(PassRefPtr<AndroidAnimation> anim)165 void LayerAndroid::addAnimation(PassRefPtr<AndroidAnimation> anim)
166 {
167     m_animations.add(anim->name(), anim);
168 }
169 
removeAnimation(const String & name)170 void LayerAndroid::removeAnimation(const String& name)
171 {
172     m_animations.remove(name);
173 }
174 
175 // We only use the bounding rect of the layer as mask...
176 // TODO: use a real mask?
setMaskLayer(LayerAndroid * layer)177 void LayerAndroid::setMaskLayer(LayerAndroid* layer)
178 {
179     if (layer)
180         m_haveClip = true;
181 }
182 
setMasksToBounds(bool masksToBounds)183 void LayerAndroid::setMasksToBounds(bool masksToBounds)
184 {
185     m_haveClip = masksToBounds;
186 }
187 
setBackgroundColor(SkColor color)188 void LayerAndroid::setBackgroundColor(SkColor color)
189 {
190     m_backgroundColor = color;
191 }
192 
193 static int gDebugChildLevel;
194 
bounds(SkRect * rect) const195 void LayerAndroid::bounds(SkRect* rect) const
196 {
197     const SkPoint& pos = this->getPosition();
198     const SkSize& size = this->getSize();
199     rect->fLeft = pos.fX + m_translation.fX;
200     rect->fTop = pos.fY + m_translation.fY;
201     rect->fRight = rect->fLeft + size.width();
202     rect->fBottom = rect->fTop + size.height();
203 }
204 
boundsIsUnique(const SkTDArray<SkRect> & region,const SkRect & local)205 static bool boundsIsUnique(const SkTDArray<SkRect>& region,
206                            const SkRect& local)
207 {
208     for (int i = 0; i < region.count(); i++) {
209         if (region[i].contains(local))
210             return false;
211     }
212     return true;
213 }
214 
clipArea(SkTDArray<SkRect> * region) const215 void LayerAndroid::clipArea(SkTDArray<SkRect>* region) const
216 {
217     SkRect local;
218     local.set(0, 0, std::numeric_limits<float>::max(),
219         std::numeric_limits<float>::max());
220     clipInner(region, local);
221 }
222 
clipInner(SkTDArray<SkRect> * region,const SkRect & local) const223 void LayerAndroid::clipInner(SkTDArray<SkRect>* region,
224                              const SkRect& local) const
225 {
226     SkRect localBounds;
227     bounds(&localBounds);
228     localBounds.intersect(local);
229     if (localBounds.isEmpty())
230         return;
231     if (m_recordingPicture && boundsIsUnique(*region, localBounds))
232         *region->append() = localBounds;
233     for (int i = 0; i < countChildren(); i++)
234         getChild(i)->clipInner(region, m_haveClip ? localBounds : local);
235 }
236 
find(int x,int y) const237 const LayerAndroid* LayerAndroid::find(int x, int y) const
238 {
239     for (int i = 0; i < countChildren(); i++) {
240         const LayerAndroid* found = getChild(i)->find(x, y);
241         if (found)
242             return found;
243     }
244     SkRect localBounds;
245     bounds(&localBounds);
246     if (localBounds.contains(x, y))
247         return this;
248     return 0;
249 }
250 
251 ///////////////////////////////////////////////////////////////////////////////
252 
253 // The Layer bounds and the renderview bounds are not always indentical.
254 // We need to compute the intersection to correctly compute the
255 // positiong...
computeLayerRect(LayerAndroid * layer)256 static SkRect computeLayerRect(LayerAndroid* layer) {
257   SkRect layerRect, viewRect;
258   SkScalar fX, fY;
259   fX = layer->getOffset().fX;
260   fY = layer->getOffset().fY;
261   layerRect.set(0, 0, layer->getSize().width(), layer->getSize().height());
262   viewRect.set(-fX, -fY, -fX + layer->getFixedWidth(), -fY + layer->getFixedHeight());
263   layerRect.intersect(viewRect);
264   return layerRect;
265 }
266 
updateFixedLayersPositions(const SkRect & viewport)267 void LayerAndroid::updateFixedLayersPositions(const SkRect& viewport)
268 {
269     if (m_isFixed) {
270         float w = viewport.width();
271         float h = viewport.height();
272         float dx = viewport.fLeft;
273         float dy = viewport.fTop;
274         float x = dx;
275         float y = dy;
276 
277         SkRect layerRect = computeLayerRect(this);
278 
279         if (m_fixedLeft.defined())
280             x += m_fixedMarginLeft.calcFloatValue(w) + m_fixedLeft.calcFloatValue(w) - layerRect.fLeft;
281         else if (m_fixedRight.defined())
282             x += w - m_fixedMarginRight.calcFloatValue(w) - m_fixedRight.calcFloatValue(w) - layerRect.width();
283 
284         if (m_fixedTop.defined())
285             y += m_fixedMarginTop.calcFloatValue(h) + m_fixedTop.calcFloatValue(h) - layerRect.fTop;
286         else if (m_fixedBottom.defined())
287             y += h - m_fixedMarginBottom.calcFloatValue(h) - m_fixedBottom.calcFloatValue(h) - layerRect.fTop - layerRect.height();
288 
289         this->setPosition(x, y);
290     }
291 
292     int count = this->countChildren();
293     for (int i = 0; i < count; i++) {
294         this->getChild(i)->updateFixedLayersPositions(viewport);
295     }
296 }
297 
updatePositions()298 void LayerAndroid::updatePositions() {
299     // apply the viewport to us
300     SkMatrix matrix;
301     if (!m_isFixed) {
302         // turn our fields into a matrix.
303         //
304         // TODO: this should happen in the caller, and we should remove these
305         // fields from our subclass
306         matrix.setTranslate(m_translation.fX, m_translation.fY);
307         if (m_doRotation) {
308             matrix.preRotate(m_angleTransform);
309         }
310         matrix.preScale(m_scale.fX, m_scale.fY);
311         this->setMatrix(matrix);
312     }
313 
314     // now apply it to our children
315     int count = this->countChildren();
316     for (int i = 0; i < count; i++) {
317         this->getChild(i)->updatePositions();
318     }
319 }
320 
onDraw(SkCanvas * canvas,SkScalar opacity)321 void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity) {
322     if (m_haveClip) {
323         SkRect r;
324         r.set(0, 0, getSize().width(), getSize().height());
325         canvas->clipRect(r);
326     }
327 
328     if (!prepareContext())
329         return;
330 
331     // we just have this save/restore for opacity...
332     SkAutoCanvasRestore restore(canvas, true);
333 
334     int canvasOpacity = SkScalarRound(opacity * 255);
335     if (canvasOpacity < 255)
336         canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity));
337 
338     canvas->drawPicture(*m_recordingPicture);
339     if (m_extra)
340         m_extra->draw(canvas, this);
341 
342 #ifdef LAYER_DEBUG
343     float w = getSize().width();
344     float h = getSize().height();
345     SkPaint paint;
346     paint.setARGB(128, 255, 0, 0);
347     canvas->drawLine(0, 0, w, h, paint);
348     canvas->drawLine(0, h, w, 0, paint);
349     paint.setARGB(128, 0, 255, 0);
350     canvas->drawLine(0, 0, 0, h, paint);
351     canvas->drawLine(0, h, w, h, paint);
352     canvas->drawLine(w, h, w, 0, paint);
353     canvas->drawLine(w, 0, 0, 0, paint);
354 
355     if (m_isFixed) {
356       SkRect layerRect = computeLayerRect(this);
357       SkPaint paint;
358       paint.setARGB(128, 0, 0, 255);
359       canvas->drawRect(layerRect, paint);
360     }
361 #endif
362 }
363 
recordContext()364 SkPicture* LayerAndroid::recordContext()
365 {
366     if (prepareContext(true))
367         return m_recordingPicture;
368     return 0;
369 }
370 
prepareContext(bool force)371 bool LayerAndroid::prepareContext(bool force)
372 {
373     if (!m_isRootLayer) {
374         if (force || !m_recordingPicture
375             || (m_recordingPicture
376                 && ((m_recordingPicture->width() != (int) getSize().width())
377                    || (m_recordingPicture->height() != (int) getSize().height())))) {
378             m_recordingPicture->safeUnref();
379             m_recordingPicture = new SkPicture();
380         }
381     } else if (m_recordingPicture) {
382         m_recordingPicture->safeUnref();
383         m_recordingPicture = 0;
384     }
385 
386     return m_recordingPicture;
387 }
388 
subtractLayers(const SkRect & visibleRect) const389 SkRect LayerAndroid::subtractLayers(const SkRect& visibleRect) const
390 {
391     SkRect result;
392     if (m_recordingPicture) {
393         SkRect globalRect = bounds();
394         globalRect.offset(-getPosition()); // localToGlobal adds in position
395         SkMatrix globalMatrix;
396         localToGlobal(&globalMatrix);
397         globalMatrix.mapRect(&globalRect);
398         SkIRect roundedGlobal;
399         globalRect.round(&roundedGlobal);
400         SkIRect iVisibleRect;
401         visibleRect.round(&iVisibleRect);
402         SkRegion visRegion(iVisibleRect);
403         visRegion.op(roundedGlobal, SkRegion::kDifference_Op);
404         result.set(visRegion.getBounds());
405 #if DEBUG_NAV_UI
406         SkDebugf("%s visibleRect=(%g,%g,r=%g,b=%g) globalRect=(%g,%g,r=%g,b=%g)"
407             "result=(%g,%g,r=%g,b=%g)", __FUNCTION__,
408             visibleRect.fLeft, visibleRect.fTop,
409             visibleRect.fRight, visibleRect.fBottom,
410             globalRect.fLeft, globalRect.fTop,
411             globalRect.fRight, globalRect.fBottom,
412             result.fLeft, result.fTop, result.fRight, result.fBottom);
413 #endif
414     } else
415         result = visibleRect;
416     for (int i = 0; i < countChildren(); i++)
417         result = getChild(i)->subtractLayers(result);
418     return result;
419 }
420 
421 // Debug tools : dump the layers tree in a file.
422 // The format is simple:
423 // properties have the form: key = value;
424 // all statements are finished with a semi-colon.
425 // value can be:
426 // - int
427 // - float
428 // - array of elements
429 // - composed type
430 // a composed type enclose properties in { and }
431 // an array enclose composed types in { }, separated with a comma.
432 // exemple:
433 // {
434 //   x = 3;
435 //   y = 4;
436 //   value = {
437 //     x = 3;
438 //     y = 4;
439 //   };
440 //   anarray = [
441 //     { x = 3; },
442 //     { y = 4; }
443 //   ];
444 // }
445 
lwrite(FILE * file,const char * str)446 void lwrite(FILE* file, const char* str)
447 {
448     fwrite(str, sizeof(char), strlen(str), file);
449 }
450 
writeIndent(FILE * file,int indentLevel)451 void writeIndent(FILE* file, int indentLevel)
452 {
453     if (indentLevel)
454         fprintf(file, "%*s", indentLevel*2, " ");
455 }
456 
writeln(FILE * file,int indentLevel,const char * str)457 void writeln(FILE* file, int indentLevel, const char* str)
458 {
459     writeIndent(file, indentLevel);
460     lwrite(file, str);
461     lwrite(file, "\n");
462 }
463 
writeIntVal(FILE * file,int indentLevel,const char * str,int value)464 void writeIntVal(FILE* file, int indentLevel, const char* str, int value)
465 {
466     writeIndent(file, indentLevel);
467     fprintf(file, "%s = %d;\n", str, value);
468 }
469 
writeHexVal(FILE * file,int indentLevel,const char * str,int value)470 void writeHexVal(FILE* file, int indentLevel, const char* str, int value)
471 {
472     writeIndent(file, indentLevel);
473     fprintf(file, "%s = %x;\n", str, value);
474 }
475 
writeFloatVal(FILE * file,int indentLevel,const char * str,float value)476 void writeFloatVal(FILE* file, int indentLevel, const char* str, float value)
477 {
478     writeIndent(file, indentLevel);
479     fprintf(file, "%s = %.3f;\n", str, value);
480 }
481 
writePoint(FILE * file,int indentLevel,const char * str,SkPoint point)482 void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point)
483 {
484     writeIndent(file, indentLevel);
485     fprintf(file, "%s = { x = %.3f; y = %.3f; };\n", str, point.fX, point.fY);
486 }
487 
writeSize(FILE * file,int indentLevel,const char * str,SkSize size)488 void writeSize(FILE* file, int indentLevel, const char* str, SkSize size)
489 {
490     writeIndent(file, indentLevel);
491     fprintf(file, "%s = { w = %.3f; h = %.3f; };\n", str, size.width(), size.height());
492 }
493 
writeLength(FILE * file,int indentLevel,const char * str,SkLength length)494 void writeLength(FILE* file, int indentLevel, const char* str, SkLength length)
495 {
496     if (!length.defined()) return;
497     writeIndent(file, indentLevel);
498     fprintf(file, "%s = { type = %d; value = %.2f; };\n", str, length.type, length.value);
499 }
500 
dumpLayers(FILE * file,int indentLevel) const501 void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const
502 {
503     writeln(file, indentLevel, "{");
504 
505     writeHexVal(file, indentLevel + 1, "layer", (int)this);
506     writeIntVal(file, indentLevel + 1, "layerId", m_uniqueId);
507     writeIntVal(file, indentLevel + 1, "haveClip", m_haveClip);
508     writeIntVal(file, indentLevel + 1, "isRootLayer", m_isRootLayer);
509     writeIntVal(file, indentLevel + 1, "isFixed", m_isFixed);
510 
511     writeFloatVal(file, indentLevel + 1, "opacity", getOpacity());
512     writeSize(file, indentLevel + 1, "size", getSize());
513     writePoint(file, indentLevel + 1, "position", getPosition());
514     writePoint(file, indentLevel + 1, "translation", m_translation);
515     writePoint(file, indentLevel + 1, "anchor", getAnchorPoint());
516     writePoint(file, indentLevel + 1, "scale", m_scale);
517 
518     if (m_doRotation)
519         writeFloatVal(file, indentLevel + 1, "angle", m_angleTransform);
520 
521     if (m_isFixed) {
522         writeLength(file, indentLevel + 1, "fixedLeft", m_fixedLeft);
523         writeLength(file, indentLevel + 1, "fixedTop", m_fixedTop);
524         writeLength(file, indentLevel + 1, "fixedRight", m_fixedRight);
525         writeLength(file, indentLevel + 1, "fixedBottom", m_fixedBottom);
526         writeLength(file, indentLevel + 1, "fixedMarginLeft", m_fixedMarginLeft);
527         writeLength(file, indentLevel + 1, "fixedMarginTop", m_fixedMarginTop);
528         writeLength(file, indentLevel + 1, "fixedMarginRight", m_fixedMarginRight);
529         writeLength(file, indentLevel + 1, "fixedMarginBottom", m_fixedMarginBottom);
530         writePoint(file, indentLevel + 1, "fixedOffset", m_fixedOffset);
531         writeIntVal(file, indentLevel + 1, "fixedWidth", m_fixedWidth);
532         writeIntVal(file, indentLevel + 1, "fixedHeight", m_fixedHeight);
533     }
534 
535     if (m_recordingPicture) {
536         writeIntVal(file, indentLevel + 1, "picture width", m_recordingPicture->width());
537         writeIntVal(file, indentLevel + 1, "picture height", m_recordingPicture->height());
538     }
539 
540     if (countChildren()) {
541         writeln(file, indentLevel + 1, "children = [");
542         for (int i = 0; i < countChildren(); i++) {
543             if (i > 0)
544                 writeln(file, indentLevel + 1, ", ");
545             getChild(i)->dumpLayers(file, indentLevel + 1);
546         }
547         writeln(file, indentLevel + 1, "];");
548     }
549     writeln(file, indentLevel, "}");
550 }
551 
dumpToLog() const552 void LayerAndroid::dumpToLog() const
553 {
554     FILE* file = fopen("/data/data/com.android.browser/layertmp", "w");
555     dumpLayers(file, 0);
556     fclose(file);
557     file = fopen("/data/data/com.android.browser/layertmp", "r");
558     char buffer[512];
559     bzero(buffer, sizeof(buffer));
560     while (fgets(buffer, sizeof(buffer), file))
561         SkDebugf("%s", buffer);
562     fclose(file);
563 }
564 
findById(int match) const565 const LayerAndroid* LayerAndroid::findById(int match) const
566 {
567     if (m_uniqueId == match)
568         return this;
569     for (int i = 0; i < countChildren(); i++) {
570         const LayerAndroid* result = getChild(i)->findById(match);
571         if (result)
572             return result;
573     }
574     return 0;
575 }
576 
setExtra(DrawExtra * extra)577 void LayerAndroid::setExtra(DrawExtra* extra)
578 {
579     m_extra = extra;
580     for (int i = 0; i < countChildren(); i++)
581         getChild(i)->setExtra(extra);
582 }
583 
584 } // namespace WebCore
585 
586 #endif // USE(ACCELERATED_COMPOSITING)
587