[GPOS] CursivePosFormat1
This commit is contained in:
parent
70632add33
commit
d18fd8e3f7
|
@ -532,9 +532,6 @@ ASSERT_SIZE (PairPos, 2);
|
|||
|
||||
|
||||
struct EntryExitRecord {
|
||||
/* TODO */
|
||||
|
||||
private:
|
||||
OffsetTo<Anchor>
|
||||
entryAnchor; /* Offset to EntryAnchor table--from
|
||||
* beginning of CursivePos
|
||||
|
@ -551,9 +548,174 @@ struct CursivePosFormat1 {
|
|||
friend struct CursivePos;
|
||||
|
||||
private:
|
||||
inline bool apply (APPLY_ARG_DEF) const {
|
||||
/* TODO */
|
||||
return false;
|
||||
inline bool apply (APPLY_ARG_DEF) const
|
||||
{
|
||||
struct hb_ot_layout_t::gpos_info_t *gpi = &layout->gpos_info;
|
||||
hb_codepoint_t last_pos = gpi->last;
|
||||
gpi->last = 0xFFFF;
|
||||
|
||||
/* We don't handle mark glyphs here. */
|
||||
if (property == HB_OT_LAYOUT_GLYPH_CLASS_MARK)
|
||||
return false;
|
||||
|
||||
unsigned int index = (this+coverage) (IN_CURGLYPH ());
|
||||
if (HB_LIKELY (index == NOT_COVERED))
|
||||
return false;
|
||||
|
||||
/* Now comes the messiest part of the whole OpenType
|
||||
specification. At first glance, cursive connections seem easy
|
||||
to understand, but there are pitfalls! The reason is that
|
||||
the specs don't mention how to compute the advance values
|
||||
resp. glyph offsets. I was told it would be an omission, to
|
||||
be fixed in the next OpenType version... Again many thanks to
|
||||
Andrei Burago <andreib@microsoft.com> for clarifications.
|
||||
|
||||
Consider the following example:
|
||||
|
||||
| xadv1 |
|
||||
+---------+
|
||||
| |
|
||||
+-----+--+ 1 |
|
||||
| | .| |
|
||||
| 0+--+------+
|
||||
| 2 |
|
||||
| |
|
||||
0+--------+
|
||||
| xadv2 |
|
||||
|
||||
glyph1: advance width = 12
|
||||
anchor point = (3,1)
|
||||
|
||||
glyph2: advance width = 11
|
||||
anchor point = (9,4)
|
||||
|
||||
LSB is 1 for both glyphs (so the boxes drawn above are glyph
|
||||
bboxes). Writing direction is R2L; `0' denotes the glyph's
|
||||
coordinate origin.
|
||||
|
||||
Now the surprising part: The advance width of the *left* glyph
|
||||
(resp. of the *bottom* glyph) will be modified, no matter
|
||||
whether the writing direction is L2R or R2L (resp. T2B or
|
||||
B2T)! This assymetry is caused by the fact that the glyph's
|
||||
coordinate origin is always the lower left corner for all
|
||||
writing directions.
|
||||
|
||||
Continuing the above example, we can compute the new
|
||||
(horizontal) advance width of glyph2 as
|
||||
|
||||
9 - 3 = 6 ,
|
||||
|
||||
and the new vertical offset of glyph2 as
|
||||
|
||||
1 - 4 = -3 .
|
||||
|
||||
|
||||
Vertical writing direction is far more complicated:
|
||||
|
||||
a) Assuming that we recompute the advance height of the lower glyph:
|
||||
|
||||
--
|
||||
+---------+
|
||||
-- | |
|
||||
+-----+--+ 1 | yadv1
|
||||
| | .| |
|
||||
yadv2 | 0+--+------+ -- BSB1 --
|
||||
| 2 | -- -- y_offset
|
||||
| |
|
||||
BSB2 -- 0+--------+ --
|
||||
-- --
|
||||
|
||||
glyph1: advance height = 6
|
||||
anchor point = (3,1)
|
||||
|
||||
glyph2: advance height = 7
|
||||
anchor point = (9,4)
|
||||
|
||||
TSB is 1 for both glyphs; writing direction is T2B.
|
||||
|
||||
|
||||
BSB1 = yadv1 - (TSB1 + ymax1)
|
||||
BSB2 = yadv2 - (TSB2 + ymax2)
|
||||
y_offset = y2 - y1
|
||||
|
||||
vertical advance width of glyph2
|
||||
= y_offset + BSB2 - BSB1
|
||||
= (y2 - y1) + (yadv2 - (TSB2 + ymax2)) - (yadv1 - (TSB1 + ymax1))
|
||||
= y2 - y1 + yadv2 - TSB2 - ymax2 - (yadv1 - TSB1 - ymax1)
|
||||
= y2 - y1 + yadv2 - TSB2 - ymax2 - yadv1 + TSB1 + ymax1
|
||||
|
||||
|
||||
b) Assuming that we recompute the advance height of the upper glyph:
|
||||
|
||||
-- --
|
||||
+---------+ -- TSB1
|
||||
-- -- | |
|
||||
TSB2 -- +-----+--+ 1 | yadv1 ymax1
|
||||
| | .| |
|
||||
yadv2 | 0+--+------+ -- --
|
||||
ymax2 | 2 | -- y_offset
|
||||
| |
|
||||
-- 0+--------+ --
|
||||
--
|
||||
|
||||
glyph1: advance height = 6
|
||||
anchor point = (3,1)
|
||||
|
||||
glyph2: advance height = 7
|
||||
anchor point = (9,4)
|
||||
|
||||
TSB is 1 for both glyphs; writing direction is T2B.
|
||||
|
||||
y_offset = y2 - y1
|
||||
|
||||
vertical advance width of glyph2
|
||||
= TSB1 + ymax1 + y_offset - (TSB2 + ymax2)
|
||||
= TSB1 + ymax1 + y2 - y1 - TSB2 - ymax2
|
||||
|
||||
|
||||
Comparing a) with b) shows that b) is easier to compute. I'll wait
|
||||
for a reply from Andrei to see what should really be implemented...
|
||||
|
||||
Since horizontal advance widths or vertical advance heights
|
||||
can be used alone but not together, no ambiguity occurs. */
|
||||
|
||||
const EntryExitRecord &record = entryExitRecord[index];
|
||||
|
||||
hb_position_t entry_x, entry_y, exit_x, exit_y;
|
||||
|
||||
if (last_pos == 0xFFFF || !record.entryAnchor)
|
||||
goto end;
|
||||
|
||||
(this+record.entryAnchor).get_anchor (layout, IN_CURGLYPH (), &entry_x, &entry_y);
|
||||
|
||||
if (gpi->r2l)
|
||||
{
|
||||
POSITION (buffer->in_pos)->x_advance = entry_x - gpi->anchor_x;
|
||||
POSITION (buffer->in_pos)->new_advance = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
POSITION (gpi->last)->x_advance = gpi->anchor_x - entry_x;
|
||||
POSITION (gpi->last)->new_advance = TRUE;
|
||||
}
|
||||
|
||||
if (lookup_flag & LookupFlag::RightToLeft)
|
||||
{
|
||||
POSITION (gpi->last)->cursive_chain = gpi->last - buffer->in_pos;
|
||||
POSITION (gpi->last)->y_pos = entry_y - gpi->anchor_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
POSITION (buffer->in_pos)->cursive_chain = buffer->in_pos - gpi->last;
|
||||
POSITION (buffer->in_pos)->y_pos = gpi->anchor_y - entry_y;
|
||||
}
|
||||
|
||||
end:
|
||||
if (record.exitAnchor)
|
||||
(this+record.exitAnchor).get_anchor (layout, IN_CURGLYPH (), &gpi->anchor_x, &gpi->anchor_y);
|
||||
|
||||
buffer->in_pos++;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -47,7 +47,7 @@ struct _hb_ot_layout_t {
|
|||
} new_gdef;
|
||||
|
||||
/* TODO full-matrix transformation? */
|
||||
struct {
|
||||
struct gpos_info_t {
|
||||
unsigned int x_ppem, y_ppem;
|
||||
hb_16dot16_t x_scale, y_scale;
|
||||
|
||||
|
|
Loading…
Reference in New Issue