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