hb-harfrust.cc (5656B)
1 /* 2 * This is part of HarfBuzz, a text shaping library. 3 * 4 * Permission is hereby granted, without written agreement and without 5 * license or royalty fees, to use, copy, modify, and distribute this 6 * software and its documentation for any purpose, provided that the 7 * above copyright notice and the following two paragraphs appear in 8 * all copies of this software. 9 * 10 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 11 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 12 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 13 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 14 * DAMAGE. 15 * 16 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 17 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 19 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 20 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 21 * 22 * Author(s): Behdad Esfahbod 23 */ 24 25 #include "hb.hh" 26 27 #ifdef HAVE_HARFRUST 28 29 #include "hb-shaper-impl.hh" 30 31 #include "hb-utf.hh" 32 33 34 /* 35 * buffer 36 */ 37 extern "C" void * 38 _hb_harfrust_buffer_create_rs (void); 39 40 extern "C" void 41 _hb_harfrust_buffer_destroy_rs (void *data); 42 43 44 /* 45 * shaper face data 46 */ 47 48 extern "C" void * 49 _hb_harfrust_shaper_face_data_create_rs (hb_face_t *face); 50 51 hb_harfrust_face_data_t * 52 _hb_harfrust_shaper_face_data_create (hb_face_t *face) 53 { 54 return (hb_harfrust_face_data_t *) _hb_harfrust_shaper_face_data_create_rs (face); 55 } 56 57 extern "C" void 58 _hb_harfrust_shaper_face_data_destroy_rs (void *data); 59 60 void 61 _hb_harfrust_shaper_face_data_destroy (hb_harfrust_face_data_t *data) 62 { 63 _hb_harfrust_shaper_face_data_destroy_rs (data); 64 } 65 66 67 /* 68 * shaper font data 69 */ 70 71 extern "C" void * 72 _hb_harfrust_shaper_font_data_create_rs (hb_font_t *font, const void *face_data); 73 74 hb_harfrust_font_data_t * 75 _hb_harfrust_shaper_font_data_create (hb_font_t *font) 76 { 77 const hb_harfrust_face_data_t *face_data = font->face->data.harfrust; 78 return (hb_harfrust_font_data_t *) _hb_harfrust_shaper_font_data_create_rs (font, face_data); 79 } 80 81 extern "C" void 82 _hb_harfrust_shaper_font_data_destroy_rs (void *data); 83 84 void 85 _hb_harfrust_shaper_font_data_destroy (hb_harfrust_font_data_t *data) 86 { 87 _hb_harfrust_shaper_font_data_destroy_rs (data); 88 } 89 90 91 /* 92 * shape plan 93 */ 94 95 extern "C" void * 96 _hb_harfrust_shape_plan_create_rs (const void *font_data, 97 hb_script_t script, 98 hb_language_t language, 99 hb_direction_t direction); 100 101 extern "C" void 102 _hb_harfrust_shape_plan_destroy_rs (void *data); 103 104 105 /* 106 * shaper 107 */ 108 109 extern "C" hb_bool_t 110 _hb_harfrust_shape_rs (const void *font_data, 111 const void *face_data, 112 const void *rs_shape_plan, 113 const void *rs_buffer, 114 hb_font_t *font, 115 hb_buffer_t *buffer, 116 const uint8_t *pre_context, 117 uint32_t pre_context_len, 118 const uint8_t *post_context, 119 uint32_t post_context_len, 120 const hb_feature_t *features, 121 unsigned int num_features); 122 123 static hb_user_data_key_t hb_object_key = {0}; 124 125 hb_bool_t 126 _hb_harfrust_shape (hb_shape_plan_t *shape_plan, 127 hb_font_t *font, 128 hb_buffer_t *buffer, 129 const hb_feature_t *features, 130 unsigned int num_features) 131 { 132 const hb_harfrust_font_data_t *font_data = font->data.harfrust; 133 const hb_harfrust_face_data_t *face_data = font->face->data.harfrust; 134 135 retry_buffer: 136 void *hr_buffer = hb_buffer_get_user_data (buffer, &hb_object_key); 137 if (unlikely (!hr_buffer)) 138 { 139 hr_buffer = _hb_harfrust_buffer_create_rs (); 140 if (unlikely (!hr_buffer)) 141 return false; 142 143 if (!hb_buffer_set_user_data (buffer, 144 &hb_object_key, 145 hr_buffer, 146 _hb_harfrust_buffer_destroy_rs, 147 false)) 148 { 149 _hb_harfrust_buffer_destroy_rs (hr_buffer); 150 goto retry_buffer; 151 } 152 } 153 154 void *hr_shape_plan = nullptr; 155 156 if (!num_features) 157 { 158 retry_shape_plan: 159 hr_shape_plan = hb_shape_plan_get_user_data (shape_plan, &hb_object_key); 160 if (unlikely (!hr_shape_plan)) 161 { 162 hr_shape_plan = _hb_harfrust_shape_plan_create_rs (font_data, 163 shape_plan->key.props.script, 164 shape_plan->key.props.language, 165 shape_plan->key.props.direction); 166 if (hr_shape_plan && 167 !hb_shape_plan_set_user_data (shape_plan, 168 &hb_object_key, 169 hr_shape_plan, 170 _hb_harfrust_shape_plan_destroy_rs, 171 false)) 172 { 173 _hb_harfrust_shape_plan_destroy_rs (hr_shape_plan); 174 goto retry_shape_plan; 175 } 176 } 177 } 178 179 // Encode buffer pre/post-context as UTF-8, so that HarfRust can use it. 180 constexpr int CONTEXT_BYTE_SIZE = 4 * hb_buffer_t::CONTEXT_LENGTH; 181 uint8_t pre_context[CONTEXT_BYTE_SIZE]; 182 unsigned pre_context_len = 0; 183 for (unsigned i = buffer->context_len[0]; i; i--) 184 pre_context_len = hb_utf8_t::encode (pre_context + pre_context_len, 185 pre_context + CONTEXT_BYTE_SIZE, 186 buffer->context[0][i - 1]) - pre_context; 187 uint8_t post_context[CONTEXT_BYTE_SIZE]; 188 unsigned post_context_len = 0; 189 for (unsigned i = 0; i < buffer->context_len[1]; i++) 190 post_context_len = hb_utf8_t::encode (post_context + post_context_len, 191 post_context + CONTEXT_BYTE_SIZE, 192 buffer->context[1][i]) - post_context; 193 194 return _hb_harfrust_shape_rs (font_data, 195 face_data, 196 hr_shape_plan, 197 hr_buffer, 198 font, 199 buffer, 200 pre_context, 201 pre_context_len, 202 post_context, 203 post_context_len, 204 features, 205 num_features); 206 } 207 208 209 #endif