[GPOS] CursivePosFormat1

This commit is contained in:
Behdad Esfahbod 2009-05-19 23:25:41 -04:00
parent 70632add33
commit d18fd8e3f7
2 changed files with 169 additions and 7 deletions

View File

@ -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:

View File

@ -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;