• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SkParseEncodedOrigin(const uint8_t * data,size_t data_length,SkEncodedOrigin * orientation)11 bool 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