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/table/truetype/loca_table.h"
18 #include "sfntly/port/exception_type.h"
19
20 namespace sfntly {
21 /******************************************************************************
22 * LocaTable class
23 ******************************************************************************/
~LocaTable()24 LocaTable::~LocaTable() {}
25
GlyphOffset(int32_t glyph_id)26 int32_t LocaTable::GlyphOffset(int32_t glyph_id) {
27 if (glyph_id < 0 || glyph_id >= num_glyphs_) {
28 #if !defined (SFNTLY_NO_EXCEPTION)
29 throw IndexOutOfBoundException("Glyph ID is out of bounds.");
30 #endif
31 return 0;
32 }
33 return Loca(glyph_id);
34 }
35
GlyphLength(int32_t glyph_id)36 int32_t LocaTable::GlyphLength(int32_t glyph_id) {
37 if (glyph_id < 0 || glyph_id >= num_glyphs_) {
38 #if !defined (SFNTLY_NO_EXCEPTION)
39 throw IndexOutOfBoundException("Glyph ID is out of bounds.");
40 #endif
41 return 0;
42 }
43 int32_t glyph_val = Loca(glyph_id);
44 int32_t glyph_next_val = Loca(glyph_id + 1);
45 if (glyph_val < 0 || glyph_next_val < 0 || glyph_next_val <= glyph_val)
46 return 0;
47 return glyph_next_val - glyph_val;
48 }
49
NumLocas()50 int32_t LocaTable::NumLocas() {
51 return num_glyphs_ + 1;
52 }
53
Loca(int32_t index)54 int32_t LocaTable::Loca(int32_t index) {
55 if (index > num_glyphs_) {
56 #if !defined (SFNTLY_NO_EXCEPTION)
57 throw IndexOutOfBoundException();
58 #endif
59 return 0;
60 }
61 if (format_version_ == IndexToLocFormat::kShortOffset) {
62 return 2 * data_->ReadUShort(index * DataSize::kUSHORT);
63 }
64 return data_->ReadULongAsInt(index * DataSize::kULONG);
65 }
66
LocaTable(Header * header,ReadableFontData * data,int32_t format_version,int32_t num_glyphs)67 LocaTable::LocaTable(Header* header,
68 ReadableFontData* data,
69 int32_t format_version,
70 int32_t num_glyphs)
71 : Table(header, data),
72 format_version_(format_version),
73 num_glyphs_(num_glyphs) {
74 }
75
76 /******************************************************************************
77 * LocaTable::Iterator class
78 ******************************************************************************/
LocaIterator(LocaTable * table)79 LocaTable::LocaIterator::LocaIterator(LocaTable* table)
80 : PODIterator<int32_t, LocaTable>(table), index_(-1) {
81 }
82
HasNext()83 bool LocaTable::LocaIterator::HasNext() {
84 return index_ <= container()->num_glyphs_;
85 }
86
Next()87 int32_t LocaTable::LocaIterator::Next() {
88 return container()->Loca(index_++);
89 }
90
91 /******************************************************************************
92 * LocaTable::Builder class
93 ******************************************************************************/
Builder(Header * header,WritableFontData * data)94 LocaTable::Builder::Builder(Header* header, WritableFontData* data)
95 : Table::Builder(header, data),
96 format_version_(IndexToLocFormat::kLongOffset),
97 num_glyphs_(-1) {
98 }
99
Builder(Header * header,ReadableFontData * data)100 LocaTable::Builder::Builder(Header* header, ReadableFontData* data)
101 : Table::Builder(header, data),
102 format_version_(IndexToLocFormat::kLongOffset),
103 num_glyphs_(-1) {
104 }
105
~Builder()106 LocaTable::Builder::~Builder() {}
107
108 CALLER_ATTACH
CreateBuilder(Header * header,WritableFontData * data)109 LocaTable::Builder* LocaTable::Builder::CreateBuilder(Header* header,
110 WritableFontData* data) {
111 Ptr<LocaTable::Builder> builder;
112 builder = new LocaTable::Builder(header, data);
113 return builder.Detach();
114 }
115
LocaList()116 std::vector<int32_t>* LocaTable::Builder::LocaList() {
117 return GetLocaList();
118 }
119
SetLocaList(std::vector<int32_t> * list)120 void LocaTable::Builder::SetLocaList(std::vector<int32_t>* list) {
121 loca_.clear();
122 if (list) {
123 loca_ = *list;
124 set_model_changed();
125 }
126 }
127
GlyphOffset(int32_t glyph_id)128 int32_t LocaTable::Builder::GlyphOffset(int32_t glyph_id) {
129 if (CheckGlyphRange(glyph_id) == -1) {
130 return 0;
131 }
132 return GetLocaList()->at(glyph_id);
133 }
134
GlyphLength(int32_t glyph_id)135 int32_t LocaTable::Builder::GlyphLength(int32_t glyph_id) {
136 if (CheckGlyphRange(glyph_id) == -1) {
137 return 0;
138 }
139 return GetLocaList()->at(glyph_id + 1) - GetLocaList()->at(glyph_id);
140 }
141
SetNumGlyphs(int32_t num_glyphs)142 void LocaTable::Builder::SetNumGlyphs(int32_t num_glyphs) {
143 assert(num_glyphs >= 0);
144 num_glyphs_ = num_glyphs;
145 }
146
NumGlyphs()147 int32_t LocaTable::Builder::NumGlyphs() {
148 return LastGlyphIndex() - 1;
149 }
150
Revert()151 void LocaTable::Builder::Revert() {
152 loca_.clear();
153 set_model_changed(false);
154 }
155
NumLocas()156 int32_t LocaTable::Builder::NumLocas() {
157 return GetLocaList()->size();
158 }
159
Loca(int32_t index)160 int32_t LocaTable::Builder::Loca(int32_t index) {
161 return GetLocaList()->at(index);
162 }
163
164 CALLER_ATTACH
SubBuildTable(ReadableFontData * data)165 FontDataTable* LocaTable::Builder::SubBuildTable(ReadableFontData* data) {
166 FontDataTablePtr table =
167 new LocaTable(header(), data, format_version_, num_glyphs_);
168 return table.Detach();
169 }
170
SubDataSet()171 void LocaTable::Builder::SubDataSet() {
172 Initialize(InternalReadData());
173 }
174
SubDataSizeToSerialize()175 int32_t LocaTable::Builder::SubDataSizeToSerialize() {
176 if (loca_.empty()) {
177 return 0;
178 }
179 if (format_version_ == IndexToLocFormat::kLongOffset) {
180 return loca_.size() * DataSize::kULONG;
181 }
182 return loca_.size() * DataSize::kUSHORT;
183 }
184
SubReadyToSerialize()185 bool LocaTable::Builder::SubReadyToSerialize() {
186 return !loca_.empty();
187 }
188
SubSerialize(WritableFontData * new_data)189 int32_t LocaTable::Builder::SubSerialize(WritableFontData* new_data) {
190 int32_t size = 0;
191 for (std::vector<int32_t>::iterator l = loca_.begin(), end = loca_.end();
192 l != end; ++l) {
193 if (format_version_ == IndexToLocFormat::kLongOffset) {
194 size += new_data->WriteULong(size, *l);
195 } else {
196 size += new_data->WriteUShort(size, *l / 2);
197 }
198 }
199 num_glyphs_ = loca_.size() - 1;
200 return size;
201 }
202
Initialize(ReadableFontData * data)203 void LocaTable::Builder::Initialize(ReadableFontData* data) {
204 ClearLoca(false);
205 if (data) {
206 if (NumGlyphs() < 0) {
207 #if !defined (SFNTLY_NO_EXCEPTION)
208 throw IllegalStateException("numglyphs not set on LocaTable Builder.");
209 #endif
210 return;
211 }
212 LocaTablePtr table =
213 new LocaTable(header(), data, format_version_, num_glyphs_);
214 Ptr<LocaTable::LocaIterator> loca_iter =
215 new LocaTable::LocaIterator(table);
216 while (loca_iter->HasNext()) {
217 loca_.push_back(loca_iter->Next());
218 }
219 }
220 }
221
CheckGlyphRange(int32_t glyph_id)222 int32_t LocaTable::Builder::CheckGlyphRange(int32_t glyph_id) {
223 if (glyph_id < 0 || glyph_id > LastGlyphIndex()) {
224 #if !defined (SFNTLY_NO_EXCEPTION)
225 throw IndexOutOfBoundsException("Glyph ID is outside of the allowed range");
226 #endif
227 return -1;
228 }
229 return glyph_id;
230 }
231
LastGlyphIndex()232 int32_t LocaTable::Builder::LastGlyphIndex() {
233 return !loca_.empty() ? loca_.size() - 2 : num_glyphs_ - 1;
234 }
235
GetLocaList()236 std::vector<int32_t>* LocaTable::Builder::GetLocaList() {
237 if (loca_.empty()) {
238 Initialize(InternalReadData());
239 set_model_changed();
240 }
241 return &loca_;
242 }
243
ClearLoca(bool nullify)244 void LocaTable::Builder::ClearLoca(bool nullify) {
245 // Note: in C++ port, nullify is not used at all.
246 UNREFERENCED_PARAMETER(nullify);
247 loca_.clear();
248 set_model_changed(false);
249 }
250
251 } // namespace sfntly
252