readable_font_data.cc revision 87114756046ef50158ad5bbf357bf40e05ebdd94
1/*
2 * Copyright 2011 Google Inc. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "sfntly/data/readable_font_data.h"
18#include "sfntly/data/writable_font_data.h"
19#include "sfntly/port/exception_type.h"
20
21namespace sfntly {
22
23ReadableFontData::ReadableFontData(ByteArray* array)
24    : FontData(array),
25      checksum_set_(false),
26      checksum_(0) {
27}
28
29ReadableFontData::~ReadableFontData() {}
30
31int64_t ReadableFontData::Checksum() {
32  // TODO(arthurhsu): IMPLEMENT: atomicity
33  if (!checksum_set_) {
34    ComputeChecksum();
35  }
36  return checksum_;
37}
38
39void ReadableFontData::SetCheckSumRanges(const IntegerList& ranges) {
40  checksum_range_ = ranges;
41  checksum_set_ = false;  // UNIMPLEMENTED: atomicity
42}
43
44int32_t ReadableFontData::ReadUByte(int32_t index) {
45  return 0xff & array_->Get(BoundOffset(index));
46}
47
48int32_t ReadableFontData::ReadByte(int32_t index) {
49  return (array_->Get(BoundOffset(index)) << 24) >> 24;
50}
51
52int32_t ReadableFontData::ReadBytes(int32_t index,
53                                    ByteVector* b,
54                                    int32_t offset,
55                                    int32_t length) {
56  return array_->Get(BoundOffset(index), b, offset, BoundLength(index, length));
57}
58
59int32_t ReadableFontData::ReadChar(int32_t index) {
60  return ReadUByte(index);
61}
62
63int32_t ReadableFontData::ReadUShort(int32_t index) {
64  return 0xffff & (ReadUByte(index) << 8 | ReadUByte(index + 1));
65}
66
67int32_t ReadableFontData::ReadShort(int32_t index) {
68  return ((ReadByte(index) << 8 | ReadUByte(index + 1)) << 16) >> 16;
69}
70
71int32_t ReadableFontData::ReadUInt24(int32_t index) {
72  return 0xffffff & (ReadUByte(index) << 16 |
73                     ReadUByte(index + 1) << 8 |
74                     ReadUByte(index + 2));
75}
76
77int64_t ReadableFontData::ReadULong(int32_t index) {
78  return 0xffffffffL & (ReadUByte(index) << 24 |
79                        ReadUByte(index + 1) << 16 |
80                        ReadUByte(index + 2) << 8 |
81                        ReadUByte(index + 3));
82}
83
84int32_t ReadableFontData::ReadULongAsInt(int32_t index) {
85  int64_t ulong = ReadULong(index);
86#if !defined (SFNTLY_NO_EXCEPTION)
87  if ((ulong & 0x80000000) == 0x80000000) {
88    throw ArithmeticException("Long value too large to fit into an integer.");
89  }
90#endif
91  return ((int32_t)ulong) & ~0x80000000;
92}
93
94int32_t ReadableFontData::ReadLong(int32_t index) {
95  return ReadByte(index) << 24 |
96         ReadUByte(index + 1) << 16 |
97         ReadUByte(index + 2) << 8 |
98         ReadUByte(index + 3);
99}
100
101int32_t ReadableFontData::ReadFixed(int32_t index) {
102  return ReadLong(index);
103}
104
105int64_t ReadableFontData::ReadDateTimeAsLong(int32_t index) {
106  return (int64_t)ReadULong(index) << 32 | ReadULong(index + 4);
107}
108
109int32_t ReadableFontData::ReadFWord(int32_t index) {
110  return ReadShort(index);
111}
112
113int32_t ReadableFontData::ReadFUFWord(int32_t index) {
114  return ReadUShort(index);
115}
116
117int32_t ReadableFontData::CopyTo(OutputStream* os) {
118  return array_->CopyTo(os, BoundOffset(0), Length());
119}
120
121int32_t ReadableFontData::CopyTo(WritableFontData* wfd) {
122  return array_->CopyTo(wfd->BoundOffset(0),
123                        wfd->array_,
124                        BoundOffset(0),
125                        Length());
126}
127
128int32_t ReadableFontData::CopyTo(ByteArray* ba) {
129  return array_->CopyTo(ba, BoundOffset(0), Length());
130}
131
132CALLER_ATTACH FontData* ReadableFontData::Slice(int32_t offset,
133                                                int32_t length) {
134  if (offset < 0 || offset + length > Size()) {
135    return NULL;
136  }
137  FontDataPtr slice = new ReadableFontData(this, offset, length);
138  // Note: exception not ported because the condition is always false in C++.
139  // if (slice == null) { throw new IndexOutOfBoundsException( ...
140  return slice.Detach();
141}
142
143CALLER_ATTACH FontData* ReadableFontData::Slice(int32_t offset) {
144  if (offset < 0 || offset > Size()) {
145    return NULL;
146  }
147  FontDataPtr slice = new ReadableFontData(this, offset);
148  // Note: exception not ported because the condition is always false in C++.
149  // if (slice == null) { throw new IndexOutOfBoundsException( ...
150  return slice.Detach();
151}
152
153ReadableFontData::ReadableFontData(ReadableFontData* data, int32_t offset)
154    : FontData(data, offset),
155      checksum_set_(false),
156      checksum_(0) {
157}
158
159ReadableFontData::ReadableFontData(ReadableFontData* data,
160                                   int32_t offset,
161                                   int32_t length)
162    : FontData(data, offset, length),
163      checksum_set_(false),
164      checksum_(0) {
165}
166
167/* OpenType checksum
168ULONG
169CalcTableChecksum(ULONG *Table, ULONG Length)
170{
171ULONG Sum = 0L;
172ULONG *Endptr = Table+((Length+3) & ~3) / sizeof(ULONG);
173while (Table < EndPtr)
174  Sum += *Table++;
175return Sum;
176}
177*/
178void ReadableFontData::ComputeChecksum() {
179  // TODO(arthurhsu): IMPLEMENT: synchronization/atomicity
180  int64_t sum = 0;
181  if (checksum_range_.empty()) {
182    sum = ComputeCheckSum(0, Length());
183  } else {
184    for (uint32_t low_bound_index = 0; low_bound_index < checksum_range_.size();
185         low_bound_index += 2) {
186      int32_t low_bound = checksum_range_[low_bound_index];
187      int32_t high_bound = (low_bound_index == checksum_range_.size() - 1) ?
188                                Length() :
189                                checksum_range_[low_bound_index + 1];
190      sum += ComputeCheckSum(low_bound, high_bound);
191    }
192  }
193
194  checksum_ = sum & 0xffffffffL;
195  checksum_set_ = true;
196}
197
198int64_t ReadableFontData::ComputeCheckSum(int32_t low_bound,
199                                          int32_t high_bound) {
200  int64_t sum = 0;
201  // Checksum all whole 4-byte chunks.
202  for (int32_t i = low_bound; i <= high_bound - 4; i += 4) {
203    sum += ReadULong(i);
204  }
205
206  // Add last fragment if not 4-byte multiple
207  int32_t off = high_bound & -4;
208  if (off < high_bound) {
209    int32_t b3 = ReadUByte(off);
210    int32_t b2 = (off + 1 < high_bound) ? ReadUByte(off + 1) : 0;
211    int32_t b1 = (off + 2 < high_bound) ? ReadUByte(off + 2) : 0;
212    int32_t b0 = 0;
213    sum += (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
214  }
215  return sum;
216}
217
218}  // namespace sfntly
219