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/font_data_table.h"
18
19#include "sfntly/data/font_output_stream.h"
20
21namespace sfntly {
22
23/******************************************************************************
24 * FontDataTable class
25 ******************************************************************************/
26
27FontDataTable::FontDataTable(ReadableFontData* data) {
28  data_ = data;
29}
30
31FontDataTable::~FontDataTable() {}
32
33ReadableFontData* FontDataTable::ReadFontData() {
34  return data_;
35}
36
37int32_t FontDataTable::DataLength() {
38  return data_->Length();
39}
40
41int32_t FontDataTable::Serialize(OutputStream* os) {
42  return data_->CopyTo(os);
43}
44
45int32_t FontDataTable::Serialize(WritableFontData* data) {
46  return data_->CopyTo(data);
47}
48
49/******************************************************************************
50 * FontDataTable::Builder class
51 ******************************************************************************/
52CALLER_ATTACH WritableFontData* FontDataTable::Builder::Data() {
53  WritableFontDataPtr new_data;
54  if (model_changed_) {
55    if (!SubReadyToSerialize()) {
56#if !defined (SFNTLY_NO_EXCEPTION)
57      throw IOException("Table not ready to build.");
58#endif
59      return NULL;
60    }
61    int32_t size = SubDataSizeToSerialize();
62    new_data.Attach(WritableFontData::CreateWritableFontData(size));
63    SubSerialize(new_data);
64  } else {
65    ReadableFontDataPtr data = InternalReadData();
66    new_data.Attach(WritableFontData::CreateWritableFontData(
67                        data != NULL ? data->Length() : 0));
68    if (data != NULL) {
69      data->CopyTo(new_data);
70    }
71  }
72  return new_data.Detach();
73}
74
75void FontDataTable::Builder::SetData(ReadableFontData* data) {
76  InternalSetData(data, true);
77}
78
79
80CALLER_ATTACH FontDataTable* FontDataTable::Builder::Build() {
81  FontDataTablePtr table;  // NULL default table
82  ReadableFontDataPtr data = InternalReadData();
83  if (model_changed_) {
84    // Let subclass serialize from model.
85    if (!SubReadyToSerialize()) {
86#if !defined (SFNTLY_NO_EXCEPTION)
87      throw IOException("Table not ready to build.");
88#endif
89      return NULL;
90    }
91    int32_t size = SubDataSizeToSerialize();
92    WritableFontDataPtr new_data;
93    new_data.Attach(WritableFontData::CreateWritableFontData(size));
94    SubSerialize(new_data);
95    data = new_data;
96  }
97
98  if (data != NULL) {
99    table = SubBuildTable(data);
100    NotifyPostTableBuild(table);
101  }
102
103  r_data_.Release();
104  w_data_.Release();
105  return table;
106}
107
108bool FontDataTable::Builder::ReadyToBuild() {
109  return true;
110}
111
112ReadableFontData* FontDataTable::Builder::InternalReadData() {
113  return (r_data_ != NULL) ? r_data_.p_ :
114                             static_cast<ReadableFontData*>(w_data_.p_);
115}
116
117WritableFontData* FontDataTable::Builder::InternalWriteData() {
118  if (w_data_ == NULL) {
119    WritableFontDataPtr new_data;
120    new_data.Attach(WritableFontData::CreateWritableFontData(
121                        r_data_ == NULL ? 0 : r_data_->Length()));
122#if !defined (SFNTLY_NO_EXCEPTION)
123    try {
124#endif
125      if (r_data_) {
126        r_data_->CopyTo(new_data);
127      }
128#if !defined (SFNTLY_NO_EXCEPTION)
129    } catch (IOException& e) {
130      // TODO(stuartg): fix when IOExceptions are cleaned up
131    }
132#endif
133    InternalSetData(new_data, false);
134  }
135  return w_data_.p_;
136}
137
138FontDataTable::Builder::Builder()
139    : model_changed_(false),
140      contained_model_changed_(false),
141      data_changed_(false) {
142}
143
144FontDataTable::Builder::Builder(int32_t data_size)
145    : model_changed_(false),
146      contained_model_changed_(false),
147      data_changed_(false) {
148  w_data_.Attach(WritableFontData::CreateWritableFontData(data_size));
149}
150
151FontDataTable::Builder::Builder(WritableFontData* data)
152    : model_changed_(false),
153      contained_model_changed_(false),
154      data_changed_(false) {
155  w_data_ = data;
156}
157
158FontDataTable::Builder::Builder(ReadableFontData* data)
159    : model_changed_(false),
160      contained_model_changed_(false),
161      data_changed_(false) {
162  r_data_ = data;
163}
164
165FontDataTable::Builder::~Builder() {
166}
167
168void FontDataTable::Builder::NotifyPostTableBuild(FontDataTable* table) {
169  // Default: NOP.
170  UNREFERENCED_PARAMETER(table);
171}
172
173void FontDataTable::Builder::InternalSetData(WritableFontData* data,
174                                             bool data_changed) {
175  w_data_ = data;
176  r_data_ = NULL;
177  if (data_changed) {
178    data_changed_ = true;
179    SubDataSet();
180  }
181}
182
183void FontDataTable::Builder::InternalSetData(ReadableFontData* data,
184                                             bool data_changed) {
185  w_data_ = NULL;
186  r_data_ = data;
187  if (data_changed) {
188    data_changed_ = true;
189    SubDataSet();
190  }
191}
192
193}  // namespace sfntly
194