Source code

Revision control

Copy as Markdown

Other Tools

/*
* 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