| 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 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 429 | 429 |
| 430 bool listenerNeedsNewFrameCapture = false; | 430 bool listenerNeedsNewFrameCapture = false; |
| 431 for (const CanvasDrawListener* listener : m_listeners) { | 431 for (const CanvasDrawListener* listener : m_listeners) { |
| 432 if (listener->needsNewFrame()) { | 432 if (listener->needsNewFrame()) { |
| 433 listenerNeedsNewFrameCapture = true; | 433 listenerNeedsNewFrameCapture = true; |
| 434 } | 434 } |
| 435 } | 435 } |
| 436 | 436 |
| 437 if (listenerNeedsNewFrameCapture) { | 437 if (listenerNeedsNewFrameCapture) { |
| 438 SourceImageStatus status; | 438 SourceImageStatus status; |
| 439 RefPtr<Image> sourceImage = getSourceImageForCanvas(&status, PreferAccel
eration); | 439 RefPtr<Image> sourceImage = getSourceImageForCanvas(&status, PreferNoAcc
eleration, SnapshotReasonCanvasListenerCapture); |
| 440 if (status != NormalSourceImageStatus) | 440 if (status != NormalSourceImageStatus) |
| 441 return; | 441 return; |
| 442 RefPtr<SkImage> image = sourceImage->imageForCurrentFrame(); | 442 RefPtr<SkImage> image = sourceImage->imageForCurrentFrame(); |
| 443 for (CanvasDrawListener* listener : m_listeners) { | 443 for (CanvasDrawListener* listener : m_listeners) { |
| 444 if (listener->needsNewFrame()) { | 444 if (listener->needsNewFrame()) { |
| 445 listener->sendNewFrame(image); | 445 listener->sendNewFrame(image); |
| 446 } | 446 } |
| 447 } | 447 } |
| 448 } | 448 } |
| 449 | 449 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 return AtomicString(toDataURLInternal(DefaultMimeType, 0, FrontBuffer)); | 510 return AtomicString(toDataURLInternal(DefaultMimeType, 0, FrontBuffer)); |
| 511 } | 511 } |
| 512 | 512 |
| 513 void HTMLCanvasElement::prepareSurfaceForPaintingIfNeeded() const | 513 void HTMLCanvasElement::prepareSurfaceForPaintingIfNeeded() const |
| 514 { | 514 { |
| 515 ASSERT(m_context && m_context->is2d()); // This function is called by the 2d
context | 515 ASSERT(m_context && m_context->is2d()); // This function is called by the 2d
context |
| 516 if (buffer()) | 516 if (buffer()) |
| 517 m_imageBuffer->prepareSurfaceForPaintingIfNeeded(); | 517 m_imageBuffer->prepareSurfaceForPaintingIfNeeded(); |
| 518 } | 518 } |
| 519 | 519 |
| 520 ImageData* HTMLCanvasElement::toImageData(SourceDrawingBuffer sourceBuffer) cons
t | 520 ImageData* HTMLCanvasElement::toImageData(SourceDrawingBuffer sourceBuffer, Snap
shotReason reason) const |
| 521 { | 521 { |
| 522 ImageData* imageData; | 522 ImageData* imageData; |
| 523 if (is3D()) { | 523 if (is3D()) { |
| 524 // Get non-premultiplied data because of inaccurate premultiplied alpha
conversion of buffer()->toDataURL(). | 524 // Get non-premultiplied data because of inaccurate premultiplied alpha
conversion of buffer()->toDataURL(). |
| 525 imageData = m_context->paintRenderingResultsToImageData(sourceBuffer); | 525 imageData = m_context->paintRenderingResultsToImageData(sourceBuffer); |
| 526 if (imageData) | 526 if (imageData) |
| 527 return imageData; | 527 return imageData; |
| 528 | 528 |
| 529 m_context->paintRenderingResultsToCanvas(sourceBuffer); | 529 m_context->paintRenderingResultsToCanvas(sourceBuffer); |
| 530 imageData = ImageData::create(m_size); | 530 imageData = ImageData::create(m_size); |
| 531 RefPtr<SkImage> snapshot = buffer()->newSkImageSnapshot(PreferNoAccelera
tion); | 531 RefPtr<SkImage> snapshot = buffer()->newSkImageSnapshot(PreferNoAccelera
tion, reason); |
| 532 if (snapshot) { | 532 if (snapshot) { |
| 533 SkImageInfo imageInfo = SkImageInfo::Make(width(), height(), kRGBA_8
888_SkColorType, kUnpremul_SkAlphaType); | 533 SkImageInfo imageInfo = SkImageInfo::Make(width(), height(), kRGBA_8
888_SkColorType, kUnpremul_SkAlphaType); |
| 534 snapshot->readPixels(imageInfo, imageData->data()->data(), imageInfo
.minRowBytes(), 0, 0); | 534 snapshot->readPixels(imageInfo, imageData->data()->data(), imageInfo
.minRowBytes(), 0, 0); |
| 535 } | 535 } |
| 536 return imageData; | 536 return imageData; |
| 537 } | 537 } |
| 538 | 538 |
| 539 imageData = ImageData::create(m_size); | 539 imageData = ImageData::create(m_size); |
| 540 | 540 |
| 541 if (!m_context) | 541 if (!m_context) |
| 542 return imageData; | 542 return imageData; |
| 543 | 543 |
| 544 ASSERT(m_context->is2d()); | 544 ASSERT(m_context->is2d()); |
| 545 RefPtr<SkImage> snapshot = buffer()->newSkImageSnapshot(PreferNoAcceleration
); | 545 RefPtr<SkImage> snapshot = buffer()->newSkImageSnapshot(PreferNoAcceleration
, reason); |
| 546 if (snapshot) { | 546 if (snapshot) { |
| 547 SkImageInfo imageInfo = SkImageInfo::Make(width(), height(), kRGBA_8888_
SkColorType, kUnpremul_SkAlphaType); | 547 SkImageInfo imageInfo = SkImageInfo::Make(width(), height(), kRGBA_8888_
SkColorType, kUnpremul_SkAlphaType); |
| 548 snapshot->readPixels(imageInfo, imageData->data()->data(), imageInfo.min
RowBytes(), 0, 0); | 548 snapshot->readPixels(imageInfo, imageData->data()->data(), imageInfo.min
RowBytes(), 0, 0); |
| 549 } | 549 } |
| 550 | 550 |
| 551 return imageData; | 551 return imageData; |
| 552 } | 552 } |
| 553 | 553 |
| 554 String HTMLCanvasElement::toDataURLInternal(const String& mimeType, const double
& quality, SourceDrawingBuffer sourceBuffer) const | 554 String HTMLCanvasElement::toDataURLInternal(const String& mimeType, const double
& quality, SourceDrawingBuffer sourceBuffer) const |
| 555 { | 555 { |
| 556 if (!isPaintable()) | 556 if (!isPaintable()) |
| 557 return String("data:,"); | 557 return String("data:,"); |
| 558 | 558 |
| 559 String encodingMimeType = toEncodingMimeType(mimeType); | 559 String encodingMimeType = toEncodingMimeType(mimeType); |
| 560 | 560 |
| 561 ImageData* imageData = toImageData(sourceBuffer); | 561 ImageData* imageData = toImageData(sourceBuffer, SnapshotReasonToDataURL); |
| 562 ScopedDisposal<ImageData> disposer(imageData); | 562 ScopedDisposal<ImageData> disposer(imageData); |
| 563 | 563 |
| 564 return ImageDataBuffer(imageData->size(), imageData->data()->data()).toDataU
RL(encodingMimeType, quality); | 564 return ImageDataBuffer(imageData->size(), imageData->data()->data()).toDataU
RL(encodingMimeType, quality); |
| 565 } | 565 } |
| 566 | 566 |
| 567 String HTMLCanvasElement::toDataURL(const String& mimeType, const ScriptValue& q
ualityArgument, ExceptionState& exceptionState) const | 567 String HTMLCanvasElement::toDataURL(const String& mimeType, const ScriptValue& q
ualityArgument, ExceptionState& exceptionState) const |
| 568 { | 568 { |
| 569 if (!originClean()) { | 569 if (!originClean()) { |
| 570 exceptionState.throwSecurityError("Tainted canvases may not be exported.
"); | 570 exceptionState.throwSecurityError("Tainted canvases may not be exported.
"); |
| 571 return String(); | 571 return String(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 596 double quality = UndefinedQualityValue; | 596 double quality = UndefinedQualityValue; |
| 597 if (!qualityArgument.isEmpty()) { | 597 if (!qualityArgument.isEmpty()) { |
| 598 v8::Local<v8::Value> v8Value = qualityArgument.v8Value(); | 598 v8::Local<v8::Value> v8Value = qualityArgument.v8Value(); |
| 599 if (v8Value->IsNumber()) { | 599 if (v8Value->IsNumber()) { |
| 600 quality = v8Value.As<v8::Number>()->Value(); | 600 quality = v8Value.As<v8::Number>()->Value(); |
| 601 } | 601 } |
| 602 } | 602 } |
| 603 | 603 |
| 604 String encodingMimeType = toEncodingMimeType(mimeType); | 604 String encodingMimeType = toEncodingMimeType(mimeType); |
| 605 | 605 |
| 606 ImageData* imageData = toImageData(BackBuffer); | 606 ImageData* imageData = toImageData(BackBuffer, SnapshotReasonToBlob); |
| 607 // imageData unref its data, which we still keep alive for the async toBlob
thread | 607 // imageData unref its data, which we still keep alive for the async toBlob
thread |
| 608 ScopedDisposal<ImageData> disposer(imageData); | 608 ScopedDisposal<ImageData> disposer(imageData); |
| 609 // Add a ref to keep image data alive until completion of encoding | 609 // Add a ref to keep image data alive until completion of encoding |
| 610 RefPtr<DOMUint8ClampedArray> imageDataRef(imageData->data()); | 610 RefPtr<DOMUint8ClampedArray> imageDataRef(imageData->data()); |
| 611 | 611 |
| 612 RefPtr<CanvasAsyncBlobCreator> asyncCreatorRef = CanvasAsyncBlobCreator::cre
ate(imageDataRef.release(), encodingMimeType, imageData->size(), callback); | 612 RefPtr<CanvasAsyncBlobCreator> asyncCreatorRef = CanvasAsyncBlobCreator::cre
ate(imageDataRef.release(), encodingMimeType, imageData->size(), callback); |
| 613 | 613 |
| 614 if (encodingMimeType == DefaultMimeType) { | 614 if (encodingMimeType == DefaultMimeType) { |
| 615 asyncCreatorRef->scheduleAsyncBlobCreation(true); | 615 asyncCreatorRef->scheduleAsyncBlobCreation(true); |
| 616 } else { | 616 } else { |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 846 // Subtracting two intptr_t that are known to be positive will never underfl
ow. | 846 // Subtracting two intptr_t that are known to be positive will never underfl
ow. |
| 847 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(externallyA
llocatedMemory - m_externallyAllocatedMemory); | 847 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(externallyA
llocatedMemory - m_externallyAllocatedMemory); |
| 848 m_externallyAllocatedMemory = externallyAllocatedMemory; | 848 m_externallyAllocatedMemory = externallyAllocatedMemory; |
| 849 } | 849 } |
| 850 | 850 |
| 851 SkCanvas* HTMLCanvasElement::drawingCanvas() const | 851 SkCanvas* HTMLCanvasElement::drawingCanvas() const |
| 852 { | 852 { |
| 853 return buffer() ? m_imageBuffer->canvas() : nullptr; | 853 return buffer() ? m_imageBuffer->canvas() : nullptr; |
| 854 } | 854 } |
| 855 | 855 |
| 856 void HTMLCanvasElement::disableDeferral() const | 856 void HTMLCanvasElement::disableDeferral(DisableDeferralReason reason) const |
| 857 { | 857 { |
| 858 if (buffer()) | 858 if (buffer()) |
| 859 m_imageBuffer->disableDeferral(); | 859 m_imageBuffer->disableDeferral(reason); |
| 860 } | 860 } |
| 861 | 861 |
| 862 SkCanvas* HTMLCanvasElement::existingDrawingCanvas() const | 862 SkCanvas* HTMLCanvasElement::existingDrawingCanvas() const |
| 863 { | 863 { |
| 864 if (!hasImageBuffer()) | 864 if (!hasImageBuffer()) |
| 865 return nullptr; | 865 return nullptr; |
| 866 | 866 |
| 867 return m_imageBuffer->canvas(); | 867 return m_imageBuffer->canvas(); |
| 868 } | 868 } |
| 869 | 869 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 959 if (m_context) | 959 if (m_context) |
| 960 m_context->styleDidChange(oldStyle, newStyle); | 960 m_context->styleDidChange(oldStyle, newStyle); |
| 961 } | 961 } |
| 962 | 962 |
| 963 void HTMLCanvasElement::didMoveToNewDocument(Document& oldDocument) | 963 void HTMLCanvasElement::didMoveToNewDocument(Document& oldDocument) |
| 964 { | 964 { |
| 965 setObservedDocument(document()); | 965 setObservedDocument(document()); |
| 966 HTMLElement::didMoveToNewDocument(oldDocument); | 966 HTMLElement::didMoveToNewDocument(oldDocument); |
| 967 } | 967 } |
| 968 | 968 |
| 969 PassRefPtr<Image> HTMLCanvasElement::getSourceImageForCanvas(SourceImageStatus*
status, AccelerationHint hint) const | 969 PassRefPtr<Image> HTMLCanvasElement::getSourceImageForCanvas(SourceImageStatus*
status, AccelerationHint hint, SnapshotReason reason) const |
| 970 { | 970 { |
| 971 if (!width() || !height()) { | 971 if (!width() || !height()) { |
| 972 *status = ZeroSizeCanvasSourceImageStatus; | 972 *status = ZeroSizeCanvasSourceImageStatus; |
| 973 return nullptr; | 973 return nullptr; |
| 974 } | 974 } |
| 975 | 975 |
| 976 if (!isPaintable()) { | 976 if (!isPaintable()) { |
| 977 *status = InvalidSourceImageStatus; | 977 *status = InvalidSourceImageStatus; |
| 978 return nullptr; | 978 return nullptr; |
| 979 } | 979 } |
| 980 | 980 |
| 981 if (!m_context) { | 981 if (!m_context) { |
| 982 *status = NormalSourceImageStatus; | 982 *status = NormalSourceImageStatus; |
| 983 return createTransparentImage(size()); | 983 return createTransparentImage(size()); |
| 984 } | 984 } |
| 985 | 985 |
| 986 if (m_context->is3d()) { | 986 if (m_context->is3d()) { |
| 987 m_context->paintRenderingResultsToCanvas(BackBuffer); | 987 m_context->paintRenderingResultsToCanvas(BackBuffer); |
| 988 } | 988 } |
| 989 | 989 |
| 990 RefPtr<SkImage> image = buffer()->newSkImageSnapshot(hint); | 990 RefPtr<SkImage> image = buffer()->newSkImageSnapshot(hint, reason); |
| 991 if (image) { | 991 if (image) { |
| 992 *status = NormalSourceImageStatus; | 992 *status = NormalSourceImageStatus; |
| 993 return StaticBitmapImage::create(image.release()); | 993 return StaticBitmapImage::create(image.release()); |
| 994 } | 994 } |
| 995 | 995 |
| 996 *status = InvalidSourceImageStatus; | 996 *status = InvalidSourceImageStatus; |
| 997 return nullptr; | 997 return nullptr; |
| 998 } | 998 } |
| 999 | 999 |
| 1000 bool HTMLCanvasElement::wouldTaintOrigin(SecurityOrigin*) const | 1000 bool HTMLCanvasElement::wouldTaintOrigin(SecurityOrigin*) const |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1021 } | 1021 } |
| 1022 return ImageBitmapSource::fulfillImageBitmap(scriptState, isPaintable() ? Im
ageBitmap::create(this, IntRect(sx, sy, sw, sh), options) : nullptr); | 1022 return ImageBitmapSource::fulfillImageBitmap(scriptState, isPaintable() ? Im
ageBitmap::create(this, IntRect(sx, sy, sw, sh), options) : nullptr); |
| 1023 } | 1023 } |
| 1024 | 1024 |
| 1025 bool HTMLCanvasElement::isOpaque() const | 1025 bool HTMLCanvasElement::isOpaque() const |
| 1026 { | 1026 { |
| 1027 return m_context && !m_context->hasAlpha(); | 1027 return m_context && !m_context->hasAlpha(); |
| 1028 } | 1028 } |
| 1029 | 1029 |
| 1030 } // namespace blink | 1030 } // namespace blink |
| OLD | NEW |