130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/*
230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Copyright 2011 Google Inc. All Rights Reserved.
330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *
430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Licensed under the Apache License, Version 2.0 (the "License");
530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * you may not use this file except in compliance with the License.
630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * You may obtain a copy of the License at
730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *
830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *      http://www.apache.org/licenses/LICENSE-2.0
930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *
1030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Unless required by applicable law or agreed to in writing, software
1130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * distributed under the License is distributed on an "AS IS" BASIS,
1230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * See the License for the specific language governing permissions and
1430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * limitations under the License.
1530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun */
1630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
1730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <vector>
1830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <algorithm>
1930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "gtest/gtest.h"
2130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/port/type.h"
2230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/data/writable_font_data.h"
2330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/data/memory_byte_array.h"
2430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunnamespace sfntly {
2630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t BYTE_ARRAY_SIZES[] =
2830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  {1, 7, 127, 128, 129, 255, 256, 257, 666, 1023, 0x10000};
2930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
3030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// array data for searching
3130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t LOWER_BYTE_ARRAY_FOR_SEARCHING[] = {2, 4, 7, 13, 127};
3230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t UPPER_BYTE_ARRAY_FOR_SEARCHING[] = {2, 5, 12, 16, 256};
3330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t kLowerByteArrayForSearchingLength = 5;
3430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t kUpperByteArrayForSearchingLength = 5;
3530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
3630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// search test result pairs - number to search for; index found at
3730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t SEARCH_TEST_PAIRS[][2] = {
3830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  {0, -1}, {1, -1}, {2, 0}, {3, -1}, {4, 1}, {5, 1}, {6, -1}, {12, 2},
3930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  {13, 3}, {17, -1}, {126, -1}, {127, 4}, {256, 4}, {257, -1}, {0x1000, -1}
4030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun};
4130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t kSearchTestPairsLength = 15;
4230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
4330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// offset and start index data for searching data
4430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// array data size, lower_start_index, lower_offset, upper_start_index,
4530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// upper_offset
4630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t SEARCH_TEST_OFFSETS[][5] = {
4730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // lower[], upper[]
4830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  { (kLowerByteArrayForSearchingLength + kUpperByteArrayForSearchingLength)
4930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    * DataSize::kUSHORT,
5030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    0,
5130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    DataSize::kUSHORT,
5230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    kLowerByteArrayForSearchingLength * DataSize::kUSHORT,
5330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    DataSize::kUSHORT },
5430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
5530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // {lower, upper} []
5630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  { (kLowerByteArrayForSearchingLength + kUpperByteArrayForSearchingLength)
5730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    * DataSize::kUSHORT,
5830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    0,
5930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    2 * DataSize::kUSHORT,
6030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    DataSize::kUSHORT,
6130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    2 * DataSize::kUSHORT },
6230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
6330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // upper[], lower[]
6430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  { (kLowerByteArrayForSearchingLength + kUpperByteArrayForSearchingLength)
6530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    * DataSize::kUSHORT,
6630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    kLowerByteArrayForSearchingLength * DataSize::kUSHORT,
6730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    DataSize::kUSHORT,
6830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    0,
6930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    DataSize::kUSHORT },
7030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
7130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // {upper, lower} []
7230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  { (kLowerByteArrayForSearchingLength + kUpperByteArrayForSearchingLength)
7330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    * DataSize::kUSHORT,
7430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    DataSize::kUSHORT,
7530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    2 * DataSize::kUSHORT,
7630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    0,
7730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    2 * DataSize::kUSHORT }
7830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun};
7930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t kSearchTestOffsetLength = 4;
8030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
8130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunReadableFontData*
8230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFillTestFontDataWithShortsForSearching(WritableFontData* wfd,
8330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                       const int32_t* lower_data,
8430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                       int32_t lower_start_index,
8530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                       int32_t lower_offset,
8630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                       const int32_t* upper_data,
8730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                       int32_t upper_start_index,
8830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                       int32_t upper_offset) {
8930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // lower data
9030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int offset = lower_start_index;
9130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t i = 0; i < kLowerByteArrayForSearchingLength; ++i) {
9230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    wfd->WriteUShort(offset, lower_data[i]);
9330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    offset += lower_offset;
9430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
9530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
9630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // upper data
9730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  offset = upper_start_index;
9830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t i = 0; i < kUpperByteArrayForSearchingLength; ++i) {
9930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    wfd->WriteUShort(offset, upper_data[i]);
10030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    offset += upper_offset;
10130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
10230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
10330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return wfd;
10430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
10530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
10630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool TestReadableFontDataSearching() {
10730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t i = 0; i < kSearchTestOffsetLength; ++i) {
10830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    const int32_t* array_setup_offset = SEARCH_TEST_OFFSETS[i];
10930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    WritableFontDataPtr wfd;
11030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    wfd.Attach(WritableFontData::CreateWritableFontData(array_setup_offset[0]));
11130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    FillTestFontDataWithShortsForSearching(wfd,
11230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                           LOWER_BYTE_ARRAY_FOR_SEARCHING,
11330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                           array_setup_offset[1],
11430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                           array_setup_offset[2],
11530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                           UPPER_BYTE_ARRAY_FOR_SEARCHING,
11630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                           array_setup_offset[3],
11730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                           array_setup_offset[4]);
11830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    for (int32_t j = 0; j < kSearchTestPairsLength; ++j) {
11930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      const int32_t* test_case = SEARCH_TEST_PAIRS[j];
12030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      int32_t found = wfd->SearchUShort(array_setup_offset[1],
12130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                        array_setup_offset[2],
12230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                        array_setup_offset[3],
12330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                        array_setup_offset[4],
12430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                        kLowerByteArrayForSearchingLength,
12530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                        test_case[0]);
12630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined (SFNTLY_DEBUG_FONTDATA)
12730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      fprintf(stderr, "Searching for %d; Got %d; Expected %d; "
12830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun              "[test %d][offset %d]\n",
12930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun              test_case[0], found, test_case[1], j, i);
13030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
13130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      EXPECT_EQ(test_case[1], found);
13230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
13330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
13430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return true;
13530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
13630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
13730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FillTestByteArray(ByteArray* ba, int32_t size) {
13830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t i = 0; i < size; ++i) {
13930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    ba->Put(i, (byte_t)(i % 256));
14030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
14130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
14230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
14330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid ReadFontDataWithSingleByte(ReadableFontData* rfd, ByteVector* buffer) {
14430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  buffer->resize(rfd->Length());
14530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t index = 0; index < rfd->Length(); ++index) {
14630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    (*buffer)[index] = (byte_t)(rfd->ReadByte(index));
14730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
14830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
14930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
15030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid ReadFontDataWithBuffer(ReadableFontData* rfd,
15130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                            int32_t buffer_size,
15230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                            ByteVector* b) {
15330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ByteVector buffer(buffer_size);
15430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  b->resize(rfd->Length());
15530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
15630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t index = 0;
15730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  while (index < rfd->Length()) {
15830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t bytes_read = rfd->ReadBytes(index, &(buffer[0]), 0, buffer.size());
15930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    EXPECT_GE(bytes_read, 0);
16030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    std::copy(buffer.begin(), buffer.begin() + bytes_read, b->begin() + index);
16130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    index += bytes_read;
16230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
16330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
16430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
16530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid ReadFontDataWithSlidingWindow(ReadableFontData* rfd, int32_t window_size,
16630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                   ByteVector* b) {
16730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  b->resize(rfd->Length());
16830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t index = 0;
16930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  while (index < rfd->Length()) {
17030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t actual_window_size =
17130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        std::min<int32_t>(window_size, b->size() - index);
17230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t bytes_read =
17330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        rfd->ReadBytes(index, &((*b)[0]), index, actual_window_size);
17430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    EXPECT_GE(bytes_read, 0);
17530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    index += bytes_read;
17630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
17730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
17830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
17930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid WriteFontDataWithSingleByte(ReadableFontData* rfd, WritableFontData* wfd) {
18030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t index = 0; index < rfd->Length(); ++index) {
18130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    byte_t b = (byte_t)(rfd->ReadByte(index));
18230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    wfd->WriteByte(index, b);
18330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
18430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
18530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
18630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid WriteFontDataWithBuffer(ReadableFontData* rfd,
18730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                             WritableFontData* wfd,
18830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                             int32_t buffer_size) {
18930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ByteVector buffer(buffer_size);
19030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t index = 0;
19130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  while (index < rfd->Length()) {
19230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t bytesRead = rfd->ReadBytes(index, &(buffer[0]), 0, buffer.size());
19330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    wfd->WriteBytes(index, &(buffer[0]), 0, buffer.size());
19430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    index += bytesRead;
19530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
19630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
19730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
19830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid WriteFontDataWithSlidingWindow(ReadableFontData* rfd,
19930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                    WritableFontData* wfd,
20030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                    int32_t window_size) {
20130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ByteVector b(rfd->Length());
20230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t index = 0;
20330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  while (index < rfd->Length()) {
20430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t sliding_size = std::min<int32_t>(window_size, b.size() - index);
20530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t bytes_read = rfd->ReadBytes(index, &(b[0]), index, sliding_size);
20630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    wfd->WriteBytes(index, &(b[0]), index, sliding_size);
20730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    index += bytes_read;
20830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
20930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
21030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
21130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool ReadComparison(int32_t offset,
21230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                    int32_t length,
21330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                    ReadableFontData* rfd1,
21430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                    ReadableFontData* rfd2) {
21530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  EXPECT_TRUE(length == rfd2->Length());
21630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ByteVector b1, b2;
21730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  b1.resize(length);
21830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  b2.resize(length);
21930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
22030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // single byte reads
22130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ReadFontDataWithSingleByte(rfd1, &b1);
22230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ReadFontDataWithSingleByte(rfd2, &b2);
22330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  EXPECT_EQ(memcmp(&(b1[offset]), &(b2[0]), length), 0);
22430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
22530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // buffer reads
22630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t increments = std::max<int32_t>(length / 11, 1);
22730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t buffer_size = 1; buffer_size <= length;
22830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun       buffer_size += increments) {
22930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    b1.clear();
23030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    b2.clear();
23130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    b1.resize(length);
23230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    b2.resize(length);
23330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    ReadFontDataWithBuffer(rfd1, buffer_size, &b1);
23430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    ReadFontDataWithBuffer(rfd2, buffer_size, &b2);
23530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int result = memcmp(&(b1[offset]), &(b2[0]), length);
23630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    EXPECT_EQ(result, 0);
23730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
23830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
23930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // sliding window reads
24030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t window_size = 1; window_size <= length;
24130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun       window_size += increments) {
24230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    b1.clear();
24330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    b2.clear();
24430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    b1.resize(length);
24530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    b2.resize(length);
24630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    ReadFontDataWithSlidingWindow(rfd1, window_size, &b1);
24730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    ReadFontDataWithSlidingWindow(rfd2, window_size, &b2);
24830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int result = memcmp(&(b1[offset]), &(b2[0]), length);
24930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    EXPECT_EQ(result, 0);
25030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
25130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return true;
25230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
25330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
25430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid SlicingReadTest(ReadableFontData* rfd) {
25530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  fprintf(stderr, "read - trim = ");
25630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t trim = 0; trim < (rfd->Length() / 2) + 1;
25730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun       trim += (rfd->Length() / 21) + 1) {
25830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    fprintf(stderr, "%d ", trim);
25930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t length = rfd->Length() - 2 * trim;
26030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    ReadableFontDataPtr slice;
26130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    slice.Attach(down_cast<ReadableFontData*>(rfd->Slice(trim, length)));
26230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    EXPECT_TRUE(ReadComparison(trim, length, rfd, slice));
26330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
26430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  fprintf(stderr, "\n");
26530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
26630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
26730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid SlicingWriteTest(ReadableFontData* rfd, WritableFontData* wfd) {
26830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  fprintf(stderr, "write - trim = ");
26930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t trim = 0; trim < (rfd->Length() / 2) + 1;
27030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun       trim += (rfd->Length() / 21) + 1) {
27130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    fprintf(stderr, "%d ", trim);
27230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t length = rfd->Length() - 2 * trim;
27330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    WritableFontDataPtr w_slice;
27430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    ReadableFontDataPtr r_slice;
27530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
27630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    // single byte writes
27730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    w_slice.Attach(down_cast<WritableFontData*>(wfd->Slice(trim, length)));
27830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    r_slice.Attach(down_cast<ReadableFontData*>(rfd->Slice(trim, length)));
27930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    WriteFontDataWithSingleByte(r_slice, w_slice);
28030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    EXPECT_TRUE(ReadComparison(trim, length, rfd, w_slice));
28130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
28230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    // buffer writes
28330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t increments = std::max<int32_t>(length / 11, 1);
28430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    for (int32_t buffer_size = 1; buffer_size < length;
28530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun         buffer_size += increments) {
28630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      w_slice.Attach(down_cast<WritableFontData*>(wfd->Slice(trim, length)));
28730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      r_slice.Attach(down_cast<ReadableFontData*>(rfd->Slice(trim, length)));
28830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      WriteFontDataWithBuffer(r_slice, w_slice, buffer_size);
28930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      EXPECT_TRUE(ReadComparison(trim, length, rfd, w_slice));
29030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
29130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
29230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    // sliding window writes
29330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    for (int window_size = 1; window_size < length; window_size += increments) {
29430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      w_slice.Attach(down_cast<WritableFontData*>(wfd->Slice(trim, length)));
29530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      r_slice.Attach(down_cast<ReadableFontData*>(rfd->Slice(trim, length)));
29630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      WriteFontDataWithSlidingWindow(r_slice, w_slice, window_size);
29730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      EXPECT_TRUE(ReadComparison(trim, length, rfd, w_slice));
29830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
29930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
30030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  fprintf(stderr, "\n");
30130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
30230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
30330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool TestReadableFontData() {
30430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (size_t i = 0; i < sizeof(BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) {
30530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t size = BYTE_ARRAY_SIZES[i];
30630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    ByteArrayPtr ba = new MemoryByteArray(size);
30730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    FillTestByteArray(ba, size);
30830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    ReadableFontDataPtr rfd = new ReadableFontData(ba);
30930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    SlicingReadTest(rfd);
31030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
31130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return true;
31230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
31330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
31430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool TestWritableFontData() {
31530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (size_t i = 0; i < sizeof(BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) {
31630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t size = BYTE_ARRAY_SIZES[i];
31730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    ByteArrayPtr ba = new MemoryByteArray(size);
31830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    FillTestByteArray(ba, size);
31930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    WritableFontDataPtr wfd = new WritableFontData(ba);
32030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    SlicingReadTest(wfd);
32130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    ByteArrayPtr temp = new MemoryByteArray(size);
32230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    WritableFontDataPtr wfd_copy = new WritableFontData(temp);
32330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    SlicingWriteTest(wfd, wfd_copy);
32430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
32530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return true;
32630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
32730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
32830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}  // namespace sfntly
32930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
33030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunTEST(FontData, ReadableFontDataSearching) {
33130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ASSERT_TRUE(sfntly::TestReadableFontDataSearching());
33230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
33330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
33430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunTEST(FontData, All) {
33530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ASSERT_TRUE(sfntly::TestReadableFontData());
33630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ASSERT_TRUE(sfntly::TestWritableFontData());
33730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
338