Line data Source code
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/core/name_table.h"
18 :
19 : #include <stdio.h>
20 : #include <string.h>
21 :
22 : #include <unicode/unistr.h>
23 :
24 : #include "sfntly/font.h"
25 : #include "sfntly/port/exception_type.h"
26 :
27 : namespace sfntly {
28 : /******************************************************************************
29 : * NameTable::NameEntryId class
30 : ******************************************************************************/
31 0 : NameTable::NameEntryId::NameEntryId()
32 : : platform_id_(0),
33 : encoding_id_(0),
34 : language_id_(0),
35 0 : name_id_(0) {
36 0 : }
37 :
38 0 : NameTable::NameEntryId::NameEntryId(int32_t platform_id,
39 : int32_t encoding_id,
40 : int32_t language_id,
41 0 : int32_t name_id)
42 : : platform_id_(platform_id),
43 : encoding_id_(encoding_id),
44 : language_id_(language_id),
45 0 : name_id_(name_id) {
46 0 : }
47 :
48 0 : NameTable::NameEntryId::NameEntryId(const NameTable::NameEntryId& rhs) {
49 0 : *this = rhs;
50 0 : }
51 :
52 : const NameTable::NameEntryId&
53 0 : NameTable::NameEntryId::operator=(const NameTable::NameEntryId& rhs) const {
54 0 : platform_id_ = rhs.platform_id_;
55 0 : encoding_id_ = rhs.encoding_id_;
56 0 : language_id_ = rhs.language_id_;
57 0 : name_id_ = rhs.name_id_;
58 0 : return *this;
59 : }
60 :
61 0 : bool NameTable::NameEntryId::operator==(const NameEntryId& rhs) const {
62 0 : return platform_id_ == rhs.platform_id_ &&
63 0 : encoding_id_ == rhs.encoding_id_ &&
64 0 : language_id_ == rhs.language_id_ &&
65 0 : name_id_ == rhs.name_id_;
66 : }
67 :
68 0 : bool NameTable::NameEntryId::operator<(const NameEntryId& rhs) const {
69 0 : if (platform_id_ != rhs.platform_id_) return platform_id_ < rhs.platform_id_;
70 0 : if (encoding_id_ != rhs.encoding_id_) return encoding_id_ < rhs.encoding_id_;
71 0 : if (language_id_ != rhs.language_id_) return language_id_ < rhs.language_id_;
72 0 : return name_id_ < rhs.name_id_;
73 : }
74 :
75 : /******************************************************************************
76 : * NameTable::NameEntry class
77 : ******************************************************************************/
78 0 : NameTable::NameEntry::NameEntry() {
79 0 : Init(0, 0, 0, 0, NULL);
80 0 : }
81 :
82 0 : NameTable::NameEntry::NameEntry(const NameEntryId& name_entry_id,
83 0 : const ByteVector& name_bytes) {
84 0 : Init(name_entry_id.platform_id(),
85 : name_entry_id.encoding_id(),
86 : name_entry_id.language_id(),
87 : name_entry_id.name_id(),
88 0 : &name_bytes);
89 0 : }
90 :
91 0 : NameTable::NameEntry::NameEntry(int32_t platform_id,
92 : int32_t encoding_id,
93 : int32_t language_id,
94 : int32_t name_id,
95 0 : const ByteVector& name_bytes) {
96 0 : Init(platform_id, encoding_id, language_id, name_id, &name_bytes);
97 0 : }
98 :
99 0 : NameTable::NameEntry::~NameEntry() {}
100 :
101 0 : ByteVector* NameTable::NameEntry::NameAsBytes() {
102 0 : return &name_bytes_;
103 : }
104 :
105 0 : int32_t NameTable::NameEntry::NameBytesLength() {
106 0 : return name_bytes_.size();
107 : }
108 :
109 0 : UChar* NameTable::NameEntry::Name() {
110 0 : return NameTable::ConvertFromNameBytes(&name_bytes_,
111 : platform_id(),
112 0 : encoding_id());
113 : }
114 :
115 0 : bool NameTable::NameEntry::operator==(const NameEntry& rhs) const {
116 0 : return (name_entry_id_ == rhs.name_entry_id_ &&
117 0 : name_bytes_ == rhs.name_bytes_);
118 : }
119 :
120 0 : void NameTable::NameEntry::Init(int32_t platform_id,
121 : int32_t encoding_id,
122 : int32_t language_id,
123 : int32_t name_id,
124 : const ByteVector* name_bytes) {
125 0 : name_entry_id_ = NameEntryId(platform_id, encoding_id, language_id, name_id);
126 0 : if (name_bytes) {
127 0 : name_bytes_ = *name_bytes;
128 : } else {
129 0 : name_bytes_.clear();
130 : }
131 0 : }
132 :
133 : /******************************************************************************
134 : * NameTable::NameEntryBuilder class
135 : ******************************************************************************/
136 0 : NameTable::NameEntryBuilder::NameEntryBuilder() {
137 0 : Init(0, 0, 0, 0, NULL);
138 0 : }
139 :
140 0 : NameTable::NameEntryBuilder::NameEntryBuilder(const NameEntryId& name_entry_id,
141 0 : const ByteVector& name_bytes) {
142 0 : Init(name_entry_id.platform_id(),
143 : name_entry_id.encoding_id(),
144 : name_entry_id.language_id(),
145 : name_entry_id.name_id(),
146 0 : &name_bytes);
147 0 : }
148 :
149 0 : NameTable::NameEntryBuilder::NameEntryBuilder(
150 0 : const NameEntryId& name_entry_id) {
151 0 : Init(name_entry_id.platform_id(),
152 : name_entry_id.encoding_id(),
153 : name_entry_id.language_id(),
154 : name_entry_id.name_id(),
155 0 : NULL);
156 0 : }
157 :
158 0 : NameTable::NameEntryBuilder::NameEntryBuilder(NameEntry* b) {
159 0 : Init(b->platform_id(),
160 : b->encoding_id(),
161 : b->language_id(),
162 : b->name_id(),
163 0 : b->NameAsBytes());
164 0 : }
165 :
166 0 : NameTable::NameEntryBuilder::~NameEntryBuilder() {}
167 :
168 0 : void NameTable::NameEntryBuilder::SetName(const UChar* name) {
169 0 : if (name == NULL) {
170 0 : name_entry_->name_bytes_.clear();
171 0 : return;
172 : }
173 0 : NameTable::ConvertToNameBytes(name,
174 : name_entry_->platform_id(),
175 : name_entry_->encoding_id(),
176 0 : &name_entry_->name_bytes_);
177 : }
178 :
179 0 : void NameTable::NameEntryBuilder::SetName(const ByteVector& name_bytes) {
180 0 : name_entry_->name_bytes_.clear();
181 : std::copy(name_bytes.begin(),
182 : name_bytes.end(),
183 0 : name_entry_->name_bytes_.begin());
184 0 : }
185 :
186 0 : void NameTable::NameEntryBuilder::SetName(const ByteVector& name_bytes,
187 : int32_t offset,
188 : int32_t length) {
189 0 : name_entry_->name_bytes_.clear();
190 0 : std::copy(name_bytes.begin() + offset,
191 0 : name_bytes.begin() + offset + length,
192 0 : name_entry_->name_bytes_.begin());
193 0 : }
194 :
195 0 : void NameTable::NameEntryBuilder::Init(int32_t platform_id,
196 : int32_t encoding_id,
197 : int32_t language_id,
198 : int32_t name_id,
199 : const ByteVector* name_bytes) {
200 0 : name_entry_ = new NameEntry();
201 0 : name_entry_->Init(platform_id, encoding_id, language_id, name_id, name_bytes);
202 0 : }
203 :
204 : /******************************************************************************
205 : * NameTable::NameEntryFilterInPlace class (C++ port only)
206 : ******************************************************************************/
207 0 : NameTable::NameEntryFilterInPlace::NameEntryFilterInPlace(int32_t platform_id,
208 : int32_t encoding_id,
209 : int32_t language_id,
210 0 : int32_t name_id)
211 : : platform_id_(platform_id),
212 : encoding_id_(encoding_id),
213 : language_id_(language_id),
214 0 : name_id_(name_id) {
215 0 : }
216 :
217 0 : bool NameTable::NameEntryFilterInPlace::Accept(int32_t platform_id,
218 : int32_t encoding_id,
219 : int32_t language_id,
220 : int32_t name_id) {
221 0 : return (platform_id_ == platform_id &&
222 0 : encoding_id_ == encoding_id &&
223 0 : language_id_ == language_id &&
224 0 : name_id_ == name_id);
225 : }
226 :
227 : /******************************************************************************
228 : * NameTable::NameEntryIterator class
229 : ******************************************************************************/
230 0 : NameTable::NameEntryIterator::NameEntryIterator(NameTable* table)
231 : : RefIterator<NameEntry, NameTable>(table),
232 : name_index_(0),
233 0 : filter_(NULL) {
234 0 : }
235 :
236 0 : NameTable::NameEntryIterator::NameEntryIterator(NameTable* table,
237 0 : NameEntryFilter* filter)
238 : : RefIterator<NameEntry, NameTable>(table),
239 : name_index_(0),
240 0 : filter_(filter) {
241 0 : }
242 :
243 0 : bool NameTable::NameEntryIterator::HasNext() {
244 0 : if (!filter_) {
245 0 : if (name_index_ < container()->NameCount()) {
246 0 : return true;
247 : }
248 0 : return false;
249 : }
250 0 : for (; name_index_ < container()->NameCount(); ++name_index_) {
251 0 : if (filter_->Accept(container()->PlatformId(name_index_),
252 0 : container()->EncodingId(name_index_),
253 0 : container()->LanguageId(name_index_),
254 0 : container()->NameId(name_index_))) {
255 0 : return true;
256 : }
257 : }
258 0 : return false;
259 : }
260 :
261 0 : CALLER_ATTACH NameTable::NameEntry* NameTable::NameEntryIterator::Next() {
262 0 : if (!HasNext())
263 0 : return NULL;
264 0 : return container()->GetNameEntry(name_index_++);
265 : }
266 :
267 : /******************************************************************************
268 : * NameTable::Builder class
269 : ******************************************************************************/
270 0 : NameTable::Builder::Builder(Header* header, WritableFontData* data)
271 0 : : SubTableContainerTable::Builder(header, data) {
272 0 : }
273 :
274 0 : NameTable::Builder::Builder(Header* header, ReadableFontData* data)
275 0 : : SubTableContainerTable::Builder(header, data) {
276 0 : }
277 :
278 : CALLER_ATTACH NameTable::Builder*
279 0 : NameTable::Builder::CreateBuilder(Header* header,
280 : WritableFontData* data) {
281 0 : Ptr<NameTable::Builder> builder;
282 0 : builder = new NameTable::Builder(header, data);
283 0 : return builder.Detach();
284 : }
285 :
286 0 : void NameTable::Builder::RevertNames() {
287 0 : name_entry_map_.clear();
288 0 : set_model_changed(false);
289 0 : }
290 :
291 0 : int32_t NameTable::Builder::BuilderCount() {
292 0 : GetNameBuilders(); // Ensure name_entry_map_ is built.
293 0 : return (int32_t)name_entry_map_.size();
294 : }
295 :
296 0 : bool NameTable::Builder::Has(int32_t platform_id,
297 : int32_t encoding_id,
298 : int32_t language_id,
299 : int32_t name_id) {
300 0 : NameEntryId probe(platform_id, encoding_id, language_id, name_id);
301 0 : GetNameBuilders(); // Ensure name_entry_map_ is built.
302 0 : return (name_entry_map_.find(probe) != name_entry_map_.end());
303 : }
304 :
305 : CALLER_ATTACH NameTable::NameEntryBuilder*
306 0 : NameTable::Builder::NameBuilder(int32_t platform_id,
307 : int32_t encoding_id,
308 : int32_t language_id,
309 : int32_t name_id) {
310 0 : NameEntryId probe(platform_id, encoding_id, language_id, name_id);
311 0 : NameEntryBuilderMap builders;
312 0 : GetNameBuilders(); // Ensure name_entry_map_ is built.
313 0 : if (name_entry_map_.find(probe) != name_entry_map_.end()) {
314 0 : return name_entry_map_[probe];
315 : }
316 0 : NameEntryBuilderPtr builder = new NameEntryBuilder(probe);
317 0 : name_entry_map_[probe] = builder;
318 0 : return builder.Detach();
319 : }
320 :
321 0 : bool NameTable::Builder::Remove(int32_t platform_id,
322 : int32_t encoding_id,
323 : int32_t language_id,
324 : int32_t name_id) {
325 0 : NameEntryId probe(platform_id, encoding_id, language_id, name_id);
326 0 : GetNameBuilders(); // Ensure name_entry_map_ is built.
327 0 : NameEntryBuilderMap::iterator position = name_entry_map_.find(probe);
328 0 : if (position != name_entry_map_.end()) {
329 0 : name_entry_map_.erase(position);
330 0 : return true;
331 : }
332 0 : return false;
333 : }
334 :
335 : CALLER_ATTACH FontDataTable*
336 0 : NameTable::Builder::SubBuildTable(ReadableFontData* data) {
337 0 : FontDataTablePtr table = new NameTable(header(), data);
338 0 : return table.Detach();
339 : }
340 :
341 0 : void NameTable::Builder::SubDataSet() {
342 0 : name_entry_map_.clear();
343 0 : set_model_changed(false);
344 0 : }
345 :
346 0 : int32_t NameTable::Builder::SubDataSizeToSerialize() {
347 0 : if (name_entry_map_.empty()) {
348 0 : return 0;
349 : }
350 :
351 0 : int32_t size = NameTable::Offset::kNameRecordStart +
352 0 : name_entry_map_.size() * NameTable::Offset::kNameRecordSize;
353 0 : for (NameEntryBuilderMap::iterator b = name_entry_map_.begin(),
354 0 : end = name_entry_map_.end();
355 : b != end; ++b) {
356 0 : NameEntryBuilderPtr p = b->second;
357 0 : NameEntry* entry = p->name_entry();
358 0 : size += entry->NameBytesLength();
359 : }
360 0 : return size;
361 : }
362 :
363 0 : bool NameTable::Builder::SubReadyToSerialize() {
364 0 : return !name_entry_map_.empty();
365 : }
366 :
367 0 : int32_t NameTable::Builder::SubSerialize(WritableFontData* new_data) {
368 : int32_t string_table_start_offset =
369 0 : NameTable::Offset::kNameRecordStart +
370 0 : name_entry_map_.size() * NameTable::Offset::kNameRecordSize;
371 :
372 : // Header
373 0 : new_data->WriteUShort(NameTable::Offset::kFormat, 0);
374 0 : new_data->WriteUShort(NameTable::Offset::kCount, name_entry_map_.size());
375 : new_data->WriteUShort(NameTable::Offset::kStringOffset,
376 0 : string_table_start_offset);
377 0 : int32_t name_record_offset = NameTable::Offset::kNameRecordStart;
378 0 : int32_t string_offset = 0;
379 : // Note: we offered operator< in NameEntryId, which will be used by std::less,
380 : // and therefore our map will act like TreeMap in Java to provide
381 : // sorted key set.
382 0 : for (NameEntryBuilderMap::iterator b = name_entry_map_.begin(),
383 0 : end = name_entry_map_.end();
384 : b != end; ++b) {
385 0 : new_data->WriteUShort(
386 : name_record_offset + NameTable::Offset::kNameRecordPlatformId,
387 0 : b->first.platform_id());
388 0 : new_data->WriteUShort(
389 : name_record_offset + NameTable::Offset::kNameRecordEncodingId,
390 0 : b->first.encoding_id());
391 0 : new_data->WriteUShort(
392 : name_record_offset + NameTable::Offset::kNameRecordLanguageId,
393 0 : b->first.language_id());
394 0 : new_data->WriteUShort(
395 : name_record_offset + NameTable::Offset::kNameRecordNameId,
396 0 : b->first.name_id());
397 0 : NameEntry* builder_entry = b->second->name_entry();
398 0 : new_data->WriteUShort(
399 : name_record_offset + NameTable::Offset::kNameRecordStringLength,
400 0 : builder_entry->NameBytesLength());
401 0 : new_data->WriteUShort(
402 : name_record_offset + NameTable::Offset::kNameRecordStringOffset,
403 0 : string_offset);
404 0 : name_record_offset += NameTable::Offset::kNameRecordSize;
405 0 : string_offset += new_data->WriteBytes(
406 : string_offset + string_table_start_offset,
407 0 : builder_entry->NameAsBytes());
408 : }
409 :
410 0 : return string_offset + string_table_start_offset;
411 : }
412 :
413 0 : void NameTable::Builder::Initialize(ReadableFontData* data) {
414 0 : if (data) {
415 0 : NameTablePtr table = new NameTable(header(), data);
416 0 : Ptr<NameEntryIterator> name_iter;
417 0 : name_iter.Attach(table->Iterator());
418 0 : while (name_iter->HasNext()) {
419 0 : NameEntryPtr name_entry;
420 0 : name_entry.Attach(name_iter->Next());
421 0 : NameEntryBuilderPtr name_entry_builder = new NameEntryBuilder(name_entry);
422 0 : NameEntry* builder_entry = name_entry_builder->name_entry();
423 0 : NameEntryId probe = builder_entry->name_entry_id();
424 0 : name_entry_map_[probe] = name_entry_builder;
425 : }
426 : }
427 0 : }
428 :
429 0 : NameTable::NameEntryBuilderMap* NameTable::Builder::GetNameBuilders() {
430 0 : if (name_entry_map_.empty()) {
431 0 : Initialize(InternalReadData());
432 : }
433 0 : set_model_changed();
434 0 : return &name_entry_map_;
435 : }
436 :
437 : /******************************************************************************
438 : * NameTable class
439 : ******************************************************************************/
440 0 : NameTable::~NameTable() {}
441 :
442 0 : int32_t NameTable::Format() {
443 0 : return data_->ReadUShort(Offset::kFormat);
444 : }
445 :
446 0 : int32_t NameTable::NameCount() {
447 0 : return data_->ReadUShort(Offset::kCount);
448 : }
449 :
450 0 : int32_t NameTable::PlatformId(int32_t index) {
451 0 : return data_->ReadUShort(Offset::kNameRecordPlatformId +
452 0 : OffsetForNameRecord(index));
453 : }
454 :
455 0 : int32_t NameTable::EncodingId(int32_t index) {
456 0 : return data_->ReadUShort(Offset::kNameRecordEncodingId +
457 0 : OffsetForNameRecord(index));
458 : }
459 :
460 0 : int32_t NameTable::LanguageId(int32_t index) {
461 0 : return data_->ReadUShort(Offset::kNameRecordLanguageId +
462 0 : OffsetForNameRecord(index));
463 : }
464 :
465 0 : int32_t NameTable::NameId(int32_t index) {
466 0 : return data_->ReadUShort(Offset::kNameRecordNameId +
467 0 : OffsetForNameRecord(index));
468 : }
469 :
470 0 : void NameTable::NameAsBytes(int32_t index, ByteVector* b) {
471 0 : assert(b);
472 0 : b->clear();
473 :
474 0 : int32_t length = NameLength(index);
475 0 : if (length <= 0)
476 0 : return;
477 :
478 0 : b->resize(length);
479 0 : data_->ReadBytes(NameOffset(index), &((*b)[0]), 0, length);
480 : }
481 :
482 0 : void NameTable::NameAsBytes(int32_t platform_id,
483 : int32_t encoding_id,
484 : int32_t language_id,
485 : int32_t name_id,
486 : ByteVector* b) {
487 0 : assert(b);
488 0 : NameEntryPtr entry;
489 0 : entry.Attach(GetNameEntry(platform_id, encoding_id, language_id, name_id));
490 0 : if (entry) {
491 0 : ByteVector* name = entry->NameAsBytes();
492 0 : std::copy(name->begin(), name->end(), b->begin());
493 : }
494 0 : }
495 :
496 0 : UChar* NameTable::Name(int32_t index) {
497 0 : ByteVector b;
498 0 : NameAsBytes(index, &b);
499 0 : return ConvertFromNameBytes(&b, PlatformId(index), EncodingId(index));
500 : }
501 :
502 0 : UChar* NameTable::Name(int32_t platform_id,
503 : int32_t encoding_id,
504 : int32_t language_id,
505 : int32_t name_id) {
506 0 : NameEntryPtr entry;
507 0 : entry.Attach(GetNameEntry(platform_id, encoding_id, language_id, name_id));
508 0 : if (entry) {
509 0 : return entry->Name();
510 : }
511 0 : return NULL;
512 : }
513 :
514 0 : CALLER_ATTACH NameTable::NameEntry* NameTable::GetNameEntry(int32_t index) {
515 0 : ByteVector b;
516 0 : NameAsBytes(index, &b);
517 0 : NameEntryPtr instance = new NameEntry(PlatformId(index),
518 0 : EncodingId(index),
519 0 : LanguageId(index),
520 0 : NameId(index), b);
521 0 : return instance.Detach();
522 : }
523 :
524 0 : CALLER_ATTACH NameTable::NameEntry* NameTable::GetNameEntry(int32_t platform_id,
525 : int32_t encoding_id,
526 : int32_t language_id,
527 : int32_t name_id) {
528 : NameTable::NameEntryFilterInPlace
529 0 : filter(platform_id, encoding_id, language_id, name_id);
530 0 : Ptr<NameTable::NameEntryIterator> name_entry_iter;
531 0 : name_entry_iter.Attach(Iterator(&filter));
532 0 : NameEntryPtr result;
533 0 : if (name_entry_iter->HasNext()) {
534 0 : result = name_entry_iter->Next();
535 : }
536 0 : return result;
537 : }
538 :
539 0 : CALLER_ATTACH NameTable::NameEntryIterator* NameTable::Iterator() {
540 0 : Ptr<NameEntryIterator> output = new NameTable::NameEntryIterator(this);
541 0 : return output.Detach();
542 : }
543 :
544 : CALLER_ATTACH
545 0 : NameTable::NameEntryIterator* NameTable::Iterator(NameEntryFilter* filter) {
546 : Ptr<NameEntryIterator> output =
547 0 : new NameTable::NameEntryIterator(this, filter);
548 0 : return output.Detach();
549 : }
550 :
551 0 : NameTable::NameTable(Header* header, ReadableFontData* data)
552 0 : : SubTableContainerTable(header, data) {}
553 :
554 0 : int32_t NameTable::StringOffset() {
555 0 : return data_->ReadUShort(Offset::kStringOffset);
556 : }
557 :
558 0 : int32_t NameTable::OffsetForNameRecord(int32_t index) {
559 0 : return Offset::kNameRecordStart + index * Offset::kNameRecordSize;
560 : }
561 :
562 0 : int32_t NameTable::NameLength(int32_t index) {
563 0 : return data_->ReadUShort(Offset::kNameRecordStringLength +
564 0 : OffsetForNameRecord(index));
565 : }
566 :
567 0 : int32_t NameTable::NameOffset(int32_t index) {
568 0 : return data_->ReadUShort(Offset::kNameRecordStringOffset +
569 0 : OffsetForNameRecord(index)) + StringOffset();
570 : }
571 :
572 0 : const char* NameTable::GetEncodingName(int32_t platform_id,
573 : int32_t encoding_id) {
574 0 : switch (platform_id) {
575 : case PlatformId::kUnicode:
576 0 : return "UTF-16BE";
577 : case PlatformId::kMacintosh:
578 0 : switch (encoding_id) {
579 : case MacintoshEncodingId::kRoman:
580 0 : return "MacRoman";
581 : case MacintoshEncodingId::kJapanese:
582 0 : return "Shift-JIS";
583 : case MacintoshEncodingId::kChineseTraditional:
584 0 : return "Big5";
585 : case MacintoshEncodingId::kKorean:
586 0 : return "EUC-KR";
587 : case MacintoshEncodingId::kArabic:
588 0 : return "MacArabic";
589 : case MacintoshEncodingId::kHebrew:
590 0 : return "MacHebrew";
591 : case MacintoshEncodingId::kGreek:
592 0 : return "MacGreek";
593 : case MacintoshEncodingId::kRussian:
594 0 : return "MacCyrillic";
595 : case MacintoshEncodingId::kRSymbol:
596 0 : return "MacSymbol";
597 : case MacintoshEncodingId::kThai:
598 0 : return "MacThai";
599 : case MacintoshEncodingId::kChineseSimplified:
600 0 : return "EUC-CN";
601 : default: // Note: unknown/unconfirmed cases are not ported.
602 0 : break;
603 : }
604 0 : break;
605 : case PlatformId::kISO:
606 0 : break;
607 : case PlatformId::kWindows:
608 0 : switch (encoding_id) {
609 : case WindowsEncodingId::kSymbol:
610 : case WindowsEncodingId::kUnicodeUCS2:
611 0 : return "UTF-16BE";
612 : case WindowsEncodingId::kShiftJIS:
613 0 : return "windows-933";
614 : case WindowsEncodingId::kPRC:
615 0 : return "windows-936";
616 : case WindowsEncodingId::kBig5:
617 0 : return "windows-950";
618 : case WindowsEncodingId::kWansung:
619 0 : return "windows-949";
620 : case WindowsEncodingId::kJohab:
621 0 : return "ms1361";
622 : case WindowsEncodingId::kUnicodeUCS4:
623 0 : return "UCS-4";
624 : }
625 0 : break;
626 : case PlatformId::kCustom:
627 0 : break;
628 : default:
629 0 : break;
630 : }
631 0 : return NULL;
632 : }
633 :
634 0 : UConverter* NameTable::GetCharset(int32_t platform_id, int32_t encoding_id) {
635 0 : UErrorCode error_code = U_ZERO_ERROR;
636 0 : UConverter* conv = ucnv_open(GetEncodingName(platform_id, encoding_id),
637 0 : &error_code);
638 0 : if (U_SUCCESS(error_code)) {
639 0 : return conv;
640 : }
641 :
642 0 : if (conv) {
643 0 : ucnv_close(conv);
644 : }
645 0 : return NULL;
646 : }
647 :
648 0 : void NameTable::ConvertToNameBytes(const UChar* name,
649 : int32_t platform_id,
650 : int32_t encoding_id,
651 : ByteVector* b) {
652 0 : assert(b);
653 0 : assert(name);
654 0 : b->clear();
655 0 : UConverter* cs = GetCharset(platform_id, encoding_id);
656 0 : if (cs == NULL) {
657 0 : return;
658 : }
659 :
660 : // Preflight to get buffer size.
661 0 : UErrorCode error_code = U_ZERO_ERROR;
662 0 : int32_t length = ucnv_fromUChars(cs, NULL, 0, name, -1, &error_code);
663 0 : b->resize(length + 4); // The longest termination "\0" is 4 bytes.
664 0 : memset(&((*b)[0]), 0, length + 4);
665 0 : error_code = U_ZERO_ERROR;
666 0 : ucnv_fromUChars(cs,
667 0 : reinterpret_cast<char*>(&((*b)[0])),
668 : length + 4,
669 : name,
670 : -1,
671 0 : &error_code);
672 0 : if (!U_SUCCESS(error_code)) {
673 0 : b->clear();
674 : }
675 0 : ucnv_close(cs);
676 : }
677 :
678 0 : UChar* NameTable::ConvertFromNameBytes(ByteVector* name_bytes,
679 : int32_t platform_id,
680 : int32_t encoding_id) {
681 0 : if (name_bytes == NULL || name_bytes->size() == 0) {
682 0 : return NULL;
683 : }
684 0 : UConverter* cs = GetCharset(platform_id, encoding_id);
685 0 : UErrorCode error_code = U_ZERO_ERROR;
686 0 : if (cs == NULL) {
687 0 : char buffer[11] = {0};
688 : #if defined (WIN32)
689 : _itoa_s(platform_id, buffer, 16);
690 : #else
691 0 : snprintf(buffer, sizeof(buffer), "%x", platform_id);
692 : #endif
693 0 : UChar* result = new UChar[12];
694 0 : memset(result, 0, sizeof(UChar) * 12);
695 0 : cs = ucnv_open("utf-8", &error_code);
696 0 : if (U_SUCCESS(error_code)) {
697 0 : ucnv_toUChars(cs, result, 12, buffer, 11, &error_code);
698 0 : ucnv_close(cs);
699 0 : if (U_SUCCESS(error_code)) {
700 0 : return result;
701 : }
702 : }
703 0 : delete[] result;
704 0 : return NULL;
705 : }
706 :
707 : // No preflight needed here, we will be bigger.
708 0 : UChar* output_buffer = new UChar[name_bytes->size() + 1];
709 0 : memset(output_buffer, 0, sizeof(UChar) * (name_bytes->size() + 1));
710 0 : int32_t length = ucnv_toUChars(cs,
711 : output_buffer,
712 0 : name_bytes->size(),
713 0 : reinterpret_cast<char*>(&((*name_bytes)[0])),
714 0 : name_bytes->size(),
715 0 : &error_code);
716 0 : ucnv_close(cs);
717 0 : if (length > 0) {
718 0 : return output_buffer;
719 : }
720 :
721 0 : delete[] output_buffer;
722 0 : return NULL;
723 : }
724 :
725 : } // namespace sfntly
|