1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/codec/SkCodec.h" 9cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h" 10cb93a386Sopenharmony_ci#include "include/core/SkData.h" 11cb93a386Sopenharmony_ci#include "include/core/SkImageInfo.h" 12cb93a386Sopenharmony_ci#include "include/core/SkRefCnt.h" 13cb93a386Sopenharmony_ci#include "include/core/SkStream.h" 14cb93a386Sopenharmony_ci#include "include/private/SkTemplates.h" 15cb93a386Sopenharmony_ci#include "tests/Test.h" 16cb93a386Sopenharmony_ci#include "tools/Resources.h" 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_ci#include <cstring> 19cb93a386Sopenharmony_ci#include <initializer_list> 20cb93a386Sopenharmony_ci#include <memory> 21cb93a386Sopenharmony_ci#include <utility> 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_cinamespace { 24cb93a386Sopenharmony_ci// This class wraps another SkStream. It does not own the underlying stream, so 25cb93a386Sopenharmony_ci// that the underlying stream can be reused starting from where the first 26cb93a386Sopenharmony_ci// client left off. This mimics Android's JavaInputStreamAdaptor. 27cb93a386Sopenharmony_ciclass UnowningStream : public SkStream { 28cb93a386Sopenharmony_cipublic: 29cb93a386Sopenharmony_ci explicit UnowningStream(SkStream* stream) 30cb93a386Sopenharmony_ci : fStream(stream) 31cb93a386Sopenharmony_ci {} 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_ci size_t read(void* buf, size_t bytes) override { 34cb93a386Sopenharmony_ci return fStream->read(buf, bytes); 35cb93a386Sopenharmony_ci } 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_ci bool rewind() override { 38cb93a386Sopenharmony_ci return fStream->rewind(); 39cb93a386Sopenharmony_ci } 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ci bool isAtEnd() const override { 42cb93a386Sopenharmony_ci return fStream->isAtEnd(); 43cb93a386Sopenharmony_ci } 44cb93a386Sopenharmony_ciprivate: 45cb93a386Sopenharmony_ci SkStream* fStream; // Unowned. 46cb93a386Sopenharmony_ci}; 47cb93a386Sopenharmony_ci} // namespace 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ci// Test that some SkCodecs do not attempt to read input beyond the logical 50cb93a386Sopenharmony_ci// end of the data. Some other SkCodecs do, but some Android apps rely on not 51cb93a386Sopenharmony_ci// doing so for PNGs. Test on other formats that work. 52cb93a386Sopenharmony_ciDEF_TEST(Codec_end, r) { 53cb93a386Sopenharmony_ci for (const char* path : { "images/plane.png", 54cb93a386Sopenharmony_ci "images/yellow_rose.png", 55cb93a386Sopenharmony_ci "images/plane_interlaced.png", 56cb93a386Sopenharmony_ci "images/mandrill.wbmp", 57cb93a386Sopenharmony_ci "images/randPixels.bmp", 58cb93a386Sopenharmony_ci }) { 59cb93a386Sopenharmony_ci sk_sp<SkData> data = GetResourceAsData(path); 60cb93a386Sopenharmony_ci if (!data) { 61cb93a386Sopenharmony_ci continue; 62cb93a386Sopenharmony_ci } 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_ci const int kNumImages = 2; 65cb93a386Sopenharmony_ci const size_t size = data->size(); 66cb93a386Sopenharmony_ci sk_sp<SkData> multiData = SkData::MakeUninitialized(size * kNumImages); 67cb93a386Sopenharmony_ci void* dst = multiData->writable_data(); 68cb93a386Sopenharmony_ci for (int i = 0; i < kNumImages; i++) { 69cb93a386Sopenharmony_ci memcpy(SkTAddOffset<void>(dst, size * i), data->data(), size); 70cb93a386Sopenharmony_ci } 71cb93a386Sopenharmony_ci data.reset(); 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ci SkMemoryStream stream(std::move(multiData)); 74cb93a386Sopenharmony_ci for (int i = 0; i < kNumImages; ++i) { 75cb93a386Sopenharmony_ci std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream( 76cb93a386Sopenharmony_ci std::make_unique<UnowningStream>(&stream))); 77cb93a386Sopenharmony_ci if (!codec) { 78cb93a386Sopenharmony_ci ERRORF(r, "Failed to create a codec from %s, iteration %i", path, i); 79cb93a386Sopenharmony_ci continue; 80cb93a386Sopenharmony_ci } 81cb93a386Sopenharmony_ci 82cb93a386Sopenharmony_ci auto info = codec->getInfo().makeColorType(kN32_SkColorType); 83cb93a386Sopenharmony_ci SkBitmap bm; 84cb93a386Sopenharmony_ci bm.allocPixels(info); 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_ci auto result = codec->getPixels(bm.info(), bm.getPixels(), bm.rowBytes()); 87cb93a386Sopenharmony_ci if (result != SkCodec::kSuccess) { 88cb93a386Sopenharmony_ci ERRORF(r, "Failed to getPixels from %s, iteration %i error %i", path, i, result); 89cb93a386Sopenharmony_ci continue; 90cb93a386Sopenharmony_ci } 91cb93a386Sopenharmony_ci } 92cb93a386Sopenharmony_ci } 93cb93a386Sopenharmony_ci} 94