// Copyright 2013 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Glyph normalization

#include "./normalize.h"

#include <inttypes.h>
#include <stddef.h>

#include "./ots.h"
#include "./port.h"
#include "./font.h"
#include "./glyph.h"
#include "./round.h"
#include "./store_bytes.h"

namespace woff2 {

namespace {

void StoreLoca(int index_fmt, uint32_t value, size_t* offset, uint8_t* dst) {
  if (index_fmt == 0) {
    Store16(value >> 1, offset, dst);
  } else {
    StoreU32(value, offset, dst);
  }
}

void NormalizeSimpleGlyphBoundingBox(Glyph* glyph) {
  if (glyph->contours.empty() || glyph->contours[0].empty()) {
    return;
  }
  int16_t x_min = glyph->contours[0][0].x;
  int16_t y_min = glyph->contours[0][0].y;
  int16_t x_max = x_min;
  int16_t y_max = y_min;
  for (const auto& contour : glyph->contours) {
    for (const auto& point : contour) {
      if (point.x < x_min) x_min = point.x;
      if (point.x > x_max) x_max = point.x;
      if (point.y < y_min) y_min = point.y;
      if (point.y > y_max) y_max = point.y;
    }
  }
  glyph->x_min = x_min;
  glyph->y_min = y_min;
  glyph->x_max = x_max;
  glyph->y_max = y_max;
}

}  // namespace

bool NormalizeGlyphs(Font* font) {
  Font::Table* head_table = font->FindTable(kHeadTableTag);
  Font::Table* glyf_table = font->FindTable(kGlyfTableTag);
  Font::Table* loca_table = font->FindTable(kLocaTableTag);
  if (head_table == NULL || loca_table == NULL || glyf_table == NULL) {
    return OTS_FAILURE();
  }
  int index_fmt = head_table->data[51];
  int num_glyphs = NumGlyphs(*font);

  // We need to allocate a bit more than its original length for the normalized
  // glyf table, since it can happen that the glyphs in the original table are
  // 2-byte aligned, while in the normalized table they are 4-byte aligned.
  // That gives a maximum of 2 bytes increase per glyph. However, there is no
  // theoretical guarantee that the total size of the flags plus the coordinates
  // is the smallest possible in the normalized version, so we have to allow
  // some general overhead.
  // TODO(user) Figure out some more precise upper bound on the size of
  // the overhead.
  size_t max_normalized_glyf_size = 1.1 * glyf_table->length + 2 * num_glyphs;

  glyf_table->buffer.resize(max_normalized_glyf_size);
  loca_table->buffer.resize(Round4(loca_table->length));
  uint8_t* glyf_dst = &glyf_table->buffer[0];
  uint8_t* loca_dst = &loca_table->buffer[0];
  uint32_t glyf_offset = 0;
  size_t loca_offset = 0;

  for (int i = 0; i < num_glyphs; ++i) {
    StoreLoca(index_fmt, glyf_offset, &loca_offset, loca_dst);
    Glyph glyph;
    const uint8_t* glyph_data;
    size_t glyph_size;
    if (!GetGlyphData(*font, i, &glyph_data, &glyph_size) ||
        (glyph_size > 0 && !ReadGlyph(glyph_data, glyph_size, &glyph))) {
      return OTS_FAILURE();
    }
    NormalizeSimpleGlyphBoundingBox(&glyph);
    size_t glyf_dst_size = glyf_table->buffer.size() - glyf_offset;
    if (!StoreGlyph(glyph, glyf_dst + glyf_offset, &glyf_dst_size)) {
      return OTS_FAILURE();
    }
    glyf_dst_size = Round4(glyf_dst_size);
    if (glyf_dst_size > std::numeric_limits<uint32_t>::max() ||
        glyf_offset + static_cast<uint32_t>(glyf_dst_size) < glyf_offset ||
        (index_fmt == 0 && glyf_offset + glyf_dst_size >= (1UL << 17))) {
      return OTS_FAILURE();
    }
    glyf_offset += glyf_dst_size;
  }
  StoreLoca(index_fmt, glyf_offset, &loca_offset, loca_dst);

  glyf_table->buffer.resize(glyf_offset);
  glyf_table->data = &glyf_table->buffer[0];
  glyf_table->length = glyf_offset;
  loca_table->data = &loca_table->buffer[0];

  return true;
}

bool NormalizeOffsets(Font* font) {
  uint32_t offset = 12 + 16 * font->num_tables;
  for (auto& i : font->tables) {
    i.second.offset = offset;
    offset += Round4(i.second.length);
  }
  return true;
}

namespace {

uint32_t ComputeChecksum(const uint8_t* buf, size_t size) {
  uint32_t checksum = 0;
  for (size_t i = 0; i < size; i += 4) {
    checksum += ((buf[i] << 24) |
                 (buf[i + 1] << 16) |
                 (buf[i + 2] << 8) |
                 buf[i + 3]);
  }
  return checksum;
}

uint32_t ComputeHeaderChecksum(const Font& font) {
  uint32_t checksum = font.flavor;
  uint16_t max_pow2 = font.num_tables ? Log2Floor(font.num_tables) : 0;
  uint16_t search_range = max_pow2 ? 1 << (max_pow2 + 4) : 0;
  uint16_t range_shift = (font.num_tables << 4) - search_range;
  checksum += (font.num_tables << 16 | search_range);
  checksum += (max_pow2 << 16 | range_shift);
  for (const auto& i : font.tables) {
    checksum += i.second.tag;
    checksum += i.second.checksum;
    checksum += i.second.offset;
    checksum += i.second.length;
  }
  return checksum;
}

}  // namespace

bool FixChecksums(Font* font) {
  Font::Table* head_table = font->FindTable(kHeadTableTag);
  if (head_table == NULL || head_table->length < 12) {
    return OTS_FAILURE();
  }
  head_table->buffer.resize(Round4(head_table->length));
  uint8_t* head_buf = &head_table->buffer[0];
  memcpy(head_buf, head_table->data, Round4(head_table->length));
  head_table->data = head_buf;
  size_t offset = 8;
  StoreU32(0, &offset, head_buf);
  uint32_t file_checksum = 0;
  for (auto& i : font->tables) {
    Font::Table* table = &i.second;
    table->checksum = ComputeChecksum(table->data, table->length);
    file_checksum += table->checksum;
  }
  file_checksum += ComputeHeaderChecksum(*font);
  offset = 8;
  StoreU32(0xb1b0afba - file_checksum, &offset, head_buf);
  return true;
}

bool NormalizeFont(Font* font) {
  return (NormalizeGlyphs(font) &&
          NormalizeOffsets(font) &&
          FixChecksums(font));
}

} // namespace woff2
