Changeset 230350 in webkit


Ignore:
Timestamp:
Apr 6, 2018 12:33:32 PM (6 years ago)
Author:
Ms2ger@igalia.com
Message:

Implement createImageBitmap(Blob)
https://bugs.webkit.org/show_bug.cgi?id=183247

Reviewed by Dean Jackson.

LayoutTests/imported/w3c:

Update expectations.

  • web-platform-tests/2dcontext/imagebitmap/createImageBitmap-drawImage-expected.txt:
  • web-platform-tests/2dcontext/imagebitmap/createImageBitmap-invalid-args-expected.txt:

Source/WebCore:

Tests:

  • imported/w3c/web-platform-tests/2dcontext/imagebitmap/createImageBitmap-drawImage.html
  • imported/w3c/web-platform-tests/2dcontext/imagebitmap/createImageBitmap-invalid-args.html
  • fileapi/FileReaderLoader.h:

(WebCore::FileReaderLoader::url): expose the Blob's URL.

  • html/ImageBitmap.cpp: implement createImageBitmap(Blob).
  • html/ImageBitmap.h: allow the BlobImageObserver class access to the creation function.
  • loader/cache/CachedImage.cpp: reuse extracted code.

(WebCore::CachedImage::isPDFResource const):
(WebCore::CachedImage::isPostScriptResource const):
(WebCore::CachedImage::createImage):

  • platform/graphics/Image.cpp: extract some code from CachedImage to reuse.

(WebCore::Image::create):
(WebCore::Image::isPDFResource):
(WebCore::Image::isPostScriptResource):

  • platform/graphics/Image.h: add declarations.

LayoutTests:

Update expectations.

  • platform/gtk/imported/w3c/web-platform-tests/2dcontext/imagebitmap/createImageBitmap-invalid-args-expected.txt:
Location:
trunk
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r230349 r230350  
     12018-04-06  Ms2ger  <Ms2ger@igalia.com>
     2
     3        Implement createImageBitmap(Blob)
     4        https://bugs.webkit.org/show_bug.cgi?id=183247
     5
     6        Reviewed by Dean Jackson.
     7
     8        Update expectations.
     9
     10        * platform/gtk/imported/w3c/web-platform-tests/2dcontext/imagebitmap/createImageBitmap-invalid-args-expected.txt:
     11
    1122018-04-06  Zalan Bujtas  <zalan@apple.com>
    213
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r230348 r230350  
     12018-04-06  Ms2ger  <Ms2ger@igalia.com>
     2
     3        Implement createImageBitmap(Blob)
     4        https://bugs.webkit.org/show_bug.cgi?id=183247
     5
     6        Reviewed by Dean Jackson.
     7
     8        Update expectations.
     9
     10        * web-platform-tests/2dcontext/imagebitmap/createImageBitmap-drawImage-expected.txt:
     11        * web-platform-tests/2dcontext/imagebitmap/createImageBitmap-invalid-args-expected.txt:
     12
    1132018-04-06  Ms2ger  <Ms2ger@igalia.com>
    214
  • trunk/LayoutTests/imported/w3c/web-platform-tests/2dcontext/imagebitmap/createImageBitmap-drawImage-expected.txt

    r228092 r230350  
    5050PASS createImageBitmap from an ImageBitmap resized, and drawImage on the created ImageBitmap
    5151FAIL createImageBitmap from an ImageBitmap with negative sw/sh, and drawImage on the created ImageBitmap promise_test: Unhandled rejection with value: object "RangeError: Cannot create ImageBitmap with a negative width or height"
    52 FAIL createImageBitmap from a Blob, and drawImage on the created ImageBitmap promise_test: Unhandled rejection with value: object "TypeError: createImageBitmap with ArrayBuffer or Blob is not implemented"
    53 FAIL createImageBitmap from a Blob scaled down, and drawImage on the created ImageBitmap promise_test: Unhandled rejection with value: object "TypeError: createImageBitmap with ArrayBuffer or Blob is not implemented"
    54 FAIL createImageBitmap from a Blob scaled up, and drawImage on the created ImageBitmap promise_test: Unhandled rejection with value: object "TypeError: createImageBitmap with ArrayBuffer or Blob is not implemented"
    55 FAIL createImageBitmap from a Blob resized, and drawImage on the created ImageBitmap promise_test: Unhandled rejection with value: object "TypeError: createImageBitmap with ArrayBuffer or Blob is not implemented"
     52PASS createImageBitmap from a Blob, and drawImage on the created ImageBitmap
     53PASS createImageBitmap from a Blob scaled down, and drawImage on the created ImageBitmap
     54PASS createImageBitmap from a Blob scaled up, and drawImage on the created ImageBitmap
     55PASS createImageBitmap from a Blob resized, and drawImage on the created ImageBitmap
    5656FAIL createImageBitmap from a Blob with negative sw/sh, and drawImage on the created ImageBitmap promise_test: Unhandled rejection with value: object "RangeError: Cannot create ImageBitmap with a negative width or height"
    5757
  • trunk/LayoutTests/imported/w3c/web-platform-tests/2dcontext/imagebitmap/createImageBitmap-invalid-args-expected.txt

    r228092 r230350  
    3333PASS createImageBitmap with a a Blob source and sw set to 0
    3434PASS createImageBitmap with a a Blob source and sh set to 0
    35 FAIL createImageBitmap with a a Blob source and oversized (unallocatable) crop region assert_throws: function "function () { throw e }" threw object "TypeError: createImageBitmap with ArrayBuffer or Blob is not implemented" ("TypeError") expected object "InvalidStateError" ("InvalidStateError")
     35FAIL createImageBitmap with a a Blob source and oversized (unallocatable) crop region assert_unreached: Should have rejected: undefined Reached unreachable code
    3636PASS createImageBitmap with undefined image source.
    3737PASS createImageBitmap with null image source.
     
    4444PASS createImageBitmap with an oversized canvas source.
    4545FAIL createImageBitmap with an invalid OffscreenCanvas source. assert_throws: function "function () { throw e }" threw object "TypeError: Type error" that is not a DOMException InvalidStateError: property "code" is equal to undefined, expected 11
    46 FAIL createImageBitmap with an undecodable blob source. assert_throws: function "function () { throw e }" threw object "TypeError: createImageBitmap with ArrayBuffer or Blob is not implemented" that is not a DOMException InvalidStateError: property "code" is equal to undefined, expected 11
     46PASS createImageBitmap with an undecodable blob source.
    4747PASS createImageBitmap with a broken image source.
    4848FAIL createImageBitmap with an available but undecodable image source. assert_unreached: Should have rejected: undefined Reached unreachable code
  • trunk/LayoutTests/platform/gtk/imported/w3c/web-platform-tests/2dcontext/imagebitmap/createImageBitmap-invalid-args-expected.txt

    r228092 r230350  
    3333PASS createImageBitmap with a a Blob source and sw set to 0
    3434PASS createImageBitmap with a a Blob source and sh set to 0
    35 FAIL createImageBitmap with a a Blob source and oversized (unallocatable) crop region assert_throws: function "function () { throw e }" threw object "TypeError: createImageBitmap with ArrayBuffer or Blob is not implemented" ("TypeError") expected object "InvalidStateError" ("InvalidStateError")
     35FAIL createImageBitmap with a a Blob source and oversized (unallocatable) crop region assert_unreached: Should have rejected: undefined Reached unreachable code
    3636PASS createImageBitmap with undefined image source.
    3737PASS createImageBitmap with null image source.
     
    4444PASS createImageBitmap with an oversized canvas source.
    4545FAIL createImageBitmap with an invalid OffscreenCanvas source. assert_throws: function "function () { throw e }" threw object "TypeError: Type error" that is not a DOMException InvalidStateError: property "code" is equal to undefined, expected 11
    46 FAIL createImageBitmap with an undecodable blob source. assert_throws: function "function () { throw e }" threw object "TypeError: createImageBitmap with ArrayBuffer or Blob is not implemented" that is not a DOMException InvalidStateError: property "code" is equal to undefined, expected 11
     46PASS createImageBitmap with an undecodable blob source.
    4747PASS createImageBitmap with a broken image source.
    4848FAIL createImageBitmap with an available but undecodable image source. promise_test: Unhandled rejection with value: object "[object Event]"
  • trunk/Source/WebCore/ChangeLog

    r230349 r230350  
     12018-04-06  Ms2ger  <Ms2ger@igalia.com>
     2
     3        Implement createImageBitmap(Blob)
     4        https://bugs.webkit.org/show_bug.cgi?id=183247
     5
     6        Reviewed by Dean Jackson.
     7
     8        Tests:
     9            - imported/w3c/web-platform-tests/2dcontext/imagebitmap/createImageBitmap-drawImage.html
     10            - imported/w3c/web-platform-tests/2dcontext/imagebitmap/createImageBitmap-invalid-args.html
     11
     12        * fileapi/FileReaderLoader.h:
     13        (WebCore::FileReaderLoader::url): expose the Blob's URL.
     14        * html/ImageBitmap.cpp: implement createImageBitmap(Blob).
     15        * html/ImageBitmap.h: allow the BlobImageObserver class access to the creation function.
     16        * loader/cache/CachedImage.cpp: reuse extracted code.
     17        (WebCore::CachedImage::isPDFResource const):
     18        (WebCore::CachedImage::isPostScriptResource const):
     19        (WebCore::CachedImage::createImage):
     20        * platform/graphics/Image.cpp: extract some code from CachedImage to reuse.
     21        (WebCore::Image::create):
     22        (WebCore::Image::isPDFResource):
     23        (WebCore::Image::isPostScriptResource):
     24        * platform/graphics/Image.h: add declarations.
     25
    1262018-04-06  Zalan Bujtas  <zalan@apple.com>
    227
  • trunk/Source/WebCore/fileapi/FileReaderLoader.h

    r219699 r230350  
    8383    void setDataType(const String& dataType) { m_dataType = dataType; }
    8484
     85    const URL& url() { return m_urlForReading; }
     86
    8587private:
    8688    void terminate();
  • trunk/Source/WebCore/html/ImageBitmap.cpp

    r230348 r230350  
    491491}
    492492
     493class ImageBitmapImageObserver final : public RefCounted<ImageBitmapImageObserver>, public ImageObserver {
     494public:
     495    static Ref<ImageBitmapImageObserver> create(String mimeType, long long expectedContentLength, const URL& sourceUrl)
     496    {
     497        return adoptRef(*new ImageBitmapImageObserver(mimeType, expectedContentLength, sourceUrl));
     498    }
     499
     500    URL sourceUrl() const override { return m_sourceUrl; }
     501    String mimeType() const override { return m_mimeType; }
     502    long long expectedContentLength() const override { return m_expectedContentLength; }
     503
     504    void decodedSizeChanged(const Image&, long long) override { }
     505
     506    void didDraw(const Image&) override { }
     507
     508    bool canDestroyDecodedData(const Image&) override { return true; }
     509    void imageFrameAvailable(const Image&, ImageAnimatingState, const IntRect* = nullptr, DecodingStatus = DecodingStatus::Invalid) override { }
     510    void changedInRect(const Image&, const IntRect* = nullptr) override { }
     511
     512private:
     513    ImageBitmapImageObserver(String mimeType, long long expectedContentLength, const URL& sourceUrl)
     514        : m_mimeType(mimeType)
     515        , m_expectedContentLength(expectedContentLength)
     516        , m_sourceUrl(sourceUrl)
     517    { }
     518
     519    String m_mimeType;
     520    long long m_expectedContentLength;
     521    URL m_sourceUrl;
     522};
     523
    493524class PendingImageBitmap final : public ActiveDOMObject, public FileReaderLoaderClient {
    494525public:
     
    551582    }
    552583
    553     void createImageBitmap(RefPtr<ArrayBuffer> arrayBuffer)
    554     {
    555         UNUSED_PARAM(arrayBuffer);
    556 
    557         // 3. Read the Blob object's data. If an error occurs during reading of the object,
    558         //    then reject the promise with an "InvalidStateError" DOMException, and abort
    559         //    these steps.
    560 
    561         // 4. Apply the image sniffing rules to determine the file format of the image data,
    562         //    with MIME type of the Blob (as given by the Blob object's type attribute) giving
    563         //    the official type.
    564 
    565         // 5. If the image data is not in a supported image file format (e.g. it's not an image
    566         //    at all), or if the image data is corrupted in some fatal way such that the image
    567         //    dimensions cannot be obtained (e.g. a vector graphic with no intrinsic size), then
    568         //    reject the promise with an "InvalidStateError" DOMException, and abort these steps.
    569 
    570         // 6. Create a new ImageBitmap object.
    571 
    572         // 7. Let the ImageBitmap object's bitmap data be the image data read from the Blob object,
    573         //    cropped to the source rectangle with formatting. If this is an animated image, the
    574         //    ImageBitmap object's bitmap data must only be taken from the default image of the
    575         //    animation (the one that the format defines is to be used when animation is not supported
    576         //    or is disabled), or, if there is no such image, the first frame of the animation.
    577 
    578         // 8. Resolve the promise with the new ImageBitmap object as the value.
    579         m_promise.reject(TypeError, "createImageBitmap with ArrayBuffer or Blob is not implemented");
     584    void createImageBitmap(RefPtr<ArrayBuffer>&& arrayBuffer)
     585    {
     586        if (!arrayBuffer) {
     587            m_promise.reject(InvalidStateError, "An error occured reading the Blob argument to createImageBitmap");
     588            return;
     589        }
     590
     591        ImageBitmap::createFromBuffer(arrayBuffer.releaseNonNull(), m_blob->type(), m_blob->size(), m_blobLoader.url(), WTFMove(m_options), WTFMove(m_rect), WTFMove(m_promise));
    580592    }
    581593
     
    587599};
    588600
     601void ImageBitmap::createFromBuffer(
     602    Ref<ArrayBuffer>&& arrayBuffer,
     603    String mimeType,
     604    long long expectedContentLength,
     605    const URL& sourceUrl,
     606    ImageBitmapOptions&& options,
     607    std::optional<IntRect> rect,
     608    ImageBitmap::Promise&& promise)
     609{
     610    if (!arrayBuffer->byteLength()) {
     611        promise.reject(InvalidStateError, "Cannot create an ImageBitmap from an empty buffer");
     612        return;
     613    }
     614
     615    auto sharedBuffer = SharedBuffer::create(static_cast<const char*>(arrayBuffer->data()), arrayBuffer->byteLength());
     616    auto observer = ImageBitmapImageObserver::create(mimeType, expectedContentLength, sourceUrl);
     617    auto image = Image::create(observer.get());
     618    if (!image) {
     619        promise.reject(InvalidStateError, "The type of the argument to createImageBitmap is not supported");
     620        return;
     621    }
     622
     623    auto result = image->setData(sharedBuffer.copyRef(), true);
     624    if (result != EncodedDataStatus::Complete) {
     625        promise.reject(InvalidStateError, "Cannot decode the data in the argument to createImageBitmap");
     626        return;
     627    }
     628
     629    auto sourceRectangle = croppedSourceRectangleWithFormatting(roundedIntSize(image->size()), options, rect);
     630    if (sourceRectangle.hasException()) {
     631        promise.reject(sourceRectangle.releaseException());
     632        return;
     633    }
     634
     635    auto outputSize = outputSizeForSourceRectangle(sourceRectangle.returnValue(), options);
     636    auto bitmapData = ImageBuffer::create(FloatSize(outputSize.width(), outputSize.height()), bufferRenderingMode);
     637    if (!bitmapData) {
     638        promise.reject(InvalidStateError, "Cannot create an image buffer from the argument to createImageBitmap");
     639        return;
     640    }
     641
     642    FloatRect destRect(FloatPoint(), outputSize);
     643    ImagePaintingOptions paintingOptions;
     644    paintingOptions.m_interpolationQuality = interpolationQualityForResizeQuality(options.resizeQuality);
     645
     646    bitmapData->context().drawImage(*image, destRect, sourceRectangle.releaseReturnValue(), paintingOptions);
     647
     648    auto imageBitmap = create(WTFMove(bitmapData));
     649
     650    promise.resolve(WTFMove(imageBitmap));
     651}
     652
    589653void ImageBitmap::createPromise(ScriptExecutionContext& scriptExecutionContext, RefPtr<Blob>& blob, ImageBitmapOptions&& options, std::optional<IntRect> rect, ImageBitmap::Promise&& promise)
    590654{
  • trunk/Source/WebCore/html/ImageBitmap.h

    r230348 r230350  
    3838class HTMLImageElement;
    3939class HTMLVideoElement;
     40class ImageBitmapImageObserver;
    4041class ImageBuffer;
    4142class ImageData;
     
    4445class PendingImageBitmap;
    4546class ScriptExecutionContext;
     47class URL;
    4648struct ImageBitmapOptions;
    4749
     
    8486
    8587private:
     88    friend class ImageBitmapImageObserver;
    8689    friend class PendingImageBitmap;
    8790
     
    97100    static void createPromise(ScriptExecutionContext&, RefPtr<Blob>&, ImageBitmapOptions&&, std::optional<IntRect>, Promise&&);
    98101    static void createPromise(ScriptExecutionContext&, RefPtr<ImageData>&, ImageBitmapOptions&&, std::optional<IntRect>, Promise&&);
     102    static void createFromBuffer(Ref<ArrayBuffer>&&, String mimeType, long long expectedContentLength, const URL&, ImageBitmapOptions&&, std::optional<IntRect>, Promise&&);
    99103
    100104    std::unique_ptr<ImageBuffer> m_bitmapData;
  • trunk/Source/WebCore/loader/cache/CachedImage.cpp

    r229209 r230350  
    311311bool CachedImage::isPDFResource() const
    312312{
    313     if (m_response.mimeType().isEmpty())
    314         return url().path().endsWithIgnoringASCIICase(".pdf");
    315     return MIMETypeRegistry::isPDFMIMEType(m_response.mimeType());
     313    return Image::isPDFResource(m_response.mimeType(), url());
    316314}
    317315
    318316bool CachedImage::isPostScriptResource() const
    319317{
    320     if (m_response.mimeType().isEmpty())
    321         return url().path().endsWithIgnoringASCIICase(".ps");
    322     return MIMETypeRegistry::isPostScriptMIMEType(m_response.mimeType());
     318    return Image::isPostScriptResource(m_response.mimeType(), url());
    323319}
    324320
     
    340336    m_imageObserver = CachedImageObserver::create(*this);
    341337
    342     if (m_response.mimeType() == "image/svg+xml") {
    343         auto svgImage = SVGImage::create(*m_imageObserver);
    344         m_svgImageCache = std::make_unique<SVGImageCache>(svgImage.ptr());
    345         m_image = WTFMove(svgImage);
    346     } else if (isPDFResource() || isPostScriptResource()) {
    347 #if USE(CG) && !USE(WEBKIT_IMAGE_DECODERS)
    348         m_image = PDFDocumentImage::create(m_imageObserver.get());
    349 #endif
    350     } else
    351         m_image = BitmapImage::create(m_imageObserver.get());
     338    m_image = Image::create(*m_imageObserver);
    352339
    353340    if (m_image) {
     341        if (is<SVGImage>(*m_image))
     342            m_svgImageCache = std::make_unique<SVGImageCache>(&downcast<SVGImage>(*m_image));
     343
    354344        // Send queued container size requests.
    355345        if (m_image->usesContainerSize()) {
  • trunk/Source/WebCore/platform/graphics/Image.cpp

    r225091 r230350  
    3434#include "Length.h"
    3535#include "MIMETypeRegistry.h"
     36#include "SVGImage.h"
    3637#include "SharedBuffer.h"
    3738#include "URL.h"
     
    4243
    4344#if USE(CG)
     45#include "PDFDocumentImage.h"
    4446#include <CoreFoundation/CoreFoundation.h>
    4547#endif
     
    6264}
    6365
     66RefPtr<Image> Image::create(ImageObserver& observer)
     67{
     68    auto mimeType = observer.mimeType();
     69    if (mimeType == "image/svg+xml")
     70        return SVGImage::create(observer);
     71
     72    auto url = observer.sourceUrl();
     73    if (isPDFResource(mimeType, url) || isPostScriptResource(mimeType, url)) {
     74#if USE(CG) && !USE(WEBKIT_IMAGE_DECODERS)
     75        return PDFDocumentImage::create(&observer);
     76#else
     77        return nullptr;
     78#endif
     79    }
     80
     81    return BitmapImage::create(&observer);
     82}
     83
    6484bool Image::supportsType(const String& type)
    6585{
    6686    return MIMETypeRegistry::isSupportedImageResourceMIMEType(type);
    6787}
     88
     89bool Image::isPDFResource(const String& mimeType, const URL& url)
     90{
     91    if (mimeType.isEmpty())
     92        return url.path().endsWithIgnoringASCIICase(".pdf");
     93    return MIMETypeRegistry::isPDFMIMEType(mimeType);
     94}
     95
     96bool Image::isPostScriptResource(const String& mimeType, const URL& url)
     97{
     98    if (mimeType.isEmpty())
     99        return url.path().endsWithIgnoringASCIICase(".ps");
     100    return MIMETypeRegistry::isPostScriptMIMEType(mimeType);
     101}
     102
    68103
    69104EncodedDataStatus Image::setData(RefPtr<SharedBuffer>&& data, bool allDataReceived)
  • trunk/Source/WebCore/platform/graphics/Image.h

    r230334 r230350  
    8282   
    8383    WEBCORE_EXPORT static Ref<Image> loadPlatformResource(const char* name);
     84    WEBCORE_EXPORT static RefPtr<Image> create(ImageObserver&);
    8485    WEBCORE_EXPORT static bool supportsType(const String&);
     86    static bool isPDFResource(const String& mimeType, const URL&);
     87    static bool isPostScriptResource(const String& mimeType, const URL&);
    8588
    8689    virtual bool isBitmapImage() const { return false; }
Note: See TracChangeset for help on using the changeset viewer.