1 /*
2  * Copyright 2020 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "experimental/skrive/src/reader/StreamReader.h"
9 
10 #include "include/core/SkStream.h"
11 
12 #include <cstring>
13 
14 namespace skrive::internal {
15 
16 static constexpr char   kBinaryPrefix[]   = "FLARE";
17 static constexpr size_t kBinaryPrefixSize = sizeof(kBinaryPrefix) - 1;
18 
19 extern std::unique_ptr<StreamReader> MakeJsonStreamReader(const char[], size_t);
20 extern std::unique_ptr<StreamReader> MakeBinaryStreamReader(std::unique_ptr<SkStreamAsset>);
21 
Make(const sk_sp<SkData> & data)22 std::unique_ptr<StreamReader> StreamReader::Make(const sk_sp<SkData>& data) {
23     if (data->size() >= kBinaryPrefixSize &&
24         !memcmp(data->data(), kBinaryPrefix, kBinaryPrefixSize)) {
25         auto reader = SkMemoryStream::Make(data);
26         reader->skip(kBinaryPrefixSize);
27 
28         return MakeBinaryStreamReader(std::move(reader));
29     }
30 
31     return MakeJsonStreamReader(static_cast<const char*>(data->data()), data->size());
32 }
33 
Make(std::unique_ptr<SkStreamAsset> stream)34 std::unique_ptr<StreamReader> StreamReader::Make(std::unique_ptr<SkStreamAsset> stream) {
35     char buf[kBinaryPrefixSize];
36 
37     if (stream->read(buf, kBinaryPrefixSize) == kBinaryPrefixSize) {
38         if (!strncmp(buf, kBinaryPrefix, kBinaryPrefixSize)) {
39             // binary stream - we can stay in streaming mode
40             return MakeBinaryStreamReader(std::move(stream));
41         }
42     } else {
43         // stream too short to hold anything useful
44         return nullptr;
45     }
46 
47     if (!stream->rewind()) {
48         SkDebugf("!! failed to rewind stream.\n");
49         return nullptr;
50     }
51 
52     // read to memory to figure what we're dealing with
53     return StreamReader::Make(SkData::MakeFromStream(stream.get(), stream->getLength()));
54 }
55 
readV2(const char label[])56 SkV2 StreamReader::readV2(const char label[]) {
57     SkV2 v2{0,0};
58 
59     this->readFloatArray(label, reinterpret_cast<float*>(&v2), 2);
60 
61     return v2;
62 }
63 
readColor(const char label[])64 SkColor4f StreamReader::readColor(const char label[]) {
65     SkColor4f color{0,0,0,1};
66 
67     this->readFloatArray(label, reinterpret_cast<float*>(&color), 4);
68 
69     return color;
70 }
71 
72 } // namespace skrive::internal
73