| /* |
| * This is part of HarfBuzz, a text shaping library. |
| * |
| * Permission is hereby granted, without written agreement and without |
| * license or royalty fees, to use, copy, modify, and distribute this |
| * software and its documentation for any purpose, provided that the |
| * above copyright notice and the following two paragraphs appear in |
| * all copies of this software. |
| * |
| * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
| * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
| * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
| * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
| * DAMAGE. |
| * |
| * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
| * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
| * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
| * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
| * |
| * Author(s): Behdad Esfahbod |
| */ |
| |
| #include "hb.hh" |
| |
| #ifdef HAVE_HARFRUST |
| |
| #include "hb-shaper-impl.hh" |
| |
| #include "hb-utf.hh" |
| |
| |
| /* |
| * buffer |
| */ |
| extern "C" void * |
| _hb_harfrust_buffer_create_rs (void); |
| |
| extern "C" void |
| _hb_harfrust_buffer_destroy_rs (void *data); |
| |
| |
| /* |
| * shaper face data |
| */ |
| |
| extern "C" void * |
| _hb_harfrust_shaper_face_data_create_rs (hb_face_t *face); |
| |
| hb_harfrust_face_data_t * |
| _hb_harfrust_shaper_face_data_create (hb_face_t *face) |
| { |
| return (hb_harfrust_face_data_t *) _hb_harfrust_shaper_face_data_create_rs (face); |
| } |
| |
| extern "C" void |
| _hb_harfrust_shaper_face_data_destroy_rs (void *data); |
| |
| void |
| _hb_harfrust_shaper_face_data_destroy (hb_harfrust_face_data_t *data) |
| { |
| _hb_harfrust_shaper_face_data_destroy_rs (data); |
| } |
| |
| |
| /* |
| * shaper font data |
| */ |
| |
| extern "C" void * |
| _hb_harfrust_shaper_font_data_create_rs (hb_font_t *font, const void *face_data); |
| |
| hb_harfrust_font_data_t * |
| _hb_harfrust_shaper_font_data_create (hb_font_t *font) |
| { |
| const hb_harfrust_face_data_t *face_data = font->face->data.harfrust; |
| return (hb_harfrust_font_data_t *) _hb_harfrust_shaper_font_data_create_rs (font, face_data); |
| } |
| |
| extern "C" void |
| _hb_harfrust_shaper_font_data_destroy_rs (void *data); |
| |
| void |
| _hb_harfrust_shaper_font_data_destroy (hb_harfrust_font_data_t *data) |
| { |
| _hb_harfrust_shaper_font_data_destroy_rs (data); |
| } |
| |
| |
| /* |
| * shape plan |
| */ |
| |
| extern "C" void * |
| _hb_harfrust_shape_plan_create_rs (const void *font_data, |
| hb_script_t script, |
| hb_language_t language, |
| hb_direction_t direction); |
| |
| extern "C" void |
| _hb_harfrust_shape_plan_destroy_rs (void *data); |
| |
| |
| /* |
| * shaper |
| */ |
| |
| extern "C" hb_bool_t |
| _hb_harfrust_shape_rs (const void *font_data, |
| const void *face_data, |
| const void *rs_shape_plan, |
| const void *rs_buffer, |
| hb_font_t *font, |
| hb_buffer_t *buffer, |
| const uint8_t *pre_context, |
| uint32_t pre_context_len, |
| const uint8_t *post_context, |
| uint32_t post_context_len, |
| const hb_feature_t *features, |
| unsigned int num_features); |
| |
| static hb_user_data_key_t hb_object_key = {0}; |
| |
| hb_bool_t |
| _hb_harfrust_shape (hb_shape_plan_t *shape_plan, |
| hb_font_t *font, |
| hb_buffer_t *buffer, |
| const hb_feature_t *features, |
| unsigned int num_features) |
| { |
| const hb_harfrust_font_data_t *font_data = font->data.harfrust; |
| const hb_harfrust_face_data_t *face_data = font->face->data.harfrust; |
| |
| retry_buffer: |
| void *hr_buffer = hb_buffer_get_user_data (buffer, &hb_object_key); |
| if (unlikely (!hr_buffer)) |
| { |
| hr_buffer = _hb_harfrust_buffer_create_rs (); |
| if (unlikely (!hr_buffer)) |
| return false; |
| |
| if (!hb_buffer_set_user_data (buffer, |
| &hb_object_key, |
| hr_buffer, |
| _hb_harfrust_buffer_destroy_rs, |
| false)) |
| { |
| _hb_harfrust_buffer_destroy_rs (hr_buffer); |
| goto retry_buffer; |
| } |
| } |
| |
| void *hr_shape_plan = nullptr; |
| |
| if (!num_features) |
| { |
| retry_shape_plan: |
| hr_shape_plan = hb_shape_plan_get_user_data (shape_plan, &hb_object_key); |
| if (unlikely (!hr_shape_plan)) |
| { |
| hr_shape_plan = _hb_harfrust_shape_plan_create_rs (font_data, |
| shape_plan->key.props.script, |
| shape_plan->key.props.language, |
| shape_plan->key.props.direction); |
| if (hr_shape_plan && |
| !hb_shape_plan_set_user_data (shape_plan, |
| &hb_object_key, |
| hr_shape_plan, |
| _hb_harfrust_shape_plan_destroy_rs, |
| false)) |
| { |
| _hb_harfrust_shape_plan_destroy_rs (hr_shape_plan); |
| goto retry_shape_plan; |
| } |
| } |
| } |
| |
| // Encode buffer pre/post-context as UTF-8, so that HarfRust can use it. |
| constexpr int CONTEXT_BYTE_SIZE = 4 * hb_buffer_t::CONTEXT_LENGTH; |
| uint8_t pre_context[CONTEXT_BYTE_SIZE]; |
| unsigned pre_context_len = 0; |
| for (unsigned i = buffer->context_len[0]; i; i--) |
| pre_context_len = hb_utf8_t::encode (pre_context + pre_context_len, |
| pre_context + CONTEXT_BYTE_SIZE, |
| buffer->context[0][i - 1]) - pre_context; |
| uint8_t post_context[CONTEXT_BYTE_SIZE]; |
| unsigned post_context_len = 0; |
| for (unsigned i = 0; i < buffer->context_len[1]; i++) |
| post_context_len = hb_utf8_t::encode (post_context + post_context_len, |
| post_context + CONTEXT_BYTE_SIZE, |
| buffer->context[1][i]) - post_context; |
| |
| return _hb_harfrust_shape_rs (font_data, |
| face_data, |
| hr_shape_plan, |
| hr_buffer, |
| font, |
| buffer, |
| pre_context, |
| pre_context_len, |
| post_context, |
| post_context_len, |
| features, |
| num_features); |
| } |
| |
| |
| #endif |