Skip to content

Commit

Permalink
Merge pull request #208 from harfbuzz/ot-var
Browse files Browse the repository at this point in the history
Bind hb-ot-var APIs
  • Loading branch information
khaledhosny authored Sep 15, 2024
2 parents 3a15def + ad35cf8 commit 3653e79
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 1 deletion.
79 changes: 78 additions & 1 deletion src/uharfbuzz/_harfbuzz.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ from libc.stdlib cimport free, malloc, calloc
from libc.string cimport const_char
from collections import namedtuple
from cpython.pycapsule cimport PyCapsule_GetPointer, PyCapsule_IsValid
from typing import Callable, Dict, List, Sequence, Tuple, Union
from typing import Callable, Dict, List, Sequence, Tuple, Union, NamedTuple
from pathlib import Path


Expand Down Expand Up @@ -421,6 +421,26 @@ cdef class Blob:
return self._data


class OTVarAxisFlags(IntFlag):
HIDDEN = HB_OT_VAR_AXIS_FLAG_HIDDEN


class OTVarAxisInfo(NamedTuple):
axis_index: int
tag: str
name_id: int
flags: OTVarAxisFlags
min_value: float
default_value: float
max_value: float


class OTVarNamedInstance(NamedTuple):
subfamily_name_id: int
postscript_name_id: int
design_coords: List[float]


cdef hb_user_data_key_t k


Expand Down Expand Up @@ -557,6 +577,63 @@ cdef class Face:
hb_face_collect_variation_unicodes(self._hb_face, variation_selector, s._hb_set)
return s

@property
def has_var_data(self) -> bool:
return hb_ot_var_has_data(self._hb_face)

@property
def axis_infos(self) -> list[OTVarAxisInfo]:
cdef unsigned int axis_count = STATIC_ARRAY_SIZE
cdef hb_ot_var_axis_info_t axis_array[STATIC_ARRAY_SIZE]
cdef list infos = []
cdef char cstr[5]
cdef bytes packed
cdef unsigned int i
cdef unsigned int start_offset = 0
while axis_count == STATIC_ARRAY_SIZE:
hb_ot_var_get_axis_infos(
self._hb_face, start_offset, &axis_count, axis_array)
for i in range(axis_count):
hb_tag_to_string(axis_array[i].tag, cstr)
cstr[4] = b'\0'
packed = cstr
infos.append(
OTVarAxisInfo(
axis_index=axis_array[i].axis_index,
tag=packed.decode(),
name_id=axis_array[i].name_id,
flags=axis_array[i].flags,
min_value=axis_array[i].min_value,
default_value=axis_array[i].default_value,
max_value=axis_array[i].max_value
)
)
start_offset += axis_count
return infos

@property
def named_instances(self) -> list[OTVarNamedInstance]:
instances = []
cdef hb_face_t* face = self._hb_face
cdef unsigned int instance_count = hb_ot_var_get_named_instance_count(face)
cdef unsigned int axis_count = hb_ot_var_get_axis_count(face)
cdef hb_ot_name_id_t subfamily_name_id
cdef hb_ot_name_id_t postscript_name_id
cdef float* coords = <float*>malloc(axis_count * sizeof(float))
cdef unsigned int coord_length
for i in range(instance_count):
coord_length = axis_count
hb_ot_var_named_instance_get_design_coords(face, i, &coord_length, coords)
instances.append(
OTVarNamedInstance(
subfamily_name_id=hb_ot_var_named_instance_get_subfamily_name_id(face, i),
postscript_name_id=hb_ot_var_named_instance_get_postscript_name_id(face, i),
design_coords=[coords[j] for j in range(coord_length)],
)
)
free(coords)
return instances


# typing.NamedTuple doesn't seem to work with cython
GlyphExtents = namedtuple(
Expand Down
52 changes: 52 additions & 0 deletions src/uharfbuzz/charfbuzz.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -1211,6 +1211,58 @@ cdef extern from "hb-ot.h":
hb_font_t *font,
hb_ot_metrics_tag_t metrics_tag)

# hb-ot-var.h
ctypedef enum hb_ot_var_axis_flags_t:
HB_OT_VAR_AXIS_FLAG_HIDDEN
_HB_OT_VAR_AXIS_FLAG_MAX_VALUE

ctypedef struct hb_ot_var_axis_info_t:
unsigned int axis_index
hb_tag_t tag
hb_ot_name_id_t name_id
hb_ot_var_axis_flags_t flags
float min_value
float default_value
float max_value
unsigned int reserved

hb_bool_t hb_ot_var_has_data(hb_face_t *face)
unsigned int hb_ot_var_get_axis_count(hb_face_t *face)
unsigned int hb_ot_var_get_axis_infos(
hb_face_t *face,
unsigned int start_offset,
unsigned int *axes_count, # IN/OUT
hb_ot_var_axis_info_t *axes_array) # OUT
hb_bool_t hb_ot_var_find_axis_info(
hb_face_t *face,
hb_tag_t tag,
hb_ot_var_axis_info_t *axis_info)

unsigned int hb_ot_var_get_named_instance_count(hb_face_t *face)
hb_ot_name_id_t hb_ot_var_named_instance_get_subfamily_name_id(
hb_face_t *face,
unsigned int instance_index)
hb_ot_name_id_t hb_ot_var_named_instance_get_postscript_name_id(
hb_face_t *face,
unsigned int instance_index)
unsigned int hb_ot_var_named_instance_get_design_coords(
hb_face_t *face,
unsigned int instance_index,
unsigned int *coords_length, # IN/OUT
float *coords) # OUT

void hb_ot_var_normalize_variations(
hb_face_t *face,
const hb_variation_t *variations, # IN
unsigned int variations_length,
int *coords, # OUT
unsigned int coords_length)
void hb_ot_var_normalize_coords(
hb_face_t *face,
unsigned int coords_length,
const float *design_coords, # IN
int *normalized_coords) # OUT

cdef extern from "hb-subset-repacker.h":
ctypedef struct hb_link_t:
unsigned int width
Expand Down
26 changes: 26 additions & 0 deletions tests/test_uharfbuzz.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,32 @@ def test_properties(self, blankfont):
assert face.variation_selectors == hb.Set()
assert face.variation_unicodes(1) == hb.Set()

def test_has_var_data(self, blankfont, mutatorsans):
assert blankfont.face.has_var_data == False
assert mutatorsans.face.has_var_data == True

def test_axis_infos(self, mutatorsans):
face = mutatorsans.face
assert face.axis_infos == [
(0, "wdth", 256, 0, 0.0, 0.0, 1000.0),
(1, "wght", 257, 0, 0.0, 0.0, 1000.0),
]

def test_named_instances(self, mutatorsans):
face = mutatorsans.face
assert face.named_instances == [
(258, 259, [0.0, 0.0]),
(260, 261, [0.0, 1000.0]),
(262, 263, [1000.0, 0.0]),
(264, 265, [1000.0, 1000.0]),
(266, 267, [327.0, 500.0]),
(268, 269, [569.0780029296875, 1000.0]),
(270, 271, [1000.0, 500.0]),
(272, 273, [794.52197265625, 775.6090087890625]),
(274, 65535, [93.052001953125, 658.5969848632812]),
(275, 276, [328.0, 500.0]),
]


class TestFont:
def test_get_glyph_extents(self, opensans):
Expand Down

0 comments on commit 3653e79

Please sign in to comment.