/*
Port from c++ is protected by a GNU Lesser GPLv3
Copyright © 2013 Sylvain BERTRAND <sylvain.bertrand@gmail.com>
<sylware@legeek.net>
*/
#include <stdlib.h>
#include "hb.h"
#include "hb-private.h"
#include "hb-atomic-private.h"
#include "hb-unicode-private.h"
static hb_unicode_combining_class_t
hb_unicode_combining_class_nil(hb_unicode_funcs_t * ufuncs HB_UNUSED,
hb_codepoint_t unicode HB_UNUSED,
void *user_data HB_UNUSED)
{
return HB_UNICODE_COMBINING_CLASS_NOT_REORDERED;
}
static unsigned int hb_unicode_eastasian_width_nil(hb_unicode_funcs_t *
ufuncs HB_UNUSED,
hb_codepoint_t unicode
HB_UNUSED,
void *user_data HB_UNUSED)
{
return 1;
}
static hb_unicode_general_category_t
hb_unicode_general_category_nil(hb_unicode_funcs_t * ufuncs HB_UNUSED,
hb_codepoint_t unicode HB_UNUSED,
void *user_data HB_UNUSED)
{
return HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER;
}
static hb_codepoint_t hb_unicode_mirroring_nil(hb_unicode_funcs_t *
ufuncs HB_UNUSED,
hb_codepoint_t unicode HB_UNUSED,
void *user_data HB_UNUSED)
{
return unicode;
}
static hb_script_t hb_unicode_script_nil(hb_unicode_funcs_t * ufuncs HB_UNUSED,
hb_codepoint_t unicode HB_UNUSED,
void *user_data HB_UNUSED)
{
return HB_SCRIPT_UNKNOWN;
}
static hb_bool_t hb_unicode_compose_nil(hb_unicode_funcs_t * ufuncs HB_UNUSED,
hb_codepoint_t a HB_UNUSED,
hb_codepoint_t b HB_UNUSED,
hb_codepoint_t * ab HB_UNUSED,
void *user_data HB_UNUSED)
{
return FALSE;
}
static hb_bool_t hb_unicode_decompose_nil(hb_unicode_funcs_t * ufuncs HB_UNUSED,
hb_codepoint_t ab HB_UNUSED,
hb_codepoint_t * a HB_UNUSED,
hb_codepoint_t * b HB_UNUSED,
void *user_data HB_UNUSED)
{
return FALSE;
}
static unsigned int hb_unicode_decompose_compatibility_nil(hb_unicode_funcs_t *
ufuncs HB_UNUSED,
hb_codepoint_t u
HB_UNUSED,
hb_codepoint_t *
decomposed HB_UNUSED,
void *user_data
HB_UNUSED)
{
return 0;
}
/*must be public*/
hb_unicode_funcs_t _hb_unicode_funcs_nil = {
REF_CNT_INVALID_VAL, /*ref_cnt */
NULL, /*parent */
TRUE, /*immutable */
{ /*func */
hb_unicode_combining_class_nil,
hb_unicode_eastasian_width_nil,
hb_unicode_general_category_nil,
hb_unicode_mirroring_nil,
hb_unicode_script_nil,
hb_unicode_compose_nil,
hb_unicode_decompose_nil,
hb_unicode_decompose_compatibility_nil}
,
{ /*user_data */
NULL, /*combining_class */
NULL, /*eastasian_width */
NULL, /*general_category */
NULL, /*mirroring */
NULL, /*script */
NULL, /*compose */
NULL, /*decompose */
NULL /*decompose_compatibility */
}
,
{ /*destroy */
NULL, /*combining_class */
NULL, /*eastasian_width */
NULL, /*general_category */
NULL, /*mirroring */
NULL, /*script */
NULL, /*compose */
NULL, /*decompose */
NULL /*decompose_compatibility */
}
};
/*
Default_Ignorable codepoints:
Note that as of Oct 2012 (Unicode 6.2), U+180E MONGOLIAN VOWEL SEPARATOR
is NOT Default_Ignorable, but it really behaves in a way that it should
be. That has been reported to the Unicode Technical Committee for
consideration. As such, we include it here, since Uniscribe removes it.
It *is* in Unicode 6.3 however. U+061C ARABIC LETTER MARK from Unicode
6.3 is also added manually. The new Unicode 6.3 bidi formatting
characters are encoded in a block that was Default_Ignorable already.
Note: While U+115F and U+1160 are Default_Ignorable, we do NOT want to
hide them, as the way Uniscribe has implemented them is with regular
spacing glyphs, and that's the way fonts are made to work. As such,
we make exceptions for those two.
Gathered from:
http://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:DI:]&abb=on&ucd=on&esc=on
Last updated to the page with the following versions:
Version 3.6; ICU version: 50.0.1.0; Unicode version: 6.1.0.0
4,167 Code Points
[\u00AD\u034F\u115F\u1160\u17B4\u17B5\u180B-\u180D\u200B-\u200F\u202A-\u202E\u2060-\u206F\u3164\uFE00-\uFE0F\uFEFF\uFFA0\uFFF0-\uFFF8\U0001D173-\U0001D17A\U000E0000-\U000E0FFF]
00AD ;SOFT HYPHEN
034F ;COMBINING GRAPHEME JOINER
#115F ;HANGUL CHOSEONG FILLER
#1160 ;HANGUL JUNGSEONG FILLER
17B4 ;KHMER VOWEL INHERENT AQ
17B5 ;KHMER VOWEL INHERENT AA
180B..180D ;MONGOLIAN FREE VARIATION SELECTOR THREE
200B..200F ;RIGHT-TO-LEFT MARK
202A..202E ;RIGHT-TO-LEFT OVERRIDE
2060..206F ;NOMINAL DIGIT SHAPES
3164 ;HANGUL FILLER
FE00..FE0F ;VARIATION SELECTOR-16
FEFF ;ZERO WIDTH NO-BREAK SPACE
FFA0 ;HALFWIDTH HANGUL FILLER
FFF0..FFF8 ;<unassigned-FFF8>
1D173..1D17A ;MUSICAL SYMBOL END PHRASE
E0000..E0FFF ;<unassigned-E0FFF>
*/
hb_bool_t hb_unicode_is_default_ignorable(hb_codepoint_t ch)
{
hb_codepoint_t plane;
plane = ch >> 16;
if (plane == 0) {
hb_codepoint_t page;
/*BMP*/ page = ch >> 8;
switch (page) {
case 0x00:
return ch == 0x00AD;
case 0x03:
return ch == 0x034F;
case 0x06:
return ch == 0x061C;
case 0x17:
return hb_codepoint_in_range(ch, 0x17B4, 0x17B5);
case 0x18:
return hb_codepoint_in_range(ch, 0x180B, 0x180E);
case 0x20:
return hb_codepoint_in_ranges(ch, 0x200B, 0x200F,
0x202A, 0x202E, 0x2060,
0x206F);
case 0x31:
return ch == 0x3164;
case 0xFE:
return hb_codepoint_in_range(ch, 0xFE00, 0xFE0F)
|| ch == 0xFEFF;
case 0xFF:
return hb_codepoint_in_range(ch, 0xFFF0, 0xFFF8)
|| ch == 0xFFA0;
default:
return FALSE;
}
} else {
/*Other planes */
switch (plane) {
case 0x01:
return hb_codepoint_in_range(ch, 0x0001D173,
0x0001D17A);
case 0x0E:
return hb_codepoint_in_range(ch, 0x000E0000,
0x000E0FFF);
default:
return FALSE;
}
}
}
hb_unicode_funcs_t *hb_unicode_funcs_get_empty(void)
{
return &_hb_unicode_funcs_nil;
}
hb_unicode_funcs_t *hb_unicode_funcs_reference(hb_unicode_funcs_t * ufuncs)
{
if (hb_atomic_int32_get(&ufuncs->ref_cnt) != REF_CNT_INVALID_VAL)
hb_atomic_int32_add(&ufuncs->ref_cnt, 1);
return ufuncs;
}
extern hb_unicode_funcs_t *hb_glib_get_unicode_funcs(void);
extern hb_unicode_funcs_t *hb_nil_get_unicode_funcs(void);
hb_unicode_funcs_t *hb_unicode_funcs_get_default(void)
{
#ifdef HAVE_GLIB
return hb_glib_get_unicode_funcs();
#else
return hb_unicode_funcs_get_empty();
#endif
}
void hb_unicode_funcs_destroy(hb_unicode_funcs_t * ufuncs)
{
if (!ufuncs)
return;
if (hb_atomic_int32_get(&ufuncs->ref_cnt) == REF_CNT_INVALID_VAL)
return;
hb_atomic_int32_add(&ufuncs->ref_cnt, -1);
if (hb_atomic_int32_get(&ufuncs->ref_cnt) > 0)
return;
hb_atomic_int32_set(&ufuncs->ref_cnt, REF_CNT_INVALID_VAL);
if (ufuncs->destroy.combining_class)
ufuncs->destroy.combining_class(ufuncs->user_data.
combining_class);
if (ufuncs->destroy.eastasian_width)
ufuncs->destroy.eastasian_width(ufuncs->user_data.
eastasian_width);
if (ufuncs->destroy.general_category)
ufuncs->destroy.general_category(ufuncs->user_data.
general_category);
if (ufuncs->destroy.mirroring)
ufuncs->destroy.mirroring(ufuncs->user_data.mirroring);
if (ufuncs->destroy.script)
ufuncs->destroy.script(ufuncs->user_data.script);
if (ufuncs->destroy.compose)
ufuncs->destroy.compose(ufuncs->user_data.compose);
if (ufuncs->destroy.decompose)
ufuncs->destroy.decompose(ufuncs->user_data.decompose);
if (ufuncs->destroy.decompose_compatibility)
ufuncs->destroy.decompose_compatibility(ufuncs->user_data.
decompose_compatibility);
hb_unicode_funcs_destroy(ufuncs->parent);
free(ufuncs);
}