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/writable_font_data.h"
18464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
198f090032dd4f8f8908f338cc73bb840b788377f2stuartg@google.com#include <algorithm>
208f090032dd4f8f8908f338cc73bb840b788377f2stuartg@google.com
2133e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com#include "sfntly/data/memory_byte_array.h"
2233e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com#include "sfntly/data/growable_memory_byte_array.h"
2333e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com
24464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comnamespace sfntly {
25464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
26464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comWritableFontData::WritableFontData(ByteArray* ba) : ReadableFontData(ba) {
27464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
28464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
29246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comWritableFontData::~WritableFontData() {}
30464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
3133e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com// static
3233e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.comCALLER_ATTACH
3333e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.comWritableFontData* WritableFontData::CreateWritableFontData(int32_t length) {
3433e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com  ByteArrayPtr ba;
3533e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com  if (length > 0) {
3633e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com    ba = new MemoryByteArray(length);
3733e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com    ba->SetFilledLength(length);
3833e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com  } else {
3933e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com    ba = new GrowableMemoryByteArray();
4033e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com  }
4133e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com  WritableFontDataPtr wfd = new WritableFontData(ba);
4233e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com  return wfd.Detach();
4333e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com}
4433e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com
4532a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com// TODO(arthurhsu): re-investigate the memory model of this function.  It's
4632a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com//                  not too useful without copying, but it's not performance
4732a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com//                  savvy to do copying.
4833e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.comCALLER_ATTACH
4933e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.comWritableFontData* WritableFontData::CreateWritableFontData(ByteVector* b) {
5033e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com  ByteArrayPtr ba = new GrowableMemoryByteArray();
5133e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com  ba->Put(0, b);
5233e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com  WritableFontDataPtr wfd = new WritableFontData(ba);
5333e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com  return wfd.Detach();
5433e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com}
5533e4b13b001b82d8b26a2066ba77fe04bbd6f9a8dfilimon@google.com
56246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t WritableFontData::WriteByte(int32_t index, byte_t b) {
57246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  array_->Put(BoundOffset(index), b);
58464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return 1;
59464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
60464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
6132a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.comint32_t WritableFontData::WriteBytes(int32_t index,
6232a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com                                     byte_t* b,
6332a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com                                     int32_t offset,
64246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                                     int32_t length) {
6532a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com  return array_->Put(BoundOffset(index),
66246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                     b,
6732a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com                     offset,
6832a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com                     BoundLength(index, length));
69464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
70464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
71246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t WritableFontData::WriteBytes(int32_t index, ByteVector* b) {
7232a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com  assert(b);
7332a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com  return WriteBytes(index, &((*b)[0]), 0, b->size());
74464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
75464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
766b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.comint32_t WritableFontData::WriteBytesPad(int32_t index,
776b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com                                        ByteVector* b,
786b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com                                        int32_t offset,
796b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com                                        int32_t length,
806b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com                                        byte_t pad) {
816b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com  int32_t written =
826b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com      array_->Put(BoundOffset(index),
836b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com                  &((*b)[0]),
846b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com                  offset,
856b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com                  BoundLength(index,
866b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com                              std::min<int32_t>(length, b->size() - offset)));
87333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com  written += WritePadding(written + index, length - written, pad);
886b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com  return written;
896b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com}
906b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com
91333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.comint32_t WritableFontData::WritePadding(int32_t index, int32_t count) {
92333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com  return WritePadding(index, count, (byte_t)0);
93333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com}
94333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com
95333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.comint32_t WritableFontData::WritePadding(int32_t index, int32_t count,
96333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com                                       byte_t pad) {
97333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com  for (int32_t i = 0; i < count; ++i) {
98333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com    array_->Put(index + i, pad);
99333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com  }
100333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com  return count;
101333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com}
102333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com
103246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t WritableFontData::WriteChar(int32_t index, byte_t c) {
104246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return WriteByte(index, c);
105464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
106464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
107246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t WritableFontData::WriteUShort(int32_t index, int32_t us) {
108246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  WriteByte(index, (byte_t)((us >> 8) & 0xff));
109246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  WriteByte(index + 1, (byte_t)(us & 0xff));
110464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return 2;
111464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
112464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
113246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t WritableFontData::WriteUShortLE(int32_t index, int32_t us) {
114246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  WriteByte(index, (byte_t)(us & 0xff));
115246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  WriteByte(index + 1, (byte_t)((us >> 8) & 0xff));
116464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return 2;
117464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
118464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
119246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t WritableFontData::WriteShort(int32_t index, int32_t s) {
120246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return WriteUShort(index, s);
121464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
122464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
123246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t WritableFontData::WriteUInt24(int32_t index, int32_t ui) {
124246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  WriteByte(index, (byte_t)((ui >> 16) & 0xff));
125246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  WriteByte(index + 1, (byte_t)((ui >> 8) & 0xff));
126246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  WriteByte(index + 2, (byte_t)(ui & 0xff));
127464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return 3;
128464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
129464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
130246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t WritableFontData::WriteULong(int32_t index, int64_t ul) {
131246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  WriteByte(index, (byte_t)((ul >> 24) & 0xff));
132246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  WriteByte(index + 1, (byte_t)((ul >> 16) & 0xff));
133246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  WriteByte(index + 2, (byte_t)((ul >> 8) & 0xff));
134246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  WriteByte(index + 3, (byte_t)(ul & 0xff));
135464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return 4;
136464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
137464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
138246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t WritableFontData::WriteULongLE(int32_t index, int64_t ul) {
139246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  WriteByte(index, (byte_t)(ul & 0xff));
140246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  WriteByte(index + 1, (byte_t)((ul >> 8) & 0xff));
141246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  WriteByte(index + 2, (byte_t)((ul >> 16) & 0xff));
142246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  WriteByte(index + 3, (byte_t)((ul >> 24) & 0xff));
143464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return 4;
144464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
145464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
146246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t WritableFontData::WriteLong(int32_t index, int64_t l) {
147246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return WriteULong(index, l);
148464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
149464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
15032a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.comint32_t WritableFontData::WriteFixed(int32_t index, int32_t f) {
15132a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com  return WriteLong(index, f);
152464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
153464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
154246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t WritableFontData::WriteDateTime(int32_t index, int64_t date) {
155246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  WriteULong(index, (date >> 32) & 0xffffffff);
156246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  WriteULong(index + 4, date & 0xffffffff);
157464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return 8;
158464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
159464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
160c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.comvoid WritableFontData::CopyFrom(InputStream* is, int32_t length) {
161c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com  array_->CopyFrom(is, length);
162c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com}
163c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com
164c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.comvoid WritableFontData::CopyFrom(InputStream* is) {
165c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com  array_->CopyFrom(is);
166c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com}
167c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com
168246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCALLER_ATTACH FontData* WritableFontData::Slice(int32_t offset,
169464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                                                int32_t length) {
170246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  if (offset < 0 || offset + length > Size()) {
171144e5cb2b372c30d8a4b90267b52646368dd89fcarthurhsu@google.com#if !defined (SFNTLY_NO_EXCEPTION)
172144e5cb2b372c30d8a4b90267b52646368dd89fcarthurhsu@google.com    throw IndexOutOfBoundsException(
173144e5cb2b372c30d8a4b90267b52646368dd89fcarthurhsu@google.com        "Attempt to bind data outside of its limits");
174144e5cb2b372c30d8a4b90267b52646368dd89fcarthurhsu@google.com#endif
175464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    return NULL;
176464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
177464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  FontDataPtr slice = new WritableFontData(this, offset, length);
178246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return slice.Detach();
179464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
180464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
181246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCALLER_ATTACH FontData* WritableFontData::Slice(int32_t offset) {
182246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  if (offset > Size()) {
183144e5cb2b372c30d8a4b90267b52646368dd89fcarthurhsu@google.com#if !defined (SFNTLY_NO_EXCEPTION)
184144e5cb2b372c30d8a4b90267b52646368dd89fcarthurhsu@google.com    throw IndexOutOfBoundsException(
185144e5cb2b372c30d8a4b90267b52646368dd89fcarthurhsu@google.com        "Attempt to bind data outside of its limits");
186144e5cb2b372c30d8a4b90267b52646368dd89fcarthurhsu@google.com#endif
187464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    return NULL;
188464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
189464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  FontDataPtr slice = new WritableFontData(this, offset);
190246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return slice.Detach();
191246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
192246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
193246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comWritableFontData::WritableFontData(WritableFontData* data, int32_t offset)
194246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    : ReadableFontData(data, offset) {
195246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
196246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
197246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comWritableFontData::WritableFontData(WritableFontData* data,
198246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                                   int32_t offset,
199246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                                   int32_t length)
200246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    : ReadableFontData(data, offset, length) {
201464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
202464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
203464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}  // namespace sfntly
204