1464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com/* 2464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Copyright 2011 Google Inc. All Rights Reserved. 3464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * 4464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Licensed under the Apache License, Version 2.0 (the "License"); 5464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * you may not use this file except in compliance with the License. 6464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * You may obtain a copy of the License at 7464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * 8464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * http://www.apache.org/licenses/LICENSE-2.0 9464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * 10464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Unless required by applicable law or agreed to in writing, software 11464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * distributed under the License is distributed on an "AS IS" BASIS, 12464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * See the License for the specific language governing permissions and 14464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * limitations under the License. 15464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com */ 16464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 17464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include "sfntly/data/readable_font_data.h" 18760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com 19760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com#include <stdio.h> 20760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com 2109f3dda615ba59d0b686e8c36f1e8426b9235746arthurhsu@google.com#include "sfntly/data/memory_byte_array.h" 22464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include "sfntly/data/writable_font_data.h" 23464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include "sfntly/port/exception_type.h" 24464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 25464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comnamespace sfntly { 26464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 27464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comReadableFontData::ReadableFontData(ByteArray* array) 28246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com : FontData(array), 29246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com checksum_set_(false), 30246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com checksum_(0) { 31464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 32464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 33246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comReadableFontData::~ReadableFontData() {} 34464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 3532a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com// TODO(arthurhsu): re-investigate the memory model of this function. It's 3632a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com// not too useful without copying, but it's not performance 3732a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com// savvy to do copying. 3832a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.comCALLER_ATTACH 3932a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.comReadableFontData* ReadableFontData::CreateReadableFontData(ByteVector* b) { 4032a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com assert(b); 4132a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com ByteArrayPtr ba = new MemoryByteArray(b->size()); 4232a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com ba->Put(0, b); 4332a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com ReadableFontDataPtr wfd = new ReadableFontData(ba); 4432a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com return wfd.Detach(); 4532a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com} 4632a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com 47246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint64_t ReadableFontData::Checksum() { 4809f3dda615ba59d0b686e8c36f1e8426b9235746arthurhsu@google.com AutoLock lock(checksum_lock_); 49464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com if (!checksum_set_) { 50246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com ComputeChecksum(); 51464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 52464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return checksum_; 53464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 54464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 55246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid ReadableFontData::SetCheckSumRanges(const IntegerList& ranges) { 56464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com checksum_range_ = ranges; 57464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com checksum_set_ = false; // UNIMPLEMENTED: atomicity 58464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 59464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 60246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ReadableFontData::ReadUByte(int32_t index) { 6132a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com int32_t b = array_->Get(BoundOffset(index)); 6232a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com#if !defined (SFNTLY_NO_EXCEPTION) 6332a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com if (b < 0) { 6432a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com throw IndexOutOfBoundException( 6532a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com "Index attempted to be read from is out of bounds", index); 6632a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com } 6732a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com#endif 6832a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com return b; 69464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 70464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 71246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ReadableFontData::ReadByte(int32_t index) { 7232a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com int32_t b = array_->Get(BoundOffset(index)); 7332a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com#if !defined (SFNTLY_NO_EXCEPTION) 7432a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com if (b < 0) { 7532a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com throw IndexOutOfBoundException( 7632a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com "Index attempted to be read from is out of bounds", index); 7732a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com } 7832a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com#endif 7932a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com return (b << 24) >> 24; 80464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 81464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 82246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ReadableFontData::ReadBytes(int32_t index, 8332a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com byte_t* b, 84246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com int32_t offset, 85246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com int32_t length) { 86246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return array_->Get(BoundOffset(index), b, offset, BoundLength(index, length)); 87464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 88464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 89246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ReadableFontData::ReadChar(int32_t index) { 90246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return ReadUByte(index); 91464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 92464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 93246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ReadableFontData::ReadUShort(int32_t index) { 94246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return 0xffff & (ReadUByte(index) << 8 | ReadUByte(index + 1)); 95464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 96464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 97246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ReadableFontData::ReadShort(int32_t index) { 98246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return ((ReadByte(index) << 8 | ReadUByte(index + 1)) << 16) >> 16; 99464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 100464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 101246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ReadableFontData::ReadUInt24(int32_t index) { 102246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return 0xffffff & (ReadUByte(index) << 16 | 103246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com ReadUByte(index + 1) << 8 | 104246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com ReadUByte(index + 2)); 105464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 106464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 107246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint64_t ReadableFontData::ReadULong(int32_t index) { 108246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return 0xffffffffL & (ReadUByte(index) << 24 | 109246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com ReadUByte(index + 1) << 16 | 110246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com ReadUByte(index + 2) << 8 | 111246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com ReadUByte(index + 3)); 112464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 113464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 114246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ReadableFontData::ReadULongAsInt(int32_t index) { 115246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com int64_t ulong = ReadULong(index); 1160e411afcef9fc211b3f8f70d31bc1dfa4c0f85d3arthurhsu@google.com#if !defined (SFNTLY_NO_EXCEPTION) 117464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com if ((ulong & 0x80000000) == 0x80000000) { 118464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com throw ArithmeticException("Long value too large to fit into an integer."); 119464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 1200e411afcef9fc211b3f8f70d31bc1dfa4c0f85d3arthurhsu@google.com#endif 12132a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com return static_cast<int32_t>(ulong); 122464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 123464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 124333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.comint64_t ReadableFontData::ReadULongLE(int32_t index) { 125333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com return 0xffffffffL & (ReadUByte(index) | 126333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com ReadUByte(index + 1) << 8 | 127333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com ReadUByte(index + 2) << 16 | 128333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com ReadUByte(index + 3) << 24); 129333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com} 130333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com 131246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ReadableFontData::ReadLong(int32_t index) { 132246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return ReadByte(index) << 24 | 133246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com ReadUByte(index + 1) << 16 | 134246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com ReadUByte(index + 2) << 8 | 135246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com ReadUByte(index + 3); 136464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 137464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 138246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ReadableFontData::ReadFixed(int32_t index) { 139246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return ReadLong(index); 140464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 141464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 142246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint64_t ReadableFontData::ReadDateTimeAsLong(int32_t index) { 143246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return (int64_t)ReadULong(index) << 32 | ReadULong(index + 4); 144464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 145464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 146246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ReadableFontData::ReadFWord(int32_t index) { 147246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return ReadShort(index); 148464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 149464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 150246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ReadableFontData::ReadFUFWord(int32_t index) { 151246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return ReadUShort(index); 152464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 153464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 154246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ReadableFontData::CopyTo(OutputStream* os) { 155246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return array_->CopyTo(os, BoundOffset(0), Length()); 156464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 157464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 158246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ReadableFontData::CopyTo(WritableFontData* wfd) { 159246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return array_->CopyTo(wfd->BoundOffset(0), 160246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com wfd->array_, 161246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com BoundOffset(0), 162246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com Length()); 163464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 164464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 165246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ReadableFontData::CopyTo(ByteArray* ba) { 166246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return array_->CopyTo(ba, BoundOffset(0), Length()); 167464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 168464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 169760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.comint32_t ReadableFontData::SearchUShort(int32_t start_index, 170760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t start_offset, 171760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t end_index, 172760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t end_offset, 173760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t length, 174760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t key) { 175760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t location = 0; 176760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t bottom = 0; 177760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t top = length; 178760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com while (top != bottom) { 179760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com location = (top + bottom) / 2; 180760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t location_start = ReadUShort(start_index + location * start_offset); 181760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com if (key < location_start) { 182760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com // location is below current location 183760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com top = location; 184760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com } else { 185760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com // is key below the upper bound? 186760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t location_end = ReadUShort(end_index + location * end_offset); 187760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com#if defined (SFNTLY_DEBUG_FONTDATA) 188760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com fprintf(stderr, "**start: %d; end: %d\n", location_start, location_end); 189760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com#endif 190760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com if (key <= location_end) { 191760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com return location; 192760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com } else { 193760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com // location is above the current location 194760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com bottom = location + 1; 195760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com } 196760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com } 197760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com } 198760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com return -1; 199760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com} 200760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com 2016b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.comint32_t ReadableFontData::SearchUShort(int32_t start_index, 2026b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com int32_t start_offset, 2036b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com int32_t length, 2046b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com int32_t key) { 2056b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com int32_t location = 0; 2066b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com int32_t bottom = 0; 2076b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com int32_t top = length; 2086b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com while (top != bottom) { 2096b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com location = (top + bottom) / 2; 2106b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com int32_t location_start = ReadUShort(start_index + location * start_offset); 2116b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com if (key < location_start) { 2126b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com // location is below current location 2136b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com top = location; 2146b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com } else if (key > location_start) { 2156b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com // location is above current location 2166b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com bottom = location + 1; 2176b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com } else { 2186b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com return location; 2196b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com } 2206b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com } 2216b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com return -1; 2226b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com} 2236b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com 224760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.comint32_t ReadableFontData::SearchULong(int32_t start_index, 225760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t start_offset, 226760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t end_index, 227760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t end_offset, 228760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t length, 229760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t key) { 230760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t location = 0; 231760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t bottom = 0; 232760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t top = length; 233760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com while (top != bottom) { 234760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com location = (top + bottom) / 2; 235760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t location_start = ReadULongAsInt(start_index 236760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com + location * start_offset); 237760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com if (key < location_start) { 238760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com // location is below current location 239760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com top = location; 240760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com } else { 241760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com // is key below the upper bound? 242760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com int32_t location_end = ReadULongAsInt(end_index + location * end_offset); 243760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com#if defined (SFNTLY_DEBUG_FONTDATA) 244760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com fprintf(stderr, "**start: %d; end: %d\n", location_start, location_end); 245760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com#endif 246760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com if (key <= location_end) { 247760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com return location; 248760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com } else { 249760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com // location is above the current location 250760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com bottom = location + 1; 251760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com } 252760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com } 253760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com } 254760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com return -1; 255760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com} 256760e6005f25f8d45d413d286ab5a38263ece63addfilimon@google.com 257246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCALLER_ATTACH FontData* ReadableFontData::Slice(int32_t offset, 258464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com int32_t length) { 259246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com if (offset < 0 || offset + length > Size()) { 260144e5cb2b372c30d8a4b90267b52646368dd89fcarthurhsu@google.com#if !defined (SFNTLY_NO_EXCEPTION) 261144e5cb2b372c30d8a4b90267b52646368dd89fcarthurhsu@google.com throw IndexOutOfBoundsException( 262144e5cb2b372c30d8a4b90267b52646368dd89fcarthurhsu@google.com "Attempt to bind data outside of its limits"); 263144e5cb2b372c30d8a4b90267b52646368dd89fcarthurhsu@google.com#endif 264464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return NULL; 265464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 266464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com FontDataPtr slice = new ReadableFontData(this, offset, length); 267246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return slice.Detach(); 268464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 269464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 270246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCALLER_ATTACH FontData* ReadableFontData::Slice(int32_t offset) { 271246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com if (offset < 0 || offset > Size()) { 272144e5cb2b372c30d8a4b90267b52646368dd89fcarthurhsu@google.com#if !defined (SFNTLY_NO_EXCEPTION) 273144e5cb2b372c30d8a4b90267b52646368dd89fcarthurhsu@google.com throw IndexOutOfBoundsException( 274144e5cb2b372c30d8a4b90267b52646368dd89fcarthurhsu@google.com "Attempt to bind data outside of its limits"); 275144e5cb2b372c30d8a4b90267b52646368dd89fcarthurhsu@google.com#endif 276464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return NULL; 277464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 278464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com FontDataPtr slice = new ReadableFontData(this, offset); 279246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return slice.Detach(); 280246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com} 281246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com 282246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comReadableFontData::ReadableFontData(ReadableFontData* data, int32_t offset) 283246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com : FontData(data, offset), 284246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com checksum_set_(false), 285246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com checksum_(0) { 286246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com} 287246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com 288246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comReadableFontData::ReadableFontData(ReadableFontData* data, 289246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com int32_t offset, 290246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com int32_t length) 291246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com : FontData(data, offset, length), 292246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com checksum_set_(false), 293246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com checksum_(0) { 294246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com} 295246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com 296246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid ReadableFontData::ComputeChecksum() { 297246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com // TODO(arthurhsu): IMPLEMENT: synchronization/atomicity 298246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com int64_t sum = 0; 299246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com if (checksum_range_.empty()) { 300246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com sum = ComputeCheckSum(0, Length()); 301246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com } else { 302246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com for (uint32_t low_bound_index = 0; low_bound_index < checksum_range_.size(); 303246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com low_bound_index += 2) { 304246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com int32_t low_bound = checksum_range_[low_bound_index]; 305246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com int32_t high_bound = (low_bound_index == checksum_range_.size() - 1) ? 306246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com Length() : 307246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com checksum_range_[low_bound_index + 1]; 308246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com sum += ComputeCheckSum(low_bound, high_bound); 309246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com } 310246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com } 311246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com 312246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com checksum_ = sum & 0xffffffffL; 313246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com checksum_set_ = true; 314246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com} 315246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com 316246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint64_t ReadableFontData::ComputeCheckSum(int32_t low_bound, 317246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com int32_t high_bound) { 318246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com int64_t sum = 0; 319c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com // Checksum all whole 4-byte chunks. 320c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com for (int32_t i = low_bound; i <= high_bound - 4; i += 4) { 321c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com sum += ReadULong(i); 322c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com } 323c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com 324c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com // Add last fragment if not 4-byte multiple 325c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com int32_t off = high_bound & -4; 326c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com if (off < high_bound) { 327c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com int32_t b3 = ReadUByte(off); 328c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com int32_t b2 = (off + 1 < high_bound) ? ReadUByte(off + 1) : 0; 329c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com int32_t b1 = (off + 2 < high_bound) ? ReadUByte(off + 2) : 0; 330c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com int32_t b0 = 0; 331246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com sum += (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; 332246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com } 333246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return sum; 334464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 335464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 336464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} // namespace sfntly 337