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