1/*
2 * Copyright 2018 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 "include/core/SkTypes.h"
9#include "src/codec/SkCodecPriv.h"
10
11bool SkParseEncodedOrigin(const uint8_t* data, size_t data_length, SkEncodedOrigin* orientation) {
12 SkASSERT(orientation);
13 bool littleEndian;
14 // We need eight bytes to read the endian marker and the offset, below.
15 if (data_length < 8 || !is_valid_endian_marker(data, &littleEndian)) {
16 return false;
17 }
18
19 auto getEndianInt = [](const uint8_t* data, bool littleEndian) -> uint32_t {
20 if (littleEndian) {
21 return (data[3] << 24) | (data[2] << 16) | (data[1] << 8) | (data[0]);
22 }
23
24 return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3]);
25 };
26
27 // Get the offset from the start of the marker.
28 // Though this only reads four bytes, use a larger int in case it overflows.
29 uint64_t offset = getEndianInt(data + 4, littleEndian);
30
31 // Require that the marker is at least large enough to contain the number of entries.
32 if (data_length < offset + 2) {
33 return false;
34 }
35 uint32_t numEntries = get_endian_short(data + offset, littleEndian);
36
37 // Tag (2 bytes), Datatype (2 bytes), Number of elements (4 bytes), Data (4 bytes)
38 const uint32_t kEntrySize = 12;
39 const auto max = SkTo<uint32_t>((data_length - offset - 2) / kEntrySize);
40 numEntries = std::min(numEntries, max);
41
42 // Advance the data to the start of the entries.
43 data += offset + 2;
44
45 const uint16_t kOriginTag = 0x112;
46 const uint16_t kOriginType = 3;
47 for (uint32_t i = 0; i < numEntries; i++, data += kEntrySize) {
48 uint16_t tag = get_endian_short(data, littleEndian);
49 uint16_t type = get_endian_short(data + 2, littleEndian);
50 uint32_t count = getEndianInt(data + 4, littleEndian);
51 if (kOriginTag == tag && kOriginType == type && 1 == count) {
52 uint16_t val = get_endian_short(data + 8, littleEndian);
53 if (0 < val && val <= kLast_SkEncodedOrigin) {
54 *orientation = (SkEncodedOrigin) val;
55 return true;
56 }
57 }
58 }
59
60 return false;
61}
62