From 74f45f7c2ac4bb1d465926ebf2c3fba5a4572767 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Fri, 24 Jun 2022 23:14:30 +0000 Subject: [PATCH] [reorg] Move remaining GPOS lookup types to new directory. --- src/OT/Layout/GPOS/ChainContextPos.hh | 14 + src/OT/Layout/GPOS/ContextPos.hh | 14 + src/OT/Layout/GPOS/ExtensionPos.hh | 17 + src/OT/Layout/GPOS/GPOS.hh | 101 +++++- src/OT/Layout/GPOS/MarkBasePos.hh | 1 + src/OT/Layout/GPOS/MarkLigPos.hh | 1 + src/OT/Layout/GPOS/MarkMarkPos.hh | 36 +++ src/OT/Layout/GPOS/MarkMarkPosFormat1.hh | 227 ++++++++++++++ src/OT/Layout/GPOS/PosLookup.hh | 1 - src/OT/Layout/GPOS/PosLookupSubTable.hh | 6 +- src/OT/Layout/GPOS/ValueFormat.hh | 2 + src/hb-ot-layout-gpos-table.hh | 382 +---------------------- src/hb-ot-layout.cc | 15 +- src/hb-subset-plan.cc | 6 +- src/hb-subset.cc | 3 +- 15 files changed, 442 insertions(+), 384 deletions(-) create mode 100644 src/OT/Layout/GPOS/ChainContextPos.hh create mode 100644 src/OT/Layout/GPOS/ContextPos.hh create mode 100644 src/OT/Layout/GPOS/ExtensionPos.hh create mode 100644 src/OT/Layout/GPOS/MarkMarkPos.hh create mode 100644 src/OT/Layout/GPOS/MarkMarkPosFormat1.hh diff --git a/src/OT/Layout/GPOS/ChainContextPos.hh b/src/OT/Layout/GPOS/ChainContextPos.hh new file mode 100644 index 000000000..3b9c3022c --- /dev/null +++ b/src/OT/Layout/GPOS/ChainContextPos.hh @@ -0,0 +1,14 @@ +#ifndef OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH +#define OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH + +namespace OT { +namespace Layout { +namespace GPOS { + +struct ChainContextPos : ChainContext {}; + +} +} +} + +#endif /* OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH */ diff --git a/src/OT/Layout/GPOS/ContextPos.hh b/src/OT/Layout/GPOS/ContextPos.hh new file mode 100644 index 000000000..f4ec6f30e --- /dev/null +++ b/src/OT/Layout/GPOS/ContextPos.hh @@ -0,0 +1,14 @@ +#ifndef OT_LAYOUT_GPOS_CONTEXTPOS_HH +#define OT_LAYOUT_GPOS_CONTEXTPOS_HH + +namespace OT { +namespace Layout { +namespace GPOS { + +struct ContextPos : Context {}; + +} +} +} + +#endif /* OT_LAYOUT_GPOS_CONTEXTPOS_HH */ diff --git a/src/OT/Layout/GPOS/ExtensionPos.hh b/src/OT/Layout/GPOS/ExtensionPos.hh new file mode 100644 index 000000000..89c6de2fd --- /dev/null +++ b/src/OT/Layout/GPOS/ExtensionPos.hh @@ -0,0 +1,17 @@ +#ifndef OT_LAYOUT_GPOS_EXTENSIONPOS_HH +#define OT_LAYOUT_GPOS_EXTENSIONPOS_HH + +namespace OT { +namespace Layout { +namespace GPOS { + +struct ExtensionPos : Extension +{ + typedef struct PosLookupSubTable SubTable; +}; + +} +} +} + +#endif /* OT_LAYOUT_GPOS_EXTENSIONPOS_HH */ diff --git a/src/OT/Layout/GPOS/GPOS.hh b/src/OT/Layout/GPOS/GPOS.hh index 28a54d939..d914e0281 100644 --- a/src/OT/Layout/GPOS/GPOS.hh +++ b/src/OT/Layout/GPOS/GPOS.hh @@ -1,15 +1,22 @@ #ifndef OT_LAYOUT_GPOS_GPOS_HH #define OT_LAYOUT_GPOS_GPOS_HH -// TODO(garretrieger): move to new layout. #include "../../../hb-ot-layout-common.hh" #include "../../../hb-ot-layout-gsubgpos.hh" +#include "Common.hh" #include "PosLookup.hh" namespace OT { namespace Layout { namespace GPOS { +static void +propagate_attachment_offsets (hb_glyph_position_t *pos, + unsigned int len, + unsigned int i, + hb_direction_t direction, + unsigned nesting_level = HB_MAX_NESTING_LEVEL); + /* * GPOS -- Glyph Positioning * https://docs.microsoft.com/en-us/typography/opentype/spec/gpos @@ -58,12 +65,104 @@ struct GPOS : GSUBGPOS typedef GSUBGPOS::accelerator_t accelerator_t; }; + +static void +propagate_attachment_offsets (hb_glyph_position_t *pos, + unsigned int len, + unsigned int i, + hb_direction_t direction) +{ + /* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate + * offset of glyph they are attached to. */ + int chain = pos[i].attach_chain(), type = pos[i].attach_type(); + if (likely (!chain)) + return; + + pos[i].attach_chain() = 0; + + unsigned int j = (int) i + chain; + + if (unlikely (j >= len)) + return; + + if (unlikely (!nesting_level)) + return; + + propagate_attachment_offsets (pos, len, j, direction, nesting_level - 1); + + assert (!!(type & ATTACH_TYPE_MARK) ^ !!(type & ATTACH_TYPE_CURSIVE)); + + if (type & ATTACH_TYPE_CURSIVE) + { + if (HB_DIRECTION_IS_HORIZONTAL (direction)) + pos[i].y_offset += pos[j].y_offset; + else + pos[i].x_offset += pos[j].x_offset; + } + else /*if (type & ATTACH_TYPE_MARK)*/ + { + pos[i].x_offset += pos[j].x_offset; + pos[i].y_offset += pos[j].y_offset; + + assert (j < i); + if (HB_DIRECTION_IS_FORWARD (direction)) + for (unsigned int k = j; k < i; k++) { + pos[i].x_offset -= pos[k].x_advance; + pos[i].y_offset -= pos[k].y_advance; + } + else + for (unsigned int k = j + 1; k < i + 1; k++) { + pos[i].x_offset += pos[k].x_advance; + pos[i].y_offset += pos[k].y_advance; + } + } +} + +void +GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) +{ + unsigned int count = buffer->len; + for (unsigned int i = 0; i < count; i++) + buffer->pos[i].attach_chain() = buffer->pos[i].attach_type() = 0; +} + +void +GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED) +{ + //_hb_buffer_assert_gsubgpos_vars (buffer); +} + +void +GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer) +{ + _hb_buffer_assert_gsubgpos_vars (buffer); + + unsigned int len; + hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len); + hb_direction_t direction = buffer->props.direction; + + /* Handle attachments */ + if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT) + for (unsigned i = 0; i < len; i++) + propagate_attachment_offsets (pos, len, i, direction); + + if (unlikely (font->slant)) + { + for (unsigned i = 0; i < len; i++) + if (unlikely (pos[i].y_offset)) + pos[i].x_offset += _hb_roundf (font->slant_xy * pos[i].y_offset); + } +} + } } struct GPOS_accelerator_t : Layout::GPOS::GPOS::accelerator_t { GPOS_accelerator_t (hb_face_t *face) : Layout::GPOS::GPOS::accelerator_t (face) {} }; + } + + #endif /* OT_LAYOUT_GSUB_GSUB_HH */ diff --git a/src/OT/Layout/GPOS/MarkBasePos.hh b/src/OT/Layout/GPOS/MarkBasePos.hh index 818da9ef2..31938f866 100644 --- a/src/OT/Layout/GPOS/MarkBasePos.hh +++ b/src/OT/Layout/GPOS/MarkBasePos.hh @@ -15,6 +15,7 @@ struct MarkBasePos MarkBasePosFormat1 format1; } u; + public: template typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { diff --git a/src/OT/Layout/GPOS/MarkLigPos.hh b/src/OT/Layout/GPOS/MarkLigPos.hh index d80c3cea0..2597d6976 100644 --- a/src/OT/Layout/GPOS/MarkLigPos.hh +++ b/src/OT/Layout/GPOS/MarkLigPos.hh @@ -15,6 +15,7 @@ struct MarkLigPos MarkLigPosFormat1 format1; } u; + public: template typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { diff --git a/src/OT/Layout/GPOS/MarkMarkPos.hh b/src/OT/Layout/GPOS/MarkMarkPos.hh new file mode 100644 index 000000000..e600f1550 --- /dev/null +++ b/src/OT/Layout/GPOS/MarkMarkPos.hh @@ -0,0 +1,36 @@ +#ifndef OT_LAYOUT_GPOS_MARKMARKPOS_HH +#define OT_LAYOUT_GPOS_MARKMARKPOS_HH + +#include "MarkMarkPosFormat1.hh" + +namespace OT { +namespace Layout { +namespace GPOS { + +struct MarkMarkPos +{ + protected: + union { + HBUINT16 format; /* Format identifier */ + MarkMarkPosFormat1 format1; + } u; + + public: + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const + { + TRACE_DISPATCH (this, u.format); + if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { + case 1: return_trace (c->dispatch (u.format1, std::forward (ds)...)); + default:return_trace (c->default_return_value ()); + } + } +}; + + +} +} +} + +#endif /* OT_LAYOUT_GPOS_MARKMARKPOS_HH */ diff --git a/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh b/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh new file mode 100644 index 000000000..ebe31bbec --- /dev/null +++ b/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh @@ -0,0 +1,227 @@ +#ifndef OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH +#define OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH + +#include "MarkMarkPosFormat1.hh" + +namespace OT { +namespace Layout { +namespace GPOS { + +typedef AnchorMatrix Mark2Array; /* mark2-major-- + * in order of Mark2Coverage Index--, + * mark1-minor-- + * ordered by class--zero-based. */ + +struct MarkMarkPosFormat1 +{ + protected: + HBUINT16 format; /* Format identifier--format = 1 */ + Offset16To + mark1Coverage; /* Offset to Combining Mark1 Coverage + * table--from beginning of MarkMarkPos + * subtable */ + Offset16To + mark2Coverage; /* Offset to Combining Mark2 Coverage + * table--from beginning of MarkMarkPos + * subtable */ + HBUINT16 classCount; /* Number of defined mark classes */ + Offset16To + mark1Array; /* Offset to Mark1Array table--from + * beginning of MarkMarkPos subtable */ + Offset16To + mark2Array; /* Offset to Mark2Array table--from + * beginning of MarkMarkPos subtable */ + public: + DEFINE_SIZE_STATIC (12); + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + mark1Coverage.sanitize (c, this) && + mark2Coverage.sanitize (c, this) && + mark1Array.sanitize (c, this) && + mark2Array.sanitize (c, this, (unsigned int) classCount)); + } + + bool intersects (const hb_set_t *glyphs) const + { + return (this+mark1Coverage).intersects (glyphs) && + (this+mark2Coverage).intersects (glyphs); + } + + void closure_lookups (hb_closure_lookups_context_t *c) const {} + + void collect_variation_indices (hb_collect_variation_indices_context_t *c) const + { + + hb_zip (this+mark1Coverage, this+mark1Array) + | hb_filter (c->glyph_set, hb_first) + | hb_map (hb_second) + | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+mark1Array)); }) + ; + + hb_map_t klass_mapping; + Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, *c->glyph_set, &klass_mapping); + + unsigned mark2_count = (this+mark2Array).rows; + auto mark2_iter = + + hb_zip (this+mark2Coverage, hb_range (mark2_count)) + | hb_filter (c->glyph_set, hb_first) + | hb_map (hb_second) + ; + + hb_sorted_vector_t mark2_indexes; + for (const unsigned row : mark2_iter) + { + + hb_range ((unsigned) classCount) + | hb_filter (klass_mapping) + | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; }) + | hb_sink (mark2_indexes) + ; + } + (this+mark2Array).collect_variation_indices (c, mark2_indexes.iter ()); + } + + void collect_glyphs (hb_collect_glyphs_context_t *c) const + { + if (unlikely (!(this+mark1Coverage).collect_coverage (c->input))) return; + if (unlikely (!(this+mark2Coverage).collect_coverage (c->input))) return; + } + + const Coverage &get_coverage () const { return this+mark1Coverage; } + + bool apply (hb_ot_apply_context_t *c) const + { + TRACE_APPLY (this); + hb_buffer_t *buffer = c->buffer; + unsigned int mark1_index = (this+mark1Coverage).get_coverage (buffer->cur().codepoint); + if (likely (mark1_index == NOT_COVERED)) return_trace (false); + + /* now we search backwards for a suitable mark glyph until a non-mark glyph */ + hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; + skippy_iter.reset (buffer->idx, 1); + skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags); + unsigned unsafe_from; + if (!skippy_iter.prev (&unsafe_from)) + { + buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1); + return_trace (false); + } + + if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])) + { + buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); + return_trace (false); + } + + unsigned int j = skippy_iter.idx; + + unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur()); + unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]); + unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur()); + unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]); + + if (likely (id1 == id2)) + { + if (id1 == 0) /* Marks belonging to the same base. */ + goto good; + else if (comp1 == comp2) /* Marks belonging to the same ligature component. */ + goto good; + } + else + { + /* If ligature ids don't match, it may be the case that one of the marks + * itself is a ligature. In which case match. */ + if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2)) + goto good; + } + + /* Didn't match. */ + buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); + return_trace (false); + + good: + unsigned int mark2_index = (this+mark2Coverage).get_coverage (buffer->info[j].codepoint); + if (mark2_index == NOT_COVERED) + { + buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); + return_trace (false); + } + + return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j)); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); + const hb_map_t &glyph_map = *c->plan->glyph_map; + + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + out->format = format; + + hb_map_t klass_mapping; + Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, glyphset, &klass_mapping); + + if (!klass_mapping.get_population ()) return_trace (false); + out->classCount = klass_mapping.get_population (); + + auto mark1_iter = + + hb_zip (this+mark1Coverage, this+mark1Array) + | hb_filter (glyphset, hb_first) + ; + + hb_sorted_vector_t new_coverage; + + mark1_iter + | hb_map (hb_first) + | hb_map (glyph_map) + | hb_sink (new_coverage) + ; + + if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ())) + return_trace (false); + + out->mark1Array.serialize_subset (c, mark1Array, this, + (this+mark1Coverage).iter (), + &klass_mapping); + + unsigned mark2count = (this+mark2Array).rows; + auto mark2_iter = + + hb_zip (this+mark2Coverage, hb_range (mark2count)) + | hb_filter (glyphset, hb_first) + ; + + new_coverage.reset (); + + mark2_iter + | hb_map (hb_first) + | hb_map (glyph_map) + | hb_sink (new_coverage) + ; + + if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ())) + return_trace (false); + + hb_sorted_vector_t mark2_indexes; + for (const unsigned row : + mark2_iter + | hb_map (hb_second)) + { + + hb_range ((unsigned) classCount) + | hb_filter (klass_mapping) + | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; }) + | hb_sink (mark2_indexes) + ; + } + + out->mark2Array.serialize_subset (c, mark2Array, this, mark2_iter.len (), mark2_indexes.iter ()); + + return_trace (true); + } +}; + + +} +} +} + +#endif /* OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH */ diff --git a/src/OT/Layout/GPOS/PosLookup.hh b/src/OT/Layout/GPOS/PosLookup.hh index e8e1b2c97..336689391 100644 --- a/src/OT/Layout/GPOS/PosLookup.hh +++ b/src/OT/Layout/GPOS/PosLookup.hh @@ -72,7 +72,6 @@ struct PosLookup : Lookup { return Lookup::sanitize (c); } }; - } } } diff --git a/src/OT/Layout/GPOS/PosLookupSubTable.hh b/src/OT/Layout/GPOS/PosLookupSubTable.hh index acec901bd..c90b771d8 100644 --- a/src/OT/Layout/GPOS/PosLookupSubTable.hh +++ b/src/OT/Layout/GPOS/PosLookupSubTable.hh @@ -6,6 +6,10 @@ #include "CursivePos.hh" #include "MarkBasePos.hh" #include "MarkLigPos.hh" +#include "MarkMarkPos.hh" +#include "ContextPos.hh" +#include "ChainContextPos.hh" +#include "ExtensionPos.hh" namespace OT { namespace Layout { @@ -13,7 +17,7 @@ namespace GPOS { struct PosLookupSubTable { - friend struct Lookup; + friend struct ::OT::Lookup; friend struct PosLookup; enum Type { diff --git a/src/OT/Layout/GPOS/ValueFormat.hh b/src/OT/Layout/GPOS/ValueFormat.hh index 32fcde61c..e2fc2c199 100644 --- a/src/OT/Layout/GPOS/ValueFormat.hh +++ b/src/OT/Layout/GPOS/ValueFormat.hh @@ -1,6 +1,8 @@ #ifndef OT_LAYOUT_GPOS_VALUEFORMAT_HH #define OT_LAYOUT_GPOS_VALUEFORMAT_HH +#include "../../../hb-ot-layout-gsubgpos.hh" + namespace OT { namespace Layout { namespace GPOS { diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 8aed07671..ccc51c136 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -33,291 +33,28 @@ namespace OT { -struct MarkArray; -static void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage, - const MarkArray &mark_array, - const hb_set_t &glyphset, - hb_map_t* klass_mapping /* INOUT */); +using Layout::GPOS::PosLookup; +using OT::Layout::GPOS::ATTACH_TYPE_NONE; +using OT::Layout::GPOS::ATTACH_TYPE_MARK; +using OT::Layout::GPOS::ATTACH_TYPE_CURSIVE; + +// struct MarkArray; +// static void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage, +// const MarkArray &mark_array, +// const hb_set_t &glyphset, +// hb_map_t* klass_mapping /* INOUT */); /* Shared Tables: ValueRecord, Anchor Table, and MarkArray */ - - /* Lookups */ -struct MarkMarkPos -{ - template - typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const - { - TRACE_DISPATCH (this, u.format); - if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); - switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, std::forward (ds)...)); - default:return_trace (c->default_return_value ()); - } - } - - protected: - union { - HBUINT16 format; /* Format identifier */ - MarkMarkPosFormat1 format1; - } u; -}; - - -typedef AnchorMatrix Mark2Array; /* mark2-major-- - * in order of Mark2Coverage Index--, - * mark1-minor-- - * ordered by class--zero-based. */ - -struct MarkMarkPosFormat1 -{ - bool intersects (const hb_set_t *glyphs) const - { - return (this+mark1Coverage).intersects (glyphs) && - (this+mark2Coverage).intersects (glyphs); - } - - void closure_lookups (hb_closure_lookups_context_t *c) const {} - - void collect_variation_indices (hb_collect_variation_indices_context_t *c) const - { - + hb_zip (this+mark1Coverage, this+mark1Array) - | hb_filter (c->glyph_set, hb_first) - | hb_map (hb_second) - | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+mark1Array)); }) - ; - - hb_map_t klass_mapping; - Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, *c->glyph_set, &klass_mapping); - - unsigned mark2_count = (this+mark2Array).rows; - auto mark2_iter = - + hb_zip (this+mark2Coverage, hb_range (mark2_count)) - | hb_filter (c->glyph_set, hb_first) - | hb_map (hb_second) - ; - - hb_sorted_vector_t mark2_indexes; - for (const unsigned row : mark2_iter) - { - + hb_range ((unsigned) classCount) - | hb_filter (klass_mapping) - | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; }) - | hb_sink (mark2_indexes) - ; - } - (this+mark2Array).collect_variation_indices (c, mark2_indexes.iter ()); - } - - void collect_glyphs (hb_collect_glyphs_context_t *c) const - { - if (unlikely (!(this+mark1Coverage).collect_coverage (c->input))) return; - if (unlikely (!(this+mark2Coverage).collect_coverage (c->input))) return; - } - - const Coverage &get_coverage () const { return this+mark1Coverage; } - - bool apply (hb_ot_apply_context_t *c) const - { - TRACE_APPLY (this); - hb_buffer_t *buffer = c->buffer; - unsigned int mark1_index = (this+mark1Coverage).get_coverage (buffer->cur().codepoint); - if (likely (mark1_index == NOT_COVERED)) return_trace (false); - - /* now we search backwards for a suitable mark glyph until a non-mark glyph */ - hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; - skippy_iter.reset (buffer->idx, 1); - skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags); - unsigned unsafe_from; - if (!skippy_iter.prev (&unsafe_from)) - { - buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1); - return_trace (false); - } - - if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])) - { - buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); - return_trace (false); - } - - unsigned int j = skippy_iter.idx; - - unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur()); - unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]); - unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur()); - unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]); - - if (likely (id1 == id2)) - { - if (id1 == 0) /* Marks belonging to the same base. */ - goto good; - else if (comp1 == comp2) /* Marks belonging to the same ligature component. */ - goto good; - } - else - { - /* If ligature ids don't match, it may be the case that one of the marks - * itself is a ligature. In which case match. */ - if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2)) - goto good; - } - - /* Didn't match. */ - buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); - return_trace (false); - - good: - unsigned int mark2_index = (this+mark2Coverage).get_coverage (buffer->info[j].codepoint); - if (mark2_index == NOT_COVERED) - { - buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); - return_trace (false); - } - - return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j)); - } - - bool subset (hb_subset_context_t *c) const - { - TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset_gsub (); - const hb_map_t &glyph_map = *c->plan->glyph_map; - - auto *out = c->serializer->start_embed (*this); - if (unlikely (!c->serializer->extend_min (out))) return_trace (false); - out->format = format; - - hb_map_t klass_mapping; - Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, glyphset, &klass_mapping); - - if (!klass_mapping.get_population ()) return_trace (false); - out->classCount = klass_mapping.get_population (); - - auto mark1_iter = - + hb_zip (this+mark1Coverage, this+mark1Array) - | hb_filter (glyphset, hb_first) - ; - - hb_sorted_vector_t new_coverage; - + mark1_iter - | hb_map (hb_first) - | hb_map (glyph_map) - | hb_sink (new_coverage) - ; - - if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ())) - return_trace (false); - - out->mark1Array.serialize_subset (c, mark1Array, this, - (this+mark1Coverage).iter (), - &klass_mapping); - - unsigned mark2count = (this+mark2Array).rows; - auto mark2_iter = - + hb_zip (this+mark2Coverage, hb_range (mark2count)) - | hb_filter (glyphset, hb_first) - ; - - new_coverage.reset (); - + mark2_iter - | hb_map (hb_first) - | hb_map (glyph_map) - | hb_sink (new_coverage) - ; - - if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ())) - return_trace (false); - - hb_sorted_vector_t mark2_indexes; - for (const unsigned row : + mark2_iter - | hb_map (hb_second)) - { - + hb_range ((unsigned) classCount) - | hb_filter (klass_mapping) - | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; }) - | hb_sink (mark2_indexes) - ; - } - - out->mark2Array.serialize_subset (c, mark2Array, this, mark2_iter.len (), mark2_indexes.iter ()); - - return_trace (true); - } - - bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - mark1Coverage.sanitize (c, this) && - mark2Coverage.sanitize (c, this) && - mark1Array.sanitize (c, this) && - mark2Array.sanitize (c, this, (unsigned int) classCount)); - } - - protected: - HBUINT16 format; /* Format identifier--format = 1 */ - Offset16To - mark1Coverage; /* Offset to Combining Mark1 Coverage - * table--from beginning of MarkMarkPos - * subtable */ - Offset16To - mark2Coverage; /* Offset to Combining Mark2 Coverage - * table--from beginning of MarkMarkPos - * subtable */ - HBUINT16 classCount; /* Number of defined mark classes */ - Offset16To - mark1Array; /* Offset to Mark1Array table--from - * beginning of MarkMarkPos subtable */ - Offset16To - mark2Array; /* Offset to Mark2Array table--from - * beginning of MarkMarkPos subtable */ - public: - DEFINE_SIZE_STATIC (12); -}; - -struct MarkMarkPos -{ - template - typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const - { - TRACE_DISPATCH (this, u.format); - if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); - switch (u.format) { - case 1: return_trace (c->dispatch (u.format1, std::forward (ds)...)); - default:return_trace (c->default_return_value ()); - } - } - - protected: - union { - HBUINT16 format; /* Format identifier */ - MarkMarkPosFormat1 format1; - } u; -}; - - -struct ContextPos : Context {}; - -struct ChainContextPos : ChainContext {}; - -struct ExtensionPos : Extension -{ - typedef struct PosLookupSubTable SubTable; -}; - - - - static void reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent) { int chain = pos[i].attach_chain(), type = pos[i].attach_type(); - if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE))) + if (likely (!chain || 0 == (type & OT::Layout::GPOS::ATTACH_TYPE_CURSIVE))) return; pos[i].attach_chain() = 0; @@ -338,103 +75,9 @@ reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direc pos[j].attach_chain() = -chain; pos[j].attach_type() = type; } -static void -propagate_attachment_offsets (hb_glyph_position_t *pos, - unsigned int len, - unsigned int i, - hb_direction_t direction, - unsigned nesting_level = HB_MAX_NESTING_LEVEL) -{ - /* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate - * offset of glyph they are attached to. */ - int chain = pos[i].attach_chain(), type = pos[i].attach_type(); - if (likely (!chain)) - return; - - pos[i].attach_chain() = 0; - - unsigned int j = (int) i + chain; - - if (unlikely (j >= len)) - return; - - if (unlikely (!nesting_level)) - return; - - propagate_attachment_offsets (pos, len, j, direction, nesting_level - 1); - - assert (!!(type & ATTACH_TYPE_MARK) ^ !!(type & ATTACH_TYPE_CURSIVE)); - - if (type & ATTACH_TYPE_CURSIVE) - { - if (HB_DIRECTION_IS_HORIZONTAL (direction)) - pos[i].y_offset += pos[j].y_offset; - else - pos[i].x_offset += pos[j].x_offset; - } - else /*if (type & ATTACH_TYPE_MARK)*/ - { - pos[i].x_offset += pos[j].x_offset; - pos[i].y_offset += pos[j].y_offset; - - assert (j < i); - if (HB_DIRECTION_IS_FORWARD (direction)) - for (unsigned int k = j; k < i; k++) { - pos[i].x_offset -= pos[k].x_advance; - pos[i].y_offset -= pos[k].y_advance; - } - else - for (unsigned int k = j + 1; k < i + 1; k++) { - pos[i].x_offset += pos[k].x_advance; - pos[i].y_offset += pos[k].y_advance; - } - } -} - -void -GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) -{ - unsigned int count = buffer->len; - for (unsigned int i = 0; i < count; i++) - buffer->pos[i].attach_chain() = buffer->pos[i].attach_type() = 0; -} - -void -GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED) -{ - //_hb_buffer_assert_gsubgpos_vars (buffer); -} - -void -GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer) -{ - _hb_buffer_assert_gsubgpos_vars (buffer); - - unsigned int len; - hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len); - hb_direction_t direction = buffer->props.direction; - - /* Handle attachments */ - if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT) - for (unsigned i = 0; i < len; i++) - propagate_attachment_offsets (pos, len, i, direction); - - if (unlikely (font->slant)) - { - for (unsigned i = 0; i < len; i++) - if (unlikely (pos[i].y_offset)) - pos[i].x_offset += _hb_roundf (font->slant_xy * pos[i].y_offset); - } -} - - -struct GPOS_accelerator_t : GPOS::accelerator_t { - GPOS_accelerator_t (hb_face_t *face) : GPOS::accelerator_t (face) {} -}; - +// TODO(garretrieger): Move into new layout directory. /* Out-of-class implementation for methods recursing */ - #ifndef HB_NO_OT_LAYOUT template /*static*/ typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index) @@ -466,7 +109,6 @@ inline bool PosLookup::dispatch_recurse_func (hb_ot_apply } #endif - } /* namespace OT */ diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index aa5321362..a17f5f8b0 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -55,6 +55,7 @@ #include "hb-aat-layout-opbd-table.hh" // Just so we compile it; unused otherwise. using OT::Layout::GSUB::GSUB; +using OT::Layout::GPOS::GPOS; /** * SECTION:hb-ot-layout @@ -400,7 +401,7 @@ GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED, } bool -OT::GPOS::is_blocklisted (hb_blob_t *blob HB_UNUSED, +GPOS::is_blocklisted (hb_blob_t *blob HB_UNUSED, hb_face_t *face HB_UNUSED) const { #ifdef HB_NO_OT_LAYOUT_BLOCKLIST @@ -1550,7 +1551,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face, } /* - * OT::GPOS + * GPOS */ @@ -1581,7 +1582,7 @@ hb_ot_layout_has_positioning (hb_face_t *face) void hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer) { - OT::GPOS::position_start (font, buffer); + GPOS::position_start (font, buffer); } @@ -1596,7 +1597,7 @@ hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer) void hb_ot_layout_position_finish_advances (hb_font_t *font, hb_buffer_t *buffer) { - OT::GPOS::position_finish_advances (font, buffer); + GPOS::position_finish_advances (font, buffer); } /** @@ -1610,7 +1611,7 @@ hb_ot_layout_position_finish_advances (hb_font_t *font, hb_buffer_t *buffer) void hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer) { - OT::GPOS::position_finish_offsets (font, buffer); + GPOS::position_finish_offsets (font, buffer); } @@ -1645,7 +1646,7 @@ hb_ot_layout_get_size_params (hb_face_t *face, unsigned int *range_start, /* OUT. May be NULL */ unsigned int *range_end /* OUT. May be NULL */) { - const OT::GPOS &gpos = *face->table.GPOS->table; + const GPOS &gpos = *face->table.GPOS->table; const hb_tag_t tag = HB_TAG ('s','i','z','e'); unsigned int num_features = gpos.get_feature_count (); @@ -1817,7 +1818,7 @@ struct GPOSProxy table (*face->table.GPOS->table), accels (face->table.GPOS->accels) {} - const OT::GPOS &table; + const GPOS &table; const OT::hb_ot_layout_lookup_accelerator_t *accels; }; diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index 7a0baecab..123767c59 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -41,7 +41,7 @@ #include "hb-ot-math-table.hh" using OT::Layout::GSUB::GSUB; - +using OT::Layout::GPOS::GPOS; typedef hb_hashmap_t> script_langsys_map; #ifndef HB_NO_SUBSET_CFF @@ -204,7 +204,7 @@ static inline void hb_map_t *layout_variation_idx_map) { hb_blob_ptr_t gdef = hb_sanitize_context_t ().reference_table (face); - hb_blob_ptr_t gpos = hb_sanitize_context_t ().reference_table (face); + hb_blob_ptr_t gpos = hb_sanitize_context_t ().reference_table (face); if (!gdef->has_data ()) { @@ -403,7 +403,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, plan->gsub_langsys); if (close_over_gpos) - _closure_glyphs_lookups_features ( + _closure_glyphs_lookups_features ( plan->source, plan->_glyphset_gsub, plan->layout_features, diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 428a9dd12..d8b9d87b1 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -56,6 +56,7 @@ #include "hb-repacker.hh" using OT::Layout::GSUB::GSUB; +using OT::Layout::GPOS::GPOS; /** * SECTION:hb-subset @@ -432,7 +433,7 @@ _subset_table (hb_subset_plan_t *plan, #ifndef HB_NO_SUBSET_LAYOUT case HB_OT_TAG_GDEF: return _subset (plan, buf); case HB_OT_TAG_GSUB: return _subset (plan, buf); - case HB_OT_TAG_GPOS: return _subset (plan, buf); + case HB_OT_TAG_GPOS: return _subset (plan, buf); case HB_OT_TAG_gvar: return _subset (plan, buf); case HB_OT_TAG_HVAR: return _subset (plan, buf); case HB_OT_TAG_VVAR: return _subset (plan, buf);