78 static void * |
78 static void * |
79 data_create_hangul (const hb_ot_shape_plan_t *plan) |
79 data_create_hangul (const hb_ot_shape_plan_t *plan) |
80 { |
80 { |
81 hangul_shape_plan_t *hangul_plan = (hangul_shape_plan_t *) calloc (1, sizeof (hangul_shape_plan_t)); |
81 hangul_shape_plan_t *hangul_plan = (hangul_shape_plan_t *) calloc (1, sizeof (hangul_shape_plan_t)); |
82 if (unlikely (!hangul_plan)) |
82 if (unlikely (!hangul_plan)) |
83 return NULL; |
83 return nullptr; |
84 |
84 |
85 for (unsigned int i = 0; i < HANGUL_FEATURE_COUNT; i++) |
85 for (unsigned int i = 0; i < HANGUL_FEATURE_COUNT; i++) |
86 hangul_plan->mask_array[i] = plan->map.get_1_mask (hangul_features[i]); |
86 hangul_plan->mask_array[i] = plan->map.get_1_mask (hangul_features[i]); |
87 |
87 |
88 return hangul_plan; |
88 return hangul_plan; |
103 #define TCount 28u |
103 #define TCount 28u |
104 #define SBase 0xAC00u |
104 #define SBase 0xAC00u |
105 #define NCount (VCount * TCount) |
105 #define NCount (VCount * TCount) |
106 #define SCount (LCount * NCount) |
106 #define SCount (LCount * NCount) |
107 |
107 |
108 #define isCombiningL(u) (hb_in_range ((u), LBase, LBase+LCount-1)) |
108 #define isCombiningL(u) (hb_in_range<hb_codepoint_t> ((u), LBase, LBase+LCount-1)) |
109 #define isCombiningV(u) (hb_in_range ((u), VBase, VBase+VCount-1)) |
109 #define isCombiningV(u) (hb_in_range<hb_codepoint_t> ((u), VBase, VBase+VCount-1)) |
110 #define isCombiningT(u) (hb_in_range ((u), TBase+1, TBase+TCount-1)) |
110 #define isCombiningT(u) (hb_in_range<hb_codepoint_t> ((u), TBase+1, TBase+TCount-1)) |
111 #define isCombinedS(u) (hb_in_range ((u), SBase, SBase+SCount-1)) |
111 #define isCombinedS(u) (hb_in_range<hb_codepoint_t> ((u), SBase, SBase+SCount-1)) |
112 |
112 |
113 #define isL(u) (hb_in_ranges ((u), 0x1100u, 0x115Fu, 0xA960u, 0xA97Cu)) |
113 #define isL(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1100u, 0x115Fu, 0xA960u, 0xA97Cu)) |
114 #define isV(u) (hb_in_ranges ((u), 0x1160u, 0x11A7u, 0xD7B0u, 0xD7C6u)) |
114 #define isV(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1160u, 0x11A7u, 0xD7B0u, 0xD7C6u)) |
115 #define isT(u) (hb_in_ranges ((u), 0x11A8u, 0x11FFu, 0xD7CBu, 0xD7FBu)) |
115 #define isT(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x11A8u, 0x11FFu, 0xD7CBu, 0xD7FBu)) |
116 |
116 |
117 #define isHangulTone(u) (hb_in_range ((u), 0x302Eu, 0x302Fu)) |
117 #define isHangulTone(u) (hb_in_range<hb_codepoint_t> ((u), 0x302Eu, 0x302Fu)) |
118 |
118 |
119 /* buffer var allocations */ |
119 /* buffer var allocations */ |
120 #define hangul_shaping_feature() complex_var_u8_0() /* hangul jamo shaping feature */ |
120 #define hangul_shaping_feature() complex_var_u8_0() /* hangul jamo shaping feature */ |
121 |
121 |
122 static bool |
122 static bool |
200 * I didn't bother for now. |
200 * I didn't bother for now. |
201 */ |
201 */ |
202 if (start < end && end == buffer->out_len) |
202 if (start < end && end == buffer->out_len) |
203 { |
203 { |
204 /* Tone mark follows a valid syllable; move it in front, unless it's zero width. */ |
204 /* Tone mark follows a valid syllable; move it in front, unless it's zero width. */ |
|
205 buffer->unsafe_to_break_from_outbuffer (start, buffer->idx); |
205 buffer->next_glyph (); |
206 buffer->next_glyph (); |
206 if (!is_zero_width_char (font, u)) |
207 if (!is_zero_width_char (font, u)) |
207 { |
208 { |
208 buffer->merge_out_clusters (start, end + 1); |
209 buffer->merge_out_clusters (start, end + 1); |
209 hb_glyph_info_t *info = buffer->out_info; |
210 hb_glyph_info_t *info = buffer->out_info; |
256 if (isT (t)) |
257 if (isT (t)) |
257 tindex = t - TBase; /* Only used if isCombiningT (t); otherwise invalid. */ |
258 tindex = t - TBase; /* Only used if isCombiningT (t); otherwise invalid. */ |
258 else |
259 else |
259 t = 0; /* The next character was not a trailing jamo. */ |
260 t = 0; /* The next character was not a trailing jamo. */ |
260 } |
261 } |
|
262 buffer->unsafe_to_break (buffer->idx, buffer->idx + (t ? 3 : 2)); |
261 |
263 |
262 /* We've got a syllable <L,V,T?>; see if it can potentially be composed. */ |
264 /* We've got a syllable <L,V,T?>; see if it can potentially be composed. */ |
263 if (isCombiningL (l) && isCombiningV (v) && (t == 0 || isCombiningT (t))) |
265 if (isCombiningL (l) && isCombiningV (v) && (t == 0 || isCombiningT (t))) |
264 { |
266 { |
265 /* Try to compose; if this succeeds, end is set to start+1. */ |
267 /* Try to compose; if this succeeds, end is set to start+1. */ |
320 if (unlikely (buffer->in_error)) |
322 if (unlikely (buffer->in_error)) |
321 return; |
323 return; |
322 end = start + 1; |
324 end = start + 1; |
323 continue; |
325 continue; |
324 } |
326 } |
|
327 else |
|
328 buffer->unsafe_to_break (buffer->idx, buffer->idx + 2); /* Mark unsafe between LV and T. */ |
325 } |
329 } |
326 |
330 |
327 /* Otherwise, decompose if font doesn't support <LV> or <LVT>, |
331 /* Otherwise, decompose if font doesn't support <LV> or <LVT>, |
328 * or if having non-combining <LV,T>. Note that we already handled |
332 * or if having non-combining <LV,T>. Note that we already handled |
329 * combining <LV,T> above. */ |
333 * combining <LV,T> above. */ |
366 info[i++].hangul_shaping_feature() = TJMO; |
370 info[i++].hangul_shaping_feature() = TJMO; |
367 if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) |
371 if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) |
368 buffer->merge_out_clusters (start, end); |
372 buffer->merge_out_clusters (start, end); |
369 continue; |
373 continue; |
370 } |
374 } |
|
375 else if ((!tindex && buffer->idx + 1 < count && isT (buffer->cur(+1).codepoint))) |
|
376 buffer->unsafe_to_break (buffer->idx, buffer->idx + 2); /* Mark unsafe between LV and T. */ |
371 } |
377 } |
372 |
378 |
373 if (has_glyph) |
379 if (has_glyph) |
374 { |
380 { |
375 /* We didn't decompose the S, so just advance past it. */ |
381 /* We didn't decompose the S, so just advance past it. */ |
406 } |
412 } |
407 |
413 |
408 |
414 |
409 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul = |
415 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul = |
410 { |
416 { |
411 "hangul", |
|
412 collect_features_hangul, |
417 collect_features_hangul, |
413 override_features_hangul, |
418 override_features_hangul, |
414 data_create_hangul, |
419 data_create_hangul, |
415 data_destroy_hangul, |
420 data_destroy_hangul, |
416 preprocess_text_hangul, |
421 preprocess_text_hangul, |
417 NULL, /* postprocess_glyphs */ |
422 nullptr, /* postprocess_glyphs */ |
418 HB_OT_SHAPE_NORMALIZATION_MODE_NONE, |
423 HB_OT_SHAPE_NORMALIZATION_MODE_NONE, |
419 NULL, /* decompose */ |
424 nullptr, /* decompose */ |
420 NULL, /* compose */ |
425 nullptr, /* compose */ |
421 setup_masks_hangul, |
426 setup_masks_hangul, |
422 NULL, /* disable_otl */ |
427 nullptr, /* disable_otl */ |
|
428 nullptr, /* reorder_marks */ |
423 HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, |
429 HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, |
424 false, /* fallback_position */ |
430 false, /* fallback_position */ |
425 }; |
431 }; |