Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/frame/ImageBitmap.h" | 5 #include "core/frame/ImageBitmap.h" |
| 6 | 6 |
| 7 #include "core/html/HTMLCanvasElement.h" | 7 #include "core/html/HTMLCanvasElement.h" |
| 8 #include "core/html/HTMLVideoElement.h" | 8 #include "core/html/HTMLVideoElement.h" |
| 9 #include "core/html/ImageData.h" | 9 #include "core/html/ImageData.h" |
| 10 #include "platform/graphics/skia/SkiaUtils.h" | 10 #include "platform/graphics/skia/SkiaUtils.h" |
| 11 #include "platform/image-decoders/ImageDecoder.h" | 11 #include "platform/image-decoders/ImageDecoder.h" |
| 12 #include "third_party/skia/include/core/SkCanvas.h" | 12 #include "third_party/skia/include/core/SkCanvas.h" |
| 13 #include "third_party/skia/include/core/SkSurface.h" | 13 #include "third_party/skia/include/core/SkSurface.h" |
| 14 #include "wtf/PtrUtil.h" | 14 #include "wtf/PtrUtil.h" |
| 15 #include "wtf/RefPtr.h" | 15 #include "wtf/RefPtr.h" |
| 16 #include <memory> | 16 #include <memory> |
| 17 | 17 |
| 18 namespace blink { | |
| 19 | |
| 20 static const char* imageOrientationFlipY = "flipY"; | 18 static const char* imageOrientationFlipY = "flipY"; |
| 21 static const char* imageBitmapOptionNone = "none"; | 19 static const char* imageBitmapOptionNone = "none"; |
| 22 | 20 |
| 21 namespace { | |
|
jbroman
2016/07/07 21:21:45
nit: move this anonymous namespace inside the blin
xidachen
2016/07/13 14:50:22
Done.
| |
| 22 | |
| 23 struct ParsedOptions { | |
| 24 bool flipY = false; | |
| 25 bool premultiplyAlpha = true; | |
| 26 bool shouldScaleInput = false; | |
| 27 unsigned resizeWidth = 0; | |
| 28 unsigned resizeHeight = 0; | |
| 29 SkFilterQuality resizeQuality = kLow_SkFilterQuality; | |
| 30 }; | |
| 31 | |
| 32 ParsedOptions parseOptions(const blink::ImageBitmapOptions& options, int sourceW idth, int sourceHeight) | |
| 33 { | |
| 34 ParsedOptions parsedOptions; | |
| 35 if (options.imageOrientation() == imageOrientationFlipY) { | |
| 36 parsedOptions.flipY = true; | |
| 37 } else { | |
| 38 parsedOptions.flipY = false; | |
| 39 DCHECK(options.imageOrientation() == imageBitmapOptionNone); | |
| 40 } | |
| 41 if (options.premultiplyAlpha() == imageBitmapOptionNone) { | |
| 42 parsedOptions.premultiplyAlpha = false; | |
| 43 } else { | |
| 44 parsedOptions.premultiplyAlpha = true; | |
| 45 DCHECK(options.premultiplyAlpha() == "default" || options.premultiplyAlp ha() == "premultiply"); | |
| 46 } | |
| 47 | |
| 48 parsedOptions.shouldScaleInput = false; | |
| 49 if (!options.hasResizeWidth() && !options.hasResizeHeight()) | |
| 50 return parsedOptions; | |
| 51 if (options.hasResizeWidth() && options.hasResizeHeight()) { | |
| 52 parsedOptions.resizeWidth = options.resizeWidth(); | |
| 53 parsedOptions.resizeHeight = options.resizeHeight(); | |
| 54 } else if (options.hasResizeWidth() && !options.hasResizeHeight()) { | |
| 55 parsedOptions.resizeWidth = options.resizeWidth(); | |
| 56 parsedOptions.resizeHeight = ceil(static_cast<float>(options.resizeWidth ()) / sourceWidth * sourceHeight); | |
| 57 } else { | |
| 58 parsedOptions.resizeHeight = options.resizeHeight(); | |
| 59 parsedOptions.resizeWidth = ceil(static_cast<float>(options.resizeHeight ()) / sourceHeight * sourceWidth); | |
| 60 } | |
| 61 if (static_cast<int>(parsedOptions.resizeWidth) != sourceWidth || static_cas t<int>(parsedOptions.resizeHeight) != sourceHeight) | |
| 62 parsedOptions.shouldScaleInput = true; | |
| 63 else | |
| 64 return parsedOptions; | |
| 65 | |
| 66 if (options.resizeQuality() == "high") | |
| 67 parsedOptions.resizeQuality = kHigh_SkFilterQuality; | |
| 68 else if (options.resizeQuality() == "medium") | |
| 69 parsedOptions.resizeQuality = kMedium_SkFilterQuality; | |
| 70 else if (options.resizeQuality() == "pixelated") | |
| 71 parsedOptions.resizeQuality = kNone_SkFilterQuality; | |
| 72 else | |
| 73 parsedOptions.resizeQuality = kLow_SkFilterQuality; | |
| 74 return parsedOptions; | |
| 75 } | |
| 76 | |
| 77 } // namespace | |
| 78 | |
| 79 namespace blink { | |
| 80 | |
| 23 // The following two functions are helpers used in cropImage | 81 // The following two functions are helpers used in cropImage |
| 24 static inline IntRect normalizeRect(const IntRect& rect) | 82 static inline IntRect normalizeRect(const IntRect& rect) |
| 25 { | 83 { |
| 26 return IntRect(std::min(rect.x(), rect.maxX()), | 84 return IntRect(std::min(rect.x(), rect.maxX()), |
| 27 std::min(rect.y(), rect.maxY()), | 85 std::min(rect.y(), rect.maxY()), |
| 28 std::max(rect.width(), -rect.width()), | 86 std::max(rect.width(), -rect.width()), |
| 29 std::max(rect.height(), -rect.height())); | 87 std::max(rect.height(), -rect.height())); |
| 30 } | 88 } |
| 31 | 89 |
| 32 static bool frameIsValid(const SkBitmap& frameBitmap) | 90 static bool frameIsValid(const SkBitmap& frameBitmap) |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 106 return nullptr; | 164 return nullptr; |
| 107 ImageFrame* frame = decoder->frameBufferAtIndex(0); | 165 ImageFrame* frame = decoder->frameBufferAtIndex(0); |
| 108 if (!frame || frame->getStatus() != ImageFrame::FrameComplete) | 166 if (!frame || frame->getStatus() != ImageFrame::FrameComplete) |
| 109 return nullptr; | 167 return nullptr; |
| 110 SkBitmap bitmap = frame->bitmap(); | 168 SkBitmap bitmap = frame->bitmap(); |
| 111 if (!frameIsValid(bitmap)) | 169 if (!frameIsValid(bitmap)) |
| 112 return nullptr; | 170 return nullptr; |
| 113 return fromSkSp(SkImage::MakeFromBitmap(bitmap)); | 171 return fromSkSp(SkImage::MakeFromBitmap(bitmap)); |
| 114 } | 172 } |
| 115 | 173 |
| 174 bool ImageBitmap::isResizeOptionValid(const ImageBitmapOptions& options, Excepti onState& exceptionState) | |
|
jbroman
2016/07/07 21:21:45
nit: prefer static functions, or functions in anon
xidachen
2016/07/13 14:50:22
Per offline discussion, will leave it as it is her
| |
| 175 { | |
| 176 if ((options.hasResizeWidth() && options.resizeWidth() == 0) || (options.has ResizeHeight() && options.resizeHeight() == 0)) { | |
| 177 exceptionState.throwDOMException(InvalidStateError, "The resizeWidth or/ and resizeHeight is less than or equals to 0."); | |
|
jbroman
2016/07/07 21:21:45
nit: For developer clarity, please specify which w
xidachen
2016/07/13 14:50:22
Done.
| |
| 178 return false; | |
| 179 } | |
| 180 return true; | |
| 181 } | |
| 182 | |
| 183 bool ImageBitmap::isSWSHValid(int sw, int sh, ExceptionState& exceptionState) | |
|
jbroman
2016/07/07 21:21:45
nit: What's a SWSH? Prefer more descriptive names,
xidachen
2016/07/13 14:50:22
Done.
| |
| 184 { | |
| 185 if (!sw || !sh) { | |
| 186 exceptionState.throwDOMException(IndexSizeError, String::format("The sou rce %s provided is 0.", sw ? "height" : "width")); | |
| 187 return false; | |
| 188 } | |
| 189 return true; | |
| 190 } | |
| 191 | |
| 116 // The parameter imageFormat indicates whether the first parameter "image" is un premultiplied or not. | 192 // The parameter imageFormat indicates whether the first parameter "image" is un premultiplied or not. |
| 117 // imageFormat = PremultiplyAlpha means the image is in premuliplied format | 193 // imageFormat = PremultiplyAlpha means the image is in premuliplied format |
| 118 // For example, if the image is already in unpremultiplied format and we want th e created ImageBitmap | 194 // For example, if the image is already in unpremultiplied format and we want th e created ImageBitmap |
| 119 // in the same format, then we don't need to use the ImageDecoder to decode the image. | 195 // in the same format, then we don't need to use the ImageDecoder to decode the image. |
| 120 static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const IntRect& crop Rect, bool flipY, bool premultiplyAlpha, AlphaDisposition imageFormat = Premulti plyAlpha, ImageDecoder::GammaAndColorProfileOption colorSpaceOp = ImageDecoder:: GammaAndColorProfileApplied) | 196 static PassRefPtr<StaticBitmapImage> cropImage(Image* image, IntRect cropRect, c onst ParsedOptions& parsedOptions, AlphaDisposition imageFormat = PremultiplyAlp ha, ImageDecoder::GammaAndColorProfileOption colorSpaceOp = ImageDecoder::GammaA ndColorProfileApplied) |
| 121 { | 197 { |
| 122 ASSERT(image); | 198 ASSERT(image); |
| 199 // Adjust the cropRect first: in the case where cropRect is not specified in the API call, | |
| 200 // the cropRect is assumed to be the same as the size of the (scaled) image. | |
| 201 if (parsedOptions.shouldScaleInput && cropRect.x() == 0 && cropRect.y() == 0 && cropRect.width() == image->width() && cropRect.height() == image->height()) { | |
| 202 cropRect.setWidth(parsedOptions.resizeWidth); | |
| 203 cropRect.setHeight(parsedOptions.resizeHeight); | |
| 204 } | |
| 123 | 205 |
| 124 IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); | 206 IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); |
| 125 const IntRect srcRect = intersection(imgRect, cropRect); | 207 const IntRect srcRect = intersection(imgRect, cropRect); |
| 126 | 208 |
| 127 // In the case when cropRect doesn't intersect the source image and it requi res a umpremul image | 209 // In the case when cropRect doesn't intersect the source image and it requi res a umpremul image |
| 128 // We immediately return a transparent black image with cropRect.size() | 210 // We immediately return a transparent black image with cropRect.size() |
| 129 if (srcRect.isEmpty() && !premultiplyAlpha) { | 211 if (srcRect.isEmpty() && !parsedOptions.premultiplyAlpha) { |
| 130 SkImageInfo info = SkImageInfo::Make(cropRect.width(), cropRect.height() , kN32_SkColorType, kUnpremul_SkAlphaType); | 212 SkImageInfo info = SkImageInfo::Make(cropRect.width(), cropRect.height() , kN32_SkColorType, kUnpremul_SkAlphaType); |
| 131 std::unique_ptr<uint8_t[]> dstPixels = wrapArrayUnique(new uint8_t[cropR ect.width() * cropRect.height() * info.bytesPerPixel()]()); | 213 std::unique_ptr<uint8_t[]> dstPixels = wrapArrayUnique(new uint8_t[cropR ect.width() * cropRect.height() * info.bytesPerPixel()]()); |
| 132 return StaticBitmapImage::create(newSkImageFromRaster(info, std::move(ds tPixels), cropRect.width() * info.bytesPerPixel())); | 214 return StaticBitmapImage::create(newSkImageFromRaster(info, std::move(ds tPixels), cropRect.width() * info.bytesPerPixel())); |
| 133 } | 215 } |
| 134 | 216 |
| 135 RefPtr<SkImage> skiaImage = image->imageForCurrentFrame(); | 217 RefPtr<SkImage> skiaImage = image->imageForCurrentFrame(); |
| 136 // Attempt to get raw unpremultiplied image data, executed only when skiaIma ge is premultiplied. | 218 // Attempt to get raw unpremultiplied image data, executed only when skiaIma ge is premultiplied. |
| 137 if ((((!premultiplyAlpha && !skiaImage->isOpaque()) || !skiaImage) && image- >data() && imageFormat == PremultiplyAlpha) || colorSpaceOp == ImageDecoder::Gam maAndColorProfileIgnored) { | 219 if ((((!parsedOptions.premultiplyAlpha && !skiaImage->isOpaque()) || !skiaIm age) && image->data() && imageFormat == PremultiplyAlpha) || colorSpaceOp == Ima geDecoder::GammaAndColorProfileIgnored) { |
| 138 std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create(*(image->data ()), | 220 std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create(*(image->data ()), |
| 139 premultiplyAlpha ? ImageDecoder::AlphaPremultiplied : ImageDecoder:: AlphaNotPremultiplied, | 221 parsedOptions.premultiplyAlpha ? ImageDecoder::AlphaPremultiplied : ImageDecoder::AlphaNotPremultiplied, |
| 140 colorSpaceOp)); | 222 colorSpaceOp)); |
| 141 if (!decoder) | 223 if (!decoder) |
| 142 return nullptr; | 224 return nullptr; |
| 143 decoder->setData(image->data(), true); | 225 decoder->setData(image->data(), true); |
| 144 skiaImage = ImageBitmap::getSkImageFromDecoder(std::move(decoder)); | 226 skiaImage = ImageBitmap::getSkImageFromDecoder(std::move(decoder)); |
| 145 if (!skiaImage) | 227 if (!skiaImage) |
| 146 return nullptr; | 228 return nullptr; |
| 147 } | 229 } |
| 148 | 230 |
| 149 if (cropRect == srcRect) { | 231 if (cropRect == srcRect) { |
| 150 RefPtr<SkImage> croppedSkImage = fromSkSp(skiaImage->makeSubset(srcRect) ); | 232 RefPtr<SkImage> croppedSkImage = fromSkSp(skiaImage->makeSubset(srcRect) ); |
| 151 if (flipY) | 233 if (parsedOptions.flipY) |
| 152 return StaticBitmapImage::create(flipSkImageVertically(croppedSkImag e.get(), premultiplyAlpha ? PremultiplyAlpha : DontPremultiplyAlpha)); | 234 return StaticBitmapImage::create(flipSkImageVertically(croppedSkImag e.get(), parsedOptions.premultiplyAlpha ? PremultiplyAlpha : DontPremultiplyAlph a)); |
| 153 // Special case: The first parameter image is unpremul but we need to tu rn it into premul. | 235 // Special case: The first parameter image is unpremul but we need to tu rn it into premul. |
| 154 if (premultiplyAlpha && imageFormat == DontPremultiplyAlpha) | 236 if (parsedOptions.premultiplyAlpha && imageFormat == DontPremultiplyAlph a) |
| 155 return StaticBitmapImage::create(unPremulSkImageToPremul(croppedSkIm age.get())); | 237 return StaticBitmapImage::create(unPremulSkImageToPremul(croppedSkIm age.get())); |
| 156 // Call preroll to trigger image decoding. | 238 // Call preroll to trigger image decoding. |
| 157 croppedSkImage->preroll(); | 239 croppedSkImage->preroll(); |
| 158 return StaticBitmapImage::create(croppedSkImage.release()); | 240 return StaticBitmapImage::create(croppedSkImage.release()); |
| 159 } | 241 } |
| 160 | 242 |
| 161 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(cropRect.width(), cropRect.height()); | 243 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(cropRect.width(), cropRect.height()); |
| 162 if (!surface) | 244 if (!surface) |
| 163 return nullptr; | 245 return nullptr; |
| 164 if (srcRect.isEmpty()) | 246 if (srcRect.isEmpty()) |
| 165 return StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot())) ; | 247 return StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot())) ; |
| 166 | 248 |
| 167 SkScalar dstLeft = std::min(0, -cropRect.x()); | 249 SkScalar dstLeft = std::min(0, -cropRect.x()); |
| 168 SkScalar dstTop = std::min(0, -cropRect.y()); | 250 SkScalar dstTop = std::min(0, -cropRect.y()); |
| 169 if (cropRect.x() < 0) | 251 if (cropRect.x() < 0) |
| 170 dstLeft = -cropRect.x(); | 252 dstLeft = -cropRect.x(); |
| 171 if (cropRect.y() < 0) | 253 if (cropRect.y() < 0) |
| 172 dstTop = -cropRect.y(); | 254 dstTop = -cropRect.y(); |
| 173 surface->getCanvas()->drawImage(skiaImage.get(), dstLeft, dstTop); | 255 if (parsedOptions.shouldScaleInput) { |
| 256 SkRect drawDstRect = SkRect::MakeXYWH(dstLeft, dstTop, parsedOptions.res izeWidth, parsedOptions.resizeHeight); | |
| 257 SkPaint paint; | |
| 258 paint.setFilterQuality(parsedOptions.resizeQuality); | |
| 259 surface->getCanvas()->drawImageRect(skiaImage.get(), drawDstRect, &paint ); | |
| 260 } else { | |
| 261 surface->getCanvas()->drawImage(skiaImage.get(), dstLeft, dstTop); | |
| 262 } | |
| 174 skiaImage = fromSkSp(surface->makeImageSnapshot()); | 263 skiaImage = fromSkSp(surface->makeImageSnapshot()); |
| 175 if (flipY) | 264 if (parsedOptions.flipY) |
| 176 skiaImage = flipSkImageVertically(skiaImage.get(), PremultiplyAlpha); | 265 skiaImage = flipSkImageVertically(skiaImage.get(), PremultiplyAlpha); |
| 177 | 266 |
| 178 if (premultiplyAlpha) { | 267 if (parsedOptions.premultiplyAlpha) { |
| 179 if (imageFormat == PremultiplyAlpha) | 268 if (imageFormat == PremultiplyAlpha) |
| 180 return StaticBitmapImage::create(unPremulSkImageToPremul(skiaImage.g et())); | 269 return StaticBitmapImage::create(unPremulSkImageToPremul(skiaImage.g et())); |
| 181 return StaticBitmapImage::create(skiaImage.release()); | 270 return StaticBitmapImage::create(skiaImage.release()); |
| 182 } | 271 } |
| 183 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get())); | 272 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get())); |
| 184 } | 273 } |
| 185 | 274 |
| 186 ImageBitmap::ImageBitmap(HTMLImageElement* image, const IntRect& cropRect, Docum ent* document, const ImageBitmapOptions& options) | 275 ImageBitmap::ImageBitmap(HTMLImageElement* image, IntRect& cropRect, Document* d ocument, const ImageBitmapOptions& options) |
| 187 { | 276 { |
| 188 bool flipY; | 277 RefPtr<Image> input = image->cachedImage()->getImage(); |
| 189 bool premultiplyAlpha; | 278 ParsedOptions parsedOptions = parseOptions(options, input->width(), input->h eight()); |
| 190 parseOptions(options, flipY, premultiplyAlpha); | |
| 191 | 279 |
| 192 if (options.colorSpaceConversion() == "none") | 280 if (options.colorSpaceConversion() == "none") |
| 193 m_image = cropImage(image->cachedImage()->getImage(), cropRect, flipY, p remultiplyAlpha, PremultiplyAlpha, ImageDecoder::GammaAndColorProfileIgnored); | 281 m_image = cropImage(input.get(), cropRect, parsedOptions, PremultiplyAlp ha, ImageDecoder::GammaAndColorProfileIgnored); |
| 194 else | 282 else |
| 195 m_image = cropImage(image->cachedImage()->getImage(), cropRect, flipY, p remultiplyAlpha, PremultiplyAlpha, ImageDecoder::GammaAndColorProfileApplied); | 283 m_image = cropImage(input.get(), cropRect, parsedOptions, PremultiplyAlp ha, ImageDecoder::GammaAndColorProfileApplied); |
| 196 if (!m_image) | 284 if (!m_image) |
| 197 return; | 285 return; |
| 198 // In the case where the source image is lazy-decoded, m_image may not be in | 286 // In the case where the source image is lazy-decoded, m_image may not be in |
| 199 // a decoded state, we trigger it here. | 287 // a decoded state, we trigger it here. |
| 200 RefPtr<SkImage> skImage = m_image->imageForCurrentFrame(); | 288 RefPtr<SkImage> skImage = m_image->imageForCurrentFrame(); |
| 201 SkPixmap pixmap; | 289 SkPixmap pixmap; |
| 202 if (!skImage->isTextureBacked() && !skImage->peekPixels(&pixmap)) { | 290 if (!skImage->isTextureBacked() && !skImage->peekPixels(&pixmap)) { |
| 203 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(skImage->width (), skImage->height()); | 291 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(skImage->width (), skImage->height()); |
| 204 surface->getCanvas()->drawImage(skImage.get(), 0, 0); | 292 surface->getCanvas()->drawImage(skImage.get(), 0, 0); |
| 205 m_image = StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot( ))); | 293 m_image = StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot( ))); |
| 206 } | 294 } |
| 207 m_image->setOriginClean(!image->wouldTaintOrigin(document->getSecurityOrigin ())); | 295 m_image->setOriginClean(!image->wouldTaintOrigin(document->getSecurityOrigin ())); |
| 208 m_image->setPremultiplied(premultiplyAlpha); | 296 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
| 209 } | 297 } |
| 210 | 298 |
| 211 ImageBitmap::ImageBitmap(HTMLVideoElement* video, const IntRect& cropRect, Docum ent* document, const ImageBitmapOptions& options) | 299 ImageBitmap::ImageBitmap(HTMLVideoElement* video, IntRect& cropRect, Document* d ocument, const ImageBitmapOptions& options) |
| 212 { | 300 { |
| 213 IntSize playerSize; | 301 IntSize playerSize; |
| 214 if (video->webMediaPlayer()) | 302 if (video->webMediaPlayer()) |
| 215 playerSize = video->webMediaPlayer()->naturalSize(); | 303 playerSize = video->webMediaPlayer()->naturalSize(); |
| 216 | 304 |
| 217 IntRect videoRect = IntRect(IntPoint(), playerSize); | 305 IntRect videoRect = IntRect(IntPoint(), playerSize); |
| 218 IntRect srcRect = intersection(cropRect, videoRect); | 306 IntRect srcRect = intersection(cropRect, videoRect); |
| 219 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(cropRect.size(), N onOpaque, DoNotInitializeImagePixels); | 307 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(cropRect.size(), N onOpaque, DoNotInitializeImagePixels); |
| 220 if (!buffer) | 308 if (!buffer) |
| 221 return; | 309 return; |
| 222 | 310 |
| 223 IntPoint dstPoint = IntPoint(std::max(0, -cropRect.x()), std::max(0, -cropRe ct.y())); | 311 IntPoint dstPoint = IntPoint(std::max(0, -cropRect.x()), std::max(0, -cropRe ct.y())); |
| 224 video->paintCurrentFrame(buffer->canvas(), IntRect(dstPoint, srcRect.size()) , nullptr); | 312 video->paintCurrentFrame(buffer->canvas(), IntRect(dstPoint, srcRect.size()) , nullptr); |
| 225 | 313 |
| 226 bool flipY; | 314 // TODO(xidachen); implement the resize option. |
| 227 bool premultiplyAlpha; | 315 ParsedOptions parsedOptions = parseOptions(options, playerSize.width(), play erSize.height()); |
| 228 parseOptions(options, flipY, premultiplyAlpha); | |
| 229 | 316 |
| 230 if (flipY || !premultiplyAlpha) { | 317 if (parsedOptions.flipY || !parsedOptions.premultiplyAlpha) { |
| 231 RefPtr<SkImage> skiaImage = buffer->newSkImageSnapshot(PreferNoAccelerat ion, SnapshotReasonUnknown); | 318 RefPtr<SkImage> skiaImage = buffer->newSkImageSnapshot(PreferNoAccelerat ion, SnapshotReasonUnknown); |
| 232 if (flipY) | 319 if (parsedOptions.flipY) |
| 233 skiaImage = flipSkImageVertically(skiaImage.get(), PremultiplyAlpha) ; | 320 skiaImage = flipSkImageVertically(skiaImage.get(), PremultiplyAlpha) ; |
| 234 if (!premultiplyAlpha) | 321 if (!parsedOptions.premultiplyAlpha) |
| 235 skiaImage = premulSkImageToUnPremul(skiaImage.get()); | 322 skiaImage = premulSkImageToUnPremul(skiaImage.get()); |
| 236 m_image = StaticBitmapImage::create(skiaImage.release()); | 323 m_image = StaticBitmapImage::create(skiaImage.release()); |
| 237 } else { | 324 } else { |
| 238 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA cceleration, SnapshotReasonUnknown)); | 325 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA cceleration, SnapshotReasonUnknown)); |
| 239 } | 326 } |
| 240 m_image->setOriginClean(!video->wouldTaintOrigin(document->getSecurityOrigin ())); | 327 m_image->setOriginClean(!video->wouldTaintOrigin(document->getSecurityOrigin ())); |
| 241 m_image->setPremultiplied(premultiplyAlpha); | 328 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
| 242 } | 329 } |
| 243 | 330 |
| 244 ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, const IntRect& cropRect, con st ImageBitmapOptions& options) | 331 ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, IntRect& cropRect, const Ima geBitmapOptions& options) |
|
jbroman
2016/07/07 21:21:45
this is still a non-const ref; could you please ch
xidachen
2016/07/13 14:50:22
Done.
| |
| 245 { | 332 { |
| 246 ASSERT(canvas->isPaintable()); | 333 ASSERT(canvas->isPaintable()); |
| 247 bool flipY; | 334 RefPtr<Image> input = canvas->copiedImage(BackBuffer, PreferAcceleration); |
| 248 bool premultiplyAlpha; | 335 ParsedOptions parsedOptions = parseOptions(options, input->width(), input->h eight()); |
| 249 parseOptions(options, flipY, premultiplyAlpha); | |
| 250 | 336 |
| 251 // canvas is always premultiplied, so set the last parameter to true and con vert to un-premul later | 337 bool isPremultiplyAlphaReverted = false; |
| 252 m_image = cropImage(canvas->copiedImage(BackBuffer, PreferAcceleration).get( ), cropRect, flipY, true); | 338 if (!parsedOptions.premultiplyAlpha) { |
| 339 parsedOptions.premultiplyAlpha = true; | |
| 340 isPremultiplyAlphaReverted = true; | |
| 341 } | |
| 342 m_image = cropImage(input.get(), cropRect, parsedOptions); | |
| 253 if (!m_image) | 343 if (!m_image) |
| 254 return; | 344 return; |
| 255 if (!premultiplyAlpha) | 345 if (isPremultiplyAlphaReverted) { |
| 346 parsedOptions.premultiplyAlpha = false; | |
| 256 m_image = StaticBitmapImage::create(premulSkImageToUnPremul(m_image->ima geForCurrentFrame().get())); | 347 m_image = StaticBitmapImage::create(premulSkImageToUnPremul(m_image->ima geForCurrentFrame().get())); |
| 348 } | |
| 257 m_image->setOriginClean(canvas->originClean()); | 349 m_image->setOriginClean(canvas->originClean()); |
| 258 m_image->setPremultiplied(premultiplyAlpha); | 350 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
| 259 } | 351 } |
| 260 | 352 |
| 261 ImageBitmap::ImageBitmap(std::unique_ptr<uint8_t[]> data, uint32_t width, uint32 _t height, bool isImageBitmapPremultiplied, bool isImageBitmapOriginClean) | 353 ImageBitmap::ImageBitmap(std::unique_ptr<uint8_t[]> data, uint32_t width, uint32 _t height, bool isImageBitmapPremultiplied, bool isImageBitmapOriginClean) |
| 262 { | 354 { |
| 263 SkImageInfo info = SkImageInfo::MakeN32(width, height, isImageBitmapPremulti plied ? kPremul_SkAlphaType : kUnpremul_SkAlphaType); | 355 SkImageInfo info = SkImageInfo::MakeN32(width, height, isImageBitmapPremulti plied ? kPremul_SkAlphaType : kUnpremul_SkAlphaType); |
| 264 m_image = StaticBitmapImage::create(fromSkSp(SkImage::MakeRasterCopy(SkPixma p(info, data.get(), info.bytesPerPixel() * width)))); | 356 m_image = StaticBitmapImage::create(fromSkSp(SkImage::MakeRasterCopy(SkPixma p(info, data.get(), info.bytesPerPixel() * width)))); |
| 265 m_image->setPremultiplied(isImageBitmapPremultiplied); | 357 m_image->setPremultiplied(isImageBitmapPremultiplied); |
| 266 m_image->setOriginClean(isImageBitmapOriginClean); | 358 m_image->setOriginClean(isImageBitmapOriginClean); |
| 267 } | 359 } |
| 268 | 360 |
| 269 ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect, const ImageBi tmapOptions& options) | 361 ImageBitmap::ImageBitmap(ImageData* data, IntRect& cropRect, const ImageBitmapOp tions& options) |
| 270 { | 362 { |
| 271 bool flipY; | 363 // TODO(xidachen): implement the resize option |
| 272 bool premultiplyAlpha; | 364 ParsedOptions parsedOptions = parseOptions(options, data->width(), data->hei ght()); |
| 273 parseOptions(options, flipY, premultiplyAlpha); | |
| 274 IntRect srcRect = intersection(cropRect, IntRect(IntPoint(), data->size())); | 365 IntRect srcRect = intersection(cropRect, IntRect(IntPoint(), data->size())); |
| 275 | 366 |
| 276 // treat non-premultiplyAlpha as a special case | 367 // treat non-premultiplyAlpha as a special case |
| 277 if (!premultiplyAlpha) { | 368 if (!parsedOptions.premultiplyAlpha) { |
| 278 unsigned char* srcAddr = data->data()->data(); | 369 unsigned char* srcAddr = data->data()->data(); |
| 279 int srcHeight = data->size().height(); | 370 int srcHeight = data->size().height(); |
| 280 int dstHeight = cropRect.height(); | 371 int dstHeight = cropRect.height(); |
| 281 // TODO (xidachen): skia doesn't support SkImage::NewRasterCopy from a k RGBA color type. | 372 // TODO (xidachen): skia doesn't support SkImage::NewRasterCopy from a k RGBA color type. |
| 282 // For now, we swap R and B channel and uses kBGRA color type. | 373 // For now, we swap R and B channel and uses kBGRA color type. |
| 283 SkImageInfo info = SkImageInfo::Make(cropRect.width(), dstHeight, kBGRA_ 8888_SkColorType, kUnpremul_SkAlphaType); | 374 SkImageInfo info = SkImageInfo::Make(cropRect.width(), dstHeight, kBGRA_ 8888_SkColorType, kUnpremul_SkAlphaType); |
| 284 int srcPixelBytesPerRow = info.bytesPerPixel() * data->size().width(); | 375 int srcPixelBytesPerRow = info.bytesPerPixel() * data->size().width(); |
| 285 int dstPixelBytesPerRow = info.bytesPerPixel() * cropRect.width(); | 376 int dstPixelBytesPerRow = info.bytesPerPixel() * cropRect.width(); |
| 286 if (cropRect == IntRect(IntPoint(), data->size())) { | 377 if (cropRect == IntRect(IntPoint(), data->size())) { |
| 287 swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, flipY); | 378 swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, parsedOpti ons.flipY); |
| 288 m_image = StaticBitmapImage::create(fromSkSp(SkImage::MakeRasterCopy (SkPixmap(info, srcAddr, dstPixelBytesPerRow)))); | 379 m_image = StaticBitmapImage::create(fromSkSp(SkImage::MakeRasterCopy (SkPixmap(info, srcAddr, dstPixelBytesPerRow)))); |
| 289 // restore the original ImageData | 380 // restore the original ImageData |
| 290 swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, flipY); | 381 swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, parsedOpti ons.flipY); |
| 291 } else { | 382 } else { |
| 292 std::unique_ptr<uint8_t[]> copiedDataBuffer = wrapArrayUnique(new ui nt8_t[dstHeight * dstPixelBytesPerRow]()); | 383 std::unique_ptr<uint8_t[]> copiedDataBuffer = wrapArrayUnique(new ui nt8_t[dstHeight * dstPixelBytesPerRow]()); |
| 293 if (!srcRect.isEmpty()) { | 384 if (!srcRect.isEmpty()) { |
| 294 IntPoint srcPoint = IntPoint((cropRect.x() > 0) ? cropRect.x() : 0, (cropRect.y() > 0) ? cropRect.y() : 0); | 385 IntPoint srcPoint = IntPoint((cropRect.x() > 0) ? cropRect.x() : 0, (cropRect.y() > 0) ? cropRect.y() : 0); |
| 295 IntPoint dstPoint = IntPoint((cropRect.x() >= 0) ? 0 : -cropRect .x(), (cropRect.y() >= 0) ? 0 : -cropRect.y()); | 386 IntPoint dstPoint = IntPoint((cropRect.x() >= 0) ? 0 : -cropRect .x(), (cropRect.y() >= 0) ? 0 : -cropRect.y()); |
| 296 int copyHeight = srcHeight - srcPoint.y(); | 387 int copyHeight = srcHeight - srcPoint.y(); |
| 297 if (cropRect.height() < copyHeight) | 388 if (cropRect.height() < copyHeight) |
| 298 copyHeight = cropRect.height(); | 389 copyHeight = cropRect.height(); |
| 299 int copyWidth = data->size().width() - srcPoint.x(); | 390 int copyWidth = data->size().width() - srcPoint.x(); |
| 300 if (cropRect.width() < copyWidth) | 391 if (cropRect.width() < copyWidth) |
| 301 copyWidth = cropRect.width(); | 392 copyWidth = cropRect.width(); |
| 302 for (int i = 0; i < copyHeight; i++) { | 393 for (int i = 0; i < copyHeight; i++) { |
| 303 int srcStartCopyPosition = (i + srcPoint.y()) * srcPixelByte sPerRow + srcPoint.x() * info.bytesPerPixel(); | 394 int srcStartCopyPosition = (i + srcPoint.y()) * srcPixelByte sPerRow + srcPoint.x() * info.bytesPerPixel(); |
| 304 int srcEndCopyPosition = srcStartCopyPosition + copyWidth * info.bytesPerPixel(); | 395 int srcEndCopyPosition = srcStartCopyPosition + copyWidth * info.bytesPerPixel(); |
| 305 int dstStartCopyPosition; | 396 int dstStartCopyPosition; |
| 306 if (flipY) | 397 if (parsedOptions.flipY) |
| 307 dstStartCopyPosition = (dstHeight -1 - dstPoint.y() - i) * dstPixelBytesPerRow + dstPoint.x() * info.bytesPerPixel(); | 398 dstStartCopyPosition = (dstHeight -1 - dstPoint.y() - i) * dstPixelBytesPerRow + dstPoint.x() * info.bytesPerPixel(); |
| 308 else | 399 else |
| 309 dstStartCopyPosition = (dstPoint.y() + i) * dstPixelByte sPerRow + dstPoint.x() * info.bytesPerPixel(); | 400 dstStartCopyPosition = (dstPoint.y() + i) * dstPixelByte sPerRow + dstPoint.x() * info.bytesPerPixel(); |
| 310 for (int j = 0; j < srcEndCopyPosition - srcStartCopyPositio n; j++) { | 401 for (int j = 0; j < srcEndCopyPosition - srcStartCopyPositio n; j++) { |
| 311 if (j % 4 == 0) | 402 if (j % 4 == 0) |
| 312 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr [srcStartCopyPosition + j + 2]; | 403 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr [srcStartCopyPosition + j + 2]; |
| 313 else if (j % 4 == 2) | 404 else if (j % 4 == 2) |
| 314 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr [srcStartCopyPosition + j - 2]; | 405 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr [srcStartCopyPosition + j - 2]; |
| 315 else | 406 else |
| 316 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr [srcStartCopyPosition + j]; | 407 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr [srcStartCopyPosition + j]; |
| 317 } | 408 } |
| 318 } | 409 } |
| 319 } | 410 } |
| 320 m_image = StaticBitmapImage::create(newSkImageFromRaster(info, std:: move(copiedDataBuffer), dstPixelBytesPerRow)); | 411 m_image = StaticBitmapImage::create(newSkImageFromRaster(info, std:: move(copiedDataBuffer), dstPixelBytesPerRow)); |
| 321 } | 412 } |
| 322 m_image->setPremultiplied(premultiplyAlpha); | 413 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
| 323 return; | 414 return; |
| 324 } | 415 } |
| 325 | 416 |
| 326 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(cropRect.size(), N onOpaque, DoNotInitializeImagePixels); | 417 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(cropRect.size(), N onOpaque, DoNotInitializeImagePixels); |
| 327 if (!buffer) | 418 if (!buffer) |
| 328 return; | 419 return; |
| 329 | 420 |
| 330 if (srcRect.isEmpty()) { | 421 if (srcRect.isEmpty()) { |
| 331 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA cceleration, SnapshotReasonUnknown)); | 422 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA cceleration, SnapshotReasonUnknown)); |
| 332 return; | 423 return; |
| 333 } | 424 } |
| 334 | 425 |
| 335 IntPoint dstPoint = IntPoint(std::min(0, -cropRect.x()), std::min(0, -cropRe ct.y())); | 426 IntPoint dstPoint = IntPoint(std::min(0, -cropRect.x()), std::min(0, -cropRe ct.y())); |
| 336 if (cropRect.x() < 0) | 427 if (cropRect.x() < 0) |
| 337 dstPoint.setX(-cropRect.x()); | 428 dstPoint.setX(-cropRect.x()); |
| 338 if (cropRect.y() < 0) | 429 if (cropRect.y() < 0) |
| 339 dstPoint.setY(-cropRect.y()); | 430 dstPoint.setY(-cropRect.y()); |
| 340 buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), srcRe ct, dstPoint); | 431 buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), srcRe ct, dstPoint); |
| 341 if (flipY) | 432 if (parsedOptions.flipY) |
| 342 m_image = StaticBitmapImage::create(flipSkImageVertically(buffer->newSkI mageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown).get(), PremultiplyAlph a)); | 433 m_image = StaticBitmapImage::create(flipSkImageVertically(buffer->newSkI mageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown).get(), PremultiplyAlph a)); |
| 343 else | 434 else |
| 344 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA cceleration, SnapshotReasonUnknown)); | 435 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA cceleration, SnapshotReasonUnknown)); |
| 345 } | 436 } |
| 346 | 437 |
| 347 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, const IntRect& cropRect, const Ima geBitmapOptions& options) | 438 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, IntRect& cropRect, const ImageBitm apOptions& options) |
| 348 { | 439 { |
| 349 bool flipY; | 440 RefPtr<Image> input = bitmap->bitmapImage(); |
| 350 bool premultiplyAlpha; | 441 ParsedOptions parsedOptions = parseOptions(options, input->width(), input->h eight()); |
| 351 parseOptions(options, flipY, premultiplyAlpha); | 442 |
| 352 m_image = cropImage(bitmap->bitmapImage(), cropRect, flipY, premultiplyAlpha , bitmap->isPremultiplied() ? PremultiplyAlpha : DontPremultiplyAlpha); | 443 m_image = cropImage(input.get(), cropRect, parsedOptions, bitmap->isPremulti plied() ? PremultiplyAlpha : DontPremultiplyAlpha); |
| 353 if (!m_image) | 444 if (!m_image) |
| 354 return; | 445 return; |
| 355 m_image->setOriginClean(bitmap->originClean()); | 446 m_image->setOriginClean(bitmap->originClean()); |
| 356 m_image->setPremultiplied(premultiplyAlpha); | 447 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
| 357 } | 448 } |
| 358 | 449 |
| 359 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, const IntRect& cro pRect, const ImageBitmapOptions& options) | 450 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, IntRect& cropRect, const ImageBitmapOptions& options) |
| 360 { | 451 { |
| 361 bool flipY; | 452 bool originClean = image->originClean(); |
| 362 bool premultiplyAlpha; | 453 RefPtr<Image> input = image; |
| 363 parseOptions(options, flipY, premultiplyAlpha); | 454 ParsedOptions parsedOptions = parseOptions(options, input->width(), input->h eight()); |
| 364 m_image = cropImage(image.get(), cropRect, flipY, premultiplyAlpha, DontPrem ultiplyAlpha); | 455 |
| 456 m_image = cropImage(input.get(), cropRect, parsedOptions, DontPremultiplyAlp ha); | |
| 365 if (!m_image) | 457 if (!m_image) |
| 366 return; | 458 return; |
| 367 m_image->setOriginClean(image->originClean()); | 459 m_image->setOriginClean(originClean); |
| 368 m_image->setPremultiplied(premultiplyAlpha); | 460 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
| 369 } | 461 } |
| 370 | 462 |
| 371 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image) | 463 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image) |
| 372 { | 464 { |
| 373 m_image = image; | 465 m_image = image; |
| 374 } | 466 } |
| 375 | 467 |
| 376 ImageBitmap::ImageBitmap(WebExternalTextureMailbox& mailbox) | 468 ImageBitmap::ImageBitmap(WebExternalTextureMailbox& mailbox) |
| 377 { | 469 { |
| 378 m_image = StaticBitmapImage::create(mailbox); | 470 m_image = StaticBitmapImage::create(mailbox); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 485 IntSize ImageBitmap::size() const | 577 IntSize ImageBitmap::size() const |
| 486 { | 578 { |
| 487 if (!m_image) | 579 if (!m_image) |
| 488 return IntSize(); | 580 return IntSize(); |
| 489 ASSERT(m_image->width() > 0 && m_image->height() > 0); | 581 ASSERT(m_image->width() > 0 && m_image->height() > 0); |
| 490 return IntSize(m_image->width(), m_image->height()); | 582 return IntSize(m_image->width(), m_image->height()); |
| 491 } | 583 } |
| 492 | 584 |
| 493 ScriptPromise ImageBitmap::createImageBitmap(ScriptState* scriptState, EventTarg et& eventTarget, int sx, int sy, int sw, int sh, const ImageBitmapOptions& optio ns, ExceptionState& exceptionState) | 585 ScriptPromise ImageBitmap::createImageBitmap(ScriptState* scriptState, EventTarg et& eventTarget, int sx, int sy, int sw, int sh, const ImageBitmapOptions& optio ns, ExceptionState& exceptionState) |
| 494 { | 586 { |
| 495 if (!sw || !sh) { | 587 if (!isSWSHValid(sw, sh, exceptionState)) |
| 496 exceptionState.throwDOMException(IndexSizeError, String::format("The sou rce %s provided is 0.", sw ? "height" : "width")); | |
| 497 return ScriptPromise(); | 588 return ScriptPromise(); |
| 498 } | 589 if (!isResizeOptionValid(options, exceptionState)) |
| 590 return ScriptPromise(); | |
| 499 return ImageBitmapSource::fulfillImageBitmap(scriptState, create(this, IntRe ct(sx, sy, sw, sh), options)); | 591 return ImageBitmapSource::fulfillImageBitmap(scriptState, create(this, IntRe ct(sx, sy, sw, sh), options)); |
| 500 } | 592 } |
| 501 | 593 |
| 502 void ImageBitmap::parseOptions(const ImageBitmapOptions& options, bool& flipY, b ool& premultiplyAlpha) | |
| 503 { | |
| 504 if (options.imageOrientation() == imageOrientationFlipY) { | |
| 505 flipY = true; | |
| 506 } else { | |
| 507 flipY = false; | |
| 508 ASSERT(options.imageOrientation() == imageBitmapOptionNone); | |
| 509 } | |
| 510 if (options.premultiplyAlpha() == imageBitmapOptionNone) { | |
| 511 premultiplyAlpha = false; | |
| 512 } else { | |
| 513 premultiplyAlpha = true; | |
| 514 ASSERT(options.premultiplyAlpha() == "default" || options.premultiplyAlp ha() == "premultiply"); | |
| 515 } | |
| 516 } | |
| 517 | |
| 518 PassRefPtr<Image> ImageBitmap::getSourceImageForCanvas(SourceImageStatus* status , AccelerationHint, SnapshotReason, const FloatSize&) const | 594 PassRefPtr<Image> ImageBitmap::getSourceImageForCanvas(SourceImageStatus* status , AccelerationHint, SnapshotReason, const FloatSize&) const |
| 519 { | 595 { |
| 520 *status = NormalSourceImageStatus; | 596 *status = NormalSourceImageStatus; |
| 521 return m_image ? m_image : nullptr; | 597 return m_image ? m_image : nullptr; |
| 522 } | 598 } |
| 523 | 599 |
| 524 void ImageBitmap::adjustDrawRects(FloatRect* srcRect, FloatRect* dstRect) const | 600 void ImageBitmap::adjustDrawRects(FloatRect* srcRect, FloatRect* dstRect) const |
| 525 { | 601 { |
| 526 } | 602 } |
| 527 | 603 |
| 528 FloatSize ImageBitmap::elementSize(const FloatSize&) const | 604 FloatSize ImageBitmap::elementSize(const FloatSize&) const |
| 529 { | 605 { |
| 530 return FloatSize(width(), height()); | 606 return FloatSize(width(), height()); |
| 531 } | 607 } |
| 532 | 608 |
| 533 DEFINE_TRACE(ImageBitmap) | 609 DEFINE_TRACE(ImageBitmap) |
| 534 { | 610 { |
| 535 } | 611 } |
| 536 | 612 |
| 537 } // namespace blink | 613 } // namespace blink |
| OLD | NEW |