Home | History | Annotate | Download | only in android
      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 
     22 inline int LayerAndroid::instancesCount()
     23 {
     24     return gDebugLayerAndroidInstances;
     25 }
     26 
     27 class OpacityDrawFilter : public SkDrawFilter {
     28  public:
     29     OpacityDrawFilter(int opacity) : m_opacity(opacity) { }
     30     virtual bool filter(SkCanvas* canvas, SkPaint* paint, Type)
     31     {
     32         m_previousOpacity = paint->getAlpha();
     33         paint->setAlpha(m_opacity);
     34         return true;
     35     }
     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 
     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 
     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 
    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 
    120 LayerAndroid::~LayerAndroid()
    121 {
    122     removeChildren();
    123     m_recordingPicture->safeUnref();
    124     m_animations.clear();
    125     gDebugLayerAndroidInstances--;
    126 }
    127 
    128 static int gDebugNbAnims = 0;
    129 
    130 bool LayerAndroid::evaluateAnimations() const
    131 {
    132     double time = WTF::currentTime();
    133     gDebugNbAnims = 0;
    134     return evaluateAnimations(time);
    135 }
    136 
    137 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 
    146 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 
    165 void LayerAndroid::addAnimation(PassRefPtr<AndroidAnimation> anim)
    166 {
    167     m_animations.add(anim->name(), anim);
    168 }
    169 
    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?
    177 void LayerAndroid::setMaskLayer(LayerAndroid* layer)
    178 {
    179     if (layer)
    180         m_haveClip = true;
    181 }
    182 
    183 void LayerAndroid::setMasksToBounds(bool masksToBounds)
    184 {
    185     m_haveClip = masksToBounds;
    186 }
    187 
    188 void LayerAndroid::setBackgroundColor(SkColor color)
    189 {
    190     m_backgroundColor = color;
    191 }
    192 
    193 static int gDebugChildLevel;
    194 
    195 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 
    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 
    215 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 
    223 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 
    237 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...
    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 
    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 
    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 
    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 
    364 SkPicture* LayerAndroid::recordContext()
    365 {
    366     if (prepareContext(true))
    367         return m_recordingPicture;
    368     return 0;
    369 }
    370 
    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 
    389 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 
    446 void lwrite(FILE* file, const char* str)
    447 {
    448     fwrite(str, sizeof(char), strlen(str), file);
    449 }
    450 
    451 void writeIndent(FILE* file, int indentLevel)
    452 {
    453     if (indentLevel)
    454         fprintf(file, "%*s", indentLevel*2, " ");
    455 }
    456 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    501 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 
    552 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 
    565 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 
    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