// Copyright (c) 2009-2017 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "glat.h"

#include "gloc.h"
#include "lz4.h"
#include <list>

namespace ots {

// -----------------------------------------------------------------------------
// OpenTypeGLAT_v1
// -----------------------------------------------------------------------------

bool OpenTypeGLAT_v1::Parse(const uint8_t* data, size_t length) {
  Buffer table(data, length);
  OpenTypeGLOC* gloc = static_cast<OpenTypeGLOC*>(
      GetFont()->GetTypedTable(OTS_TAG_GLOC));
  if (!gloc) {
    return DropGraphite("Required Gloc table is missing");
  }

  if (!table.ReadU32(&this->version) || this->version >> 16 != 1) {
    return DropGraphite("Failed to read version");
  }

  const std::vector<uint32_t>& locations = gloc->GetLocations();
  if (locations.empty()) {
    return DropGraphite("No locations from Gloc table");
  }
  std::list<uint32_t> unverified(locations.begin(), locations.end());
  while (table.remaining()) {
    GlatEntry entry(this);
    if (table.offset() > unverified.front()) {
      return DropGraphite("Offset check failed for a GlatEntry");
    }
    if (table.offset() == unverified.front()) {
      unverified.pop_front();
    }
    if (unverified.empty()) {
      return DropGraphite("Expected more locations");
    }
    if (!entry.ParsePart(table)) {
      return DropGraphite("Failed to read a GlatEntry");
    }
    this->entries.push_back(entry);
  }

  if (unverified.size() != 1 || unverified.front() != table.offset()) {
    return DropGraphite("%zu location(s) could not be verified", unverified.size());
  }
  if (table.remaining()) {
    return Warning("%zu bytes unparsed", table.remaining());
  }
  return true;
}

bool OpenTypeGLAT_v1::Serialize(OTSStream* out) {
  if (!out->WriteU32(this->version) ||
      !SerializeParts(this->entries, out)) {
    return Error("Failed to write table");
  }
  return true;
}

bool OpenTypeGLAT_v1::GlatEntry::ParsePart(Buffer& table) {
  if (!table.ReadU8(&this->attNum)) {
    return parent->Error("GlatEntry: Failed to read attNum");
  }
  if (!table.ReadU8(&this->num)) {
    return parent->Error("GlatEntry: Failed to read num");
  }

  //this->attributes.resize(this->num);
  for (int i = 0; i < this->num; ++i) {
    this->attributes.emplace_back();
    if (!table.ReadS16(&this->attributes[i])) {
      return parent->Error("GlatEntry: Failed to read attribute %u", i);
    }
  }
  return true;
}

bool OpenTypeGLAT_v1::GlatEntry::SerializePart(OTSStream* out) const {
  if (!out->WriteU8(this->attNum) ||
      !out->WriteU8(this->num) ||
      !SerializeParts(this->attributes, out)) {
    return parent->Error("GlatEntry: Failed to write");
  }
  return true;
}

// -----------------------------------------------------------------------------
// OpenTypeGLAT_v2
// -----------------------------------------------------------------------------

bool OpenTypeGLAT_v2::Parse(const uint8_t* data, size_t length) {
  Buffer table(data, length);
  OpenTypeGLOC* gloc = static_cast<OpenTypeGLOC*>(
      GetFont()->GetTypedTable(OTS_TAG_GLOC));
  if (!gloc) {
    return DropGraphite("Required Gloc table is missing");
  }

  if (!table.ReadU32(&this->version) || this->version >> 16 != 1) {
    return DropGraphite("Failed to read version");
  }

  const std::vector<uint32_t>& locations = gloc->GetLocations();
  if (locations.empty()) {
    return DropGraphite("No locations from Gloc table");
  }
  std::list<uint32_t> unverified(locations.begin(), locations.end());
  while (table.remaining()) {
    GlatEntry entry(this);
    if (table.offset() > unverified.front()) {
      return DropGraphite("Offset check failed for a GlatEntry");
    }
    if (table.offset() == unverified.front()) {
      unverified.pop_front();
    }
    if (unverified.empty()) {
      return DropGraphite("Expected more locations");
    }
    if (!entry.ParsePart(table)) {
      return DropGraphite("Failed to read a GlatEntry");
    }
    this->entries.push_back(entry);
  }

  if (unverified.size() != 1 || unverified.front() != table.offset()) {
    return DropGraphite("%zu location(s) could not be verified", unverified.size());
  }
  if (table.remaining()) {
    return Warning("%zu bytes unparsed", table.remaining());
  }
  return true;
}

bool OpenTypeGLAT_v2::Serialize(OTSStream* out) {
  if (!out->WriteU32(this->version) ||
      !SerializeParts(this->entries, out)) {
    return Error("Failed to write table");
  }
  return true;
}

bool OpenTypeGLAT_v2::GlatEntry::ParsePart(Buffer& table) {
  if (!table.ReadS16(&this->attNum)) {
    return parent->Error("GlatEntry: Failed to read attNum");
  }
  if (!table.ReadS16(&this->num) || this->num < 0) {
    return parent->Error("GlatEntry: Failed to read valid num");
  }

  //this->attributes.resize(this->num);
  for (int i = 0; i < this->num; ++i) {
    this->attributes.emplace_back();
    if (!table.ReadS16(&this->attributes[i])) {
      return parent->Error("GlatEntry: Failed to read attribute %u", i);
    }
  }
  return true;
}

bool OpenTypeGLAT_v2::GlatEntry::SerializePart(OTSStream* out) const {
  if (!out->WriteS16(this->attNum) ||
      !out->WriteS16(this->num) ||
      !SerializeParts(this->attributes, out)) {
    return parent->Error("GlatEntry: Failed to write");
  }
  return true;
}

// -----------------------------------------------------------------------------
// OpenTypeGLAT_v3
// -----------------------------------------------------------------------------

bool OpenTypeGLAT_v3::Parse(const uint8_t* data, size_t length,
                            bool prevent_decompression) {
  Buffer table(data, length);
  OpenTypeGLOC* gloc = static_cast<OpenTypeGLOC*>(
      GetFont()->GetTypedTable(OTS_TAG_GLOC));
  if (!gloc) {
    return DropGraphite("Required Gloc table is missing");
  }

  if (!table.ReadU32(&this->version) || this->version >> 16 != 3) {
    return DropGraphite("Failed to read version");
  }
  if (!table.ReadU32(&this->compHead)) {
    return DropGraphite("Failed to read compression header");
  }
  switch ((this->compHead & SCHEME) >> 27) {
    case 0:  // uncompressed
      break;
    case 1: {  // lz4
      if (prevent_decompression) {
        return DropGraphite("Illegal nested compression");
      }
      size_t decompressed_size = this->compHead & FULL_SIZE;
      if (decompressed_size < length) {
        return DropGraphite("Decompressed size is less than compressed size");
      }
      if (decompressed_size == 0) {
        return DropGraphite("Decompressed size is set to 0");
      }
      // decompressed table must be <= OTS_MAX_DECOMPRESSED_TABLE_SIZE
      if (decompressed_size > OTS_MAX_DECOMPRESSED_TABLE_SIZE) {
        return DropGraphite("Decompressed size exceeds %gMB: %gMB",
                            OTS_MAX_DECOMPRESSED_TABLE_SIZE / (1024.0 * 1024.0),
                            decompressed_size / (1024.0 * 1024.0));
      }
      std::vector<uint8_t> decompressed(decompressed_size);
      int ret = LZ4_decompress_safe_partial(
          reinterpret_cast<const char*>(data + table.offset()),
          reinterpret_cast<char*>(decompressed.data()),
          table.remaining(),  // input buffer size (input size + padding)
          decompressed.size(),  // target output size
          decompressed.size());  // output buffer size
      if (ret < 0 || unsigned(ret) != decompressed.size()) {
        return DropGraphite("Decompression failed with error code %d", ret);
      }
      return this->Parse(decompressed.data(), decompressed.size(), true);
    }
    default:
      return DropGraphite("Unknown compression scheme");
  }
  if (this->compHead & RESERVED) {
    Warning("Nonzero reserved");
  }

  const std::vector<uint32_t>& locations = gloc->GetLocations();
  if (locations.empty()) {
    return DropGraphite("No locations from Gloc table");
  }
  std::list<uint32_t> unverified(locations.begin(), locations.end());
  //this->entries.resize(locations.size() - 1, this);
  for (size_t i = 0; i < locations.size() - 1; ++i) {
    this->entries.emplace_back(this);
    if (table.offset() != unverified.front()) {
      return DropGraphite("Offset check failed for a GlyphAttrs");
    }
    unverified.pop_front();
    if (!this->entries[i].ParsePart(table,
                                    unverified.front() - table.offset())) {
        // unverified.front() is guaranteed to exist because of the number of
        // iterations of this loop
      return DropGraphite("Failed to read a GlyphAttrs");
    }
  }

  if (unverified.size() != 1 || unverified.front() != table.offset()) {
    return DropGraphite("%zu location(s) could not be verified", unverified.size());
  }
  if (table.remaining()) {
    return Warning("%zu bytes unparsed", table.remaining());
  }
  return true;
}

bool OpenTypeGLAT_v3::Serialize(OTSStream* out) {
  if (!out->WriteU32(this->version) ||
      !out->WriteU32(this->compHead) ||
      !SerializeParts(this->entries, out)) {
    return Error("Failed to write table");
  }
  return true;
}

bool OpenTypeGLAT_v3::GlyphAttrs::ParsePart(Buffer& table, const size_t size) {
  size_t init_offset = table.offset();
  if (parent->compHead & OCTABOXES && !octabox.ParsePart(table)) {
    // parent->flags & 0b1: octaboxes are present flag
    return parent->Error("GlyphAttrs: Failed to read octabox");
  }

  while (table.offset() < init_offset + size) {
    GlatEntry entry(parent);
    if (!entry.ParsePart(table)) {
      return parent->Error("GlyphAttrs: Failed to read a GlatEntry");
    }
    this->entries.push_back(entry);
  }
  return true;
}

bool OpenTypeGLAT_v3::GlyphAttrs::SerializePart(OTSStream* out) const {
  if ((parent->compHead & OCTABOXES && !octabox.SerializePart(out)) ||
      !SerializeParts(this->entries, out)) {
    return parent->Error("GlyphAttrs: Failed to write");
  }
  return true;
}

bool OpenTypeGLAT_v3::GlyphAttrs::
OctaboxMetrics::ParsePart(Buffer& table) {
  if (!table.ReadU16(&this->subbox_bitmap)) {
    return parent->Error("OctaboxMetrics: Failed to read subbox_bitmap");
  }
  if (!table.ReadU8(&this->diag_neg_min)) {
    return parent->Error("OctaboxMetrics: Failed to read diag_neg_min");
  }
  if (!table.ReadU8(&this->diag_neg_max) ||
      this->diag_neg_max < this->diag_neg_min) {
    return parent->Error("OctaboxMetrics: Failed to read valid diag_neg_max");
  }
  if (!table.ReadU8(&this->diag_pos_min)) {
    return parent->Error("OctaboxMetrics: Failed to read diag_pos_min");
  }
  if (!table.ReadU8(&this->diag_pos_max) ||
      this->diag_pos_max < this->diag_pos_min) {
    return parent->Error("OctaboxMetrics: Failed to read valid diag_pos_max");
  }

  unsigned subboxes_len = 0;  // count of 1's in this->subbox_bitmap
  for (uint16_t i = this->subbox_bitmap; i; i >>= 1) {
    if (i & 0b1) {
      ++subboxes_len;
    }
  }
  //this->subboxes.resize(subboxes_len, parent);
  for (unsigned i = 0; i < subboxes_len; i++) {
    this->subboxes.emplace_back(parent);
    if (!this->subboxes[i].ParsePart(table)) {
      return parent->Error("OctaboxMetrics: Failed to read subbox[%u]", i);
    }
  }
  return true;
}

bool OpenTypeGLAT_v3::GlyphAttrs::
OctaboxMetrics::SerializePart(OTSStream* out) const {
  if (!out->WriteU16(this->subbox_bitmap) ||
      !out->WriteU8(this->diag_neg_min) ||
      !out->WriteU8(this->diag_neg_max) ||
      !out->WriteU8(this->diag_pos_min) ||
      !out->WriteU8(this->diag_pos_max) ||
      !SerializeParts(this->subboxes, out)) {
    return parent->Error("OctaboxMetrics: Failed to write");
  }
  return true;
}

bool OpenTypeGLAT_v3::GlyphAttrs::OctaboxMetrics::
SubboxEntry::ParsePart(Buffer& table) {
  if (!table.ReadU8(&this->left)) {
    return parent->Error("SubboxEntry: Failed to read left");
  }
  if (!table.ReadU8(&this->right) || this->right < this->left) {
    return parent->Error("SubboxEntry: Failed to read valid right");
  }
  if (!table.ReadU8(&this->bottom)) {
    return parent->Error("SubboxEntry: Failed to read bottom");
  }
  if (!table.ReadU8(&this->top) || this->top < this->bottom) {
    return parent->Error("SubboxEntry: Failed to read valid top");
  }
  if (!table.ReadU8(&this->diag_pos_min)) {
    return parent->Error("SubboxEntry: Failed to read diag_pos_min");
  }
  if (!table.ReadU8(&this->diag_pos_max) ||
      this->diag_pos_max < this->diag_pos_min) {
    return parent->Error("SubboxEntry: Failed to read valid diag_pos_max");
  }
  if (!table.ReadU8(&this->diag_neg_min)) {
    return parent->Error("SubboxEntry: Failed to read diag_neg_min");
  }
  if (!table.ReadU8(&this->diag_neg_max) ||
      this->diag_neg_max < this->diag_neg_min) {
    return parent->Error("SubboxEntry: Failed to read valid diag_neg_max");
  }
  return true;
}

bool OpenTypeGLAT_v3::GlyphAttrs::OctaboxMetrics::
SubboxEntry::SerializePart(OTSStream* out) const {
  if (!out->WriteU8(this->left) ||
      !out->WriteU8(this->right) ||
      !out->WriteU8(this->bottom) ||
      !out->WriteU8(this->top) ||
      !out->WriteU8(this->diag_pos_min) ||
      !out->WriteU8(this->diag_pos_max) ||
      !out->WriteU8(this->diag_neg_min) ||
      !out->WriteU8(this->diag_neg_max)) {
    return parent->Error("SubboxEntry: Failed to write");
  }
  return true;
}

bool OpenTypeGLAT_v3::GlyphAttrs::
GlatEntry::ParsePart(Buffer& table) {
  if (!table.ReadS16(&this->attNum)) {
    return parent->Error("GlatEntry: Failed to read attNum");
  }
  if (!table.ReadS16(&this->num) || this->num < 0) {
    return parent->Error("GlatEntry: Failed to read valid num");
  }

  //this->attributes.resize(this->num);
  for (int i = 0; i < this->num; ++i) {
    this->attributes.emplace_back();
    if (!table.ReadS16(&this->attributes[i])) {
      return parent->Error("GlatEntry: Failed to read attribute %u", i);
    }
  }
  return true;
}

bool OpenTypeGLAT_v3::GlyphAttrs::
GlatEntry::SerializePart(OTSStream* out) const {
  if (!out->WriteS16(this->attNum) ||
      !out->WriteS16(this->num) ||
      !SerializeParts(this->attributes, out)) {
    return parent->Error("GlatEntry: Failed to write");
  }
  return true;
}

// -----------------------------------------------------------------------------
// OpenTypeGLAT
// -----------------------------------------------------------------------------

bool OpenTypeGLAT::Parse(const uint8_t* data, size_t length) {
  Buffer table(data, length);
  uint32_t version;
  if (!table.ReadU32(&version)) {
    return DropGraphite("Failed to read version");
  }
  switch (version >> 16) {
    case 1:
      this->handler = new OpenTypeGLAT_v1(this->font, this->tag);
      break;
    case 2:
      this->handler = new OpenTypeGLAT_v2(this->font, this->tag);
      break;
    case 3: {
      this->handler = new OpenTypeGLAT_v3(this->font, this->tag);
      break;
    }
    default:
      return DropGraphite("Unsupported table version: %u", version >> 16);
  }
  return this->handler->Parse(data, length);
}

bool OpenTypeGLAT::Serialize(OTSStream* out) {
  if (!this->handler) {
    return Error("No Glat table parsed");
  }
  return this->handler->Serialize(out);
}

}  // namespace ots
