hb_font_set_scale() now sets the value to be used to represent a unit
pixel. For example, if rendering a 10px font with a 26.6 representation,
you would set scale to (10 << 6). For 10px in 16.16 you would set it to
(10 << 16). This space should be the same space that the get_glyph_metrics
and get_kerning callbacks work in.
typedef uint32_t hb_codepoint_t;
typedef int32_t hb_position_t;
typedef uint32_t hb_codepoint_t;
typedef int32_t hb_position_t;
-typedef int32_t hb_16dot16_t;
typedef uint32_t hb_mask_t;
typedef void (*hb_destroy_func_t) (void *user_data);
typedef uint32_t hb_mask_t;
typedef void (*hb_destroy_func_t) (void *user_data);
#include "hb-ot-head-private.hh"
#include "hb-ot-head-private.hh"
-#include "hb-ot-layout-private.hh"
-
hb_blob_t *head_blob;
const struct head *head_table;
hb_blob_t *head_blob;
const struct head *head_table;
- hb_ot_layout_t ot_layout;
+ struct hb_ot_layout_t *ot_layout;
struct _hb_font_t {
hb_reference_count_t ref_count;
struct _hb_font_t {
hb_reference_count_t ref_count;
- hb_16dot16_t x_scale;
- hb_16dot16_t y_scale;
+ unsigned int x_scale;
+ unsigned int y_scale;
unsigned int x_ppem;
unsigned int y_ppem;
unsigned int x_ppem;
unsigned int y_ppem;
NULL, /* head_blob */
NULL, /* head_table */
NULL, /* head_blob */
NULL, /* head_table */
face->destroy = destroy;
face->user_data = user_data;
face->destroy = destroy;
face->user_data = user_data;
- _hb_ot_layout_init (face);
+ face->ot_layout = _hb_ot_layout_new (face);
face->head_blob = Sanitizer<head>::sanitize (hb_face_get_table (face, HB_OT_TAG_head));
face->head_table = Sanitizer<head>::lock_instance (face->head_blob);
face->head_blob = Sanitizer<head>::sanitize (hb_face_get_table (face, HB_OT_TAG_head));
face->head_table = Sanitizer<head>::lock_instance (face->head_blob);
- _hb_ot_layout_init (face);
+ face->ot_layout = _hb_ot_layout_new (face);
{
HB_OBJECT_DO_DESTROY (face);
{
HB_OBJECT_DO_DESTROY (face);
- _hb_ot_layout_fini (face);
+ _hb_ot_layout_free (face->ot_layout);
hb_blob_unlock (face->head_blob);
hb_blob_destroy (face->head_blob);
hb_blob_unlock (face->head_blob);
hb_blob_destroy (face->head_blob);
void
hb_font_set_scale (hb_font_t *font,
void
hb_font_set_scale (hb_font_t *font,
- hb_16dot16_t x_scale,
- hb_16dot16_t y_scale)
+ unsigned int x_scale,
+ unsigned int y_scale)
{
if (HB_OBJECT_IS_INERT (font))
return;
{
if (HB_OBJECT_IS_INERT (font))
return;
- * XXX
- * should we decompose this to units_per_EM and font-size?
- * units_per_EM setting then can go into the face, or better,
- * read from the 'head' table.
- *
- * Then we either need size+shape like freetype does, or a full
- * matrix.
+ * We should add support for full matrices.
*/
void
hb_font_set_scale (hb_font_t *font,
*/
void
hb_font_set_scale (hb_font_t *font,
- hb_16dot16_t x_scale,
- hb_16dot16_t y_scale);
+ unsigned int x_scale,
+ unsigned int y_scale);
/*
* A zero value means "no hinting in that direction"
/*
* A zero value means "no hinting in that direction"
hb_ft_get_font_funcs (),
destroy, ft_face);
hb_font_set_scale (font,
hb_ft_get_font_funcs (),
destroy, ft_face);
hb_font_set_scale (font,
- ft_face->size->metrics.x_scale,
- ft_face->size->metrics.y_scale);
+ ((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM) >> 16,
+ ((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM) >> 16);
hb_font_set_ppem (font,
ft_face->size->metrics.x_ppem,
ft_face->size->metrics.y_ppem);
hb_font_set_ppem (font,
ft_face->size->metrics.x_ppem,
ft_face->size->metrics.y_ppem);
inline int get_caret_value (hb_ot_layout_context_t *c, hb_codepoint_t glyph_id HB_UNUSED) const
{
/* TODO vertical */
inline int get_caret_value (hb_ot_layout_context_t *c, hb_codepoint_t glyph_id HB_UNUSED) const
{
/* TODO vertical */
- return _hb_16dot16_mul_round (c->font->x_scale, coordinate);
+ return c->scale_x (coordinate);
}
inline bool sanitize (hb_sanitize_context_t *c) {
}
inline bool sanitize (hb_sanitize_context_t *c) {
inline int get_caret_value (hb_ot_layout_context_t *c, hb_codepoint_t glyph_id HB_UNUSED) const
{
/* TODO vertical */
inline int get_caret_value (hb_ot_layout_context_t *c, hb_codepoint_t glyph_id HB_UNUSED) const
{
/* TODO vertical */
- return _hb_16dot16_mul_round (c->font->x_scale, coordinate) +
- ((this+deviceTable).get_delta (c->font->x_ppem) << 16);
+ return c->scale_x (coordinate) +
+ ((this+deviceTable).get_delta (c->font->x_ppem) * c->font->x_scale);
}
inline bool sanitize (hb_sanitize_context_t *c) {
}
inline bool sanitize (hb_sanitize_context_t *c) {
hb_internal_glyph_position_t &glyph_pos) const
{
unsigned int x_ppem, y_ppem;
hb_internal_glyph_position_t &glyph_pos) const
{
unsigned int x_ppem, y_ppem;
- hb_16dot16_t x_scale, y_scale;
unsigned int format = *this;
if (!format) return;
unsigned int format = *this;
if (!format) return;
- x_scale = layout->font->x_scale;
- y_scale = layout->font->y_scale;
/* design units -> fractional pixel */
/* design units -> fractional pixel */
- if (format & xPlacement) glyph_pos.x_offset += _hb_16dot16_mul_round (x_scale, get_short (values++));
- if (format & yPlacement) glyph_pos.y_offset += _hb_16dot16_mul_round (y_scale, get_short (values++));
- if (format & xAdvance) glyph_pos.x_advance += _hb_16dot16_mul_round (x_scale, get_short (values++));
- if (format & yAdvance) glyph_pos.y_advance += _hb_16dot16_mul_round (y_scale, get_short (values++));
+ if (format & xPlacement) glyph_pos.x_offset += layout->scale_x (get_short (values++));
+ if (format & yPlacement) glyph_pos.y_offset += layout->scale_y (get_short (values++));
+ if (format & xAdvance) glyph_pos.x_advance += layout->scale_x (get_short (values++));
+ if (format & yAdvance) glyph_pos.y_advance += layout->scale_y (get_short (values++));
if (!has_device ()) return;
if (!has_device ()) return;
/* pixel -> fractional pixel */
if (format & xPlaDevice) {
/* pixel -> fractional pixel */
if (format & xPlaDevice) {
- if (x_ppem) glyph_pos.x_offset += (base + get_device (values++)).get_delta (x_ppem) << 16; else values++;
+ if (x_ppem) glyph_pos.x_offset += (base + get_device (values++)).get_delta (x_ppem) * layout->font->x_scale; else values++;
}
if (format & yPlaDevice) {
}
if (format & yPlaDevice) {
- if (y_ppem) glyph_pos.y_offset += (base + get_device (values++)).get_delta (y_ppem) << 16; else values++;
+ if (y_ppem) glyph_pos.y_offset += (base + get_device (values++)).get_delta (y_ppem) * layout->font->y_scale; else values++;
}
if (format & xAdvDevice) {
}
if (format & xAdvDevice) {
- if (x_ppem) glyph_pos.x_advance += (base + get_device (values++)).get_delta (x_ppem) << 16; else values++;
+ if (x_ppem) glyph_pos.x_advance += (base + get_device (values++)).get_delta (x_ppem) * layout->font->x_scale; else values++;
}
if (format & yAdvDevice) {
}
if (format & yAdvDevice) {
- if (y_ppem) glyph_pos.y_advance += (base + get_device (values++)).get_delta (y_ppem) << 16; else values++;
+ if (y_ppem) glyph_pos.y_advance += (base + get_device (values++)).get_delta (y_ppem) * layout->font->y_scale; else values++;
inline void get_anchor (hb_ot_layout_context_t *layout, hb_codepoint_t glyph_id HB_UNUSED,
hb_position_t *x, hb_position_t *y) const
{
inline void get_anchor (hb_ot_layout_context_t *layout, hb_codepoint_t glyph_id HB_UNUSED,
hb_position_t *x, hb_position_t *y) const
{
- *x = _hb_16dot16_mul_round (layout->font->x_scale, xCoordinate);
- *y = _hb_16dot16_mul_round (layout->font->y_scale, yCoordinate);
+ *x = layout->scale_x (xCoordinate);
+ *y = layout->scale_y (yCoordinate);
}
inline bool sanitize (hb_sanitize_context_t *c) {
}
inline bool sanitize (hb_sanitize_context_t *c) {
if (x_ppem || y_ppem)
ret = hb_font_get_contour_point (layout->font, layout->face, anchorPoint, glyph_id, &cx, &cy);
if (x_ppem || y_ppem)
ret = hb_font_get_contour_point (layout->font, layout->face, anchorPoint, glyph_id, &cx, &cy);
- *x = x_ppem && ret ? cx : _hb_16dot16_mul_round (layout->font->x_scale, xCoordinate);
- *y = y_ppem && ret ? cy : _hb_16dot16_mul_round (layout->font->y_scale, yCoordinate);
+ *x = x_ppem && ret ? cx : layout->scale_x (xCoordinate);
+ *y = y_ppem && ret ? cy : layout->scale_y (yCoordinate);
}
inline bool sanitize (hb_sanitize_context_t *c) {
}
inline bool sanitize (hb_sanitize_context_t *c) {
inline void get_anchor (hb_ot_layout_context_t *layout, hb_codepoint_t glyph_id HB_UNUSED,
hb_position_t *x, hb_position_t *y) const
{
inline void get_anchor (hb_ot_layout_context_t *layout, hb_codepoint_t glyph_id HB_UNUSED,
hb_position_t *x, hb_position_t *y) const
{
- *x = _hb_16dot16_mul_round (layout->font->x_scale, xCoordinate);
- *y = _hb_16dot16_mul_round (layout->font->y_scale, yCoordinate);
+ *x = layout->scale_x (xCoordinate);
+ *y = layout->scale_y (yCoordinate);
/* pixel -> fractional pixel */
if (layout->font->x_ppem)
/* pixel -> fractional pixel */
if (layout->font->x_ppem)
- *x += (this+xDeviceTable).get_delta (layout->font->x_ppem) << 16;
+ *x += (this+xDeviceTable).get_delta (layout->font->x_ppem) * layout->font->x_scale;
if (layout->font->y_ppem)
if (layout->font->y_ppem)
- *y += (this+yDeviceTable).get_delta (layout->font->y_ppem) << 16;
+ *y += (this+yDeviceTable).get_delta (layout->font->y_ppem) * layout->font->y_scale;
}
inline bool sanitize (hb_sanitize_context_t *c) {
}
inline bool sanitize (hb_sanitize_context_t *c) {
static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_index)
{
static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_index)
{
- const GPOS &gpos = *(c->layout->face->ot_layout.gpos);
+ const GPOS &gpos = *(c->layout->face->ot_layout->gpos);
const PosLookup &l = gpos.get_lookup (lookup_index);
if (unlikely (c->nesting_level_left == 0))
const PosLookup &l = gpos.get_lookup (lookup_index);
if (unlikely (c->nesting_level_left == 0))
static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_index)
{
static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_index)
{
- const GSUB &gsub = *(c->layout->face->ot_layout.gsub);
+ const GSUB &gsub = *(c->layout->face->ot_layout->gsub);
const SubstLookup &l = gsub.get_lookup (lookup_index);
if (unlikely (c->nesting_level_left == 0))
const SubstLookup &l = gsub.get_lookup (lookup_index);
if (unlikely (c->nesting_level_left == 0))
#include "hb-ot-layout.h"
#include "hb-ot-layout.h"
+#include "hb-font-private.hh"
#include "hb-buffer-private.hh"
#include "hb-buffer-private.hh"
-typedef struct _hb_ot_layout_t hb_ot_layout_t;
-
-struct _hb_ot_layout_t
{
hb_blob_t *gdef_blob;
hb_blob_t *gsub_blob;
{
hb_blob_t *gdef_blob;
hb_blob_t *gsub_blob;
-typedef struct _hb_ot_layout_context_t hb_ot_layout_context_t;
-struct _hb_ot_layout_context_t
+struct hb_ot_layout_context_t
{
hb_face_t *face;
hb_font_t *font;
{
hb_face_t *face;
hb_font_t *font;
hb_position_t anchor_y; /* of the last valid glyph */
} gpos;
} info;
hb_position_t anchor_y; /* of the last valid glyph */
} gpos;
} info;
+
+ /* Convert from font-space to user-space */
+ /* XXX div-by-zero */
+ inline hb_position_t scale_x (int16_t v) { return (int64_t) this->font->x_scale * v / this->face->head_table->unitsPerEm; }
+ inline hb_position_t scale_y (int16_t v) { return (int64_t) this->font->y_scale * v / this->face->head_table->unitsPerEm; }
-HB_INTERNAL void
-_hb_ot_layout_init (hb_face_t *face);
+HB_INTERNAL hb_ot_layout_t *
+_hb_ot_layout_new (hb_face_t *face);
-_hb_ot_layout_fini (hb_face_t *face);
+_hb_ot_layout_free (hb_ot_layout_t *layout);
-void
-_hb_ot_layout_init (hb_face_t *face)
+hb_ot_layout_t *
+_hb_ot_layout_new (hb_face_t *face)
- hb_ot_layout_t *layout = &face->ot_layout;
-
- memset (layout, 0, sizeof (*layout));
+ /* Remove this object altogether */
+ hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t));
layout->gdef_blob = Sanitizer<GDEF>::sanitize (hb_face_get_table (face, HB_OT_TAG_GDEF));
layout->gdef = Sanitizer<GDEF>::lock_instance (layout->gdef_blob);
layout->gdef_blob = Sanitizer<GDEF>::sanitize (hb_face_get_table (face, HB_OT_TAG_GDEF));
layout->gdef = Sanitizer<GDEF>::lock_instance (layout->gdef_blob);
layout->gpos_blob = Sanitizer<GPOS>::sanitize (hb_face_get_table (face, HB_OT_TAG_GPOS));
layout->gpos = Sanitizer<GPOS>::lock_instance (layout->gpos_blob);
layout->gpos_blob = Sanitizer<GPOS>::sanitize (hb_face_get_table (face, HB_OT_TAG_GPOS));
layout->gpos = Sanitizer<GPOS>::lock_instance (layout->gpos_blob);
-_hb_ot_layout_fini (hb_face_t *face)
+_hb_ot_layout_free (hb_ot_layout_t *layout)
- hb_ot_layout_t *layout = &face->ot_layout;
-
hb_blob_unlock (layout->gdef_blob);
hb_blob_unlock (layout->gsub_blob);
hb_blob_unlock (layout->gpos_blob);
hb_blob_unlock (layout->gdef_blob);
hb_blob_unlock (layout->gsub_blob);
hb_blob_unlock (layout->gpos_blob);
static const GDEF&
_get_gdef (hb_face_t *face)
{
static const GDEF&
_get_gdef (hb_face_t *face)
{
- return likely (face->ot_layout.gdef) ? *face->ot_layout.gdef : Null(GDEF);
+ return likely (face->ot_layout->gdef) ? *face->ot_layout->gdef : Null(GDEF);
}
static const GSUB&
_get_gsub (hb_face_t *face)
{
}
static const GSUB&
_get_gsub (hb_face_t *face)
{
- return likely (face->ot_layout.gsub) ? *face->ot_layout.gsub : Null(GSUB);
+ return likely (face->ot_layout->gsub) ? *face->ot_layout->gsub : Null(GSUB);
}
static const GPOS&
_get_gpos (hb_face_t *face)
{
}
static const GPOS&
_get_gpos (hb_face_t *face)
{
- return likely (face->ot_layout.gpos) ? *face->ot_layout.gpos : Null(GPOS);
+ return likely (face->ot_layout->gpos) ? *face->ot_layout->gpos : Null(GPOS);
hb_bool_t
_hb_ot_layout_has_new_glyph_classes (hb_face_t *face)
{
hb_bool_t
_hb_ot_layout_has_new_glyph_classes (hb_face_t *face)
{
- return face->ot_layout.new_gdef.len > 0;
+ return face->ot_layout->new_gdef.len > 0;
klass = gdef.get_glyph_class (glyph);
klass = gdef.get_glyph_class (glyph);
- if (!klass && glyph < face->ot_layout.new_gdef.len)
- klass = face->ot_layout.new_gdef.klasses[glyph];
+ if (!klass && glyph < face->ot_layout->new_gdef.len)
+ klass = face->ot_layout->new_gdef.klasses[glyph];
switch (klass) {
default:
switch (klass) {
default:
/* TODO optimize this? similar to old harfbuzz code for example */
/* TODO optimize this? similar to old harfbuzz code for example */
- hb_ot_layout_t *layout = &face->ot_layout;
+ hb_ot_layout_t *layout = face->ot_layout;
hb_ot_layout_class_t gdef_klass;
unsigned int len = layout->new_gdef.len;
hb_ot_layout_class_t gdef_klass;
unsigned int len = layout->new_gdef.len;
if (HB_OBJECT_IS_INERT (face))
return;
if (HB_OBJECT_IS_INERT (face))
return;
- hb_ot_layout_t *layout = &face->ot_layout;
+ hb_ot_layout_t *layout = face->ot_layout;
if (unlikely (!count || !glyphs || !klasses))
return;
if (unlikely (!count || !glyphs || !klasses))
return;
-/* Multiplies a 16dot16 value by another value, then truncates the result */
-#define _hb_16dot16_mul_round(A,B) (((int64_t) (A) * (B) + 0x8000) / 0x10000)
-
-
/* We need external help for these */
#ifdef HAVE_GLIB
/* We need external help for these */
#ifdef HAVE_GLIB