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