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 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 | 350 |
351 return true; | 351 return true; |
352 } | 352 } |
353 | 353 |
354 | 354 |
355 void HTMLCanvasElement::paint(GraphicsContext* context, const LayoutRect& r) | 355 void HTMLCanvasElement::paint(GraphicsContext* context, const LayoutRect& r) |
356 { | 356 { |
357 if (m_context) { | 357 if (m_context) { |
358 if (!paintsIntoCanvasBuffer() && !document().printing()) | 358 if (!paintsIntoCanvasBuffer() && !document().printing()) |
359 return; | 359 return; |
360 m_context->paintRenderingResultsToCanvas(CanvasRenderingContext::Front); | 360 m_context->paintRenderingResultsToCanvas(FrontBuffer); |
361 } | 361 } |
362 | 362 |
363 if (hasImageBuffer()) { | 363 if (hasImageBuffer()) { |
364 CompositeOperator compositeOperator = !m_context || m_context->hasAlpha(
) ? CompositeSourceOver : CompositeCopy; | 364 CompositeOperator compositeOperator = !m_context || m_context->hasAlpha(
) ? CompositeSourceOver : CompositeCopy; |
365 context->drawImageBuffer(buffer(), pixelSnappedIntRect(r), 0, compositeO
perator); | 365 context->drawImageBuffer(buffer(), pixelSnappedIntRect(r), 0, compositeO
perator); |
366 } else { | 366 } else { |
367 // When alpha is false, we should draw to opaque black. | 367 // When alpha is false, we should draw to opaque black. |
368 if (m_context && !m_context->hasAlpha()) | 368 if (m_context && !m_context->hasAlpha()) |
369 context->fillRect(FloatRect(r), Color(0, 0, 0)); | 369 context->fillRect(FloatRect(r), Color(0, 0, 0)); |
370 } | 370 } |
(...skipping 27 matching lines...) Expand all Loading... |
398 | 398 |
399 // FIXME: Make isSupportedImageMIMETypeForEncoding threadsafe (to allow this
method to be used on a worker thread). | 399 // FIXME: Make isSupportedImageMIMETypeForEncoding threadsafe (to allow this
method to be used on a worker thread). |
400 if (mimeType.isNull() || !MIMETypeRegistry::isSupportedImageMIMETypeForEncod
ing(lowercaseMimeType)) | 400 if (mimeType.isNull() || !MIMETypeRegistry::isSupportedImageMIMETypeForEncod
ing(lowercaseMimeType)) |
401 lowercaseMimeType = "image/png"; | 401 lowercaseMimeType = "image/png"; |
402 | 402 |
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, true)); | 408 return AtomicString(toDataURLInternal("image/png", 0, FrontBuffer)); |
409 } | 409 } |
410 | 410 |
411 String HTMLCanvasElement::toDataURLInternal(const String& mimeType, const double
* quality, bool isSaving) 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 (m_size.isEmpty() || !canCreateImageBuffer(size())) |
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) { |
418 RefPtrWillBeRawPtr<ImageData> imageData = ImageData::create(m_size); | 418 RefPtrWillBeRawPtr<ImageData> imageData = ImageData::create(m_size); |
419 return ImageDataToDataURL(ImageDataBuffer(imageData->size(), imageData->
data()), encodingMimeType, quality); | 419 return ImageDataToDataURL(ImageDataBuffer(imageData->size(), imageData->
data()), encodingMimeType, quality); |
420 } | 420 } |
421 | 421 |
422 // Try to get ImageData first, as that may avoid lossy conversions. | |
423 RefPtrWillBeRawPtr<ImageData> imageData = getImageData(); | |
424 | |
425 if (imageData) | |
426 return ImageDataToDataURL(ImageDataBuffer(imageData->size(), imageData->
data()), encodingMimeType, quality); | |
427 | |
428 if (m_context->is3d()) { | 422 if (m_context->is3d()) { |
429 m_context->paintRenderingResultsToCanvas(isSaving ? CanvasRenderingConte
xt::Front : CanvasRenderingContext::Back); | 423 // Get non-premultiplied data because of inaccurate premultiplied alpha
conversion of buffer()->toDataURL(). |
| 424 RefPtrWillBeRawPtr<ImageData> imageData = |
| 425 toWebGLRenderingContext(m_context.get())->paintRenderingResultsToIma
geData(sourceBuffer); |
| 426 if (imageData) |
| 427 return ImageDataToDataURL(ImageDataBuffer(imageData->size(), imageDa
ta->data()), encodingMimeType, quality); |
| 428 m_context->paintRenderingResultsToCanvas(sourceBuffer); |
430 } | 429 } |
431 | 430 |
432 return buffer()->toDataURL(encodingMimeType, quality); | 431 return buffer()->toDataURL(encodingMimeType, quality); |
433 } | 432 } |
434 | 433 |
435 String HTMLCanvasElement::toDataURL(const String& mimeType, const double* qualit
y, ExceptionState& exceptionState) const | 434 String HTMLCanvasElement::toDataURL(const String& mimeType, const double* qualit
y, ExceptionState& exceptionState) const |
436 { | 435 { |
437 if (!m_originClean) { | 436 if (!m_originClean) { |
438 exceptionState.throwSecurityError("Tainted canvases may not be exported.
"); | 437 exceptionState.throwSecurityError("Tainted canvases may not be exported.
"); |
439 return String(); | 438 return String(); |
440 } | 439 } |
441 | 440 |
442 return toDataURLInternal(mimeType, quality); | 441 return toDataURLInternal(mimeType, quality, BackBuffer); |
443 } | |
444 | |
445 PassRefPtrWillBeRawPtr<ImageData> HTMLCanvasElement::getImageData() const | |
446 { | |
447 if (!m_context || !m_context->is3d()) | |
448 return nullptr; | |
449 return toWebGLRenderingContext(m_context.get())->paintRenderingResultsToImag
eData(); | |
450 } | 442 } |
451 | 443 |
452 SecurityOrigin* HTMLCanvasElement::securityOrigin() const | 444 SecurityOrigin* HTMLCanvasElement::securityOrigin() const |
453 { | 445 { |
454 return document().securityOrigin(); | 446 return document().securityOrigin(); |
455 } | 447 } |
456 | 448 |
457 bool HTMLCanvasElement::shouldAccelerate(const IntSize& size) const | 449 bool HTMLCanvasElement::shouldAccelerate(const IntSize& size) const |
458 { | 450 { |
459 if (m_context && !m_context->is2d()) | 451 if (m_context && !m_context->is2d()) |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
680 void HTMLCanvasElement::ensureUnacceleratedImageBuffer() | 672 void HTMLCanvasElement::ensureUnacceleratedImageBuffer() |
681 { | 673 { |
682 if ((hasImageBuffer() && !m_imageBuffer->isAccelerated()) || m_didFailToCrea
teImageBuffer) | 674 if ((hasImageBuffer() && !m_imageBuffer->isAccelerated()) || m_didFailToCrea
teImageBuffer) |
683 return; | 675 return; |
684 discardImageBuffer(); | 676 discardImageBuffer(); |
685 OpacityMode opacityMode = !m_context || m_context->hasAlpha() ? NonOpaque :
Opaque; | 677 OpacityMode opacityMode = !m_context || m_context->hasAlpha() ? NonOpaque :
Opaque; |
686 m_imageBuffer = ImageBuffer::create(size(), opacityMode); | 678 m_imageBuffer = ImageBuffer::create(size(), opacityMode); |
687 m_didFailToCreateImageBuffer = !m_imageBuffer; | 679 m_didFailToCreateImageBuffer = !m_imageBuffer; |
688 } | 680 } |
689 | 681 |
690 Image* HTMLCanvasElement::copiedImage() const | 682 Image* HTMLCanvasElement::copiedImage(SourceDrawingBuffer sourceBuffer) const |
691 { | 683 { |
692 if (!m_copiedImage && buffer()) { | 684 if (!m_copiedImage && buffer()) { |
693 if (m_context && m_context->is3d()) { | 685 if (m_context && m_context->is3d()) |
694 m_context->paintRenderingResultsToCanvas(CanvasRenderingContext::Fro
nt); | 686 m_context->paintRenderingResultsToCanvas(sourceBuffer); |
695 } | |
696 m_copiedImage = buffer()->copyImage(CopyBackingStore, Unscaled); | 687 m_copiedImage = buffer()->copyImage(CopyBackingStore, Unscaled); |
697 updateExternallyAllocatedMemory(); | 688 updateExternallyAllocatedMemory(); |
698 } | 689 } |
699 return m_copiedImage.get(); | 690 return m_copiedImage.get(); |
700 } | 691 } |
701 | 692 |
702 void HTMLCanvasElement::discardImageBuffer() | 693 void HTMLCanvasElement::discardImageBuffer() |
703 { | 694 { |
704 m_contextStateSaver.clear(); // uses context owned by m_imageBuffer | 695 m_contextStateSaver.clear(); // uses context owned by m_imageBuffer |
705 m_imageBuffer.clear(); | 696 m_imageBuffer.clear(); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
752 *status = ZeroSizeCanvasSourceImageStatus; | 743 *status = ZeroSizeCanvasSourceImageStatus; |
753 return nullptr; | 744 return nullptr; |
754 } | 745 } |
755 | 746 |
756 if (!buffer()) { | 747 if (!buffer()) { |
757 *status = InvalidSourceImageStatus; | 748 *status = InvalidSourceImageStatus; |
758 return nullptr; | 749 return nullptr; |
759 } | 750 } |
760 | 751 |
761 if (m_context && m_context->is3d()) { | 752 if (m_context && m_context->is3d()) { |
762 m_context->paintRenderingResultsToCanvas(CanvasRenderingContext::Back); | 753 m_context->paintRenderingResultsToCanvas(BackBuffer); |
763 *status = ExternalSourceImageStatus; | 754 *status = ExternalSourceImageStatus; |
764 | 755 |
765 // can't create SkImage from WebGLImageBufferSurface (contains only SkBi
tmap) | 756 // can't create SkImage from WebGLImageBufferSurface (contains only SkBi
tmap) |
766 return m_imageBuffer->copyImage(DontCopyBackingStore, Unscaled); | 757 return m_imageBuffer->copyImage(DontCopyBackingStore, Unscaled); |
767 } | 758 } |
768 | 759 |
769 RefPtr<SkImage> image = m_imageBuffer->newImageSnapshot(); | 760 RefPtr<SkImage> image = m_imageBuffer->newImageSnapshot(); |
770 if (image) { | 761 if (image) { |
771 *status = NormalSourceImageStatus; | 762 *status = NormalSourceImageStatus; |
772 | 763 |
(...skipping 10 matching lines...) Expand all Loading... |
783 { | 774 { |
784 return !originClean(); | 775 return !originClean(); |
785 } | 776 } |
786 | 777 |
787 FloatSize HTMLCanvasElement::sourceSize() const | 778 FloatSize HTMLCanvasElement::sourceSize() const |
788 { | 779 { |
789 return FloatSize(width(), height()); | 780 return FloatSize(width(), height()); |
790 } | 781 } |
791 | 782 |
792 } | 783 } |
OLD | NEW |