2022-06-25 00:36:14 +02:00
|
|
|
#ifndef OT_LAYOUT_GPOS_MARKARRAY_HH
|
|
|
|
#define OT_LAYOUT_GPOS_MARKARRAY_HH
|
|
|
|
|
|
|
|
#include "AnchorMatrix.hh"
|
|
|
|
#include "MarkRecord.hh"
|
|
|
|
|
|
|
|
namespace OT {
|
|
|
|
namespace Layout {
|
2022-06-29 01:26:49 +02:00
|
|
|
namespace GPOS_impl {
|
2022-06-25 00:36:14 +02:00
|
|
|
|
|
|
|
struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Coverage order */
|
|
|
|
{
|
|
|
|
bool sanitize (hb_sanitize_context_t *c) const
|
|
|
|
{
|
|
|
|
TRACE_SANITIZE (this);
|
|
|
|
return_trace (Array16Of<MarkRecord>::sanitize (c, this));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool apply (hb_ot_apply_context_t *c,
|
|
|
|
unsigned int mark_index, unsigned int glyph_index,
|
|
|
|
const AnchorMatrix &anchors, unsigned int class_count,
|
|
|
|
unsigned int glyph_pos) const
|
|
|
|
{
|
|
|
|
TRACE_APPLY (this);
|
|
|
|
hb_buffer_t *buffer = c->buffer;
|
|
|
|
const MarkRecord &record = Array16Of<MarkRecord>::operator[](mark_index);
|
|
|
|
unsigned int mark_class = record.klass;
|
|
|
|
|
|
|
|
const Anchor& mark_anchor = this + record.markAnchor;
|
|
|
|
bool found;
|
|
|
|
const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found);
|
|
|
|
/* If this subtable doesn't have an anchor for this base and this class,
|
|
|
|
* return false such that the subsequent subtables have a chance at it. */
|
|
|
|
if (unlikely (!found)) return_trace (false);
|
|
|
|
|
|
|
|
float mark_x, mark_y, base_x, base_y;
|
|
|
|
|
|
|
|
buffer->unsafe_to_break (glyph_pos, buffer->idx + 1);
|
|
|
|
mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
|
|
|
|
glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
|
|
|
|
|
2022-07-25 01:14:09 +02:00
|
|
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
|
|
|
{
|
|
|
|
c->buffer->message (c->font,
|
|
|
|
"attaching mark glyph at %d to glyph at %d",
|
|
|
|
c->buffer->idx, glyph_pos);
|
|
|
|
}
|
|
|
|
|
2022-06-25 00:36:14 +02:00
|
|
|
hb_glyph_position_t &o = buffer->cur_pos();
|
|
|
|
o.x_offset = roundf (base_x - mark_x);
|
|
|
|
o.y_offset = roundf (base_y - mark_y);
|
|
|
|
o.attach_type() = ATTACH_TYPE_MARK;
|
|
|
|
o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
|
|
|
|
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
|
|
|
|
|
2022-07-25 01:14:09 +02:00
|
|
|
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
|
|
|
{
|
|
|
|
c->buffer->message (c->font,
|
|
|
|
"attached mark glyph at %d to glyph at %d",
|
|
|
|
c->buffer->idx, glyph_pos);
|
|
|
|
}
|
|
|
|
|
2022-06-25 00:36:14 +02:00
|
|
|
buffer->idx++;
|
|
|
|
return_trace (true);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Iterator,
|
|
|
|
hb_requires (hb_is_iterator (Iterator))>
|
|
|
|
bool subset (hb_subset_context_t *c,
|
|
|
|
Iterator coverage,
|
|
|
|
const hb_map_t *klass_mapping) const
|
|
|
|
{
|
|
|
|
TRACE_SUBSET (this);
|
|
|
|
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
|
|
|
|
|
|
|
auto* out = c->serializer->start_embed (this);
|
|
|
|
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
|
|
|
|
|
|
|
auto mark_iter =
|
|
|
|
+ hb_zip (coverage, this->iter ())
|
|
|
|
| hb_filter (glyphset, hb_first)
|
|
|
|
| hb_map (hb_second)
|
|
|
|
;
|
|
|
|
|
|
|
|
unsigned new_length = 0;
|
|
|
|
for (const auto& mark_record : mark_iter) {
|
|
|
|
if (unlikely (!mark_record.subset (c, this, klass_mapping)))
|
|
|
|
return_trace (false);
|
|
|
|
new_length++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (unlikely (!c->serializer->check_assign (out->len, new_length,
|
|
|
|
HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)))
|
|
|
|
return_trace (false);
|
|
|
|
|
|
|
|
return_trace (true);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
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 */)
|
|
|
|
{
|
|
|
|
hb_set_t orig_classes;
|
|
|
|
|
|
|
|
+ hb_zip (mark_coverage, mark_array)
|
|
|
|
| hb_filter (glyphset, hb_first)
|
|
|
|
| hb_map (hb_second)
|
|
|
|
| hb_map (&MarkRecord::get_class)
|
|
|
|
| hb_sink (orig_classes)
|
|
|
|
;
|
|
|
|
|
|
|
|
unsigned idx = 0;
|
|
|
|
for (auto klass : orig_classes.iter ())
|
|
|
|
{
|
|
|
|
if (klass_mapping->has (klass)) continue;
|
|
|
|
klass_mapping->set (klass, idx);
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* OT_LAYOUT_GPOS_MARKARRAY_HH */
|