GraphicsLayerAndroid.cpp revision 931e90d171935ef706b6906c5867a51fc491a83d
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "config.h" 18#include "GraphicsLayerAndroid.h" 19 20#if USE(ACCELERATED_COMPOSITING) 21 22#include "AndroidAnimation.h" 23#include "Animation.h" 24#include "FloatRect.h" 25#include "GraphicsContext.h" 26#include "Image.h" 27#include "ImagesManager.h" 28#include "Layer.h" 29#include "Length.h" 30#include "MediaLayer.h" 31#include "PlatformBridge.h" 32#include "PlatformGraphicsContext.h" 33#include "RenderLayerBacking.h" 34#include "RenderView.h" 35#include "RotateTransformOperation.h" 36#include "ScaleTransformOperation.h" 37#include "ScrollableLayerAndroid.h" 38#include "SkCanvas.h" 39#include "SkRegion.h" 40#include "TransformationMatrix.h" 41#include "TranslateTransformOperation.h" 42 43#include <cutils/log.h> 44#include <wtf/CurrentTime.h> 45#include <wtf/text/CString.h> 46 47#undef LOG 48#define LOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__) 49#define MLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__) 50#define TLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__) 51 52#undef LOG 53#define LOG(...) 54#undef MLOG 55#define MLOG(...) 56#undef TLOG 57#define TLOG(...) 58#undef LAYER_DEBUG 59 60using namespace std; 61 62static bool gPaused; 63static double gPausedDelay; 64 65namespace WebCore { 66 67static int gDebugGraphicsLayerAndroidInstances = 0; 68inline int GraphicsLayerAndroid::instancesCount() 69{ 70 return gDebugGraphicsLayerAndroidInstances; 71} 72 73static String propertyIdToString(AnimatedPropertyID property) 74{ 75 switch (property) { 76 case AnimatedPropertyWebkitTransform: 77 return "transform"; 78 case AnimatedPropertyOpacity: 79 return "opacity"; 80 case AnimatedPropertyBackgroundColor: 81 return "backgroundColor"; 82 case AnimatedPropertyInvalid: 83 ASSERT_NOT_REACHED(); 84 } 85 ASSERT_NOT_REACHED(); 86 return ""; 87} 88 89PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) 90{ 91 return new GraphicsLayerAndroid(client); 92} 93 94SkLength convertLength(Length len) 95{ 96 SkLength length; 97 length.type = SkLength::Undefined; 98 length.value = 0; 99 if (len.type() == WebCore::Percent) { 100 length.type = SkLength::Percent; 101 length.value = len.percent(); 102 } 103 if (len.type() == WebCore::Fixed) { 104 length.type = SkLength::Fixed; 105 length.value = len.value(); 106 } 107 return length; 108} 109 110static RenderLayer* renderLayerFromClient(GraphicsLayerClient* client) 111{ 112 return client ? client->owningLayer() : 0; 113} 114 115GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) : 116 GraphicsLayer(client), 117 m_needsSyncChildren(false), 118 m_needsSyncMask(false), 119 m_needsRepaint(false), 120 m_needsNotifyClient(false), 121 m_haveContents(false), 122 m_newImage(false), 123 m_image(0), 124 m_foregroundLayer(0), 125 m_foregroundClipLayer(0) 126{ 127 RenderLayer* renderLayer = renderLayerFromClient(m_client); 128 m_contentLayer = new LayerAndroid(renderLayer); 129 m_dirtyRegion.setEmpty(); 130 gDebugGraphicsLayerAndroidInstances++; 131} 132 133GraphicsLayerAndroid::~GraphicsLayerAndroid() 134{ 135 if (m_image) 136 m_image->deref(); 137 138 m_contentLayer->unref(); 139 SkSafeUnref(m_foregroundLayer); 140 SkSafeUnref(m_foregroundClipLayer); 141 gDebugGraphicsLayerAndroidInstances--; 142} 143 144void GraphicsLayerAndroid::setName(const String& name) 145{ 146 GraphicsLayer::setName(name); 147} 148 149NativeLayer GraphicsLayerAndroid::nativeLayer() const 150{ 151 LOG("(%x) nativeLayer", this); 152 return 0; 153} 154 155bool GraphicsLayerAndroid::setChildren(const Vector<GraphicsLayer*>& children) 156{ 157 bool childrenChanged = GraphicsLayer::setChildren(children); 158 if (childrenChanged) { 159 m_needsSyncChildren = true; 160 askForSync(); 161 } 162 163 return childrenChanged; 164} 165 166void GraphicsLayerAndroid::addChild(GraphicsLayer* childLayer) 167{ 168#ifndef NDEBUG 169 const String& name = childLayer->name(); 170 LOG("(%x) addChild: %x (%s)", this, childLayer, name.latin1().data()); 171#endif 172 GraphicsLayer::addChild(childLayer); 173 m_needsSyncChildren = true; 174 askForSync(); 175} 176 177void GraphicsLayerAndroid::addChildAtIndex(GraphicsLayer* childLayer, int index) 178{ 179 LOG("(%x) addChild %x AtIndex %d", this, childLayer, index); 180 GraphicsLayer::addChildAtIndex(childLayer, index); 181 m_needsSyncChildren = true; 182 askForSync(); 183} 184 185void GraphicsLayerAndroid::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling) 186{ 187 LOG("(%x) addChild %x Below %x", this, childLayer, sibling); 188 GraphicsLayer::addChildBelow(childLayer, sibling); 189 m_needsSyncChildren = true; 190 askForSync(); 191} 192 193void GraphicsLayerAndroid::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling) 194{ 195 LOG("(%x) addChild %x Above %x", this, childLayer, sibling); 196 GraphicsLayer::addChildAbove(childLayer, sibling); 197 m_needsSyncChildren = true; 198 askForSync(); 199} 200 201bool GraphicsLayerAndroid::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) 202{ 203 LOG("(%x) replaceChild %x by %x", this, oldChild, newChild); 204 bool ret = GraphicsLayer::replaceChild(oldChild, newChild); 205 if (ret) { 206 m_needsSyncChildren = true; 207 askForSync(); 208 } 209 return ret; 210} 211 212void GraphicsLayerAndroid::removeFromParent() 213{ 214 LOG("(%x) removeFromParent()", this); 215 GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent); 216 GraphicsLayer::removeFromParent(); 217 // Update the parent's children. 218 if (parent) { 219 parent->m_needsSyncChildren = true; 220 askForSync(); 221 } 222} 223 224void GraphicsLayerAndroid::updateFixedPosition() 225{ 226 RenderLayer* renderLayer = renderLayerFromClient(m_client); 227 if (!renderLayer) 228 return; 229 RenderView* view = static_cast<RenderView*>(renderLayer->renderer()); 230 231 if (!view) 232 return; 233 234 // We will need the Iframe flag in the LayerAndroid tree for fixed position 235 if (view->isRenderIFrame()) 236 m_contentLayer->setIsIframe(true); 237 // If we are a fixed position layer, just set it 238 if (view->isPositioned() && view->style()->position() == FixedPosition) { 239 // We need to get the passed CSS properties for the element 240 SkLength left, top, right, bottom; 241 left = convertLength(view->style()->left()); 242 top = convertLength(view->style()->top()); 243 right = convertLength(view->style()->right()); 244 bottom = convertLength(view->style()->bottom()); 245 246 // We also need to get the margin... 247 SkLength marginLeft, marginTop, marginRight, marginBottom; 248 marginLeft = convertLength(view->style()->marginLeft()); 249 marginTop = convertLength(view->style()->marginTop()); 250 marginRight = convertLength(view->style()->marginRight()); 251 marginBottom = convertLength(view->style()->marginBottom()); 252 253 // In order to compute the fixed element's position, we need the width 254 // and height of the element when bottom or right is defined. 255 // And here we should use the non-overflowed value, that means, the 256 // overflowed content (e.g. outset shadow) will not be counted into the 257 // width and height. 258 int w = view->width(); 259 int h = view->height(); 260 261 int paintingOffsetX = - offsetFromRenderer().width(); 262 int paintingOffsetY = - offsetFromRenderer().height(); 263 264 SkRect viewRect; 265 viewRect.set(paintingOffsetX, paintingOffsetY, paintingOffsetX + w, paintingOffsetY + h); 266 IntPoint renderLayerPos(renderLayer->x(), renderLayer->y()); 267 m_contentLayer->setFixedPosition(left, top, right, bottom, 268 marginLeft, marginTop, 269 marginRight, marginBottom, 270 renderLayerPos, 271 viewRect); 272 } 273} 274 275void GraphicsLayerAndroid::setPosition(const FloatPoint& point) 276{ 277 if (point == m_position) 278 return; 279 280 GraphicsLayer::setPosition(point); 281 282#ifdef LAYER_DEBUG_2 283 LOG("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)", 284 this, point.x(), point.y(), m_position.x(), m_position.y(), 285 m_anchorPoint.x(), m_anchorPoint.y(), m_size.width(), m_size.height()); 286#endif 287 m_contentLayer->setPosition(point.x(), point.y()); 288 askForSync(); 289} 290 291void GraphicsLayerAndroid::setPreserves3D(bool preserves3D) 292{ 293 if (preserves3D == m_preserves3D) 294 return; 295 296 GraphicsLayer::setPreserves3D(preserves3D); 297 m_contentLayer->setPreserves3D(preserves3D); 298 askForSync(); 299} 300 301void GraphicsLayerAndroid::setAnchorPoint(const FloatPoint3D& point) 302{ 303 if (point == m_anchorPoint) 304 return; 305 GraphicsLayer::setAnchorPoint(point); 306 m_contentLayer->setAnchorPoint(point.x(), point.y()); 307 m_contentLayer->setAnchorPointZ(point.z()); 308 askForSync(); 309} 310 311void GraphicsLayerAndroid::setSize(const FloatSize& size) 312{ 313 if (size == m_size) 314 return; 315 MLOG("(%x) setSize (%.2f,%.2f)", this, size.width(), size.height()); 316 GraphicsLayer::setSize(size); 317 318 // If it is a media layer the size may have changed as a result of the media 319 // element (e.g. plugin) gaining focus. Therefore, we must sync the size of 320 // the focus' outline so that our UI thread can draw accordingly. 321 RenderLayer* layer = renderLayerFromClient(m_client); 322 if (layer && m_contentLayer->isMedia()) { 323 RenderBox* box = layer->renderBox(); 324 int outline = box->view()->maximalOutlineSize(); 325 static_cast<MediaLayer*>(m_contentLayer)->setOutlineSize(outline); 326 LOG("Media Outline: %d %p %p %p", outline, m_client, layer, box); 327 LOG("Media Size: %g,%g", size.width(), size.height()); 328 } 329 330 m_contentLayer->setSize(size.width(), size.height()); 331 setNeedsDisplay(); 332 askForSync(); 333} 334 335void GraphicsLayerAndroid::setBackfaceVisibility(bool b) 336{ 337 if (b == m_backfaceVisibility) 338 return; 339 340 GraphicsLayer::setBackfaceVisibility(b); 341 m_contentLayer->setBackfaceVisibility(b); 342 askForSync(); 343} 344 345void GraphicsLayerAndroid::setTransform(const TransformationMatrix& t) 346{ 347 if (t == m_transform) 348 return; 349 350 GraphicsLayer::setTransform(t); 351 m_contentLayer->setTransform(t); 352 askForSync(); 353} 354 355void GraphicsLayerAndroid::setChildrenTransform(const TransformationMatrix& t) 356{ 357 if (t == m_childrenTransform) 358 return; 359 LOG("(%x) setChildrenTransform", this); 360 361 GraphicsLayer::setChildrenTransform(t); 362 m_contentLayer->setChildrenTransform(t); 363 for (unsigned int i = 0; i < m_children.size(); i++) { 364 GraphicsLayer* layer = m_children[i]; 365 layer->setTransform(t); 366 if (layer->children().size()) 367 layer->setChildrenTransform(t); 368 } 369 askForSync(); 370} 371 372void GraphicsLayerAndroid::setMaskLayer(GraphicsLayer* layer) 373{ 374 if (layer == m_maskLayer) 375 return; 376 377 GraphicsLayer::setMaskLayer(layer); 378 m_needsSyncMask = true; 379 askForSync(); 380} 381 382void GraphicsLayerAndroid::setMasksToBounds(bool masksToBounds) 383{ 384 if (masksToBounds == m_masksToBounds) 385 return; 386 GraphicsLayer::setMasksToBounds(masksToBounds); 387 m_needsSyncMask = true; 388 askForSync(); 389} 390 391void GraphicsLayerAndroid::setDrawsContent(bool drawsContent) 392{ 393 if (drawsContent == m_drawsContent) 394 return; 395 GraphicsLayer::setDrawsContent(drawsContent); 396 m_contentLayer->setVisible(drawsContent); 397 if (m_drawsContent) { 398 m_haveContents = true; 399 setNeedsDisplay(); 400 } 401 askForSync(); 402} 403 404void GraphicsLayerAndroid::setBackgroundColor(const Color& color) 405{ 406 if (color == m_backgroundColor && m_backgroundColorSet) 407 return; 408 LOG("(%x) setBackgroundColor", this); 409 GraphicsLayer::setBackgroundColor(color); 410 SkColor c = SkColorSetARGB(color.alpha(), color.red(), color.green(), color.blue()); 411 m_contentLayer->setBackgroundColor(c); 412 m_haveContents = true; 413 askForSync(); 414} 415 416void GraphicsLayerAndroid::clearBackgroundColor() 417{ 418 if (!m_backgroundColorSet) 419 return; 420 421 LOG("(%x) clearBackgroundColor", this); 422 GraphicsLayer::clearBackgroundColor(); 423 askForSync(); 424} 425 426void GraphicsLayerAndroid::setContentsOpaque(bool opaque) 427{ 428 if (opaque == m_contentsOpaque) 429 return; 430 LOG("(%x) setContentsOpaque (%d)", this, opaque); 431 GraphicsLayer::setContentsOpaque(opaque); 432 m_haveContents = true; 433 askForSync(); 434} 435 436void GraphicsLayerAndroid::setOpacity(float opacity) 437{ 438 LOG("(%x) setOpacity: %.2f", this, opacity); 439 float clampedOpacity = max(0.0f, min(opacity, 1.0f)); 440 441 if (clampedOpacity == m_opacity) 442 return; 443 444 MLOG("(%x) setFinalOpacity: %.2f=>%.2f (%.2f)", this, 445 opacity, clampedOpacity, m_opacity); 446 GraphicsLayer::setOpacity(clampedOpacity); 447 m_contentLayer->setOpacity(clampedOpacity); 448 askForSync(); 449} 450 451void GraphicsLayerAndroid::setNeedsDisplay() 452{ 453 LOG("(%x) setNeedsDisplay()", this); 454 FloatRect rect(0, 0, m_size.width(), m_size.height()); 455 setNeedsDisplayInRect(rect); 456} 457 458// Helper to set and clear the painting phase as well as auto restore the 459// original phase. 460class PaintingPhase { 461public: 462 PaintingPhase(GraphicsLayer* layer) 463 : m_layer(layer) 464 , m_originalPhase(layer->paintingPhase()) {} 465 466 ~PaintingPhase() 467 { 468 m_layer->setPaintingPhase(m_originalPhase); 469 } 470 471 void set(GraphicsLayerPaintingPhase phase) 472 { 473 m_layer->setPaintingPhase(phase); 474 } 475 476 void clear(GraphicsLayerPaintingPhase phase) 477 { 478 m_layer->setPaintingPhase( 479 (GraphicsLayerPaintingPhase) (m_originalPhase & ~phase)); 480 } 481private: 482 GraphicsLayer* m_layer; 483 GraphicsLayerPaintingPhase m_originalPhase; 484}; 485 486void GraphicsLayerAndroid::updateScrollingLayers() 487{ 488#if ENABLE(ANDROID_OVERFLOW_SCROLL) 489 RenderLayer* layer = renderLayerFromClient(m_client); 490 if (!layer || !m_haveContents) 491 return; 492 bool hasOverflowScroll = m_foregroundLayer || m_contentLayer->contentIsScrollable(); 493 bool layerNeedsOverflow = layer->hasOverflowScroll(); 494 bool iframeNeedsOverflow = layer->isRootLayer() && 495 layer->renderer()->frame()->ownerRenderer() && 496 layer->renderer()->frame()->view()->hasOverflowScroll(); 497 498 if (hasOverflowScroll && (layerNeedsOverflow || iframeNeedsOverflow)) { 499 // Already has overflow layers. 500 return; 501 } 502 if (!hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow) { 503 // Does not need overflow layers. 504 return; 505 } 506 if (layerNeedsOverflow || iframeNeedsOverflow) { 507 ASSERT(!hasOverflowScroll); 508 if (layerNeedsOverflow) { 509 ASSERT(!m_foregroundLayer && !m_foregroundClipLayer); 510 m_foregroundLayer = new ScrollableLayerAndroid(layer); 511 m_foregroundClipLayer = new LayerAndroid(layer); 512 m_foregroundClipLayer->setMasksToBounds(true); 513 m_foregroundClipLayer->addChild(m_foregroundLayer); 514 m_contentLayer->addChild(m_foregroundClipLayer); 515 m_contentLayer->setHasOverflowChildren(true); 516 } else { 517 ASSERT(iframeNeedsOverflow && !m_contentLayer->contentIsScrollable()); 518 // No need to copy the children as they will be removed and synced. 519 m_contentLayer->removeChildren(); 520 // Replace the content layer with a scrollable layer. 521 LayerAndroid* layer = new ScrollableLayerAndroid(*m_contentLayer); 522 m_contentLayer->unref(); 523 m_contentLayer = layer; 524 if (m_parent) { 525 // The content layer has changed so the parent needs to sync 526 // children. 527 static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true; 528 } 529 } 530 // Need to rebuild our children based on the new structure. 531 m_needsSyncChildren = true; 532 } else { 533 ASSERT(hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow); 534 ASSERT(m_contentLayer); 535 // Remove the foreground layers. 536 if (m_foregroundLayer) { 537 m_foregroundLayer->unref(); 538 m_foregroundLayer = 0; 539 m_foregroundClipLayer->unref(); 540 m_foregroundClipLayer = 0; 541 } 542 // No need to copy over children. 543 m_contentLayer->removeChildren(); 544 LayerAndroid* layer = new LayerAndroid(*m_contentLayer); 545 m_contentLayer->unref(); 546 m_contentLayer = layer; 547 if (m_parent) { 548 // The content layer has changed so the parent needs to sync 549 // children. 550 static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true; 551 } 552 // Children are all re-parented. 553 m_needsSyncChildren = true; 554 } 555#endif 556} 557 558bool GraphicsLayerAndroid::repaint() 559{ 560 LOG("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ", 561 this, gPaused, m_needsRepaint, m_haveContents); 562 563 if (!gPaused && m_haveContents && m_needsRepaint && !m_image) { 564 // with SkPicture, we request the entire layer's content. 565 IntRect layerBounds(0, 0, m_size.width(), m_size.height()); 566 567 RenderLayer* layer = renderLayerFromClient(m_client); 568 if (!layer) 569 return false; 570 if (m_foregroundLayer) { 571 PaintingPhase phase(this); 572 // Paint the background into a separate context. 573 phase.set(GraphicsLayerPaintBackground); 574 if (!paintContext(m_contentLayer->recordContext(), layerBounds)) 575 return false; 576 m_contentLayer->checkTextPresence(); 577 578 // Construct the foreground layer and draw. 579 RenderBox* box = layer->renderBox(); 580 int outline = box->view()->maximalOutlineSize(); 581 IntRect contentsRect(0, 0, 582 box->borderLeft() + box->borderRight() + layer->scrollWidth(), 583 box->borderTop() + box->borderBottom() + layer->scrollHeight()); 584 contentsRect.inflate(outline); 585 // Update the foreground layer size. 586 m_foregroundLayer->setSize(contentsRect.width(), contentsRect.height()); 587 // Paint everything else into the main recording canvas. 588 phase.clear(GraphicsLayerPaintBackground); 589 590 // Paint at 0,0. 591 IntSize scroll = layer->scrolledContentOffset(); 592 layer->scrollToOffset(0, 0); 593 // At this point, it doesn't matter if painting failed. 594 (void) paintContext(m_foregroundLayer->recordContext(), contentsRect); 595 m_foregroundLayer->checkTextPresence(); 596 layer->scrollToOffset(scroll.width(), scroll.height()); 597 598 // Construct the clip layer for masking the contents. 599 IntRect clip = layer->renderer()->absoluteBoundingBoxRect(); 600 // absoluteBoundingBoxRect does not include the outline so we need 601 // to offset the position. 602 int x = box->borderLeft() + outline; 603 int y = box->borderTop() + outline; 604 int width = clip.width() - box->borderLeft() - box->borderRight(); 605 int height = clip.height() - box->borderTop() - box->borderBottom(); 606 m_foregroundClipLayer->setPosition(x, y); 607 m_foregroundClipLayer->setSize(width, height); 608 609 // Need to offset the foreground layer by the clip layer in order 610 // for the contents to be in the correct position. 611 m_foregroundLayer->setPosition(-x, -y); 612 // Set the scrollable bounds of the layer. 613 m_foregroundLayer->setScrollLimits(-x, -y, m_size.width(), m_size.height()); 614 m_foregroundLayer->markAsDirty(m_dirtyRegion); 615 m_foregroundLayer->needsRepaint(); 616 } else { 617 // If there is no contents clip, we can draw everything into one 618 // picture. 619 if (!paintContext(m_contentLayer->recordContext(), layerBounds)) 620 return false; 621 m_contentLayer->checkTextPresence(); 622 // Check for a scrollable iframe and report the scrolling 623 // limits based on the view size. 624 if (m_contentLayer->contentIsScrollable()) { 625 FrameView* view = layer->renderer()->frame()->view(); 626 static_cast<ScrollableLayerAndroid*>(m_contentLayer)->setScrollLimits( 627 m_position.x(), m_position.y(), view->layoutWidth(), view->layoutHeight()); 628 } 629 } 630 631 LOG("(%x) repaint() on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!", 632 this, m_size.width(), m_size.height(), 633 m_contentLayer->getPosition().fX, 634 m_contentLayer->getPosition().fY, 635 m_contentLayer->getSize().width(), 636 m_contentLayer->getSize().height()); 637 638 m_contentLayer->markAsDirty(m_dirtyRegion); 639 m_dirtyRegion.setEmpty(); 640 m_contentLayer->needsRepaint(); 641 m_needsRepaint = false; 642 643 return true; 644 } 645 if (m_needsRepaint && m_image && m_newImage) { 646 // We need to tell the GL thread that we will need to repaint the 647 // texture. Only do so if we effectively have a new image! 648 m_contentLayer->markAsDirty(m_dirtyRegion); 649 m_dirtyRegion.setEmpty(); 650 m_contentLayer->needsRepaint(); 651 m_newImage = false; 652 m_needsRepaint = false; 653 return true; 654 } 655 return false; 656} 657 658bool GraphicsLayerAndroid::paintContext(SkPicture* context, 659 const IntRect& rect) 660{ 661 SkAutoPictureRecord arp(context, rect.width(), rect.height()); 662 SkCanvas* canvas = arp.getRecordingCanvas(); 663 664 if (!canvas) 665 return false; 666 667 PlatformGraphicsContext platformContext(canvas); 668 GraphicsContext graphicsContext(&platformContext); 669 670 paintGraphicsLayerContents(graphicsContext, rect); 671 return true; 672} 673 674void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect) 675{ 676 // rect is in the render object coordinates 677 678 if (!m_image && !drawsContent()) { 679 LOG("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...", 680 this, rect.x(), rect.y(), rect.width(), rect.height()); 681 return; 682 } 683 684 SkRegion region; 685 region.setRect(rect.x(), rect.y(), 686 rect.x() + rect.width(), 687 rect.y() + rect.height()); 688 m_dirtyRegion.op(region, SkRegion::kUnion_Op); 689 690 m_needsRepaint = true; 691 askForSync(); 692} 693 694void GraphicsLayerAndroid::pauseDisplay(bool state) 695{ 696 gPaused = state; 697 if (gPaused) 698 gPausedDelay = WTF::currentTime() + 1; 699} 700 701bool GraphicsLayerAndroid::addAnimation(const KeyframeValueList& valueList, 702 const IntSize& boxSize, 703 const Animation* anim, 704 const String& keyframesName, 705 double beginTime) 706{ 707 if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2) 708 return false; 709 710 bool createdAnimations = false; 711 if (valueList.property() == AnimatedPropertyWebkitTransform) { 712 createdAnimations = createTransformAnimationsFromKeyframes(valueList, 713 anim, 714 keyframesName, 715 beginTime, 716 boxSize); 717 } else { 718 createdAnimations = createAnimationFromKeyframes(valueList, 719 anim, 720 keyframesName, 721 beginTime); 722 } 723 if (createdAnimations) 724 askForSync(); 725 return createdAnimations; 726} 727 728bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& valueList, 729 const Animation* animation, const String& keyframesName, double beginTime) 730{ 731 bool isKeyframe = valueList.size() > 2; 732 TLOG("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)", 733 isKeyframe, keyframesName.latin1().data(), beginTime); 734 735 switch (valueList.property()) { 736 case AnimatedPropertyInvalid: break; 737 case AnimatedPropertyWebkitTransform: break; 738 case AnimatedPropertyBackgroundColor: break; 739 case AnimatedPropertyOpacity: { 740 MLOG("ANIMATEDPROPERTYOPACITY"); 741 742 KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyOpacity); 743 for (unsigned int i = 0; i < valueList.size(); i++) { 744 FloatAnimationValue* originalValue = (FloatAnimationValue*)valueList.at(i); 745 RefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction())); 746 FloatAnimationValue* value = new FloatAnimationValue(originalValue->keyTime(), 747 originalValue->value(), 748 timingFunction); 749 operationsList->insert(value); 750 } 751 752 RefPtr<AndroidOpacityAnimation> anim = AndroidOpacityAnimation::create(animation, 753 operationsList, 754 beginTime); 755 if (keyframesName.isEmpty()) 756 anim->setName(propertyIdToString(valueList.property())); 757 else 758 anim->setName(keyframesName); 759 760 m_contentLayer->addAnimation(anim.release()); 761 needsNotifyClient(); 762 return true; 763 } break; 764 } 765 return false; 766} 767 768void GraphicsLayerAndroid::needsNotifyClient() 769{ 770 m_needsNotifyClient = true; 771 askForSync(); 772} 773 774bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, 775 const Animation* animation, 776 const String& keyframesName, 777 double beginTime, 778 const IntSize& boxSize) 779{ 780 ASSERT(valueList.property() == AnimatedPropertyWebkitTransform); 781 TLOG("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)", 782 keyframesName.latin1().data(), beginTime); 783 784 KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyWebkitTransform); 785 for (unsigned int i = 0; i < valueList.size(); i++) { 786 TransformAnimationValue* originalValue = (TransformAnimationValue*)valueList.at(i); 787 RefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction())); 788 TransformAnimationValue* value = new TransformAnimationValue(originalValue->keyTime(), 789 originalValue->value(), 790 timingFunction); 791 operationsList->insert(value); 792 } 793 794 RefPtr<AndroidTransformAnimation> anim = AndroidTransformAnimation::create(animation, 795 operationsList, 796 beginTime); 797 798 if (keyframesName.isEmpty()) 799 anim->setName(propertyIdToString(valueList.property())); 800 else 801 anim->setName(keyframesName); 802 803 804 m_contentLayer->addAnimation(anim.release()); 805 806 needsNotifyClient(); 807 return true; 808} 809 810void GraphicsLayerAndroid::removeAnimationsForProperty(AnimatedPropertyID anID) 811{ 812 TLOG("NRO removeAnimationsForProperty(%d)", anID); 813 m_contentLayer->removeAnimationsForProperty(anID); 814 askForSync(); 815} 816 817void GraphicsLayerAndroid::removeAnimationsForKeyframes(const String& keyframesName) 818{ 819 TLOG("NRO removeAnimationsForKeyframes(%s)", keyframesName.latin1().data()); 820 m_contentLayer->removeAnimationsForKeyframes(keyframesName); 821 askForSync(); 822} 823 824void GraphicsLayerAndroid::pauseAnimation(const String& keyframesName) 825{ 826 TLOG("NRO pauseAnimation(%s)", keyframesName.latin1().data()); 827} 828 829void GraphicsLayerAndroid::suspendAnimations(double time) 830{ 831 TLOG("NRO suspendAnimations(%.2f)", time); 832} 833 834void GraphicsLayerAndroid::resumeAnimations() 835{ 836 TLOG("NRO resumeAnimations()"); 837} 838 839void GraphicsLayerAndroid::setContentsToImage(Image* image) 840{ 841 TLOG("(%x) setContentsToImage", this, image); 842 if (image && image != m_image) { 843 image->ref(); 844 if (m_image) 845 m_image->deref(); 846 m_image = image; 847 848 SkBitmapRef* bitmap = image->nativeImageForCurrentFrame(); 849 m_contentLayer->setContentsImage(bitmap); 850 851 m_haveContents = true; 852 m_newImage = true; 853 } 854 if (!image && m_image) { 855 m_contentLayer->setContentsImage(0); 856 m_image->deref(); 857 m_image = 0; 858 } 859 860 setNeedsDisplay(); 861 askForSync(); 862} 863 864void GraphicsLayerAndroid::setContentsToMedia(PlatformLayer* mediaLayer) 865{ 866 // Only fullscreen video on Android, so media doesn't get it's own layer. 867 // We might still have other layers though. 868 if (m_contentLayer != mediaLayer && mediaLayer) { 869 870 // TODO add a copy method to LayerAndroid to sync everything 871 // copy data from the original content layer to the new one 872 mediaLayer->setPosition(m_contentLayer->getPosition().fX, 873 m_contentLayer->getPosition().fY); 874 mediaLayer->setSize(m_contentLayer->getWidth(), m_contentLayer->getHeight()); 875 mediaLayer->setDrawTransform(*m_contentLayer->drawTransform()); 876 877 mediaLayer->ref(); 878 m_contentLayer->unref(); 879 m_contentLayer = mediaLayer; 880 881 // If the parent exists then notify it to re-sync it's children 882 if (m_parent) { 883 GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent); 884 parent->m_needsSyncChildren = true; 885 } 886 m_needsSyncChildren = true; 887 888 setNeedsDisplay(); 889 askForSync(); 890 } 891} 892 893PlatformLayer* GraphicsLayerAndroid::platformLayer() const 894{ 895 LOG("platformLayer"); 896 return m_contentLayer; 897} 898 899#ifndef NDEBUG 900void GraphicsLayerAndroid::setDebugBackgroundColor(const Color& color) 901{ 902} 903 904void GraphicsLayerAndroid::setDebugBorder(const Color& color, float borderWidth) 905{ 906} 907#endif 908 909void GraphicsLayerAndroid::setZPosition(float position) 910{ 911 if (position == m_zPosition) 912 return; 913 LOG("(%x) setZPosition: %.2f", this, position); 914 GraphicsLayer::setZPosition(position); 915 askForSync(); 916} 917 918void GraphicsLayerAndroid::askForSync() 919{ 920 if (!m_client) 921 return; 922 923 if (m_client) 924 m_client->notifySyncRequired(this); 925} 926 927void GraphicsLayerAndroid::syncChildren() 928{ 929 if (m_needsSyncChildren) { 930 m_contentLayer->removeChildren(); 931 LayerAndroid* layer = m_contentLayer; 932 if (m_foregroundClipLayer) { 933 m_contentLayer->addChild(m_foregroundClipLayer); 934 // Use the scrollable content layer as the parent of the children so 935 // that they move with the content. 936 layer = m_foregroundLayer; 937 layer->removeChildren(); 938 } 939 for (unsigned int i = 0; i < m_children.size(); i++) 940 layer->addChild(m_children[i]->platformLayer()); 941 m_needsSyncChildren = false; 942 } 943} 944 945void GraphicsLayerAndroid::syncMask() 946{ 947 if (m_needsSyncMask) { 948 if (m_maskLayer) { 949 LayerAndroid* mask = m_maskLayer->platformLayer(); 950 m_contentLayer->setMaskLayer(mask); 951 } else 952 m_contentLayer->setMaskLayer(0); 953 954 m_contentLayer->setMasksToBounds(m_masksToBounds); 955 m_needsSyncMask = false; 956 } 957} 958 959void GraphicsLayerAndroid::syncCompositingState() 960{ 961 for (unsigned int i = 0; i < m_children.size(); i++) 962 m_children[i]->syncCompositingState(); 963 964 updateScrollingLayers(); 965 updateFixedPosition(); 966 syncChildren(); 967 syncMask(); 968 969 if (!gPaused || WTF::currentTime() >= gPausedDelay) 970 repaint(); 971} 972 973void GraphicsLayerAndroid::notifyClientAnimationStarted() 974{ 975 for (unsigned int i = 0; i < m_children.size(); i++) 976 static_cast<GraphicsLayerAndroid*>(m_children[i])->notifyClientAnimationStarted(); 977 978 if (m_needsNotifyClient) { 979 if (client()) 980 client()->notifyAnimationStarted(this, WTF::currentTime()); 981 m_needsNotifyClient = false; 982 } 983} 984 985} // namespace WebCore 986 987#endif // USE(ACCELERATED_COMPOSITING) 988