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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
75 | 75 |
76 //In Skia, we will also limit width/height to 32767. | 76 //In Skia, we will also limit width/height to 32767. |
77 const int MaxSkiaDim = 32767; // Maximum width/height in CSS pixels. | 77 const int MaxSkiaDim = 32767; // Maximum width/height in CSS pixels. |
78 | 78 |
79 bool canCreateImageBuffer(const IntSize& deviceSize) | 79 bool canCreateImageBuffer(const IntSize& deviceSize) |
80 { | 80 { |
81 if (deviceSize.width() * deviceSize.height() > MaxCanvasArea) | 81 if (deviceSize.width() * deviceSize.height() > MaxCanvasArea) |
82 return false; | 82 return false; |
83 if (deviceSize.width() > MaxSkiaDim || deviceSize.height() > MaxSkiaDim) | 83 if (deviceSize.width() > MaxSkiaDim || deviceSize.height() > MaxSkiaDim) |
84 return false; | 84 return false; |
85 if (!deviceSize.width() || !deviceSize.height()) | 85 if (deviceSize.isEmpty()) |
86 return false; | 86 return false; |
87 return true; | 87 return true; |
88 } | 88 } |
89 | 89 |
90 } // namespace | 90 } // namespace |
91 | 91 |
92 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(CanvasObserver); | 92 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(CanvasObserver); |
93 | 93 |
94 inline HTMLCanvasElement::HTMLCanvasElement(Document& document) | 94 inline HTMLCanvasElement::HTMLCanvasElement(Document& document) |
95 : HTMLElement(canvasTag, document) | 95 : HTMLElement(canvasTag, document) |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
403 return lowercaseMimeType; | 403 return lowercaseMimeType; |
404 } | 404 } |
405 | 405 |
406 const AtomicString HTMLCanvasElement::imageSourceURL() const | 406 const AtomicString HTMLCanvasElement::imageSourceURL() const |
407 { | 407 { |
408 return AtomicString(toDataURLInternal("image/png", 0, FrontBuffer)); | 408 return AtomicString(toDataURLInternal("image/png", 0, FrontBuffer)); |
409 } | 409 } |
410 | 410 |
411 String HTMLCanvasElement::toDataURLInternal(const String& mimeType, const double * quality, SourceDrawingBuffer sourceBuffer) const | 411 String HTMLCanvasElement::toDataURLInternal(const String& mimeType, const double * quality, SourceDrawingBuffer sourceBuffer) const |
412 { | 412 { |
413 if (m_size.isEmpty() || !canCreateImageBuffer(size())) | 413 if (!buffer()) |
414 return String("data:,"); | 414 return String("data:,"); |
415 | 415 |
416 String encodingMimeType = toEncodingMimeType(mimeType); | 416 String encodingMimeType = toEncodingMimeType(mimeType); |
417 if (!m_context) { | 417 if (m_context && m_context->is3d()) { |
418 RefPtrWillBeRawPtr<ImageData> imageData = ImageData::create(m_size); | |
419 return ImageEncoder::toDataURL(ImageEncoder::RawImageBytes(imageData->si ze(), imageData->data()->data()), encodingMimeType, quality); | |
420 } | |
421 | |
422 if (m_context->is3d()) { | |
423 // Get non-premultiplied data because of inaccurate premultiplied alpha conversion of buffer()->toDataURL(). | 418 // Get non-premultiplied data because of inaccurate premultiplied alpha conversion of buffer()->toDataURL(). |
424 RefPtrWillBeRawPtr<ImageData> imageData = | 419 RefPtrWillBeRawPtr<ImageData> imageData = |
425 toWebGLRenderingContext(m_context.get())->paintRenderingResultsToIma geData(sourceBuffer); | 420 toWebGLRenderingContext(m_context.get())->paintRenderingResultsToIma geData(sourceBuffer); |
426 if (imageData) | 421 if (imageData) |
427 return ImageEncoder::toDataURL(ImageEncoder::RawImageBytes(imageData ->size(), imageData->data()->data()), encodingMimeType, quality); | 422 return ImageEncoder::toDataURL(ImageEncoder::RawImageBytes(imageData ->size(), imageData->data()->data()), encodingMimeType, quality); |
428 m_context->paintRenderingResultsToCanvas(sourceBuffer); | 423 m_context->paintRenderingResultsToCanvas(sourceBuffer); |
429 } | 424 } |
430 | 425 |
431 return buffer()->toDataURL(encodingMimeType, quality); | 426 return buffer()->toDataURL(encodingMimeType, quality); |
432 } | 427 } |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
547 if (surface->isValid()) | 542 if (surface->isValid()) |
548 return surface.release(); | 543 return surface.release(); |
549 surfaceFactory = createSurfaceFactory(deviceSize, msaaSampleCount); // r ecreate because old previous one was released | 544 surfaceFactory = createSurfaceFactory(deviceSize, msaaSampleCount); // r ecreate because old previous one was released |
550 } | 545 } |
551 | 546 |
552 return surfaceFactory->createSurface(deviceSize, opacityMode); | 547 return surfaceFactory->createSurface(deviceSize, opacityMode); |
553 } | 548 } |
554 | 549 |
555 void HTMLCanvasElement::createImageBuffer() | 550 void HTMLCanvasElement::createImageBuffer() |
556 { | 551 { |
552 ASSERT(m_context); | |
557 createImageBufferInternal(); | 553 createImageBufferInternal(); |
558 if (m_didFailToCreateImageBuffer && m_context && m_context->is2d()) | 554 if (m_didFailToCreateImageBuffer && m_context->is2d()) |
559 toCanvasRenderingContext2D(m_context.get())->loseContext(); | 555 toCanvasRenderingContext2D(m_context.get())->loseContext(); |
560 } | 556 } |
561 | 557 |
562 void HTMLCanvasElement::createImageBufferInternal() | 558 void HTMLCanvasElement::createImageBufferInternal() |
563 { | 559 { |
564 ASSERT(!m_imageBuffer); | 560 ASSERT(!m_imageBuffer); |
565 ASSERT(!m_contextStateSaver); | 561 ASSERT(!m_contextStateSaver); |
566 | 562 |
567 m_didFailToCreateImageBuffer = true; | 563 m_didFailToCreateImageBuffer = true; |
568 m_imageBufferIsClear = true; | 564 m_imageBufferIsClear = true; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
644 if (checkedExternallyAllocatedMemory.safeGet(externallyAllocatedMemory) == C heckedState::DidOverflow) | 640 if (checkedExternallyAllocatedMemory.safeGet(externallyAllocatedMemory) == C heckedState::DidOverflow) |
645 externallyAllocatedMemory = std::numeric_limits<intptr_t>::max(); | 641 externallyAllocatedMemory = std::numeric_limits<intptr_t>::max(); |
646 | 642 |
647 // Subtracting two intptr_t that are known to be positive will never underfl ow. | 643 // Subtracting two intptr_t that are known to be positive will never underfl ow. |
648 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(externallyA llocatedMemory - m_externallyAllocatedMemory); | 644 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(externallyA llocatedMemory - m_externallyAllocatedMemory); |
649 m_externallyAllocatedMemory = externallyAllocatedMemory; | 645 m_externallyAllocatedMemory = externallyAllocatedMemory; |
650 } | 646 } |
651 | 647 |
652 GraphicsContext* HTMLCanvasElement::drawingContext() const | 648 GraphicsContext* HTMLCanvasElement::drawingContext() const |
653 { | 649 { |
654 return buffer() ? m_imageBuffer->context() : 0; | 650 return buffer() && m_imageBuffer ? m_imageBuffer->context() : 0; |
655 } | 651 } |
656 | 652 |
657 GraphicsContext* HTMLCanvasElement::existingDrawingContext() const | 653 GraphicsContext* HTMLCanvasElement::existingDrawingContext() const |
658 { | 654 { |
659 if (!hasImageBuffer()) | 655 if (!hasImageBuffer()) |
660 return nullptr; | 656 return nullptr; |
661 | 657 |
662 return drawingContext(); | 658 return drawingContext(); |
663 } | 659 } |
664 | 660 |
665 ImageBuffer* HTMLCanvasElement::buffer() const | 661 ImageBuffer* HTMLCanvasElement::buffer() const |
666 { | 662 { |
663 if (!m_context) { | |
664 if (!canCreateImageBuffer(size())) | |
665 return nullptr; | |
666 m_noContextImageBuffer = ImageBuffer::create(size(), NonOpaque); | |
Justin Novosad
2014/11/27 18:58:35
Please explain how this code helps. It seems waste
Justin Novosad
2014/11/27 19:04:29
Ironically, the title of this change is "Don't mak
dshwang
2014/11/27 19:34:28
That's good question.
Two reason:
1. this method r
Justin Novosad
2014/11/27 20:18:15
That is a problem. We cannot guarantee that this m
dshwang
2014/11/27 20:42:17
That's true, but in that sense, most of layout tes
dshwang
2014/11/28 07:49:44
Let me explain more in the case of context.drawIma
| |
667 return m_noContextImageBuffer.get(); | |
668 } | |
669 if (m_noContextImageBuffer) { | |
670 m_noContextImageBuffer.clear(); | |
671 const_cast<HTMLCanvasElement*>(this)->clearCopiedImage(); | |
672 } | |
667 if (!hasImageBuffer() && !m_didFailToCreateImageBuffer) | 673 if (!hasImageBuffer() && !m_didFailToCreateImageBuffer) |
668 const_cast<HTMLCanvasElement*>(this)->createImageBuffer(); | 674 const_cast<HTMLCanvasElement*>(this)->createImageBuffer(); |
669 return m_imageBuffer.get(); | 675 return m_imageBuffer.get(); |
670 } | 676 } |
671 | 677 |
672 void HTMLCanvasElement::ensureUnacceleratedImageBuffer() | 678 void HTMLCanvasElement::ensureUnacceleratedImageBuffer() |
673 { | 679 { |
680 ASSERT(m_context); | |
674 if ((hasImageBuffer() && !m_imageBuffer->isAccelerated()) || m_didFailToCrea teImageBuffer) | 681 if ((hasImageBuffer() && !m_imageBuffer->isAccelerated()) || m_didFailToCrea teImageBuffer) |
675 return; | 682 return; |
676 discardImageBuffer(); | 683 discardImageBuffer(); |
677 OpacityMode opacityMode = !m_context || m_context->hasAlpha() ? NonOpaque : Opaque; | 684 OpacityMode opacityMode = m_context->hasAlpha() ? NonOpaque : Opaque; |
678 m_imageBuffer = ImageBuffer::create(size(), opacityMode); | 685 m_imageBuffer = ImageBuffer::create(size(), opacityMode); |
679 m_didFailToCreateImageBuffer = !m_imageBuffer; | 686 m_didFailToCreateImageBuffer = !m_imageBuffer; |
680 } | 687 } |
681 | 688 |
682 Image* HTMLCanvasElement::copiedImage(SourceDrawingBuffer sourceBuffer) const | 689 Image* HTMLCanvasElement::copiedImage(SourceDrawingBuffer sourceBuffer) const |
683 { | 690 { |
684 if (!m_copiedImage && buffer()) { | 691 if (!m_copiedImage && buffer()) { |
Justin Novosad
2014/11/27 18:58:35
Not new in this patch, but there is something wron
dshwang
2014/11/27 19:34:28
Good point. I'll fix it in the separate CL. Thank
| |
685 if (m_context && m_context->is3d()) | 692 if (m_context && m_context->is3d()) |
686 m_context->paintRenderingResultsToCanvas(sourceBuffer); | 693 m_context->paintRenderingResultsToCanvas(sourceBuffer); |
687 m_copiedImage = buffer()->copyImage(CopyBackingStore, Unscaled); | 694 m_copiedImage = buffer()->copyImage(CopyBackingStore, Unscaled); |
688 updateExternallyAllocatedMemory(); | 695 updateExternallyAllocatedMemory(); |
689 } | 696 } |
690 return m_copiedImage.get(); | 697 return m_copiedImage.get(); |
691 } | 698 } |
692 | 699 |
693 void HTMLCanvasElement::discardImageBuffer() | 700 void HTMLCanvasElement::discardImageBuffer() |
694 { | 701 { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
747 if (!buffer()) { | 754 if (!buffer()) { |
748 *status = InvalidSourceImageStatus; | 755 *status = InvalidSourceImageStatus; |
749 return nullptr; | 756 return nullptr; |
750 } | 757 } |
751 | 758 |
752 if (m_context && m_context->is3d()) { | 759 if (m_context && m_context->is3d()) { |
753 m_context->paintRenderingResultsToCanvas(BackBuffer); | 760 m_context->paintRenderingResultsToCanvas(BackBuffer); |
754 *status = ExternalSourceImageStatus; | 761 *status = ExternalSourceImageStatus; |
755 | 762 |
756 // can't create SkImage from WebGLImageBufferSurface (contains only SkBi tmap) | 763 // can't create SkImage from WebGLImageBufferSurface (contains only SkBi tmap) |
757 return m_imageBuffer->copyImage(DontCopyBackingStore, Unscaled); | 764 return buffer()->copyImage(DontCopyBackingStore, Unscaled); |
Justin Novosad
2014/11/27 18:58:35
I think this CL is a good opportunity to fix somet
dshwang
2014/11/27 19:34:28
That's good idea, but many const methods call buff
Justin Novosad
2014/11/27 20:18:15
Acknowledged.
| |
758 } | 765 } |
759 | 766 |
760 RefPtr<SkImage> image = m_imageBuffer->newImageSnapshot(); | 767 RefPtr<SkImage> image = buffer()->newImageSnapshot(); |
761 if (image) { | 768 if (image) { |
762 *status = NormalSourceImageStatus; | 769 *status = NormalSourceImageStatus; |
763 | 770 |
764 return StaticBitmapImage::create(image.release()); | 771 return StaticBitmapImage::create(image.release()); |
765 } | 772 } |
766 | 773 |
767 | 774 |
768 *status = InvalidSourceImageStatus; | 775 *status = InvalidSourceImageStatus; |
769 | 776 |
770 return nullptr; | 777 return nullptr; |
771 } | 778 } |
772 | 779 |
773 bool HTMLCanvasElement::wouldTaintOrigin(SecurityOrigin*) const | 780 bool HTMLCanvasElement::wouldTaintOrigin(SecurityOrigin*) const |
774 { | 781 { |
775 return !originClean(); | 782 return !originClean(); |
776 } | 783 } |
777 | 784 |
778 FloatSize HTMLCanvasElement::sourceSize() const | 785 FloatSize HTMLCanvasElement::sourceSize() const |
779 { | 786 { |
780 return FloatSize(width(), height()); | 787 return FloatSize(width(), height()); |
781 } | 788 } |
782 | 789 |
783 } | 790 } |
OLD | NEW |