diff --git a/src/uharfbuzz/_harfbuzz.pyx b/src/uharfbuzz/_harfbuzz.pyx index 6e57a72..f7687de 100644 --- a/src/uharfbuzz/_harfbuzz.pyx +++ b/src/uharfbuzz/_harfbuzz.pyx @@ -1,4 +1,5 @@ #cython: language_level=3 +from enum import IntEnum from charfbuzz cimport * from libc.stdlib cimport free, malloc from libc.string cimport const_char @@ -80,6 +81,13 @@ cdef class GlyphPosition: return self._hb_glyph_position.y_offset +class BufferClusterLevel(IntEnum): + MONOTONE_GRAPHEMES = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES + MONOTONE_CHARACTERS = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS + CHARACTERS = HB_BUFFER_CLUSTER_LEVEL_CHARACTERS + DEFAULT = HB_BUFFER_CLUSTER_LEVEL_DEFAULT + + cdef class Buffer: cdef hb_buffer_t* _hb_buffer cdef object _message_callback @@ -173,6 +181,16 @@ cdef class Buffer: hb_buffer_set_script( self._hb_buffer, hb_script_from_string(cstr, -1)) + @property + def cluster_level(self) -> BufferClusterLevel: + level = hb_buffer_get_cluster_level(self._hb_buffer) + return BufferClusterLevel(level) + + @cluster_level.setter + def cluster_level(self, value: BufferClusterLevel): + level = BufferClusterLevel(value) + hb_buffer_set_cluster_level(self._hb_buffer, level) + def set_language_from_ot_tag(self, value: str): cdef bytes packed = value.encode() cdef char* cstr = packed diff --git a/src/uharfbuzz/charfbuzz.pxd b/src/uharfbuzz/charfbuzz.pxd index 38cd5d8..f14f021 100644 --- a/src/uharfbuzz/charfbuzz.pxd +++ b/src/uharfbuzz/charfbuzz.pxd @@ -83,6 +83,12 @@ cdef extern from "hb.h": hb_position_t y_offset hb_var_int_t var + ctypedef enum hb_buffer_cluster_level_t: + HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES + HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS + HB_BUFFER_CLUSTER_LEVEL_CHARACTERS + HB_BUFFER_CLUSTER_LEVEL_DEFAULT + hb_buffer_t* hb_buffer_create() hb_bool_t hb_buffer_allocation_successful(hb_buffer_t* buffer) void hb_buffer_add_codepoints( @@ -116,6 +122,9 @@ cdef extern from "hb.h": void hb_buffer_set_script(hb_buffer_t* buffer, hb_script_t script) hb_language_t hb_buffer_get_language(hb_buffer_t* buffer) void hb_buffer_set_language(hb_buffer_t* buffer, hb_language_t language) + void hb_buffer_set_cluster_level(hb_buffer_t *buffer, + hb_buffer_cluster_level_t cluster_level) + hb_buffer_cluster_level_t hb_buffer_get_cluster_level(hb_buffer_t *buffer) void hb_buffer_destroy(hb_buffer_t* buffer) ctypedef hb_bool_t (*hb_buffer_message_func_t) ( hb_buffer_t *buffer, diff --git a/tests/test_uharfbuzz.py b/tests/test_uharfbuzz.py index d70c5a4..e16cca1 100644 --- a/tests/test_uharfbuzz.py +++ b/tests/test_uharfbuzz.py @@ -92,6 +92,36 @@ def test_guess_set_segment_properties(self): buf.set_language_from_ot_tag("BGR") assert buf.language == "bg" + def test_cluster_level(self): + buf = hb.Buffer() + + assert buf.cluster_level == hb.BufferClusterLevel.DEFAULT + + buf.cluster_level = hb.BufferClusterLevel.MONOTONE_CHARACTERS + assert buf.cluster_level == hb.BufferClusterLevel.MONOTONE_CHARACTERS + + buf.cluster_level = hb.BufferClusterLevel.MONOTONE_GRAPHEMES + assert buf.cluster_level == hb.BufferClusterLevel.MONOTONE_GRAPHEMES + + buf.cluster_level = hb.BufferClusterLevel.CHARACTERS + assert buf.cluster_level == hb.BufferClusterLevel.CHARACTERS + + buf.cluster_level = hb.BufferClusterLevel.DEFAULT + assert buf.cluster_level == hb.BufferClusterLevel.DEFAULT + + def test_cluster_level_int(self): + buf = hb.Buffer() + + assert buf.cluster_level == 0 + + buf.cluster_level = 1 + assert buf.cluster_level == 1 + + with pytest.raises(ValueError): + # 5 is not a valid BufferClusterLevel + buf.cluster_level = 5 + assert buf.cluster_level == 1 + class TestShape: @pytest.mark.parametrize(