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/writable_font_data.h"
18
19#include "sfntly/data/memory_byte_array.h"
20#include "sfntly/data/growable_memory_byte_array.h"
21
22namespace sfntly {
23
24WritableFontData::WritableFontData(ByteArray* ba) : ReadableFontData(ba) {
25}
26
27WritableFontData::~WritableFontData() {}
28
29// static
30CALLER_ATTACH
31WritableFontData* WritableFontData::CreateWritableFontData(int32_t length) {
32  ByteArrayPtr ba;
33  if (length > 0) {
34    ba = new MemoryByteArray(length);
35    ba->SetFilledLength(length);
36  } else {
37    ba = new GrowableMemoryByteArray();
38  }
39  WritableFontDataPtr wfd = new WritableFontData(ba);
40  return wfd.Detach();
41}
42
43// TODO(arthurhsu): re-investigate the memory model of this function.  It's
44//                  not too useful without copying, but it's not performance
45//                  savvy to do copying.
46CALLER_ATTACH
47WritableFontData* WritableFontData::CreateWritableFontData(ByteVector* b) {
48  ByteArrayPtr ba = new GrowableMemoryByteArray();
49  ba->Put(0, b);
50  WritableFontDataPtr wfd = new WritableFontData(ba);
51  return wfd.Detach();
52}
53
54int32_t WritableFontData::WriteByte(int32_t index, byte_t b) {
55  array_->Put(BoundOffset(index), b);
56  return 1;
57}
58
59int32_t WritableFontData::WriteBytes(int32_t index,
60                                     byte_t* b,
61                                     int32_t offset,
62                                     int32_t length) {
63  return array_->Put(BoundOffset(index),
64                     b,
65                     offset,
66                     BoundLength(index, length));
67}
68
69int32_t WritableFontData::WriteBytes(int32_t index, ByteVector* b) {
70  assert(b);
71  return WriteBytes(index, &((*b)[0]), 0, b->size());
72}
73
74int32_t WritableFontData::WriteBytesPad(int32_t index,
75                                        ByteVector* b,
76                                        int32_t offset,
77                                        int32_t length,
78                                        byte_t pad) {
79  int32_t written =
80      array_->Put(BoundOffset(index),
81                  &((*b)[0]),
82                  offset,
83                  BoundLength(index,
84                              std::min<int32_t>(length, b->size() - offset)));
85  written += WritePadding(written + index, length - written, pad);
86  return written;
87}
88
89int32_t WritableFontData::WritePadding(int32_t index, int32_t count) {
90  return WritePadding(index, count, (byte_t)0);
91}
92
93int32_t WritableFontData::WritePadding(int32_t index, int32_t count,
94                                       byte_t pad) {
95  for (int32_t i = 0; i < count; ++i) {
96    array_->Put(index + i, pad);
97  }
98  return count;
99}
100
101int32_t WritableFontData::WriteChar(int32_t index, byte_t c) {
102  return WriteByte(index, c);
103}
104
105int32_t WritableFontData::WriteUShort(int32_t index, int32_t us) {
106  WriteByte(index, (byte_t)((us >> 8) & 0xff));
107  WriteByte(index + 1, (byte_t)(us & 0xff));
108  return 2;
109}
110
111int32_t WritableFontData::WriteUShortLE(int32_t index, int32_t us) {
112  WriteByte(index, (byte_t)(us & 0xff));
113  WriteByte(index + 1, (byte_t)((us >> 8) & 0xff));
114  return 2;
115}
116
117int32_t WritableFontData::WriteShort(int32_t index, int32_t s) {
118  return WriteUShort(index, s);
119}
120
121int32_t WritableFontData::WriteUInt24(int32_t index, int32_t ui) {
122  WriteByte(index, (byte_t)((ui >> 16) & 0xff));
123  WriteByte(index + 1, (byte_t)((ui >> 8) & 0xff));
124  WriteByte(index + 2, (byte_t)(ui & 0xff));
125  return 3;
126}
127
128int32_t WritableFontData::WriteULong(int32_t index, int64_t ul) {
129  WriteByte(index, (byte_t)((ul >> 24) & 0xff));
130  WriteByte(index + 1, (byte_t)((ul >> 16) & 0xff));
131  WriteByte(index + 2, (byte_t)((ul >> 8) & 0xff));
132  WriteByte(index + 3, (byte_t)(ul & 0xff));
133  return 4;
134}
135
136int32_t WritableFontData::WriteULongLE(int32_t index, int64_t ul) {
137  WriteByte(index, (byte_t)(ul & 0xff));
138  WriteByte(index + 1, (byte_t)((ul >> 8) & 0xff));
139  WriteByte(index + 2, (byte_t)((ul >> 16) & 0xff));
140  WriteByte(index + 3, (byte_t)((ul >> 24) & 0xff));
141  return 4;
142}
143
144int32_t WritableFontData::WriteLong(int32_t index, int64_t l) {
145  return WriteULong(index, l);
146}
147
148int32_t WritableFontData::WriteFixed(int32_t index, int32_t f) {
149  return WriteLong(index, f);
150}
151
152int32_t WritableFontData::WriteDateTime(int32_t index, int64_t date) {
153  WriteULong(index, (date >> 32) & 0xffffffff);
154  WriteULong(index + 4, date & 0xffffffff);
155  return 8;
156}
157
158void WritableFontData::CopyFrom(InputStream* is, int32_t length) {
159  array_->CopyFrom(is, length);
160}
161
162void WritableFontData::CopyFrom(InputStream* is) {
163  array_->CopyFrom(is);
164}
165
166CALLER_ATTACH FontData* WritableFontData::Slice(int32_t offset,
167                                                int32_t length) {
168  if (offset < 0 || offset + length > Size()) {
169#if !defined (SFNTLY_NO_EXCEPTION)
170    throw IndexOutOfBoundsException(
171        "Attempt to bind data outside of its limits");
172#endif
173    return NULL;
174  }
175  FontDataPtr slice = new WritableFontData(this, offset, length);
176  return slice.Detach();
177}
178
179CALLER_ATTACH FontData* WritableFontData::Slice(int32_t offset) {
180  if (offset > Size()) {
181#if !defined (SFNTLY_NO_EXCEPTION)
182    throw IndexOutOfBoundsException(
183        "Attempt to bind data outside of its limits");
184#endif
185    return NULL;
186  }
187  FontDataPtr slice = new WritableFontData(this, offset);
188  return slice.Detach();
189}
190
191WritableFontData::WritableFontData(WritableFontData* data, int32_t offset)
192    : ReadableFontData(data, offset) {
193}
194
195WritableFontData::WritableFontData(WritableFontData* data,
196                                   int32_t offset,
197                                   int32_t length)
198    : ReadableFontData(data, offset, length) {
199}
200
201}  // namespace sfntly
202