[repacker] add make_extension_context_t.
This commit is contained in:
parent
f2a0e69162
commit
c61c05e431
|
@ -24,6 +24,10 @@
|
||||||
* Google Author(s): Garret Rieger
|
* Google Author(s): Garret Rieger
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "hb-set.hh"
|
||||||
|
#include "hb-priority-queue.hh"
|
||||||
|
#include "hb-serialize.hh"
|
||||||
|
|
||||||
#ifndef GRAPH_GRAPH_HH
|
#ifndef GRAPH_GRAPH_HH
|
||||||
#define GRAPH_GRAPH_HH
|
#define GRAPH_GRAPH_HH
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2022 Google, Inc.
|
||||||
|
*
|
||||||
|
* This is part of HarfBuzz, a text shaping library.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, without written agreement and without
|
||||||
|
* license or royalty fees, to use, copy, modify, and distribute this
|
||||||
|
* software and its documentation for any purpose, provided that the
|
||||||
|
* above copyright notice and the following two paragraphs appear in
|
||||||
|
* all copies of this software.
|
||||||
|
*
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||||
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||||
|
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||||
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||||
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
*
|
||||||
|
* Google Author(s): Garret Rieger
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gsubgpos-graph.hh"
|
||||||
|
|
||||||
|
namespace graph {
|
||||||
|
|
||||||
|
unsigned make_extension_context_t::num_non_ext_subtables () {
|
||||||
|
unsigned count = 0;
|
||||||
|
for (auto l : lookups.values ())
|
||||||
|
{
|
||||||
|
if (l->is_extension (table_tag)) continue;
|
||||||
|
count += l->number_of_subtables ();
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,13 +24,13 @@
|
||||||
* Google Author(s): Garret Rieger
|
* Google Author(s): Garret Rieger
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef GRAPH_GSUBGPOS_GRAPH_HH
|
|
||||||
#define GRAPH_GSUBGPOS_GRAPH_HH
|
|
||||||
|
|
||||||
#include "graph.hh"
|
#include "graph.hh"
|
||||||
#include "hb-ot-layout-gsubgpos.hh"
|
#include "hb-ot-layout-gsubgpos.hh"
|
||||||
#include "OT/Layout/GSUB/ExtensionSubst.hh"
|
#include "OT/Layout/GSUB/ExtensionSubst.hh"
|
||||||
|
|
||||||
|
#ifndef GRAPH_GSUBGPOS_GRAPH_HH
|
||||||
|
#define GRAPH_GSUBGPOS_GRAPH_HH
|
||||||
|
|
||||||
namespace graph {
|
namespace graph {
|
||||||
|
|
||||||
struct Lookup;
|
struct Lookup;
|
||||||
|
@ -69,10 +69,37 @@ struct GSTAR : public OT::GSUBGPOS
|
||||||
Lookup* lookup = (Lookup*) graph.object (lookup_idx).head;
|
Lookup* lookup = (Lookup*) graph.object (lookup_idx).head;
|
||||||
lookups.set (lookup_idx, lookup);
|
lookups.set (lookup_idx, lookup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct make_extension_context_t
|
||||||
|
{
|
||||||
|
hb_tag_t table_tag;
|
||||||
|
graph_t& graph;
|
||||||
|
hb_vector_t<char> buffer;
|
||||||
|
GSTAR* gstar;
|
||||||
|
hb_hashmap_t<unsigned, graph::Lookup*> lookups;
|
||||||
|
|
||||||
|
make_extension_context_t (hb_tag_t table_tag_,
|
||||||
|
graph_t& graph_)
|
||||||
|
: table_tag (table_tag_),
|
||||||
|
graph (graph_),
|
||||||
|
buffer (),
|
||||||
|
gstar (graph::GSTAR::graph_to_gstar (graph_)),
|
||||||
|
lookups ()
|
||||||
|
{
|
||||||
|
gstar->find_lookups (graph, lookups);
|
||||||
|
unsigned extension_size = OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::static_size;
|
||||||
|
buffer.alloc (num_non_ext_subtables () * extension_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool in_error () const
|
||||||
|
{
|
||||||
|
return buffer.in_error ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned num_non_ext_subtables ();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Lookup : public OT::Lookup
|
struct Lookup : public OT::Lookup
|
||||||
|
@ -87,15 +114,13 @@ struct Lookup : public OT::Lookup
|
||||||
return lookupType == extension_type (table_tag);
|
return lookupType == extension_type (table_tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool make_extension (hb_tag_t table_tag,
|
bool make_extension (make_extension_context_t& c,
|
||||||
graph_t& graph,
|
unsigned this_index)
|
||||||
unsigned this_index,
|
|
||||||
hb_vector_t<char>& buffer)
|
|
||||||
{
|
{
|
||||||
// TODO: use a context_t?
|
// TODO: use a context_t?
|
||||||
unsigned type = lookupType;
|
unsigned type = lookupType;
|
||||||
unsigned ext_type = extension_type (table_tag);
|
unsigned ext_type = extension_type (c.table_tag);
|
||||||
if (!ext_type || is_extension (table_tag))
|
if (!ext_type || is_extension (c.table_tag))
|
||||||
{
|
{
|
||||||
// NOOP
|
// NOOP
|
||||||
printf("Already extension (obj %u).\n", this_index);
|
printf("Already extension (obj %u).\n", this_index);
|
||||||
|
@ -109,11 +134,10 @@ struct Lookup : public OT::Lookup
|
||||||
|
|
||||||
for (unsigned i = 0; i < subTable.len; i++)
|
for (unsigned i = 0; i < subTable.len; i++)
|
||||||
{
|
{
|
||||||
unsigned subtable_index = graph.index_for_offset (this_index, &subTable[i]);
|
unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]);
|
||||||
if (!make_subtable_extension (graph,
|
if (!make_subtable_extension (c,
|
||||||
this_index,
|
this_index,
|
||||||
subtable_index,
|
subtable_index))
|
||||||
buffer))
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,23 +145,22 @@ struct Lookup : public OT::Lookup
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool make_subtable_extension (graph_t& graph,
|
bool make_subtable_extension (make_extension_context_t& c,
|
||||||
unsigned lookup_index,
|
unsigned lookup_index,
|
||||||
unsigned subtable_index,
|
unsigned subtable_index)
|
||||||
hb_vector_t<char>& buffer)
|
|
||||||
{
|
{
|
||||||
printf(" Promoting subtable %u in lookup %u to extension.\n", subtable_index, lookup_index);
|
printf(" Promoting subtable %u in lookup %u to extension.\n", subtable_index, lookup_index);
|
||||||
|
|
||||||
unsigned type = lookupType;
|
unsigned type = lookupType;
|
||||||
unsigned extension_size = OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::static_size;
|
unsigned extension_size = OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::static_size;
|
||||||
unsigned start = buffer.length;
|
unsigned start = c.buffer.length;
|
||||||
unsigned end = start + extension_size;
|
unsigned end = start + extension_size;
|
||||||
if (!buffer.resize (buffer.length + extension_size))
|
if (!c.buffer.resize (c.buffer.length + extension_size))
|
||||||
// TODO: resizing potentially invalidates existing head/tail pointers.
|
// TODO: resizing potentially invalidates existing head/tail pointers.
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension =
|
OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension =
|
||||||
(OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*) &buffer[start];
|
(OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*) &c.buffer[start];
|
||||||
extension->format = 1;
|
extension->format = 1;
|
||||||
extension->extensionLookupType = type;
|
extension->extensionLookupType = type;
|
||||||
extension->extensionOffset = 0;
|
extension->extensionOffset = 0;
|
||||||
|
@ -145,11 +168,11 @@ struct Lookup : public OT::Lookup
|
||||||
unsigned type_prime = extension->extensionLookupType;
|
unsigned type_prime = extension->extensionLookupType;
|
||||||
printf("Assigned type %d to extension\n", type_prime);
|
printf("Assigned type %d to extension\n", type_prime);
|
||||||
|
|
||||||
unsigned ext_index = graph.new_node (&buffer.arrayZ[start],
|
unsigned ext_index = c.graph.new_node (&c.buffer.arrayZ[start],
|
||||||
&buffer.arrayZ[end]);
|
&c.buffer.arrayZ[end]);
|
||||||
if (ext_index == (unsigned) -1) return false;
|
if (ext_index == (unsigned) -1) return false;
|
||||||
|
|
||||||
auto& lookup_vertex = graph.vertices_[lookup_index];
|
auto& lookup_vertex = c.graph.vertices_[lookup_index];
|
||||||
for (auto& l : lookup_vertex.obj.real_links.writer ())
|
for (auto& l : lookup_vertex.obj.real_links.writer ())
|
||||||
{
|
{
|
||||||
if (l.objidx == subtable_index)
|
if (l.objidx == subtable_index)
|
||||||
|
@ -161,9 +184,8 @@ struct Lookup : public OT::Lookup
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make extension point at the subtable.
|
// Make extension point at the subtable.
|
||||||
// TODO: update extension parents array.
|
auto& ext_vertex = c.graph.vertices_[ext_index];
|
||||||
auto& ext_vertex = graph.vertices_[ext_index];
|
auto& subtable_vertex = c.graph.vertices_[subtable_index];
|
||||||
auto& subtable_vertex = graph.vertices_[subtable_index];
|
|
||||||
auto* l = ext_vertex.obj.real_links.push ();
|
auto* l = ext_vertex.obj.real_links.push ();
|
||||||
|
|
||||||
l->width = 4;
|
l->width = 4;
|
||||||
|
|
|
@ -29,8 +29,6 @@
|
||||||
|
|
||||||
#include "hb-open-type.hh"
|
#include "hb-open-type.hh"
|
||||||
#include "hb-map.hh"
|
#include "hb-map.hh"
|
||||||
#include "hb-priority-queue.hh"
|
|
||||||
#include "hb-serialize.hh"
|
|
||||||
#include "hb-vector.hh"
|
#include "hb-vector.hh"
|
||||||
#include "graph/graph.hh"
|
#include "graph/graph.hh"
|
||||||
#include "graph/gsubgpos-graph.hh"
|
#include "graph/gsubgpos-graph.hh"
|
||||||
|
@ -44,35 +42,12 @@ using graph::graph_t;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
unsigned _num_non_ext_subtables (hb_tag_t table_tag,
|
bool _make_extensions (graph::make_extension_context_t& ext_context)
|
||||||
const hb_hashmap_t<unsigned, graph::Lookup*>& lookups)
|
|
||||||
{
|
|
||||||
unsigned count = 0;
|
|
||||||
for (auto l : lookups.values ())
|
|
||||||
{
|
|
||||||
if (l->is_extension (table_tag)) continue;
|
|
||||||
count += l->number_of_subtables ();
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline
|
|
||||||
bool _make_extensions (hb_tag_t table_tag, graph_t& sorted_graph, hb_vector_t<char>& buffer)
|
|
||||||
{
|
{
|
||||||
// TODO: Move this into graph or gsubgpos graph?
|
// TODO: Move this into graph or gsubgpos graph?
|
||||||
graph::GSTAR* gstar = graph::GSTAR::graph_to_gstar (sorted_graph);
|
for (auto p : ext_context.lookups.iter ())
|
||||||
hb_hashmap_t<unsigned, graph::Lookup*> lookups;
|
|
||||||
gstar->find_lookups (sorted_graph, lookups);
|
|
||||||
|
|
||||||
unsigned extension_size = OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::static_size;
|
|
||||||
if (!buffer.alloc (_num_non_ext_subtables (table_tag, lookups) * extension_size))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
|
|
||||||
for (auto p : lookups.iter ())
|
|
||||||
{
|
{
|
||||||
if (!p.second->make_extension (table_tag, sorted_graph, p.first, buffer))
|
if (!p.second->make_extension (ext_context, p.first))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -206,12 +181,15 @@ hb_resolve_overflows (const T& packed,
|
||||||
return graph::serialize (sorted_graph);
|
return graph::serialize (sorted_graph);
|
||||||
}
|
}
|
||||||
|
|
||||||
hb_vector_t<char> extension_buffer;
|
graph::make_extension_context_t ext_context (table_tag, sorted_graph);
|
||||||
|
if (ext_context.in_error ())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
if ((table_tag == HB_OT_TAG_GPOS
|
if ((table_tag == HB_OT_TAG_GPOS
|
||||||
|| table_tag == HB_OT_TAG_GSUB)
|
|| table_tag == HB_OT_TAG_GSUB)
|
||||||
&& will_overflow)
|
&& will_overflow)
|
||||||
{
|
{
|
||||||
if (!_make_extensions (table_tag, sorted_graph, extension_buffer)) {
|
if (!_make_extensions (ext_context)) {
|
||||||
printf("make extensions failed.\n");
|
printf("make extensions failed.\n");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -345,6 +345,7 @@ hb_subset_sources = files(
|
||||||
'hb-subset-plan.cc',
|
'hb-subset-plan.cc',
|
||||||
'hb-subset-plan.hh',
|
'hb-subset-plan.hh',
|
||||||
'hb-subset-repacker.cc',
|
'hb-subset-repacker.cc',
|
||||||
|
'graph/gsubgpos-graph.cc',
|
||||||
'hb-subset.cc',
|
'hb-subset.cc',
|
||||||
'hb-subset.hh',
|
'hb-subset.hh',
|
||||||
)
|
)
|
||||||
|
@ -565,7 +566,7 @@ if get_option('tests').enabled()
|
||||||
'test-number': ['test-number.cc', 'hb-number.cc'],
|
'test-number': ['test-number.cc', 'hb-number.cc'],
|
||||||
'test-ot-tag': ['hb-ot-tag.cc'],
|
'test-ot-tag': ['hb-ot-tag.cc'],
|
||||||
'test-priority-queue': ['test-priority-queue.cc', 'hb-static.cc'],
|
'test-priority-queue': ['test-priority-queue.cc', 'hb-static.cc'],
|
||||||
'test-repacker': ['test-repacker.cc', 'hb-static.cc'],
|
'test-repacker': ['test-repacker.cc', 'hb-static.cc', 'graph/gsubgpos-graph.cc'],
|
||||||
'test-set': ['test-set.cc', 'hb-static.cc'],
|
'test-set': ['test-set.cc', 'hb-static.cc'],
|
||||||
'test-serialize': ['test-serialize.cc', 'hb-static.cc'],
|
'test-serialize': ['test-serialize.cc', 'hb-static.cc'],
|
||||||
'test-unicode-ranges': ['test-unicode-ranges.cc'],
|
'test-unicode-ranges': ['test-unicode-ranges.cc'],
|
||||||
|
|
Loading…
Reference in New Issue