| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2007 Alp Toker <alp@atoker.com> | 3 * Copyright (C) 2007 Alp Toker <alp@atoker.com> |
| 4 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. | 4 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. |
| 5 * | 5 * |
| 6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
| 8 * are met: | 8 * are met: |
| 9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 } | 138 } |
| 139 | 139 |
| 140 DEFINE_NODE_FACTORY(HTMLCanvasElement) | 140 DEFINE_NODE_FACTORY(HTMLCanvasElement) |
| 141 | 141 |
| 142 HTMLCanvasElement::~HTMLCanvasElement() { | 142 HTMLCanvasElement::~HTMLCanvasElement() { |
| 143 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory( | 143 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory( |
| 144 -m_externallyAllocatedMemory); | 144 -m_externallyAllocatedMemory); |
| 145 } | 145 } |
| 146 | 146 |
| 147 void HTMLCanvasElement::dispose() { | 147 void HTMLCanvasElement::dispose() { |
| 148 releasePlaceholderFrame(); |
| 149 |
| 148 if (m_context) { | 150 if (m_context) { |
| 149 m_context->detachCanvas(); | 151 m_context->detachCanvas(); |
| 150 m_context = nullptr; | 152 m_context = nullptr; |
| 151 } | 153 } |
| 152 m_imageBuffer = nullptr; | 154 m_imageBuffer = nullptr; |
| 153 } | 155 } |
| 154 | 156 |
| 155 void HTMLCanvasElement::parseAttribute(const QualifiedName& name, | 157 void HTMLCanvasElement::parseAttribute(const QualifiedName& name, |
| 156 const AtomicString& oldValue, | 158 const AtomicString& oldValue, |
| 157 const AtomicString& value) { | 159 const AtomicString& value) { |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 463 if (layoutBox() && layoutBox()->hasAcceleratedCompositing()) | 465 if (layoutBox() && layoutBox()->hasAcceleratedCompositing()) |
| 464 layoutBox()->contentChanged(CanvasChanged); | 466 layoutBox()->contentChanged(CanvasChanged); |
| 465 } | 467 } |
| 466 if (hadImageBuffer) | 468 if (hadImageBuffer) |
| 467 layoutObject->setShouldDoFullPaintInvalidation(); | 469 layoutObject->setShouldDoFullPaintInvalidation(); |
| 468 } | 470 } |
| 469 } | 471 } |
| 470 } | 472 } |
| 471 | 473 |
| 472 bool HTMLCanvasElement::paintsIntoCanvasBuffer() const { | 474 bool HTMLCanvasElement::paintsIntoCanvasBuffer() const { |
| 475 if (placeholderFrame()) |
| 476 return false; |
| 473 DCHECK(m_context); | 477 DCHECK(m_context); |
| 474 | |
| 475 if (!m_context->isAccelerated()) | 478 if (!m_context->isAccelerated()) |
| 476 return true; | 479 return true; |
| 477 if (layoutBox() && layoutBox()->hasAcceleratedCompositing()) | 480 if (layoutBox() && layoutBox()->hasAcceleratedCompositing()) |
| 478 return false; | 481 return false; |
| 479 | 482 |
| 480 return true; | 483 return true; |
| 481 } | 484 } |
| 482 | 485 |
| 483 void HTMLCanvasElement::notifyListenersCanvasChanged() { | 486 void HTMLCanvasElement::notifyListenersCanvasChanged() { |
| 484 if (m_listeners.size() == 0) | 487 if (m_listeners.size() == 0) |
| (...skipping 23 matching lines...) Expand all Loading... |
| 508 if (listener->needsNewFrame()) { | 511 if (listener->needsNewFrame()) { |
| 509 listener->sendNewFrame(image); | 512 listener->sendNewFrame(image); |
| 510 } | 513 } |
| 511 } | 514 } |
| 512 } | 515 } |
| 513 } | 516 } |
| 514 | 517 |
| 515 void HTMLCanvasElement::paint(GraphicsContext& context, const LayoutRect& r) { | 518 void HTMLCanvasElement::paint(GraphicsContext& context, const LayoutRect& r) { |
| 516 // FIXME: crbug.com/438240; there is a bug with the new CSS blending and | 519 // FIXME: crbug.com/438240; there is a bug with the new CSS blending and |
| 517 // compositing feature. | 520 // compositing feature. |
| 518 if (!m_context) | 521 if (!m_context && !placeholderFrame()) |
| 519 return; | 522 return; |
| 520 | 523 |
| 521 const ComputedStyle* style = ensureComputedStyle(); | 524 const ComputedStyle* style = ensureComputedStyle(); |
| 522 SkFilterQuality filterQuality = | 525 SkFilterQuality filterQuality = |
| 523 (style && style->imageRendering() == ImageRenderingPixelated) | 526 (style && style->imageRendering() == ImageRenderingPixelated) |
| 524 ? kNone_SkFilterQuality | 527 ? kNone_SkFilterQuality |
| 525 : kLow_SkFilterQuality; | 528 : kLow_SkFilterQuality; |
| 526 | 529 |
| 527 if (is3D()) { | 530 if (is3D()) { |
| 528 m_context->setFilterQuality(filterQuality); | 531 m_context->setFilterQuality(filterQuality); |
| 529 } else if (hasImageBuffer()) { | 532 } else if (hasImageBuffer()) { |
| 530 m_imageBuffer->setFilterQuality(filterQuality); | 533 m_imageBuffer->setFilterQuality(filterQuality); |
| 531 } | 534 } |
| 532 | 535 |
| 533 if (hasImageBuffer() && !m_imageBufferIsClear) | 536 if (hasImageBuffer() && !m_imageBufferIsClear) |
| 534 PaintTiming::from(document()).markFirstContentfulPaint(); | 537 PaintTiming::from(document()).markFirstContentfulPaint(); |
| 535 | 538 |
| 536 if (!paintsIntoCanvasBuffer() && !document().printing()) | 539 if (!paintsIntoCanvasBuffer() && !document().printing()) |
| 537 return; | 540 return; |
| 538 | 541 |
| 542 if (placeholderFrame()) { |
| 543 DCHECK(document().printing()); |
| 544 context.drawImage(placeholderFrame().get(), pixelSnappedIntRect(r)); |
| 545 return; |
| 546 } |
| 547 |
| 539 // TODO(junov): Paint is currently only implemented by ImageBitmap contexts. | 548 // TODO(junov): Paint is currently only implemented by ImageBitmap contexts. |
| 540 // We could improve the abstraction by making all context types paint | 549 // We could improve the abstraction by making all context types paint |
| 541 // themselves (implement paint()). | 550 // themselves (implement paint()). |
| 542 if (m_context->paint(context, pixelSnappedIntRect(r))) | 551 if (m_context->paint(context, pixelSnappedIntRect(r))) |
| 543 return; | 552 return; |
| 544 | 553 |
| 545 m_context->paintRenderingResultsToCanvas(FrontBuffer); | 554 m_context->paintRenderingResultsToCanvas(FrontBuffer); |
| 546 if (hasImageBuffer()) { | 555 if (hasImageBuffer()) { |
| 547 if (!context.contextDisabled()) { | 556 if (!context.contextDisabled()) { |
| 548 SkBlendMode compositeOperator = | 557 SkBlendMode compositeOperator = |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 612 width(), height(), kRGBA_8888_SkColorType, kUnpremul_SkAlphaType); | 621 width(), height(), kRGBA_8888_SkColorType, kUnpremul_SkAlphaType); |
| 613 snapshot->readPixels(imageInfo, imageData->data()->data(), | 622 snapshot->readPixels(imageInfo, imageData->data()->data(), |
| 614 imageInfo.minRowBytes(), 0, 0); | 623 imageInfo.minRowBytes(), 0, 0); |
| 615 } | 624 } |
| 616 } | 625 } |
| 617 return imageData; | 626 return imageData; |
| 618 } | 627 } |
| 619 | 628 |
| 620 imageData = ImageData::create(m_size); | 629 imageData = ImageData::create(m_size); |
| 621 | 630 |
| 622 if (!m_context || !imageData) | 631 if ((!m_context || !imageData) && !placeholderFrame()) |
| 623 return imageData; | 632 return imageData; |
| 624 | 633 |
| 625 DCHECK(m_context->is2d()); | 634 DCHECK((m_context && m_context->is2d()) || placeholderFrame()); |
| 635 sk_sp<SkImage> snapshot; |
| 626 if (hasImageBuffer()) { | 636 if (hasImageBuffer()) { |
| 627 sk_sp<SkImage> snapshot = | 637 snapshot = buffer()->newSkImageSnapshot(PreferNoAcceleration, reason); |
| 628 buffer()->newSkImageSnapshot(PreferNoAcceleration, reason); | 638 } else if (placeholderFrame()) { |
| 629 if (snapshot) { | 639 snapshot = placeholderFrame()->imageForCurrentFrame(); |
| 630 SkImageInfo imageInfo = SkImageInfo::Make( | 640 } |
| 631 width(), height(), kRGBA_8888_SkColorType, kUnpremul_SkAlphaType); | 641 |
| 632 snapshot->readPixels(imageInfo, imageData->data()->data(), | 642 if (snapshot) { |
| 633 imageInfo.minRowBytes(), 0, 0); | 643 SkImageInfo imageInfo = SkImageInfo::Make( |
| 634 } | 644 width(), height(), kRGBA_8888_SkColorType, kUnpremul_SkAlphaType); |
| 645 snapshot->readPixels(imageInfo, imageData->data()->data(), |
| 646 imageInfo.minRowBytes(), 0, 0); |
| 635 } | 647 } |
| 636 | 648 |
| 637 return imageData; | 649 return imageData; |
| 638 } | 650 } |
| 639 | 651 |
| 640 String HTMLCanvasElement::toDataURLInternal( | 652 String HTMLCanvasElement::toDataURLInternal( |
| 641 const String& mimeType, | 653 const String& mimeType, |
| 642 const double& quality, | 654 const double& quality, |
| 643 SourceDrawingBuffer sourceBuffer) const { | 655 SourceDrawingBuffer sourceBuffer) const { |
| 644 if (!isPaintable()) | 656 if (!isPaintable()) |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 676 if (!imageData) // allocation failure | 688 if (!imageData) // allocation failure |
| 677 return String("data:,"); | 689 return String("data:,"); |
| 678 | 690 |
| 679 return ImageDataBuffer(imageData->size(), imageData->data()->data()) | 691 return ImageDataBuffer(imageData->size(), imageData->data()->data()) |
| 680 .toDataURL(encodingMimeType, quality); | 692 .toDataURL(encodingMimeType, quality); |
| 681 } | 693 } |
| 682 | 694 |
| 683 String HTMLCanvasElement::toDataURL(const String& mimeType, | 695 String HTMLCanvasElement::toDataURL(const String& mimeType, |
| 684 const ScriptValue& qualityArgument, | 696 const ScriptValue& qualityArgument, |
| 685 ExceptionState& exceptionState) const { | 697 ExceptionState& exceptionState) const { |
| 686 if (surfaceLayerBridge()) { | |
| 687 exceptionState.throwDOMException(InvalidStateError, | |
| 688 "canvas.toDataURL is not allowed for a " | |
| 689 "canvas that has transferred its control " | |
| 690 "to offscreen."); | |
| 691 return String(); | |
| 692 } | |
| 693 if (!originClean()) { | 698 if (!originClean()) { |
| 694 exceptionState.throwSecurityError("Tainted canvases may not be exported."); | 699 exceptionState.throwSecurityError("Tainted canvases may not be exported."); |
| 695 return String(); | 700 return String(); |
| 696 } | 701 } |
| 697 | 702 |
| 698 double quality = UndefinedQualityValue; | 703 double quality = UndefinedQualityValue; |
| 699 if (!qualityArgument.isEmpty()) { | 704 if (!qualityArgument.isEmpty()) { |
| 700 v8::Local<v8::Value> v8Value = qualityArgument.v8Value(); | 705 v8::Local<v8::Value> v8Value = qualityArgument.v8Value(); |
| 701 if (v8Value->IsNumber()) { | 706 if (v8Value->IsNumber()) { |
| 702 quality = v8Value.As<v8::Number>()->Value(); | 707 quality = v8Value.As<v8::Number>()->Value(); |
| 703 } | 708 } |
| 704 } | 709 } |
| 705 return toDataURLInternal(mimeType, quality, BackBuffer); | 710 return toDataURLInternal(mimeType, quality, BackBuffer); |
| 706 } | 711 } |
| 707 | 712 |
| 708 void HTMLCanvasElement::toBlob(BlobCallback* callback, | 713 void HTMLCanvasElement::toBlob(BlobCallback* callback, |
| 709 const String& mimeType, | 714 const String& mimeType, |
| 710 const ScriptValue& qualityArgument, | 715 const ScriptValue& qualityArgument, |
| 711 ExceptionState& exceptionState) { | 716 ExceptionState& exceptionState) { |
| 712 if (surfaceLayerBridge()) { | |
| 713 exceptionState.throwDOMException(InvalidStateError, | |
| 714 "canvas.toBlob is not allowed for a " | |
| 715 "canvas that has transferred its control " | |
| 716 "to offscreen."); | |
| 717 return; | |
| 718 } | |
| 719 | |
| 720 if (!originClean()) { | 717 if (!originClean()) { |
| 721 exceptionState.throwSecurityError("Tainted canvases may not be exported."); | 718 exceptionState.throwSecurityError("Tainted canvases may not be exported."); |
| 722 return; | 719 return; |
| 723 } | 720 } |
| 724 | 721 |
| 725 if (!isPaintable()) { | 722 if (!isPaintable()) { |
| 726 // If the canvas element's bitmap has no pixels | 723 // If the canvas element's bitmap has no pixels |
| 727 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, &document()) | 724 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, &document()) |
| 728 ->postTask(BLINK_FROM_HERE, | 725 ->postTask(BLINK_FROM_HERE, |
| 729 WTF::bind(&BlobCallback::handleEvent, | 726 WTF::bind(&BlobCallback::handleEvent, |
| (...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1193 if (!width() || !height()) { | 1190 if (!width() || !height()) { |
| 1194 *status = ZeroSizeCanvasSourceImageStatus; | 1191 *status = ZeroSizeCanvasSourceImageStatus; |
| 1195 return nullptr; | 1192 return nullptr; |
| 1196 } | 1193 } |
| 1197 | 1194 |
| 1198 if (!isPaintable()) { | 1195 if (!isPaintable()) { |
| 1199 *status = InvalidSourceImageStatus; | 1196 *status = InvalidSourceImageStatus; |
| 1200 return nullptr; | 1197 return nullptr; |
| 1201 } | 1198 } |
| 1202 | 1199 |
| 1200 if (placeholderFrame()) { |
| 1201 *status = NormalSourceImageStatus; |
| 1202 return placeholderFrame(); |
| 1203 } |
| 1204 |
| 1203 if (!m_context) { | 1205 if (!m_context) { |
| 1204 *status = NormalSourceImageStatus; | 1206 *status = NormalSourceImageStatus; |
| 1205 return createTransparentImage(size()); | 1207 return createTransparentImage(size()); |
| 1206 } | 1208 } |
| 1207 | 1209 |
| 1208 sk_sp<SkImage> skImage; | 1210 sk_sp<SkImage> skImage; |
| 1209 if (m_context->is3d()) { | 1211 if (m_context->is3d()) { |
| 1210 // Because WebGL sources always require making a copy of the back buffer, we | 1212 // Because WebGL sources always require making a copy of the back buffer, we |
| 1211 // use paintRenderingResultsToCanvas instead of getImage in order to keep a | 1213 // use paintRenderingResultsToCanvas instead of getImage in order to keep a |
| 1212 // cached copy of the backing in the canvas's ImageBuffer. | 1214 // cached copy of the backing in the canvas's ImageBuffer. |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1357 mojom::blink::OffscreenCanvasSurfacePtr service; | 1359 mojom::blink::OffscreenCanvasSurfacePtr service; |
| 1358 Platform::current()->interfaceProvider()->getInterface( | 1360 Platform::current()->interfaceProvider()->getInterface( |
| 1359 mojo::GetProxy(&service)); | 1361 mojo::GetProxy(&service)); |
| 1360 m_surfaceLayerBridge = | 1362 m_surfaceLayerBridge = |
| 1361 wrapUnique(new CanvasSurfaceLayerBridge(std::move(service))); | 1363 wrapUnique(new CanvasSurfaceLayerBridge(std::move(service))); |
| 1362 return m_surfaceLayerBridge->createSurfaceLayer(this->width(), | 1364 return m_surfaceLayerBridge->createSurfaceLayer(this->width(), |
| 1363 this->height()); | 1365 this->height()); |
| 1364 } | 1366 } |
| 1365 | 1367 |
| 1366 } // namespace blink | 1368 } // namespace blink |
| OLD | NEW |