| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. | 2 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. |
| 3 * | 3 * |
| 4 * This library is free software; you can redistribute it and/or | 4 * This library is free software; you can redistribute it and/or |
| 5 * modify it under the terms of the GNU Library General Public | 5 * modify it under the terms of the GNU Library General Public |
| 6 * License as published by the Free Software Foundation; either | 6 * License as published by the Free Software Foundation; either |
| 7 * version 2 of the License, or (at your option) any later version. | 7 * version 2 of the License, or (at your option) any later version. |
| 8 * | 8 * |
| 9 * This library is distributed in the hope that it will be useful, | 9 * This library is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 12 * Library General Public License for more details. | 12 * Library General Public License for more details. |
| 13 * | 13 * |
| 14 * You should have received a copy of the GNU Library General Public License | 14 * You should have received a copy of the GNU Library General Public License |
| 15 * along with this library; see the file COPYING.LIB. If not, write to | 15 * along with this library; see the file COPYING.LIB. If not, write to |
| 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 17 * Boston, MA 02110-1301, USA. | 17 * Boston, MA 02110-1301, USA. |
| 18 * | 18 * |
| 19 */ | 19 */ |
| 20 | 20 |
| 21 #include "platform/image-decoders/ImageDecoder.h" | 21 #include "platform/image-decoders/ImageDecoder.h" |
| 22 | 22 |
| 23 #include <memory> | 23 #include <memory> |
| 24 #include "platform/RuntimeEnabledFeatures.h" | 24 #include "platform/RuntimeEnabledFeatures.h" |
| 25 #include "platform/graphics/BitmapImageMetrics.h" | 25 #include "platform/graphics/BitmapImageMetrics.h" |
| 26 #include "platform/image-decoders/FastSharedBufferReader.h" | |
| 27 #include "platform/image-decoders/bmp/BMPImageDecoder.h" | |
| 28 #include "platform/image-decoders/gif/GIFImageDecoder.h" | |
| 29 #include "platform/image-decoders/ico/ICOImageDecoder.h" | |
| 30 #include "platform/image-decoders/jpeg/JPEGImageDecoder.h" | |
| 31 #include "platform/image-decoders/png/PNGImageDecoder.h" | |
| 32 #include "platform/image-decoders/webp/WEBPImageDecoder.h" | |
| 33 #include "platform/instrumentation/PlatformInstrumentation.h" | 26 #include "platform/instrumentation/PlatformInstrumentation.h" |
| 34 #include "platform/wtf/PtrUtil.h" | 27 #include "platform/wtf/PtrUtil.h" |
| 28 #include "third_party/skia/include/core/SkImageInfo.h" |
| 35 | 29 |
| 36 namespace blink { | 30 namespace blink { |
| 37 | 31 |
| 38 inline bool MatchesJPEGSignature(const char* contents) { | |
| 39 return !memcmp(contents, "\xFF\xD8\xFF", 3); | |
| 40 } | |
| 41 | |
| 42 inline bool MatchesPNGSignature(const char* contents) { | |
| 43 return !memcmp(contents, "\x89PNG\r\n\x1A\n", 8); | |
| 44 } | |
| 45 | |
| 46 inline bool MatchesGIFSignature(const char* contents) { | |
| 47 return !memcmp(contents, "GIF87a", 6) || !memcmp(contents, "GIF89a", 6); | |
| 48 } | |
| 49 | |
| 50 inline bool MatchesWebPSignature(const char* contents) { | |
| 51 return !memcmp(contents, "RIFF", 4) && !memcmp(contents + 8, "WEBPVP", 6); | |
| 52 } | |
| 53 | |
| 54 inline bool MatchesICOSignature(const char* contents) { | |
| 55 return !memcmp(contents, "\x00\x00\x01\x00", 4); | |
| 56 } | |
| 57 | |
| 58 inline bool MatchesCURSignature(const char* contents) { | |
| 59 return !memcmp(contents, "\x00\x00\x02\x00", 4); | |
| 60 } | |
| 61 | |
| 62 inline bool MatchesBMPSignature(const char* contents) { | |
| 63 return !memcmp(contents, "BM", 2); | |
| 64 } | |
| 65 | |
| 66 static constexpr size_t kLongestSignatureLength = sizeof("RIFF????WEBPVP") - 1; | |
| 67 | |
| 68 std::unique_ptr<ImageDecoder> ImageDecoder::Create( | 32 std::unique_ptr<ImageDecoder> ImageDecoder::Create( |
| 69 RefPtr<SegmentReader> data, | 33 RefPtr<SegmentReader> data, |
| 70 bool data_complete, | 34 bool data_complete, |
| 71 AlphaOption alpha_option, | 35 AlphaOption alpha_option, |
| 72 const ColorBehavior& color_behavior) { | 36 const ColorBehavior& color_behavior) { |
| 73 // At least kLongestSignatureLength bytes are needed to sniff the signature. | |
| 74 if (data->size() < kLongestSignatureLength) | |
| 75 return nullptr; | |
| 76 | |
| 77 const size_t max_decoded_bytes = | 37 const size_t max_decoded_bytes = |
| 78 Platform::Current() ? Platform::Current()->MaxDecodedImageBytes() | 38 Platform::Current() ? Platform::Current()->MaxDecodedImageBytes() |
| 79 : kNoDecodedImageByteLimit; | 39 : kNoDecodedImageByteLimit; |
| 80 | 40 |
| 81 // Access the first kLongestSignatureLength chars to sniff the signature. | 41 std::unique_ptr<ImageDecoder> decoder; |
| 82 // (note: FastSharedBufferReader only makes a copy if the bytes are segmented) | |
| 83 char buffer[kLongestSignatureLength]; | |
| 84 const FastSharedBufferReader fast_reader(data); | |
| 85 const char* contents = | |
| 86 fast_reader.GetConsecutiveData(0, kLongestSignatureLength, buffer); | |
| 87 | 42 |
| 88 std::unique_ptr<ImageDecoder> decoder; | 43 decoder.reset( |
| 89 if (MatchesJPEGSignature(contents)) { | 44 new ImageDecoder(alpha_option, color_behavior, max_decoded_bytes)); |
| 90 decoder.reset( | |
| 91 new JPEGImageDecoder(alpha_option, color_behavior, max_decoded_bytes)); | |
| 92 } else if (MatchesPNGSignature(contents)) { | |
| 93 decoder.reset( | |
| 94 new PNGImageDecoder(alpha_option, color_behavior, max_decoded_bytes)); | |
| 95 } else if (MatchesGIFSignature(contents)) { | |
| 96 decoder.reset( | |
| 97 new GIFImageDecoder(alpha_option, color_behavior, max_decoded_bytes)); | |
| 98 } else if (MatchesWebPSignature(contents)) { | |
| 99 decoder.reset( | |
| 100 new WEBPImageDecoder(alpha_option, color_behavior, max_decoded_bytes)); | |
| 101 } else if (MatchesICOSignature(contents) || MatchesCURSignature(contents)) { | |
| 102 decoder.reset( | |
| 103 new ICOImageDecoder(alpha_option, color_behavior, max_decoded_bytes)); | |
| 104 } else if (MatchesBMPSignature(contents)) { | |
| 105 decoder.reset( | |
| 106 new BMPImageDecoder(alpha_option, color_behavior, max_decoded_bytes)); | |
| 107 } | |
| 108 | 45 |
| 109 if (decoder) | 46 if (decoder) |
| 110 decoder->SetData(std::move(data), data_complete); | 47 decoder->SetData(std::move(data), data_complete); |
| 111 | 48 |
| 112 return decoder; | 49 return decoder; |
| 113 } | 50 } |
| 114 | 51 |
| 115 bool ImageDecoder::HasSufficientDataToSniffImageType(const SharedBuffer& data) { | 52 ImageDecoder::ImageDecoder(AlphaOption alpha_option, |
| 116 return data.size() >= kLongestSignatureLength; | 53 const ColorBehavior& color_behavior, |
| 54 size_t max_decoded_bytes) |
| 55 : premultiply_alpha_(alpha_option == kAlphaPremultiplied), |
| 56 color_behavior_(color_behavior), |
| 57 max_decoded_bytes_(max_decoded_bytes), |
| 58 purge_aggressively_(false), |
| 59 codec_() {} |
| 60 void ImageDecoder::OnSetData(SegmentReader* data) { |
| 61 if (data) { |
| 62 if (!codec_) { |
| 63 SkCodec* codec = SkCodec::NewFromData(data->GetAsSkData()); |
| 64 if (codec) |
| 65 codec_.reset(codec); |
| 66 else |
| 67 return; |
| 68 } |
| 69 SkImageInfo image_info = codec_->getInfo(); |
| 70 SetSize(image_info.width(), image_info.height()); |
| 71 } |
| 117 } | 72 } |
| 118 | 73 |
| 119 size_t ImageDecoder::FrameCount() { | 74 size_t ImageDecoder::FrameCount() { |
| 120 const size_t old_size = frame_buffer_cache_.size(); | 75 const size_t old_size = frame_buffer_cache_.size(); |
| 121 const size_t new_size = DecodeFrameCount(); | 76 const size_t new_size = codec_ ? codec_->getFrameCount() : 0; |
| 122 if (old_size != new_size) { | 77 if (old_size != new_size) { |
| 123 frame_buffer_cache_.resize(new_size); | 78 frame_buffer_cache_.resize(new_size); |
| 124 for (size_t i = old_size; i < new_size; ++i) { | 79 for (size_t i = old_size; i < new_size; ++i) { |
| 125 frame_buffer_cache_[i].SetPremultiplyAlpha(premultiply_alpha_); | 80 frame_buffer_cache_[i].SetPremultiplyAlpha(premultiply_alpha_); |
| 126 InitializeNewFrame(i); | 81 InitializeNewFrame(i); |
| 127 } | 82 } |
| 128 } | 83 } |
| 129 return new_size; | 84 return new_size; |
| 130 } | 85 } |
| 131 | 86 |
| 87 void ImageDecoder::Decode(size_t index) { |
| 88 if (!codec_) |
| 89 return; |
| 90 |
| 91 DCHECK(!Failed()); |
| 92 DCHECK_LT(index, frame_buffer_cache_.size()); |
| 93 |
| 94 UpdateAggressivePurging(index); |
| 95 SkImageInfo imageInfo = codec_->getInfo() |
| 96 .makeColorType(kN32_SkColorType) |
| 97 .makeColorSpace(ColorSpaceForSkImages()); |
| 98 |
| 99 SkCodec::Options options; |
| 100 options.fFrameIndex = index; |
| 101 options.fZeroInitialized = SkCodec::kYes_ZeroInitialized; |
| 102 |
| 103 ImageFrame& frame = frame_buffer_cache_[index]; |
| 104 if (frame.GetStatus() == ImageFrame::kFrameEmpty) { |
| 105 size_t required_previous_frame_index = frame.RequiredPreviousFrameIndex(); |
| 106 if (required_previous_frame_index == WTF::kNotFound) { |
| 107 frame.AllocatePixelData(Size().Width(), Size().Height(), |
| 108 ColorSpaceForSkImages()); |
| 109 } else { |
| 110 ImageFrame& required_previous_frame = |
| 111 frame_buffer_cache_[required_previous_frame_index]; |
| 112 |
| 113 if (required_previous_frame.GetStatus() != ImageFrame::kFrameComplete) |
| 114 Decode(required_previous_frame_index); |
| 115 |
| 116 // We try to reuse |required_previous_frame| as starting state to avoid |
| 117 // copying. If CanReusePreviousFrameBuffer returns false, we must copy |
| 118 // the data since |required_previous_frame| is necessary to decode this |
| 119 // or later frames. In that case copy the data instead. |
| 120 if ((!CanReusePreviousFrameBuffer(index) || |
| 121 !frame.TakeBitmapDataIfWritable(&required_previous_frame)) && |
| 122 !frame.CopyBitmapData(required_previous_frame)) { |
| 123 SetFailed(); |
| 124 return; |
| 125 } |
| 126 options.fHasPriorFrame = true; |
| 127 } |
| 128 } |
| 129 |
| 130 SkCodec::Result result = |
| 131 codec_->getPixels(imageInfo, frame.Bitmap().getPixels(), |
| 132 frame.Bitmap().rowBytes(), &options, nullptr, nullptr); |
| 133 switch (result) { |
| 134 case SkCodec::kSuccess: |
| 135 frame.SetPixelsChanged(true); |
| 136 frame.SetStatus(ImageFrame::kFrameComplete); |
| 137 PostDecodeProcessing(index); |
| 138 break; |
| 139 default: |
| 140 SetFailed(); |
| 141 return; |
| 142 } |
| 143 } |
| 144 |
| 145 bool ImageDecoder::SetFailed() { |
| 146 codec_ = nullptr; |
| 147 failed_ = true; |
| 148 return false; |
| 149 } |
| 150 |
| 132 ImageFrame* ImageDecoder::FrameBufferAtIndex(size_t index) { | 151 ImageFrame* ImageDecoder::FrameBufferAtIndex(size_t index) { |
| 133 if (index >= FrameCount()) | 152 if (index >= FrameCount()) |
| 134 return 0; | 153 return 0; |
| 135 | 154 |
| 136 ImageFrame* frame = &frame_buffer_cache_[index]; | 155 ImageFrame* frame = &frame_buffer_cache_[index]; |
| 137 if (frame->GetStatus() != ImageFrame::kFrameComplete) { | 156 if (frame->GetStatus() != ImageFrame::kFrameComplete) { |
| 138 PlatformInstrumentation::WillDecodeImage(FilenameExtension()); | 157 PlatformInstrumentation::WillDecodeImage(FilenameExtension()); |
| 139 Decode(index); | 158 Decode(index); |
| 140 PlatformInstrumentation::DidDecodeImage(); | 159 PlatformInstrumentation::DidDecodeImage(); |
| 141 } | 160 } |
| 142 | 161 |
| 143 if (!has_histogrammed_color_space_) { | 162 if (!has_histogrammed_color_space_) { |
| 144 BitmapImageMetrics::CountImageGammaAndGamut(embedded_color_space_.get()); | 163 BitmapImageMetrics::CountImageGammaAndGamut(embedded_color_space_.get()); |
| 145 has_histogrammed_color_space_ = true; | 164 has_histogrammed_color_space_ = true; |
| 146 } | 165 } |
| 147 | 166 |
| 148 frame->NotifyBitmapIfPixelsChanged(); | 167 frame->NotifyBitmapIfPixelsChanged(); |
| 149 return frame; | 168 return frame; |
| 150 } | 169 } |
| 151 | 170 |
| 152 bool ImageDecoder::FrameHasAlphaAtIndex(size_t index) const { | 171 bool ImageDecoder::FrameHasAlphaAtIndex(size_t index) const { |
| 153 return !FrameIsCompleteAtIndex(index) || | 172 return !FrameIsCompleteAtIndex(index) || |
| 154 frame_buffer_cache_[index].HasAlpha(); | 173 frame_buffer_cache_[index].HasAlpha(); |
| 155 } | 174 } |
| 156 | 175 |
| 157 bool ImageDecoder::FrameIsCompleteAtIndex(size_t index) const { | 176 bool ImageDecoder::FrameIsCompleteAtIndex(size_t index) const { |
| 158 // Animated images override this method to return the status based on the data | 177 if (!codec_) |
| 159 // received for the queried frame. | 178 return false; |
| 160 return IsAllDataReceived(); | 179 |
| 180 if (codec_->getFrameCount() <= (int)index) |
| 181 return false; |
| 182 |
| 183 if (frame_buffer_cache_.IsEmpty()) |
| 184 return false; |
| 185 |
| 186 return frame_buffer_cache_[0].GetStatus() == ImageFrame::kFrameComplete; |
| 187 } |
| 188 |
| 189 float ImageDecoder::FrameDurationAtIndex(size_t index) const { |
| 190 if (index < frame_buffer_cache_.size()) |
| 191 return frame_buffer_cache_[index].Duration(); |
| 192 return 0; |
| 161 } | 193 } |
| 162 | 194 |
| 163 bool ImageDecoder::FrameIsDecodedAtIndex(size_t index) const { | 195 bool ImageDecoder::FrameIsDecodedAtIndex(size_t index) const { |
| 164 return index < frame_buffer_cache_.size() && | 196 return index < frame_buffer_cache_.size() && |
| 165 frame_buffer_cache_[index].GetStatus() == ImageFrame::kFrameComplete; | 197 frame_buffer_cache_[index].GetStatus() == ImageFrame::kFrameComplete; |
| 166 } | 198 } |
| 167 | 199 |
| 168 size_t ImageDecoder::FrameBytesAtIndex(size_t index) const { | 200 size_t ImageDecoder::FrameBytesAtIndex(size_t index) const { |
| 169 if (index >= frame_buffer_cache_.size() || | 201 if (index >= frame_buffer_cache_.size() || |
| 170 frame_buffer_cache_[index].GetStatus() == ImageFrame::kFrameEmpty) | 202 frame_buffer_cache_[index].GetStatus() == ImageFrame::kFrameEmpty) |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 if (prev_buffer->GetDisposalMethod() == | 382 if (prev_buffer->GetDisposalMethod() == |
| 351 ImageFrame::kDisposeOverwriteBgcolor) { | 383 ImageFrame::kDisposeOverwriteBgcolor) { |
| 352 // We want to clear the previous frame to transparent, without | 384 // We want to clear the previous frame to transparent, without |
| 353 // affecting pixels in the image outside of the frame. | 385 // affecting pixels in the image outside of the frame. |
| 354 const IntRect& prev_rect = prev_buffer->OriginalFrameRect(); | 386 const IntRect& prev_rect = prev_buffer->OriginalFrameRect(); |
| 355 DCHECK(!prev_rect.Contains(IntRect(IntPoint(), Size()))); | 387 DCHECK(!prev_rect.Contains(IntRect(IntPoint(), Size()))); |
| 356 buffer->ZeroFillFrameRect(prev_rect); | 388 buffer->ZeroFillFrameRect(prev_rect); |
| 357 } | 389 } |
| 358 } | 390 } |
| 359 | 391 |
| 360 OnInitFrameBuffer(frame_index); | |
| 361 | |
| 362 // Update our status to be partially complete. | 392 // Update our status to be partially complete. |
| 363 buffer->SetStatus(ImageFrame::kFramePartial); | 393 buffer->SetStatus(ImageFrame::kFramePartial); |
| 364 | 394 |
| 365 return true; | 395 return true; |
| 366 } | 396 } |
| 367 | 397 |
| 398 int ImageDecoder::RepetitionCount() { |
| 399 if (!codec_) |
| 400 return kAnimationLoopOnce; |
| 401 |
| 402 DCHECK(!Failed()); |
| 403 |
| 404 // packets sent back by the webserver) not always. |
| 405 // SkCodec will parse forward in the file if the repetition count has not been |
| 406 // seen yet. |
| 407 int repetition_count = codec_->getRepetitionCount(); |
| 408 switch (repetition_count) { |
| 409 case 0: { |
| 410 size_t frame_count = codec_->getFrameCount(); |
| 411 if (IsAllDataReceived() && frame_count == 1) |
| 412 return kAnimationNone; |
| 413 return kAnimationLoopOnce; |
| 414 } |
| 415 case SkCodec::kRepetitionCountInfinite: |
| 416 return kAnimationLoopInfinite; |
| 417 default: |
| 418 return repetition_count; |
| 419 } |
| 420 } |
| 421 |
| 422 bool ImageDecoder::CanReusePreviousFrameBuffer(size_t index) const { |
| 423 DCHECK(index < frame_buffer_cache_.size()); |
| 424 |
| 425 // If the current frame and the next frame depend on the same frame, we cannot |
| 426 // reuse the old frame. We must preserve it for the next frame. |
| 427 // |
| 428 // However, if the current and next frame depend on different frames then we |
| 429 // know the current frame is the last one to use the frame it depends on. That |
| 430 // means the current frame can reuse the previous frame buffer. |
| 431 // |
| 432 // If we do not have information about the next frame yet, we cannot assume it |
| 433 // is safe to reuse the previous frame buffer. |
| 434 |
| 435 if (index + 1 >= frame_buffer_cache_.size()) |
| 436 return false; |
| 437 |
| 438 const ImageFrame& frame = frame_buffer_cache_[index]; |
| 439 size_t required_frame_index = frame.RequiredPreviousFrameIndex(); |
| 440 |
| 441 const ImageFrame& next_frame = frame_buffer_cache_[index + 1]; |
| 442 size_t next_required_frame_index = next_frame.RequiredPreviousFrameIndex(); |
| 443 |
| 444 return required_frame_index != next_required_frame_index; |
| 445 } |
| 446 |
| 368 void ImageDecoder::UpdateAggressivePurging(size_t index) { | 447 void ImageDecoder::UpdateAggressivePurging(size_t index) { |
| 369 if (purge_aggressively_) | 448 if (purge_aggressively_) |
| 370 return; | 449 return; |
| 371 | 450 |
| 372 // We don't want to cache so much that we cause a memory issue. | 451 // We don't want to cache so much that we cause a memory issue. |
| 373 // | 452 // |
| 374 // If we used a LRU cache we would fill it and then on next animation loop | 453 // If we used a LRU cache we would fill it and then on next animation loop |
| 375 // we would need to decode all the frames again -- the LRU would give no | 454 // we would need to decode all the frames again -- the LRU would give no |
| 376 // benefit and would consume more memory. | 455 // benefit and would consume more memory. |
| 377 // So instead, simply purge unused frames if caching all of the frames of | 456 // So instead, simply purge unused frames if caching all of the frames of |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 (prev_buffer->RequiredPreviousFrameIndex() == kNotFound)) | 527 (prev_buffer->RequiredPreviousFrameIndex() == kNotFound)) |
| 449 ? kNotFound | 528 ? kNotFound |
| 450 : prev_frame; | 529 : prev_frame; |
| 451 case ImageFrame::kDisposeOverwritePrevious: | 530 case ImageFrame::kDisposeOverwritePrevious: |
| 452 default: | 531 default: |
| 453 NOTREACHED(); | 532 NOTREACHED(); |
| 454 return kNotFound; | 533 return kNotFound; |
| 455 } | 534 } |
| 456 } | 535 } |
| 457 | 536 |
| 537 void ImageDecoder::InitializeNewFrame(size_t index) { |
| 538 DCHECK(codec_); |
| 539 |
| 540 ImageFrame& frame = frame_buffer_cache_[index]; |
| 541 // SkCodec does not inform us if only a portion of the image was updated |
| 542 // in the current frame. Because of this, rather than correctly filling in |
| 543 // the frame rect, we set the frame rect to be the image's full size. |
| 544 IntSize fullImageSize = Size(); |
| 545 frame.SetOriginalFrameRect(IntRect(IntPoint(), fullImageSize)); |
| 546 |
| 547 SkCodec::FrameInfo frame_info; |
| 548 memset(&frame_info, 0, sizeof(frame_info)); |
| 549 codec_->getFrameInfo(index, &frame_info); |
| 550 frame.SetDuration(frame_info.fDuration); |
| 551 frame.SetHasAlpha(!SkAlphaTypeIsOpaque(frame_info.fAlphaType)); |
| 552 size_t required_previous_frame_index = WTF::kNotFound; |
| 553 |
| 554 if (frame_info.fRequiredFrame > 0) { |
| 555 required_previous_frame_index = |
| 556 static_cast<size_t>(frame_info.fRequiredFrame); |
| 557 } |
| 558 |
| 559 frame.SetRequiredPreviousFrameIndex(required_previous_frame_index); |
| 560 |
| 561 // The disposal method is not required any more, but is left in place |
| 562 // for the other image decoders that do not yet rely on SkCodec. |
| 563 // For now, fill it with DisposeKeep. |
| 564 frame.SetDisposalMethod(ImageFrame::kDisposeKeep); |
| 565 } |
| 566 |
| 458 ImagePlanes::ImagePlanes() { | 567 ImagePlanes::ImagePlanes() { |
| 459 for (int i = 0; i < 3; ++i) { | 568 for (int i = 0; i < 3; ++i) { |
| 460 planes_[i] = 0; | 569 planes_[i] = 0; |
| 461 row_bytes_[i] = 0; | 570 row_bytes_[i] = 0; |
| 462 } | 571 } |
| 463 } | 572 } |
| 464 | 573 |
| 465 ImagePlanes::ImagePlanes(void* planes[3], const size_t row_bytes[3]) { | 574 ImagePlanes::ImagePlanes(void* planes[3], const size_t row_bytes[3]) { |
| 466 for (int i = 0; i < 3; ++i) { | 575 for (int i = 0; i < 3; ++i) { |
| 467 planes_[i] = planes[i]; | 576 planes_[i] = planes[i]; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 } | 667 } |
| 559 | 668 |
| 560 // For color spaces without an identifiable gamut, just fall through to | 669 // For color spaces without an identifiable gamut, just fall through to |
| 561 // sRGB. | 670 // sRGB. |
| 562 } | 671 } |
| 563 | 672 |
| 564 return SkColorSpace::MakeSRGB(); | 673 return SkColorSpace::MakeSRGB(); |
| 565 } | 674 } |
| 566 | 675 |
| 567 } // namespace blink | 676 } // namespace blink |
| OLD | NEW |