Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/gfx/ots/src/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 14 kB image not shown  

Quelle  glat.cc   Sprache: C

 
// 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 "mozilla/Compression.h"
#include <list>
#include <memory>

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) {
  assert(ShouldSerialize());
  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) {
  assert(ShouldSerialize());
  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::unique_ptr<uint8_t> decompressed(new uint8_t[decompressed_size]());
      size_t outputSize = 0;
      bool ret = mozilla::Compression::LZ4::decompressPartial(
          reinterpret_cast<const char*>(data + table.offset()),
          table.remaining(),  // input buffer size (input size + padding)
          reinterpret_cast<char*>(decompressed.get()),
          decompressed_size,  // target output size
          &outputSize);  // return output size
      if (!ret || outputSize != decompressed_size) {
        return DropGraphite("Decompression failed");
      }
      return this->Parse(decompressed.get(), 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) {
  assert(ShouldSerialize());
  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

Messung V0.5
C=93 H=94 G=93

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.