X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fhb-ot-layout-gpos-private.hh;h=59750ab1a78aae10e899d8ea53dfdda02e338301;hb=4a68684654e645882095c1189477146287ce9437;hp=6701a6a8827068467920ce53898f2d7c49053520;hpb=744970af4d884cc87ffa645804578fec8df674a9;p=framework%2Fuifw%2Fharfbuzz.git diff --git a/src/hb-ot-layout-gpos-private.hh b/src/hb-ot-layout-gpos-private.hh index 6701a6a..59750ab 100644 --- a/src/hb-ot-layout-gpos-private.hh +++ b/src/hb-ot-layout-gpos-private.hh @@ -95,20 +95,26 @@ struct ValueFormat : USHORT { return get_len () * Value::static_size; } void apply_value (hb_font_t *font, + hb_direction_t direction, const void *base, const Value *values, hb_glyph_position_t &glyph_pos) const { unsigned int x_ppem, y_ppem; unsigned int format = *this; + hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (direction); if (!format) return; - /* design units -> fractional pixel */ if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++)); if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++)); - if (format & xAdvance) glyph_pos.x_advance += font->em_scale_x (get_short (values++)); - if (format & yAdvance) glyph_pos.y_advance += font->em_scale_y (get_short (values++)); + if (format & xAdvance) { + if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values++)); else values++; + } + /* y_advance values grow downward but font-space grows upward, hence negation */ + if (format & yAdvance) { + if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values++)); else values++; + } if (!has_device ()) return; @@ -125,10 +131,11 @@ struct ValueFormat : USHORT if (y_ppem) glyph_pos.y_offset += (base + get_device (values++)).get_y_delta (font); else values++; } if (format & xAdvDevice) { - if (x_ppem) glyph_pos.x_advance += (base + get_device (values++)).get_x_delta (font); else values++; + if (horizontal && x_ppem) glyph_pos.x_advance += (base + get_device (values++)).get_x_delta (font); else values++; } if (format & yAdvDevice) { - if (y_ppem) glyph_pos.y_advance += (base + get_device (values++)).get_y_delta (font); else values++; + /* y_advance values grow downward but font-space grows upward, hence negation */ + if (!horizontal && y_ppem) glyph_pos.y_advance -= (base + get_device (values++)).get_y_delta (font); else values++; } } @@ -210,7 +217,6 @@ struct AnchorFormat1 private: inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED, - hb_direction_t direction HB_UNUSED, hb_position_t *x, hb_position_t *y) const { *x = font->em_scale_x (xCoordinate); @@ -236,7 +242,6 @@ struct AnchorFormat2 private: inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id, - hb_direction_t direction, hb_position_t *x, hb_position_t *y) const { unsigned int x_ppem = font->x_ppem; @@ -245,7 +250,7 @@ struct AnchorFormat2 hb_bool_t ret = false; if (x_ppem || y_ppem) - ret = hb_font_get_contour_point_for_direction (font, glyph_id, anchorPoint, direction, &cx, &cy); + ret = hb_font_get_glyph_contour_point_for_origin (font, glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy); *x = x_ppem && ret ? cx : font->em_scale_x (xCoordinate); *y = y_ppem && ret ? cy : font->em_scale_y (yCoordinate); } @@ -270,13 +275,11 @@ struct AnchorFormat3 private: inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED, - hb_direction_t direction HB_UNUSED, hb_position_t *x, hb_position_t *y) const { *x = font->em_scale_x (xCoordinate); *y = font->em_scale_y (yCoordinate); - /* pixel -> fractional pixel */ if (font->x_ppem) *x += (this+xDeviceTable).get_x_delta (font); if (font->y_ppem) @@ -309,15 +312,14 @@ struct AnchorFormat3 struct Anchor { inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id, - hb_direction_t direction, hb_position_t *x, hb_position_t *y) const { *x = *y = 0; switch (u.format) { - case 1: u.format1.get_anchor (font, glyph_id, direction, x, y); return; - case 2: u.format2.get_anchor (font, glyph_id, direction, x, y); return; - case 3: u.format3.get_anchor (font, glyph_id, direction, x, y); return; - default: return; + case 1: u.format1.get_anchor (font, glyph_id, x, y); return; + case 2: u.format2.get_anchor (font, glyph_id, x, y); return; + case 3: u.format3.get_anchor (font, glyph_id, x, y); return; + default: return; } } @@ -407,8 +409,8 @@ struct MarkArray : ArrayOf /* Array of MarkRecords--in Coverage orde hb_position_t mark_x, mark_y, base_x, base_y; - mark_anchor.get_anchor (c->font, c->buffer->info[c->buffer->i].codepoint, c->direction, &mark_x, &mark_y); - glyph_anchor.get_anchor (c->font, c->buffer->info[glyph_pos].codepoint, c->direction, &base_x, &base_y); + mark_anchor.get_anchor (c->font, c->buffer->info[c->buffer->i].codepoint, &mark_x, &mark_y); + glyph_anchor.get_anchor (c->font, c->buffer->info[glyph_pos].codepoint, &base_x, &base_y); hb_glyph_position_t &o = c->buffer->pos[c->buffer->i]; o.x_offset = base_x - mark_x; @@ -440,7 +442,8 @@ struct SinglePosFormat1 if (likely (index == NOT_COVERED)) return false; - valueFormat.apply_value (c->font, this, values, c->buffer->pos[c->buffer->i]); + valueFormat.apply_value (c->font, c->direction, this, + values, c->buffer->pos[c->buffer->i]); c->buffer->i++; return true; @@ -482,7 +485,7 @@ struct SinglePosFormat2 if (likely (index >= valueCount)) return false; - valueFormat.apply_value (c->font, this, + valueFormat.apply_value (c->font, c->direction, this, &values[index * valueFormat.get_len ()], c->buffer->pos[c->buffer->i]); @@ -578,8 +581,10 @@ struct PairSet { if (c->buffer->info[pos].codepoint == record->secondGlyph) { - valueFormats[0].apply_value (c->font, this, &record->values[0], c->buffer->pos[c->buffer->i]); - valueFormats[1].apply_value (c->font, this, &record->values[len1], c->buffer->pos[pos]); + valueFormats[0].apply_value (c->font, c->direction, this, + &record->values[0], c->buffer->pos[c->buffer->i]); + valueFormats[1].apply_value (c->font, c->direction, this, + &record->values[len1], c->buffer->pos[pos]); if (len2) pos++; c->buffer->i = pos; @@ -713,8 +718,10 @@ struct PairPosFormat2 return false; const Value *v = &values[record_len * (klass1 * class2Count + klass2)]; - valueFormat1.apply_value (c->font, this, v, c->buffer->pos[c->buffer->i]); - valueFormat2.apply_value (c->font, this, v + len1, c->buffer->pos[j]); + valueFormat1.apply_value (c->font, c->direction, this, + v, c->buffer->pos[c->buffer->i]); + valueFormat2.apply_value (c->font, c->direction, this, + v + len1, c->buffer->pos[j]); if (len2) j++; @@ -863,41 +870,60 @@ struct CursivePosFormat1 unsigned int i = c->buffer->i; hb_position_t entry_x, entry_y, exit_x, exit_y; - (this+this_record.exitAnchor).get_anchor (c->font, c->buffer->info[i].codepoint, c->direction, &exit_x, &exit_y); - (this+next_record.entryAnchor).get_anchor (c->font, c->buffer->info[j].codepoint, c->direction, &entry_x, &entry_y); - - /* Align the exit anchor of the left/top glyph with the entry anchor of the right/bottom glyph - * by adjusting advance of the left/top glyph. */ - if (HB_DIRECTION_IS_BACKWARD (c->direction)) - { - if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction))) - c->buffer->pos[j].x_advance = c->buffer->pos[j].x_offset + entry_x - exit_x; - else - c->buffer->pos[j].y_advance = c->buffer->pos[j].y_offset + entry_y - exit_y; - } - else - { - if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction))) - c->buffer->pos[i].x_advance = c->buffer->pos[i].x_offset + exit_x - entry_x; - else - c->buffer->pos[i].y_advance = c->buffer->pos[i].y_offset + exit_y - entry_y; + (this+this_record.exitAnchor).get_anchor (c->font, c->buffer->info[i].codepoint, &exit_x, &exit_y); + (this+next_record.entryAnchor).get_anchor (c->font, c->buffer->info[j].codepoint, &entry_x, &entry_y); + + hb_glyph_position_t *pos = c->buffer->pos; + + hb_position_t d; + /* Main-direction adjustment */ + switch (c->direction) { + case HB_DIRECTION_LTR: + pos[i].x_advance = exit_x + pos[i].x_offset; + + d = entry_x + pos[j].x_offset; + pos[j].x_advance -= d; + pos[j].x_offset -= d; + break; + case HB_DIRECTION_RTL: + d = exit_x + pos[i].x_offset; + pos[i].x_advance -= d; + pos[i].x_offset -= d; + + pos[j].x_advance = entry_x + pos[j].x_offset; + break; + case HB_DIRECTION_TTB: + pos[i].y_advance = exit_y + pos[i].y_offset; + + d = entry_y + pos[j].y_offset; + pos[j].y_advance -= d; + pos[j].y_offset -= d; + break; + case HB_DIRECTION_BTT: + d = exit_y + pos[i].y_offset; + pos[i].y_advance -= d; + pos[i].y_offset -= d; + + pos[j].y_advance = entry_y; + break; + case HB_DIRECTION_INVALID: + default: + break; } - if (c->lookup_props & LookupFlag::RightToLeft) - { - c->buffer->pos[i].cursive_chain() = j - i; + /* Cross-direction adjustment */ + if (c->lookup_props & LookupFlag::RightToLeft) { + pos[i].cursive_chain() = j - i; if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction))) - c->buffer->pos[i].y_offset = entry_y - exit_y; + pos[i].y_offset = entry_y - exit_y; else - c->buffer->pos[i].x_offset = entry_x - exit_x; - } - else - { - c->buffer->pos[j].cursive_chain() = i - j; + pos[i].x_offset = entry_x - exit_x; + } else { + pos[j].cursive_chain() = i - j; if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction))) - c->buffer->pos[j].y_offset = exit_y - entry_y; + pos[j].y_offset = exit_y - entry_y; else - c->buffer->pos[j].x_offset = exit_x - entry_x; + pos[j].x_offset = exit_x - entry_x; } c->buffer->i = j; @@ -1493,61 +1519,69 @@ struct GPOS : GSUBGPOS DEFINE_SIZE_STATIC (10); }; + +static void +fix_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction) +{ + unsigned int j = pos[i].cursive_chain(); + if (likely (!j)) + return; + + j += i; + + pos[i].cursive_chain() = 0; + + fix_cursive_minor_offset (pos, j, direction); + + if (HB_DIRECTION_IS_HORIZONTAL (direction)) + pos[i].y_offset += pos[j].y_offset; + else + pos[i].x_offset += pos[j].x_offset; +} + +static void +fix_mark_attachment (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction) +{ + if (likely (!(pos[i].attach_lookback()))) + return; + + unsigned int j = i - pos[i].attach_lookback(); + + pos[i].x_advance = 0; + pos[i].y_advance = 0; + pos[i].x_offset += pos[j].x_offset; + pos[i].y_offset += pos[j].y_offset; + + 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_finish (hb_buffer_t *buffer) { - unsigned int i, j; unsigned int len; hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len); hb_direction_t direction = buffer->props.direction; - /* Handle cursive connections: - * First handle all chain-back connections, then handle all chain-forward connections. */ - if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) + /* Handle cursive connections */ + for (unsigned int i = 0; i < len; i++) { - for (j = 0; j < len; j++) { - if (pos[j].cursive_chain() < 0) - pos[j].y_offset += pos[j + pos[j].cursive_chain()].y_offset; - } - for (i = len; i > 0; i--) { - j = i - 1; - if (pos[j].cursive_chain() > 0) - pos[j].y_offset += pos[j + pos[j].cursive_chain()].y_offset; - } + fix_cursive_minor_offset (pos, i, direction); } - else - { - for (j = 0; j < len; j++) { - if (pos[j].cursive_chain() < 0) - pos[j].x_offset += pos[j + pos[j].cursive_chain()].x_offset; - } - for (i = len; i > 0; i--) { - j = i - 1; - if (pos[j].cursive_chain() > 0) - pos[j].x_offset += pos[j + pos[j].cursive_chain()].x_offset; - } - } - /* Handle attachments */ - for (i = 0; i < len; i++) - if (pos[i].attach_lookback()) - { - unsigned int back = i - pos[i].attach_lookback(); - pos[i].x_offset += pos[back].x_offset; - pos[i].y_offset += pos[back].y_offset; - - if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) - for (j = back + 1; j < i + 1; j++) { - pos[i].x_offset += pos[j].x_advance; - pos[i].y_offset += pos[j].y_advance; - } - else - for (j = back; j < i; j++) { - pos[i].x_offset -= pos[j].x_advance; - pos[i].y_offset -= pos[j].y_advance; - } - } + for (unsigned int i = 0; i < len; i++) + { + fix_mark_attachment (pos, i, direction); + } }