mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
bug 964240 - update harfbuzz to pick up Hangul shaper improvements and other fixes. r=jdaggett
This commit is contained in:
parent
97762164c1
commit
1d0a8b5151
@ -27,7 +27,6 @@ HBSOURCES = \
|
||||
hb-buffer.cc \
|
||||
hb-cache-private.hh \
|
||||
hb-common.cc \
|
||||
hb-fallback-shape.cc \
|
||||
hb-face-private.hh \
|
||||
hb-face.cc \
|
||||
hb-font-private.hh \
|
||||
@ -92,6 +91,8 @@ HBSOURCES += \
|
||||
hb-ot-shape-complex-arabic-fallback.hh \
|
||||
hb-ot-shape-complex-arabic-table.hh \
|
||||
hb-ot-shape-complex-default.cc \
|
||||
hb-ot-shape-complex-hangul.cc \
|
||||
hb-ot-shape-complex-hebrew.cc \
|
||||
hb-ot-shape-complex-indic.cc \
|
||||
hb-ot-shape-complex-indic-machine.hh \
|
||||
hb-ot-shape-complex-indic-private.hh \
|
||||
@ -101,6 +102,7 @@ HBSOURCES += \
|
||||
hb-ot-shape-complex-sea.cc \
|
||||
hb-ot-shape-complex-sea-machine.hh \
|
||||
hb-ot-shape-complex-thai.cc \
|
||||
hb-ot-shape-complex-tibetan.cc \
|
||||
hb-ot-shape-complex-private.hh \
|
||||
hb-ot-shape-normalize-private.hh \
|
||||
hb-ot-shape-normalize.cc \
|
||||
@ -111,10 +113,15 @@ HBSOURCES += \
|
||||
HBHEADERS += \
|
||||
hb-ot.h \
|
||||
hb-ot-layout.h \
|
||||
hb-ot-shape.h \
|
||||
hb-ot-tag.h \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
if HAVE_FALLBACK
|
||||
HBSOURCES += hb-fallback-shape.cc
|
||||
endif
|
||||
|
||||
if HAVE_PTHREAD
|
||||
HBCFLAGS += $(PTHREAD_CFLAGS)
|
||||
HBLIBS += $(PTHREAD_LIBS)
|
||||
|
@ -29,7 +29,6 @@
|
||||
|
||||
#include "hb-private.hh"
|
||||
|
||||
#include "hb-blob.h"
|
||||
#include "hb-object-private.hh"
|
||||
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
|
@ -31,7 +31,6 @@
|
||||
#define HB_BUFFER_PRIVATE_HH
|
||||
|
||||
#include "hb-private.hh"
|
||||
#include "hb-buffer.h"
|
||||
#include "hb-object-private.hh"
|
||||
#include "hb-unicode-private.hh"
|
||||
|
||||
|
@ -204,7 +204,7 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
|
||||
|
||||
*p++ = '+';
|
||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance));
|
||||
if (pos->y_advance)
|
||||
if (pos[i].y_advance)
|
||||
p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance));
|
||||
}
|
||||
|
||||
|
@ -28,8 +28,6 @@
|
||||
|
||||
#include "hb-private.hh"
|
||||
|
||||
#include "hb-version.h"
|
||||
|
||||
#include "hb-mutex-private.hh"
|
||||
#include "hb-object-private.hh"
|
||||
|
||||
|
@ -94,6 +94,7 @@ typedef uint32_t hb_tag_t;
|
||||
#define HB_UNTAG(tag) ((uint8_t)((tag)>>24)), ((uint8_t)((tag)>>16)), ((uint8_t)((tag)>>8)), ((uint8_t)(tag))
|
||||
|
||||
#define HB_TAG_NONE HB_TAG(0,0,0,0)
|
||||
#define HB_TAG_MAX HB_TAG(0xff,0xff,0xff,0xff)
|
||||
|
||||
/* len=-1 means str is NUL-terminated. */
|
||||
hb_tag_t
|
||||
@ -270,7 +271,12 @@ typedef enum
|
||||
/*6.1*/ HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'),
|
||||
|
||||
/* No script set. */
|
||||
/*---*/ HB_SCRIPT_INVALID = HB_TAG_NONE
|
||||
/*---*/ HB_SCRIPT_INVALID = HB_TAG_NONE,
|
||||
|
||||
/* Dummy value to ensure any hb_tag_t value can be passed/stored as hb_script_t
|
||||
* without risking undefined behavior. */
|
||||
/*---*/ _HB_SCRIPT_MAX_VALUE = HB_TAG_MAX
|
||||
|
||||
} hb_script_t;
|
||||
|
||||
/* These are moved out of hb_script_t because glib-mkenums chokes otherwise. */
|
||||
|
@ -591,7 +591,6 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
||||
|
||||
CFMutableAttributedStringRef attr_string = CFAttributedStringCreateMutable (NULL, chars_len);
|
||||
CFAttributedStringReplaceString (attr_string, CFRangeMake (0, 0), string_ref);
|
||||
CFRelease (string_ref);
|
||||
CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
|
||||
kCTFontAttributeName, font_data->ct_font);
|
||||
|
||||
@ -671,23 +670,33 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
||||
if (buffer->in_error)
|
||||
FAIL ("Buffer resize failed");
|
||||
hb_glyph_info_t *info = buffer->info + buffer->len;
|
||||
buffer->len += range.length;
|
||||
|
||||
for (CFIndex j = 0; j < range.length; j++)
|
||||
CGGlyph notdef = 0;
|
||||
double advance = CTFontGetAdvancesForGlyphs (font_data->ct_font, kCTFontHorizontalOrientation, ¬def, NULL, 1);
|
||||
|
||||
for (CFIndex j = range.location; j < range.location + range.length; j++)
|
||||
{
|
||||
CGGlyph notdef = 0;
|
||||
double advance = CTFontGetAdvancesForGlyphs (font_data->ct_font, kCTFontHorizontalOrientation, ¬def, NULL, 1);
|
||||
UniChar ch = CFStringGetCharacterAtIndex (string_ref, j);
|
||||
if (hb_in_range<UniChar> (ch, 0xDC00, 0xDFFF) && range.location < j)
|
||||
{
|
||||
ch = CFStringGetCharacterAtIndex (string_ref, j - 1);
|
||||
if (hb_in_range<UniChar> (ch, 0xD800, 0xDBFF))
|
||||
/* This is the second of a surrogate pair. Don't need .notdef
|
||||
* for this one. */
|
||||
continue;
|
||||
}
|
||||
|
||||
info->codepoint = notdef;
|
||||
/* TODO We have to fixup clusters later. See vis_clusters in
|
||||
* hb-uniscribe.cc for example. */
|
||||
info->cluster = range.location + j;
|
||||
info->cluster = j;
|
||||
|
||||
info->mask = advance;
|
||||
info->var1.u32 = 0;
|
||||
info->var2.u32 = 0;
|
||||
|
||||
info++;
|
||||
buffer->len++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -796,6 +805,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease (string_ref);
|
||||
CFRelease (line);
|
||||
|
||||
return true;
|
||||
|
@ -31,7 +31,6 @@
|
||||
|
||||
#include "hb-private.hh"
|
||||
|
||||
#include "hb-font.h"
|
||||
#include "hb-object-private.hh"
|
||||
#include "hb-shaper-private.hh"
|
||||
#include "hb-shape-plan-private.hh"
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "hb-ot-layout-private.hh"
|
||||
|
||||
#include "hb-font-private.hh"
|
||||
#include "hb-blob.h"
|
||||
#include "hb-open-file-private.hh"
|
||||
#include "hb-ot-head-table.hh"
|
||||
#include "hb-ot-maxp-table.hh"
|
||||
|
@ -105,8 +105,9 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
|
||||
* shaper which many people unfortunately still request.
|
||||
*/
|
||||
|
||||
bool has_space;
|
||||
hb_codepoint_t space;
|
||||
font->get_glyph (' ', 0, &space);
|
||||
has_space = font->get_glyph (' ', 0, &space);
|
||||
|
||||
buffer->clear_positions ();
|
||||
|
||||
@ -114,7 +115,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
|
||||
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (buffer->unicode->is_default_ignorable (buffer->info[i].codepoint)) {
|
||||
if (has_space && buffer->unicode->is_default_ignorable (buffer->info[i].codepoint)) {
|
||||
buffer->info[i].codepoint = space;
|
||||
buffer->pos[i].x_advance = 0;
|
||||
buffer->pos[i].y_advance = 0;
|
||||
|
@ -31,7 +31,6 @@
|
||||
|
||||
#include "hb-private.hh"
|
||||
|
||||
#include "hb-font.h"
|
||||
#include "hb-object-private.hh"
|
||||
#include "hb-face-private.hh"
|
||||
#include "hb-shaper-private.hh"
|
||||
@ -145,6 +144,12 @@ struct hb_font_t {
|
||||
|
||||
/* Public getters */
|
||||
|
||||
inline hb_bool_t has_glyph (hb_codepoint_t unicode)
|
||||
{
|
||||
hb_codepoint_t glyph;
|
||||
return get_glyph (unicode, 0, &glyph);
|
||||
}
|
||||
|
||||
inline hb_bool_t get_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
|
||||
hb_codepoint_t *glyph)
|
||||
{
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "hb-ot-layout-private.hh"
|
||||
|
||||
#include "hb-font-private.hh"
|
||||
#include "hb-blob.h"
|
||||
#include "hb-open-file-private.hh"
|
||||
#include "hb-ot-head-table.hh"
|
||||
#include "hb-ot-maxp-table.hh"
|
||||
|
@ -34,8 +34,6 @@
|
||||
|
||||
#include <graphite2/Segment.h>
|
||||
|
||||
#include "hb-ot-tag.h"
|
||||
|
||||
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, face)
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, font)
|
||||
@ -109,7 +107,7 @@ _hb_graphite2_shaper_face_data_create (hb_face_t *face)
|
||||
|
||||
hb_graphite2_shaper_face_data_t *data = (hb_graphite2_shaper_face_data_t *) calloc (1, sizeof (hb_graphite2_shaper_face_data_t));
|
||||
if (unlikely (!data))
|
||||
hb_blob_destroy (silf_blob);
|
||||
return NULL;
|
||||
|
||||
data->face = face;
|
||||
data->grface = gr_make_face (data, &hb_graphite2_get_table, gr_face_preloadAll);
|
||||
|
@ -31,8 +31,6 @@
|
||||
|
||||
#include "hb-private.hh"
|
||||
|
||||
#include "hb-blob.h"
|
||||
|
||||
|
||||
namespace OT {
|
||||
|
||||
@ -594,7 +592,7 @@ struct LONGDATETIME
|
||||
TRACE_SANITIZE (this);
|
||||
return TRACE_RETURN (likely (c->check_struct (this)));
|
||||
}
|
||||
private:
|
||||
protected:
|
||||
LONG major;
|
||||
ULONG minor;
|
||||
public:
|
||||
|
@ -109,11 +109,13 @@ struct ValueFormat : USHORT
|
||||
if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++));
|
||||
if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++));
|
||||
if (format & xAdvance) {
|
||||
if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values++)); else values++;
|
||||
if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values));
|
||||
values++;
|
||||
}
|
||||
/* y_advance values grow downward but font-space grows upward, hence negation */
|
||||
if (format & yAdvance) {
|
||||
if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values++)); else values++;
|
||||
if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values));
|
||||
values++;
|
||||
}
|
||||
|
||||
if (!has_device ()) return;
|
||||
@ -125,17 +127,21 @@ struct ValueFormat : USHORT
|
||||
|
||||
/* pixel -> fractional pixel */
|
||||
if (format & xPlaDevice) {
|
||||
if (x_ppem) glyph_pos.x_offset += (base + get_device (values++)).get_x_delta (font); else values++;
|
||||
if (x_ppem) glyph_pos.x_offset += (base + get_device (values)).get_x_delta (font);
|
||||
values++;
|
||||
}
|
||||
if (format & yPlaDevice) {
|
||||
if (y_ppem) glyph_pos.y_offset += (base + get_device (values++)).get_y_delta (font); else values++;
|
||||
if (y_ppem) glyph_pos.y_offset += (base + get_device (values)).get_y_delta (font);
|
||||
values++;
|
||||
}
|
||||
if (format & xAdvDevice) {
|
||||
if (horizontal && x_ppem) glyph_pos.x_advance += (base + get_device (values++)).get_x_delta (font); else values++;
|
||||
if (horizontal && x_ppem) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font);
|
||||
values++;
|
||||
}
|
||||
if (format & yAdvDevice) {
|
||||
/* y_advance values grow downward but font-space grows upward, hence negation */
|
||||
if (!horizontal && y_ppem) glyph_pos.y_advance -= (base + get_device (values++)).get_y_delta (font); else values++;
|
||||
if (!horizontal && y_ppem) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font);
|
||||
values++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,12 +246,12 @@ struct AnchorFormat2
|
||||
unsigned int x_ppem = font->x_ppem;
|
||||
unsigned int y_ppem = font->y_ppem;
|
||||
hb_position_t cx, cy;
|
||||
hb_bool_t ret = false;
|
||||
hb_bool_t ret;
|
||||
|
||||
if (x_ppem || y_ppem)
|
||||
ret = font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
|
||||
*x = x_ppem && ret ? cx : font->em_scale_x (xCoordinate);
|
||||
*y = y_ppem && ret ? cy : font->em_scale_y (yCoordinate);
|
||||
ret = (x_ppem || y_ppem) &&
|
||||
font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
|
||||
*x = ret && x_ppem ? cx : font->em_scale_x (xCoordinate);
|
||||
*y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate);
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) {
|
||||
|
@ -31,8 +31,6 @@
|
||||
|
||||
#include "hb-private.hh"
|
||||
|
||||
#include "hb-ot-layout.h"
|
||||
|
||||
#include "hb-font-private.hh"
|
||||
#include "hb-buffer-private.hh"
|
||||
#include "hb-set-private.hh"
|
||||
|
@ -193,11 +193,6 @@ hb_ot_layout_collect_lookups (hb_face_t *face,
|
||||
const hb_tag_t *features,
|
||||
hb_set_t *lookup_indexes /* OUT */);
|
||||
|
||||
void
|
||||
hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan,
|
||||
hb_tag_t table_tag,
|
||||
hb_set_t *lookup_indexes /* OUT */);
|
||||
|
||||
void
|
||||
hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
|
||||
hb_tag_t table_tag,
|
||||
|
@ -199,7 +199,6 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
|
||||
map->add_global_bool_feature (HB_TAG('c','a','l','t'));
|
||||
map->add_gsub_pause (NULL);
|
||||
|
||||
map->add_global_bool_feature (HB_TAG('c','s','w','h'));
|
||||
map->add_global_bool_feature (HB_TAG('m','s','e','t'));
|
||||
}
|
||||
|
||||
@ -366,7 +365,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
|
||||
data_create_arabic,
|
||||
data_destroy_arabic,
|
||||
NULL, /* preprocess_text_arabic */
|
||||
NULL, /* normalization_preference */
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
|
||||
NULL, /* decompose */
|
||||
NULL, /* compose */
|
||||
setup_masks_arabic,
|
||||
|
@ -27,194 +27,18 @@
|
||||
#include "hb-ot-shape-complex-private.hh"
|
||||
|
||||
|
||||
/* TODO Add kana, and other small shapers here */
|
||||
|
||||
|
||||
/* The default shaper *only* adds additional per-script features.*/
|
||||
|
||||
static const hb_tag_t hangul_features[] =
|
||||
{
|
||||
HB_TAG('l','j','m','o'),
|
||||
HB_TAG('v','j','m','o'),
|
||||
HB_TAG('t','j','m','o'),
|
||||
HB_TAG_NONE
|
||||
};
|
||||
|
||||
static const hb_tag_t tibetan_features[] =
|
||||
{
|
||||
HB_TAG('a','b','v','s'),
|
||||
HB_TAG('b','l','w','s'),
|
||||
HB_TAG('a','b','v','m'),
|
||||
HB_TAG('b','l','w','m'),
|
||||
HB_TAG_NONE
|
||||
};
|
||||
|
||||
static void
|
||||
collect_features_default (hb_ot_shape_planner_t *plan)
|
||||
{
|
||||
const hb_tag_t *script_features = NULL;
|
||||
|
||||
switch ((hb_tag_t) plan->props.script)
|
||||
{
|
||||
/* Unicode-1.1 additions */
|
||||
case HB_SCRIPT_HANGUL:
|
||||
script_features = hangul_features;
|
||||
break;
|
||||
|
||||
/* Unicode-2.0 additions */
|
||||
case HB_SCRIPT_TIBETAN:
|
||||
script_features = tibetan_features;
|
||||
break;
|
||||
}
|
||||
|
||||
for (; script_features && *script_features; script_features++)
|
||||
plan->map.add_global_bool_feature (*script_features);
|
||||
}
|
||||
|
||||
static hb_ot_shape_normalization_mode_t
|
||||
normalization_preference_default (const hb_segment_properties_t *props)
|
||||
{
|
||||
return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS;
|
||||
}
|
||||
|
||||
static bool
|
||||
compose_default (const hb_ot_shape_normalize_context_t *c,
|
||||
hb_codepoint_t a,
|
||||
hb_codepoint_t b,
|
||||
hb_codepoint_t *ab)
|
||||
{
|
||||
/* Hebrew presentation-form shaping.
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=728866
|
||||
* Hebrew presentation forms with dagesh, for characters 0x05D0..0x05EA;
|
||||
* Note that some letters do not have a dagesh presForm encoded.
|
||||
*/
|
||||
static const hb_codepoint_t sDageshForms[0x05EA - 0x05D0 + 1] = {
|
||||
0xFB30, /* ALEF */
|
||||
0xFB31, /* BET */
|
||||
0xFB32, /* GIMEL */
|
||||
0xFB33, /* DALET */
|
||||
0xFB34, /* HE */
|
||||
0xFB35, /* VAV */
|
||||
0xFB36, /* ZAYIN */
|
||||
0x0000, /* HET */
|
||||
0xFB38, /* TET */
|
||||
0xFB39, /* YOD */
|
||||
0xFB3A, /* FINAL KAF */
|
||||
0xFB3B, /* KAF */
|
||||
0xFB3C, /* LAMED */
|
||||
0x0000, /* FINAL MEM */
|
||||
0xFB3E, /* MEM */
|
||||
0x0000, /* FINAL NUN */
|
||||
0xFB40, /* NUN */
|
||||
0xFB41, /* SAMEKH */
|
||||
0x0000, /* AYIN */
|
||||
0xFB43, /* FINAL PE */
|
||||
0xFB44, /* PE */
|
||||
0x0000, /* FINAL TSADI */
|
||||
0xFB46, /* TSADI */
|
||||
0xFB47, /* QOF */
|
||||
0xFB48, /* RESH */
|
||||
0xFB49, /* SHIN */
|
||||
0xFB4A /* TAV */
|
||||
};
|
||||
|
||||
bool found = c->unicode->compose (a, b, ab);
|
||||
|
||||
if (!found && (b & ~0x7F) == 0x0580) {
|
||||
/* Special-case Hebrew presentation forms that are excluded from
|
||||
* standard normalization, but wanted for old fonts. */
|
||||
switch (b) {
|
||||
case 0x05B4: /* HIRIQ */
|
||||
if (a == 0x05D9) { /* YOD */
|
||||
*ab = 0xFB1D;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05B7: /* patah */
|
||||
if (a == 0x05F2) { /* YIDDISH YOD YOD */
|
||||
*ab = 0xFB1F;
|
||||
found = true;
|
||||
} else if (a == 0x05D0) { /* ALEF */
|
||||
*ab = 0xFB2E;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05B8: /* QAMATS */
|
||||
if (a == 0x05D0) { /* ALEF */
|
||||
*ab = 0xFB2F;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05B9: /* HOLAM */
|
||||
if (a == 0x05D5) { /* VAV */
|
||||
*ab = 0xFB4B;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05BC: /* DAGESH */
|
||||
if (a >= 0x05D0 && a <= 0x05EA) {
|
||||
*ab = sDageshForms[a - 0x05D0];
|
||||
found = (*ab != 0);
|
||||
} else if (a == 0xFB2A) { /* SHIN WITH SHIN DOT */
|
||||
*ab = 0xFB2C;
|
||||
found = true;
|
||||
} else if (a == 0xFB2B) { /* SHIN WITH SIN DOT */
|
||||
*ab = 0xFB2D;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05BF: /* RAFE */
|
||||
switch (a) {
|
||||
case 0x05D1: /* BET */
|
||||
*ab = 0xFB4C;
|
||||
found = true;
|
||||
break;
|
||||
case 0x05DB: /* KAF */
|
||||
*ab = 0xFB4D;
|
||||
found = true;
|
||||
break;
|
||||
case 0x05E4: /* PE */
|
||||
*ab = 0xFB4E;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x05C1: /* SHIN DOT */
|
||||
if (a == 0x05E9) { /* SHIN */
|
||||
*ab = 0xFB2A;
|
||||
found = true;
|
||||
} else if (a == 0xFB49) { /* SHIN WITH DAGESH */
|
||||
*ab = 0xFB2C;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05C2: /* SIN DOT */
|
||||
if (a == 0x05E9) { /* SHIN */
|
||||
*ab = 0xFB2B;
|
||||
found = true;
|
||||
} else if (a == 0xFB49) { /* SHIN WITH DAGESH */
|
||||
*ab = 0xFB2D;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
|
||||
{
|
||||
"default",
|
||||
collect_features_default,
|
||||
NULL, /* collect_features */
|
||||
NULL, /* override_features */
|
||||
NULL, /* data_create */
|
||||
NULL, /* data_destroy */
|
||||
NULL, /* preprocess_text */
|
||||
normalization_preference_default,
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
|
||||
NULL, /* decompose */
|
||||
compose_default,
|
||||
NULL, /* compose */
|
||||
NULL, /* setup_masks */
|
||||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE,
|
||||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT,
|
||||
true, /* fallback_position */
|
||||
};
|
||||
|
417
gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc
Normal file
417
gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc
Normal file
@ -0,0 +1,417 @@
|
||||
/*
|
||||
* Copyright © 2013 Google, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb-ot-shape-complex-private.hh"
|
||||
|
||||
|
||||
/* Hangul shaper */
|
||||
|
||||
|
||||
/* Same order as the feature array below */
|
||||
enum {
|
||||
NONE,
|
||||
|
||||
LJMO,
|
||||
VJMO,
|
||||
TJMO,
|
||||
|
||||
FIRST_HANGUL_FEATURE = LJMO,
|
||||
HANGUL_FEATURE_COUNT = TJMO + 1
|
||||
};
|
||||
|
||||
static const hb_tag_t hangul_features[HANGUL_FEATURE_COUNT] =
|
||||
{
|
||||
HB_TAG_NONE,
|
||||
HB_TAG('l','j','m','o'),
|
||||
HB_TAG('v','j','m','o'),
|
||||
HB_TAG('t','j','m','o')
|
||||
};
|
||||
|
||||
static void
|
||||
collect_features_hangul (hb_ot_shape_planner_t *plan)
|
||||
{
|
||||
hb_ot_map_builder_t *map = &plan->map;
|
||||
|
||||
for (unsigned int i = FIRST_HANGUL_FEATURE; i < HANGUL_FEATURE_COUNT; i++)
|
||||
map->add_feature (hangul_features[i], 1, F_NONE);
|
||||
}
|
||||
|
||||
struct hangul_shape_plan_t
|
||||
{
|
||||
ASSERT_POD ();
|
||||
|
||||
hb_mask_t mask_array[HANGUL_FEATURE_COUNT];
|
||||
};
|
||||
|
||||
static void *
|
||||
data_create_hangul (const hb_ot_shape_plan_t *plan)
|
||||
{
|
||||
hangul_shape_plan_t *hangul_plan = (hangul_shape_plan_t *) calloc (1, sizeof (hangul_shape_plan_t));
|
||||
if (unlikely (!hangul_plan))
|
||||
return NULL;
|
||||
|
||||
for (unsigned int i = 0; i < HANGUL_FEATURE_COUNT; i++)
|
||||
hangul_plan->mask_array[i] = plan->map.get_1_mask (hangul_features[i]);
|
||||
|
||||
return hangul_plan;
|
||||
}
|
||||
|
||||
static void
|
||||
data_destroy_hangul (void *data)
|
||||
{
|
||||
free (data);
|
||||
}
|
||||
|
||||
/* Constants for algorithmic hangul syllable [de]composition. */
|
||||
#define LBase 0x1100
|
||||
#define VBase 0x1161
|
||||
#define TBase 0x11A7
|
||||
#define LCount 19
|
||||
#define VCount 21
|
||||
#define TCount 28
|
||||
#define SBase 0xAC00
|
||||
#define NCount (VCount * TCount)
|
||||
#define SCount (LCount * NCount)
|
||||
|
||||
#define isCombiningL(u) (hb_in_range<hb_codepoint_t> ((u), LBase, LBase+LCount-1))
|
||||
#define isCombiningV(u) (hb_in_range<hb_codepoint_t> ((u), VBase, VBase+VCount-1))
|
||||
#define isCombiningT(u) (hb_in_range<hb_codepoint_t> ((u), TBase+1, TBase+TCount-1))
|
||||
#define isCombinedS(u) (hb_in_range<hb_codepoint_t> ((u), SBase, SBase+SCount-1))
|
||||
|
||||
#define isL(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1100, 0x115F, 0xA960, 0xA97C))
|
||||
#define isV(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1160, 0x11A7, 0xD7B0, 0xD7C6))
|
||||
#define isT(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x11A8, 0x11FF, 0xD7CB, 0xD7FB))
|
||||
|
||||
#define isHangulTone(u) (hb_in_range<hb_codepoint_t> ((u), 0x302e, 0x302f))
|
||||
|
||||
/* buffer var allocations */
|
||||
#define hangul_shaping_feature() complex_var_u8_0() /* hangul jamo shaping feature */
|
||||
|
||||
static bool
|
||||
is_zero_width_char (hb_font_t *font,
|
||||
hb_codepoint_t unicode)
|
||||
{
|
||||
hb_codepoint_t glyph;
|
||||
return hb_font_get_glyph (font, unicode, 0, &glyph) && hb_font_get_glyph_h_advance (font, glyph) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
|
||||
hb_buffer_t *buffer,
|
||||
hb_font_t *font)
|
||||
{
|
||||
HB_BUFFER_ALLOCATE_VAR (buffer, hangul_shaping_feature);
|
||||
|
||||
/* Hangul syllables come in two shapes: LV, and LVT. Of those:
|
||||
*
|
||||
* - LV can be precomposed, or decomposed. Lets call those
|
||||
* <LV> and <L,V>,
|
||||
* - LVT can be fully precomposed, partically precomposed, or
|
||||
* fully decomposed. Ie. <LVT>, <LV,T>, or <L,V,T>.
|
||||
*
|
||||
* The composition / decomposition is mechanical. However, not
|
||||
* all <L,V> sequences compose, and not all <LV,T> sequences
|
||||
* compose.
|
||||
*
|
||||
* Here are the specifics:
|
||||
*
|
||||
* - <L>: U+1100..115F, U+A960..A97F
|
||||
* - <V>: U+1160..11A7, U+D7B0..D7C7
|
||||
* - <T>: U+11A8..11FF, U+D7CB..D7FB
|
||||
*
|
||||
* - Only the <L,V> sequences for the 11xx ranges combine.
|
||||
* - Only <LV,T> sequences for T in U+11A8..11C3 combine.
|
||||
*
|
||||
* Here is what we want to accomplish in this shaper:
|
||||
*
|
||||
* - If the whole syllable can be precomposed, do that,
|
||||
* - Otherwise, fully decompose and apply ljmo/vjmo/tjmo features.
|
||||
* - If a valid syllable is followed by a Hangul tone mark, reorder the tone
|
||||
* mark to precede the whole syllable - unless it is a zero-width glyph, in
|
||||
* which case we leave it untouched, assuming it's designed to overstrike.
|
||||
*
|
||||
* That is, of the different possible syllables:
|
||||
*
|
||||
* <L>
|
||||
* <L,V>
|
||||
* <L,V,T>
|
||||
* <LV>
|
||||
* <LVT>
|
||||
* <LV, T>
|
||||
*
|
||||
* - <L> needs no work.
|
||||
*
|
||||
* - <LV> and <LVT> can stay the way they are if the font supports them, otherwise we
|
||||
* should fully decompose them if font supports.
|
||||
*
|
||||
* - <L,V> and <L,V,T> we should compose if the whole thing can be composed.
|
||||
*
|
||||
* - <LV,T> we should compose if the whole thing can be composed, otherwise we should
|
||||
* decompose.
|
||||
*/
|
||||
|
||||
buffer->clear_output ();
|
||||
unsigned int start = 0, end = 0; /* Extent of most recently seen syllable;
|
||||
* valid only if start < end
|
||||
*/
|
||||
unsigned int count = buffer->len;
|
||||
|
||||
for (buffer->idx = 0; buffer->idx < count;)
|
||||
{
|
||||
hb_codepoint_t u = buffer->cur().codepoint;
|
||||
|
||||
if (isHangulTone (u))
|
||||
{
|
||||
/*
|
||||
* We could cache the width of the tone marks and the existence of dotted-circle,
|
||||
* but the use of the Hangul tone mark characters seems to be rare enough that
|
||||
* I didn't bother for now.
|
||||
*/
|
||||
if (start < end && end == buffer->out_len)
|
||||
{
|
||||
/* Tone mark follows a valid syllable; move it in front, unless it's zero width. */
|
||||
buffer->next_glyph ();
|
||||
if (!is_zero_width_char (font, u))
|
||||
{
|
||||
hb_glyph_info_t *info = buffer->out_info;
|
||||
hb_glyph_info_t tone = info[end];
|
||||
memmove (&info[start + 1], &info[start], (end - start) * sizeof (hb_glyph_info_t));
|
||||
info[start] = tone;
|
||||
}
|
||||
/* Merge clusters across the (possibly reordered) syllable+tone.
|
||||
* We want to merge even in the zero-width tone mark case here,
|
||||
* so that clustering behavior isn't dependent on how the tone mark
|
||||
* is handled by the font.
|
||||
*/
|
||||
buffer->merge_out_clusters (start, end + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No valid syllable as base for tone mark; try to insert dotted circle. */
|
||||
if (font->has_glyph (0x25cc))
|
||||
{
|
||||
hb_codepoint_t chars[2];
|
||||
if (!is_zero_width_char (font, u)) {
|
||||
chars[0] = u;
|
||||
chars[1] = 0x25cc;
|
||||
} else {
|
||||
chars[0] = 0x25cc;
|
||||
chars[1] = u;
|
||||
}
|
||||
buffer->replace_glyphs (1, 2, chars);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No dotted circle available in the font; just leave tone mark untouched. */
|
||||
buffer->next_glyph ();
|
||||
}
|
||||
}
|
||||
start = end = buffer->out_len;
|
||||
continue;
|
||||
}
|
||||
|
||||
start = buffer->out_len; /* Remember current position as a potential syllable start;
|
||||
* will only be used if we set end to a later position.
|
||||
*/
|
||||
|
||||
if (isL (u) && buffer->idx + 1 < count)
|
||||
{
|
||||
hb_codepoint_t l = u;
|
||||
hb_codepoint_t v = buffer->cur(+1).codepoint;
|
||||
if (isV (v))
|
||||
{
|
||||
/* Have <L,V> or <L,V,T>. */
|
||||
hb_codepoint_t t = 0;
|
||||
unsigned int tindex = 0;
|
||||
if (buffer->idx + 2 < count)
|
||||
{
|
||||
t = buffer->cur(+2).codepoint;
|
||||
if (isT (t))
|
||||
tindex = t - TBase; /* Only used if isCombiningT (t); otherwise invalid. */
|
||||
else
|
||||
t = 0; /* The next character was not a trailing jamo. */
|
||||
}
|
||||
|
||||
/* We've got a syllable <L,V,T?>; see if it can potentially be composed. */
|
||||
if (isCombiningL (l) && isCombiningV (v) && (t == 0 || isCombiningT (t)))
|
||||
{
|
||||
/* Try to compose; if this succeeds, end is set to start+1. */
|
||||
hb_codepoint_t s = SBase + (l - LBase) * NCount + (v - VBase) * TCount + tindex;
|
||||
if (font->has_glyph (s))
|
||||
{
|
||||
buffer->replace_glyphs (t ? 3 : 2, 1, &s);
|
||||
if (unlikely (buffer->in_error))
|
||||
return;
|
||||
end = start + 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* We didn't compose, either because it's an Old Hangul syllable without a
|
||||
* precomposed character in Unicode, or because the font didn't support the
|
||||
* necessary precomposed glyph.
|
||||
* Set jamo features on the individual glyphs, and advance past them.
|
||||
*/
|
||||
buffer->cur().hangul_shaping_feature() = LJMO;
|
||||
buffer->next_glyph ();
|
||||
buffer->cur().hangul_shaping_feature() = VJMO;
|
||||
buffer->next_glyph ();
|
||||
if (t)
|
||||
{
|
||||
buffer->cur().hangul_shaping_feature() = TJMO;
|
||||
buffer->next_glyph ();
|
||||
end = start + 3;
|
||||
}
|
||||
else
|
||||
end = start + 2;
|
||||
buffer->merge_out_clusters (start, end);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
else if (isCombinedS (u))
|
||||
{
|
||||
/* Have <LV>, <LVT>, or <LV,T> */
|
||||
hb_codepoint_t s = u;
|
||||
bool has_glyph = font->has_glyph (s);
|
||||
unsigned int lindex = (s - SBase) / NCount;
|
||||
unsigned int nindex = (s - SBase) % NCount;
|
||||
unsigned int vindex = nindex / TCount;
|
||||
unsigned int tindex = nindex % TCount;
|
||||
|
||||
if (!tindex &&
|
||||
buffer->idx + 1 < count &&
|
||||
isCombiningT (buffer->cur(+1).codepoint))
|
||||
{
|
||||
/* <LV,T>, try to combine. */
|
||||
unsigned int new_tindex = buffer->cur(+1).codepoint - TBase;
|
||||
hb_codepoint_t new_s = s + new_tindex;
|
||||
if (font->has_glyph (new_s))
|
||||
{
|
||||
buffer->replace_glyphs (2, 1, &new_s);
|
||||
if (unlikely (buffer->in_error))
|
||||
return;
|
||||
end = start + 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, decompose if font doesn't support <LV> or <LVT>,
|
||||
* or if having non-combining <LV,T>. Note that we already handled
|
||||
* combining <LV,T> above. */
|
||||
if (!has_glyph ||
|
||||
(!tindex &&
|
||||
buffer->idx + 1 < count &&
|
||||
isT (buffer->cur(+1).codepoint)))
|
||||
{
|
||||
hb_codepoint_t decomposed[3] = {LBase + lindex,
|
||||
VBase + vindex,
|
||||
TBase + tindex};
|
||||
if (font->has_glyph (decomposed[0]) &&
|
||||
font->has_glyph (decomposed[1]) &&
|
||||
(!tindex || font->has_glyph (decomposed[2])))
|
||||
{
|
||||
unsigned int s_len = tindex ? 3 : 2;
|
||||
buffer->replace_glyphs (1, s_len, decomposed);
|
||||
if (unlikely (buffer->in_error))
|
||||
return;
|
||||
|
||||
/* We decomposed S: apply jamo features to the individual glyphs
|
||||
* that are now in buffer->out_info.
|
||||
*/
|
||||
hb_glyph_info_t *info = buffer->out_info;
|
||||
|
||||
/* If we decomposed an LV because of a non-combining T following,
|
||||
* we want to include this T in the syllable.
|
||||
*/
|
||||
if (has_glyph && !tindex)
|
||||
{
|
||||
buffer->next_glyph ();
|
||||
s_len++;
|
||||
}
|
||||
end = start + s_len;
|
||||
|
||||
unsigned int i = start;
|
||||
info[i++].hangul_shaping_feature() = LJMO;
|
||||
info[i++].hangul_shaping_feature() = VJMO;
|
||||
if (i < end)
|
||||
info[i++].hangul_shaping_feature() = TJMO;
|
||||
buffer->merge_out_clusters (start, end);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_glyph)
|
||||
{
|
||||
/* We didn't decompose the S, so just advance past it. */
|
||||
end = start + 1;
|
||||
buffer->next_glyph ();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Didn't find a recognizable syllable, so we leave end <= start;
|
||||
* this will prevent tone-mark reordering happening.
|
||||
*/
|
||||
buffer->next_glyph ();
|
||||
}
|
||||
buffer->swap_buffers ();
|
||||
}
|
||||
|
||||
static void
|
||||
setup_masks_hangul (const hb_ot_shape_plan_t *plan,
|
||||
hb_buffer_t *buffer,
|
||||
hb_font_t *font HB_UNUSED)
|
||||
{
|
||||
const hangul_shape_plan_t *hangul_plan = (const hangul_shape_plan_t *) plan->data;
|
||||
|
||||
if (likely (hangul_plan))
|
||||
{
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++, info++)
|
||||
info->mask |= hangul_plan->mask_array[info->hangul_shaping_feature()];
|
||||
}
|
||||
|
||||
HB_BUFFER_DEALLOCATE_VAR (buffer, hangul_shaping_feature);
|
||||
}
|
||||
|
||||
|
||||
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul =
|
||||
{
|
||||
"hangul",
|
||||
collect_features_hangul,
|
||||
NULL, /* override_features */
|
||||
data_create_hangul, /* data_create */
|
||||
data_destroy_hangul, /* data_destroy */
|
||||
preprocess_text_hangul,
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
|
||||
NULL, /* decompose */
|
||||
NULL, /* compose */
|
||||
setup_masks_hangul, /* setup_masks */
|
||||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
|
||||
false, /* fallback_position */
|
||||
};
|
172
gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc
Normal file
172
gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright © 2010,2012 Google, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb-ot-shape-complex-private.hh"
|
||||
|
||||
|
||||
static bool
|
||||
compose_hebrew (const hb_ot_shape_normalize_context_t *c,
|
||||
hb_codepoint_t a,
|
||||
hb_codepoint_t b,
|
||||
hb_codepoint_t *ab)
|
||||
{
|
||||
/* Hebrew presentation-form shaping.
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=728866
|
||||
* Hebrew presentation forms with dagesh, for characters 0x05D0..0x05EA;
|
||||
* Note that some letters do not have a dagesh presForm encoded.
|
||||
*/
|
||||
static const hb_codepoint_t sDageshForms[0x05EA - 0x05D0 + 1] = {
|
||||
0xFB30, /* ALEF */
|
||||
0xFB31, /* BET */
|
||||
0xFB32, /* GIMEL */
|
||||
0xFB33, /* DALET */
|
||||
0xFB34, /* HE */
|
||||
0xFB35, /* VAV */
|
||||
0xFB36, /* ZAYIN */
|
||||
0x0000, /* HET */
|
||||
0xFB38, /* TET */
|
||||
0xFB39, /* YOD */
|
||||
0xFB3A, /* FINAL KAF */
|
||||
0xFB3B, /* KAF */
|
||||
0xFB3C, /* LAMED */
|
||||
0x0000, /* FINAL MEM */
|
||||
0xFB3E, /* MEM */
|
||||
0x0000, /* FINAL NUN */
|
||||
0xFB40, /* NUN */
|
||||
0xFB41, /* SAMEKH */
|
||||
0x0000, /* AYIN */
|
||||
0xFB43, /* FINAL PE */
|
||||
0xFB44, /* PE */
|
||||
0x0000, /* FINAL TSADI */
|
||||
0xFB46, /* TSADI */
|
||||
0xFB47, /* QOF */
|
||||
0xFB48, /* RESH */
|
||||
0xFB49, /* SHIN */
|
||||
0xFB4A /* TAV */
|
||||
};
|
||||
|
||||
bool found = c->unicode->compose (a, b, ab);
|
||||
|
||||
if (!found)
|
||||
{
|
||||
/* Special-case Hebrew presentation forms that are excluded from
|
||||
* standard normalization, but wanted for old fonts. */
|
||||
switch (b) {
|
||||
case 0x05B4: /* HIRIQ */
|
||||
if (a == 0x05D9) { /* YOD */
|
||||
*ab = 0xFB1D;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05B7: /* patah */
|
||||
if (a == 0x05F2) { /* YIDDISH YOD YOD */
|
||||
*ab = 0xFB1F;
|
||||
found = true;
|
||||
} else if (a == 0x05D0) { /* ALEF */
|
||||
*ab = 0xFB2E;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05B8: /* QAMATS */
|
||||
if (a == 0x05D0) { /* ALEF */
|
||||
*ab = 0xFB2F;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05B9: /* HOLAM */
|
||||
if (a == 0x05D5) { /* VAV */
|
||||
*ab = 0xFB4B;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05BC: /* DAGESH */
|
||||
if (a >= 0x05D0 && a <= 0x05EA) {
|
||||
*ab = sDageshForms[a - 0x05D0];
|
||||
found = (*ab != 0);
|
||||
} else if (a == 0xFB2A) { /* SHIN WITH SHIN DOT */
|
||||
*ab = 0xFB2C;
|
||||
found = true;
|
||||
} else if (a == 0xFB2B) { /* SHIN WITH SIN DOT */
|
||||
*ab = 0xFB2D;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05BF: /* RAFE */
|
||||
switch (a) {
|
||||
case 0x05D1: /* BET */
|
||||
*ab = 0xFB4C;
|
||||
found = true;
|
||||
break;
|
||||
case 0x05DB: /* KAF */
|
||||
*ab = 0xFB4D;
|
||||
found = true;
|
||||
break;
|
||||
case 0x05E4: /* PE */
|
||||
*ab = 0xFB4E;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x05C1: /* SHIN DOT */
|
||||
if (a == 0x05E9) { /* SHIN */
|
||||
*ab = 0xFB2A;
|
||||
found = true;
|
||||
} else if (a == 0xFB49) { /* SHIN WITH DAGESH */
|
||||
*ab = 0xFB2C;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05C2: /* SIN DOT */
|
||||
if (a == 0x05E9) { /* SHIN */
|
||||
*ab = 0xFB2B;
|
||||
found = true;
|
||||
} else if (a == 0xFB49) { /* SHIN WITH DAGESH */
|
||||
*ab = 0xFB2D;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
|
||||
{
|
||||
"hebrew",
|
||||
NULL, /* collect_features */
|
||||
NULL, /* override_features */
|
||||
NULL, /* data_create */
|
||||
NULL, /* data_destroy */
|
||||
NULL, /* preprocess_text */
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
|
||||
NULL, /* decompose */
|
||||
compose_hebrew,
|
||||
NULL, /* setup_masks */
|
||||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT,
|
||||
true, /* fallback_position */
|
||||
};
|
@ -1690,12 +1690,6 @@ clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
}
|
||||
|
||||
|
||||
static hb_ot_shape_normalization_mode_t
|
||||
normalization_preference_indic (const hb_segment_properties_t *props HB_UNUSED)
|
||||
{
|
||||
return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT;
|
||||
}
|
||||
|
||||
static bool
|
||||
decompose_indic (const hb_ot_shape_normalize_context_t *c,
|
||||
hb_codepoint_t ab,
|
||||
@ -1806,7 +1800,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
|
||||
data_create_indic,
|
||||
data_destroy_indic,
|
||||
NULL, /* preprocess_text */
|
||||
normalization_preference_indic,
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
|
||||
decompose_indic,
|
||||
compose_indic,
|
||||
setup_masks_indic,
|
||||
|
@ -541,13 +541,6 @@ final_reordering (const hb_ot_shape_plan_t *plan,
|
||||
}
|
||||
|
||||
|
||||
static hb_ot_shape_normalization_mode_t
|
||||
normalization_preference_myanmar (const hb_segment_properties_t *props HB_UNUSED)
|
||||
{
|
||||
return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT;
|
||||
}
|
||||
|
||||
|
||||
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
|
||||
{
|
||||
"myanmar",
|
||||
@ -556,7 +549,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
|
||||
NULL, /* data_create */
|
||||
NULL, /* data_destroy */
|
||||
NULL, /* preprocess_text */
|
||||
normalization_preference_myanmar,
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
|
||||
NULL, /* decompose */
|
||||
NULL, /* compose */
|
||||
setup_masks_myanmar,
|
||||
|
@ -44,7 +44,9 @@ enum hb_ot_shape_zero_width_marks_type_t {
|
||||
// HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY,
|
||||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE,
|
||||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
|
||||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE
|
||||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
|
||||
|
||||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT = HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE
|
||||
};
|
||||
|
||||
|
||||
@ -52,10 +54,13 @@ enum hb_ot_shape_zero_width_marks_type_t {
|
||||
#define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \
|
||||
HB_COMPLEX_SHAPER_IMPLEMENT (default) /* should be first */ \
|
||||
HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \
|
||||
HB_COMPLEX_SHAPER_IMPLEMENT (hangul) \
|
||||
HB_COMPLEX_SHAPER_IMPLEMENT (hebrew) \
|
||||
HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
|
||||
HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \
|
||||
HB_COMPLEX_SHAPER_IMPLEMENT (sea) \
|
||||
HB_COMPLEX_SHAPER_IMPLEMENT (thai) \
|
||||
HB_COMPLEX_SHAPER_IMPLEMENT (tibetan) \
|
||||
/* ^--- Add new shapers here */
|
||||
|
||||
|
||||
@ -105,12 +110,7 @@ struct hb_ot_complex_shaper_t
|
||||
hb_font_t *font);
|
||||
|
||||
|
||||
/* normalization_preference()
|
||||
* Called during shape().
|
||||
* May be NULL.
|
||||
*/
|
||||
hb_ot_shape_normalization_mode_t
|
||||
(*normalization_preference) (const hb_segment_properties_t *props);
|
||||
hb_ot_shape_normalization_mode_t normalization_preference;
|
||||
|
||||
/* decompose()
|
||||
* Called during shape()'s normalization.
|
||||
@ -189,19 +189,22 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
|
||||
return &_hb_ot_complex_shaper_thai;
|
||||
|
||||
|
||||
#if 0
|
||||
/* Note:
|
||||
* Currently we don't have a separate Hangul shaper. The default shaper handles
|
||||
* Hangul by enabling jamo features. We may want to implement a separate shaper
|
||||
* in the future. See this thread for details of what such a shaper would do:
|
||||
*
|
||||
* http://lists.freedesktop.org/archives/harfbuzz/2013-April/003070.html
|
||||
*/
|
||||
/* Unicode-1.1 additions */
|
||||
case HB_SCRIPT_HANGUL:
|
||||
|
||||
return &_hb_ot_complex_shaper_hangul;
|
||||
#endif
|
||||
|
||||
|
||||
/* Unicode-2.0 additions */
|
||||
case HB_SCRIPT_TIBETAN:
|
||||
|
||||
return &_hb_ot_complex_shaper_tibetan;
|
||||
|
||||
|
||||
/* Unicode-1.1 additions */
|
||||
case HB_SCRIPT_HEBREW:
|
||||
|
||||
return &_hb_ot_complex_shaper_hebrew;
|
||||
|
||||
|
||||
/* ^--- Add new shapers here */
|
||||
@ -241,9 +244,6 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
|
||||
case HB_SCRIPT_LAO:
|
||||
case HB_SCRIPT_THAI:
|
||||
|
||||
/* Unicode-2.0 additions */
|
||||
case HB_SCRIPT_TIBETAN:
|
||||
|
||||
/* Unicode-3.2 additions */
|
||||
case HB_SCRIPT_TAGALOG:
|
||||
case HB_SCRIPT_TAGBANWA:
|
||||
|
@ -360,13 +360,6 @@ final_reordering (const hb_ot_shape_plan_t *plan,
|
||||
}
|
||||
|
||||
|
||||
static hb_ot_shape_normalization_mode_t
|
||||
normalization_preference_sea (const hb_segment_properties_t *props HB_UNUSED)
|
||||
{
|
||||
return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT;
|
||||
}
|
||||
|
||||
|
||||
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_sea =
|
||||
{
|
||||
"sea",
|
||||
@ -375,7 +368,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_sea =
|
||||
NULL, /* data_create */
|
||||
NULL, /* data_destroy */
|
||||
NULL, /* preprocess_text */
|
||||
normalization_preference_sea,
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
|
||||
NULL, /* decompose */
|
||||
NULL, /* compose */
|
||||
setup_masks_sea,
|
||||
|
@ -369,10 +369,10 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai =
|
||||
NULL, /* data_create */
|
||||
NULL, /* data_destroy */
|
||||
preprocess_text_thai,
|
||||
NULL, /* normalization_preference */
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
|
||||
NULL, /* decompose */
|
||||
NULL, /* compose */
|
||||
NULL, /* setup_masks */
|
||||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE,
|
||||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT,
|
||||
false,/* fallback_position */
|
||||
};
|
||||
|
61
gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc
Normal file
61
gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright © 2010,2012 Google, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb-ot-shape-complex-private.hh"
|
||||
|
||||
|
||||
static const hb_tag_t tibetan_features[] =
|
||||
{
|
||||
HB_TAG('a','b','v','s'),
|
||||
HB_TAG('b','l','w','s'),
|
||||
HB_TAG('a','b','v','m'),
|
||||
HB_TAG('b','l','w','m'),
|
||||
HB_TAG_NONE
|
||||
};
|
||||
|
||||
static void
|
||||
collect_features_tibetan (hb_ot_shape_planner_t *plan)
|
||||
{
|
||||
for (const hb_tag_t *script_features = tibetan_features; script_features && *script_features; script_features++)
|
||||
plan->map.add_global_bool_feature (*script_features);
|
||||
}
|
||||
|
||||
|
||||
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_tibetan =
|
||||
{
|
||||
"default",
|
||||
collect_features_tibetan,
|
||||
NULL, /* override_features */
|
||||
NULL, /* data_create */
|
||||
NULL, /* data_destroy */
|
||||
NULL, /* preprocess_text */
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
|
||||
NULL, /* decompose */
|
||||
NULL, /* compose */
|
||||
NULL, /* setup_masks */
|
||||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT,
|
||||
true, /* fallback_position */
|
||||
};
|
@ -430,14 +430,12 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
hb_mask_t kern_mask = plan->map.get_1_mask (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ?
|
||||
HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n'));
|
||||
if (!kern_mask) return;
|
||||
if (!plan->has_kern) return;
|
||||
|
||||
unsigned int count = buffer->len;
|
||||
|
||||
OT::hb_apply_context_t c (1, font, buffer);
|
||||
c.set_lookup_mask (kern_mask);
|
||||
c.set_lookup_mask (plan->kern_mask);
|
||||
c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
|
||||
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
|
@ -29,8 +29,6 @@
|
||||
|
||||
#include "hb-private.hh"
|
||||
|
||||
#include "hb-font.h"
|
||||
#include "hb-buffer.h"
|
||||
|
||||
/* buffer var allocations, used during the normalization process */
|
||||
#define glyph_index() var1.u32
|
||||
@ -38,6 +36,7 @@
|
||||
struct hb_ot_shape_plan_t;
|
||||
|
||||
enum hb_ot_shape_normalization_mode_t {
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED,
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS, /* never composes base-to-base */
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, /* always fully decomposes and then recompose back */
|
||||
|
@ -213,8 +213,9 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor
|
||||
}
|
||||
|
||||
static inline void
|
||||
handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end)
|
||||
handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit)
|
||||
{
|
||||
/* TODO Currently if there's a variation-selector we give-up, it's just too hard. */
|
||||
hb_buffer_t * const buffer = c->buffer;
|
||||
hb_font_t * const font = c->font;
|
||||
for (; buffer->idx < end - 1;) {
|
||||
@ -250,27 +251,26 @@ handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, uns
|
||||
}
|
||||
|
||||
static inline void
|
||||
decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end)
|
||||
decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit)
|
||||
{
|
||||
hb_buffer_t * const buffer = c->buffer;
|
||||
/* TODO Currently if there's a variation-selector we give-up, it's just too hard. */
|
||||
for (unsigned int i = buffer->idx; i < end; i++)
|
||||
if (unlikely (buffer->unicode->is_variation_selector (buffer->info[i].codepoint))) {
|
||||
handle_variation_selector_cluster (c, end);
|
||||
handle_variation_selector_cluster (c, end, short_circuit);
|
||||
return;
|
||||
}
|
||||
|
||||
while (buffer->idx < end)
|
||||
decompose_current_character (c, false);
|
||||
decompose_current_character (c, short_circuit);
|
||||
}
|
||||
|
||||
static inline void
|
||||
decompose_cluster (const hb_ot_shape_normalize_context_t *c, bool short_circuit, unsigned int end)
|
||||
decompose_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool might_short_circuit, bool always_short_circuit)
|
||||
{
|
||||
if (likely (c->buffer->idx + 1 == end))
|
||||
decompose_current_character (c, short_circuit);
|
||||
decompose_current_character (c, might_short_circuit);
|
||||
else
|
||||
decompose_multi_char_cluster (c, end);
|
||||
decompose_multi_char_cluster (c, end, always_short_circuit);
|
||||
}
|
||||
|
||||
|
||||
@ -289,9 +289,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
|
||||
hb_buffer_t *buffer,
|
||||
hb_font_t *font)
|
||||
{
|
||||
hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference ?
|
||||
plan->shaper->normalization_preference (&buffer->props) :
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT;
|
||||
hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference;
|
||||
const hb_ot_shape_normalize_context_t c = {
|
||||
plan,
|
||||
buffer,
|
||||
@ -301,8 +299,10 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
|
||||
plan->shaper->compose ? plan->shaper->compose : compose_unicode
|
||||
};
|
||||
|
||||
bool short_circuit = mode != HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED &&
|
||||
mode != HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT;
|
||||
bool always_short_circuit = mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE;
|
||||
bool might_short_circuit = always_short_circuit ||
|
||||
(mode != HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED &&
|
||||
mode != HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT);
|
||||
unsigned int count;
|
||||
|
||||
/* We do a fairly straightforward yet custom normalization process in three
|
||||
@ -323,7 +323,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
|
||||
if (buffer->cur().cluster != buffer->info[end].cluster)
|
||||
break;
|
||||
|
||||
decompose_cluster (&c, short_circuit, end);
|
||||
decompose_cluster (&c, end, might_short_circuit, always_short_circuit);
|
||||
}
|
||||
buffer->swap_buffers ();
|
||||
|
||||
@ -355,7 +355,8 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
|
||||
}
|
||||
|
||||
|
||||
if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED)
|
||||
if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE ||
|
||||
mode == HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED)
|
||||
return;
|
||||
|
||||
/* Third round, recompose */
|
||||
@ -393,8 +394,9 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
|
||||
return;
|
||||
buffer->merge_out_clusters (starter, buffer->out_len);
|
||||
buffer->out_len--; /* Remove the second composable. */
|
||||
buffer->out_info[starter].codepoint = composed; /* Modify starter and carry on. */
|
||||
set_glyph (buffer->out_info[starter], font);
|
||||
/* Modify starter and carry on. */
|
||||
buffer->out_info[starter].codepoint = composed;
|
||||
buffer->out_info[starter].glyph_index() = glyph;
|
||||
_hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer->unicode);
|
||||
|
||||
continue;
|
||||
|
@ -40,6 +40,10 @@ struct hb_ot_shape_plan_t
|
||||
const struct hb_ot_complex_shaper_t *shaper;
|
||||
hb_ot_map_t map;
|
||||
const void *data;
|
||||
hb_mask_t rtlm_mask, frac_mask, numr_mask, dnom_mask;
|
||||
hb_mask_t kern_mask;
|
||||
unsigned int has_frac : 1;
|
||||
unsigned int has_kern : 1;
|
||||
|
||||
inline void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const
|
||||
{
|
||||
@ -77,6 +81,17 @@ struct hb_ot_shape_planner_t
|
||||
plan.props = props;
|
||||
plan.shaper = shaper;
|
||||
map.compile (plan.map);
|
||||
|
||||
plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m'));
|
||||
plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
|
||||
plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r'));
|
||||
plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m'));
|
||||
|
||||
plan.kern_mask = plan.map.get_mask (HB_DIRECTION_IS_HORIZONTAL (plan.props.direction) ?
|
||||
HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n'));
|
||||
|
||||
plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask);
|
||||
plan.has_kern = !!plan.kern_mask;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -88,6 +88,10 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
|
||||
break;
|
||||
}
|
||||
|
||||
map->add_feature (HB_TAG ('f','r','a','c'), 1, F_NONE);
|
||||
map->add_feature (HB_TAG ('n','u','m','r'), 1, F_NONE);
|
||||
map->add_feature (HB_TAG ('d','n','o','m'), 1, F_NONE);
|
||||
|
||||
if (planner->shaper->collect_features)
|
||||
planner->shaper->collect_features (planner);
|
||||
|
||||
@ -234,8 +238,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
|
||||
HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
|
||||
return;
|
||||
|
||||
hb_codepoint_t dottedcircle_glyph;
|
||||
if (!font->get_glyph (0x25CC, 0, &dottedcircle_glyph))
|
||||
if (!font->has_glyph (0x25CC))
|
||||
return;
|
||||
|
||||
hb_glyph_info_t dottedcircle;
|
||||
@ -292,7 +295,7 @@ hb_ot_mirror_chars (hb_ot_shape_context_t *c)
|
||||
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
hb_unicode_funcs_t *unicode = buffer->unicode;
|
||||
hb_mask_t rtlm_mask = c->plan->map.get_1_mask (HB_TAG ('r','t','l','m'));
|
||||
hb_mask_t rtlm_mask = c->plan->rtlm_mask;
|
||||
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
@ -306,13 +309,58 @@ hb_ot_mirror_chars (hb_ot_shape_context_t *c)
|
||||
}
|
||||
|
||||
static inline void
|
||||
hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
|
||||
hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c)
|
||||
{
|
||||
if (!c->plan->has_frac)
|
||||
return;
|
||||
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
/* TODO look in pre/post context text also. */
|
||||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (info[i].codepoint == 0x2044) /* FRACTION SLASH */
|
||||
{
|
||||
unsigned int start = i, end = i + 1;
|
||||
while (start &&
|
||||
_hb_glyph_info_get_general_category (&info[start - 1]) ==
|
||||
HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
|
||||
start--;
|
||||
while (end < count &&
|
||||
_hb_glyph_info_get_general_category (&info[end]) ==
|
||||
HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
|
||||
end++;
|
||||
|
||||
for (unsigned int j = start; j < i; j++)
|
||||
info[j].mask |= c->plan->numr_mask | c->plan->frac_mask;
|
||||
info[i].mask |= c->plan->frac_mask;
|
||||
for (unsigned int j = i + 1; j < end; j++)
|
||||
info[j].mask |= c->plan->frac_mask | c->plan->dnom_mask;
|
||||
|
||||
i = end - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
hb_ot_shape_initialize_masks (hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_ot_map_t *map = &c->plan->map;
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
hb_mask_t global_mask = map->get_global_mask ();
|
||||
buffer->reset_masks (global_mask);
|
||||
}
|
||||
|
||||
static inline void
|
||||
hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_ot_map_t *map = &c->plan->map;
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
hb_ot_shape_setup_masks_fraction (c);
|
||||
|
||||
if (c->plan->shaper->setup_masks)
|
||||
c->plan->shaper->setup_masks (c->plan, buffer, c->font);
|
||||
@ -358,6 +406,8 @@ hb_ot_substitute_default (hb_ot_shape_context_t *c)
|
||||
if (c->plan->shaper->preprocess_text)
|
||||
c->plan->shaper->preprocess_text (c->plan, buffer, c->font);
|
||||
|
||||
hb_ot_shape_initialize_masks (c);
|
||||
|
||||
hb_ot_mirror_chars (c);
|
||||
|
||||
HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index);
|
||||
|
54
gfx/harfbuzz/src/hb-ot-shape.h
Normal file
54
gfx/harfbuzz/src/hb-ot-shape.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright © 2013 Red Hat, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Red Hat Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_SHAPE_H
|
||||
#define HB_OT_SHAPE_H
|
||||
#define HB_OT_SHAPE_H_IN
|
||||
|
||||
#include "hb.h"
|
||||
|
||||
#include "hb-ot-layout.h"
|
||||
#include "hb-ot-tag.h"
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
/* TODO port to shape-plan / set. */
|
||||
void
|
||||
hb_ot_shape_glyphs_closure (hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
const hb_feature_t *features,
|
||||
unsigned int num_features,
|
||||
hb_set_t *glyphs);
|
||||
|
||||
void
|
||||
hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan,
|
||||
hb_tag_t table_tag,
|
||||
hb_set_t *lookup_indexes /* OUT */);
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#undef HB_OT_SHAPE_H_IN
|
||||
#endif /* HB_OT_SHAPE_H */
|
@ -27,7 +27,6 @@
|
||||
*/
|
||||
|
||||
#include "hb-private.hh"
|
||||
#include "hb-ot.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -32,17 +32,10 @@
|
||||
|
||||
#include "hb-ot-layout.h"
|
||||
#include "hb-ot-tag.h"
|
||||
#include "hb-ot-shape.h"
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
/* TODO remove */
|
||||
void
|
||||
hb_ot_shape_glyphs_closure (hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
const hb_feature_t *features,
|
||||
unsigned int num_features,
|
||||
hb_set_t *glyphs);
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#undef HB_OT_H_IN
|
||||
|
@ -807,6 +807,12 @@ hb_in_range (T u, T lo, T hi)
|
||||
return lo <= u && u <= hi;
|
||||
}
|
||||
|
||||
template <typename T> static inline bool
|
||||
hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
|
||||
{
|
||||
return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
|
||||
}
|
||||
|
||||
template <typename T> static inline bool
|
||||
hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
|
||||
{
|
||||
|
@ -28,7 +28,6 @@
|
||||
#define HB_SET_PRIVATE_HH
|
||||
|
||||
#include "hb-private.hh"
|
||||
#include "hb-set.h"
|
||||
#include "hb-object-private.hh"
|
||||
|
||||
|
||||
|
@ -28,7 +28,6 @@
|
||||
#define HB_SHAPE_PLAN_PRIVATE_HH
|
||||
|
||||
#include "hb-private.hh"
|
||||
#include "hb-shape-plan.h"
|
||||
#include "hb-object-private.hh"
|
||||
#include "hb-shaper-private.hh"
|
||||
|
||||
|
@ -52,4 +52,6 @@ HB_SHAPER_IMPLEMENT (uniscribe)
|
||||
HB_SHAPER_IMPLEMENT (coretext)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FALLBACK
|
||||
HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */
|
||||
#endif
|
||||
|
@ -31,8 +31,6 @@
|
||||
#include "hb-ot-hhea-table.hh"
|
||||
#include "hb-ot-hmtx-table.hh"
|
||||
|
||||
#include "hb-blob.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
|
@ -32,8 +32,6 @@
|
||||
#define HB_UNICODE_PRIVATE_HH
|
||||
|
||||
#include "hb-private.hh"
|
||||
|
||||
#include "hb-unicode.h"
|
||||
#include "hb-object-private.hh"
|
||||
|
||||
|
||||
@ -108,7 +106,11 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
|
||||
modified_combining_class (hb_codepoint_t unicode)
|
||||
{
|
||||
/* XXX This hack belongs to the Myanmar shaper. */
|
||||
if (unicode == 0x1037) unicode = 0x103A;
|
||||
if (unlikely (unicode == 0x1037)) unicode = 0x103A;
|
||||
|
||||
/* XXX This hack belongs to the SEA shaper (for Tai Tham):
|
||||
* Reorder SAKOT to ensure it comes after any tone marks. */
|
||||
if (unlikely (unicode == 0x1A60)) return 254;
|
||||
|
||||
return _hb_modified_combining_class[combining_class (unicode)];
|
||||
}
|
||||
@ -132,10 +134,10 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
|
||||
* 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.
|
||||
* Note: While U+115F, U+1160, U+3164 and U+FFA0 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 four.
|
||||
*
|
||||
* Gathered from:
|
||||
* http://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:DI:]&abb=on&ucd=on&esc=on
|
||||
@ -157,10 +159,10 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
|
||||
* 200B..200F ;RIGHT-TO-LEFT MARK
|
||||
* 202A..202E ;RIGHT-TO-LEFT OVERRIDE
|
||||
* 2060..206F ;NOMINAL DIGIT SHAPES
|
||||
* 3164 ;HANGUL FILLER
|
||||
* #3164 ;HANGUL FILLER
|
||||
* FE00..FE0F ;VARIATION SELECTOR-16
|
||||
* FEFF ;ZERO WIDTH NO-BREAK SPACE
|
||||
* FFA0 ;HALFWIDTH HANGUL FILLER
|
||||
* #FFA0 ;HALFWIDTH HANGUL FILLER
|
||||
* FFF0..FFF8 ;<unassigned-FFF8>
|
||||
* 1D173..1D17A ;MUSICAL SYMBOL END PHRASE
|
||||
* E0000..E0FFF ;<unassigned-E0FFF>
|
||||
@ -182,9 +184,8 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
|
||||
case 0x20: return hb_in_ranges<hb_codepoint_t> (ch, 0x200B, 0x200F,
|
||||
0x202A, 0x202E,
|
||||
0x2060, 0x206F);
|
||||
case 0x31: return unlikely (ch == 0x3164);
|
||||
case 0xFE: return hb_in_range<hb_codepoint_t> (ch, 0xFE00, 0xFE0F) || ch == 0xFEFF;
|
||||
case 0xFF: return hb_in_range<hb_codepoint_t> (ch, 0xFFF0, 0xFFF8) || ch == 0xFFA0;
|
||||
case 0xFF: return hb_in_range<hb_codepoint_t> (ch, 0xFFF0, 0xFFF8);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
@ -709,7 +709,7 @@ _hb_uniscribe_shape (hb_shape_plan_t *shape_plan,
|
||||
for (unsigned int i = 0; i < range_records.len; i++)
|
||||
{
|
||||
range_record_t *range = &range_records[i];
|
||||
range->props.potfRecords = feature_records.array + reinterpret_cast<unsigned int> (range->props.potfRecords);
|
||||
range->props.potfRecords = feature_records.array + reinterpret_cast<uintptr_t> (range->props.potfRecords);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -776,13 +776,14 @@ retry:
|
||||
}
|
||||
}
|
||||
|
||||
/* All the following types are sized in multiples of sizeof(int). */
|
||||
unsigned int glyphs_size = scratch_size / ((sizeof (WORD) +
|
||||
sizeof (SCRIPT_GLYPHPROP) +
|
||||
sizeof (int) +
|
||||
sizeof (GOFFSET) +
|
||||
sizeof (uint32_t))
|
||||
/ sizeof (int));
|
||||
/* The -2 in the following is to compensate for possible
|
||||
* alignment needed after the WORD array. sizeof(WORD) == 2. */
|
||||
unsigned int glyphs_size = (scratch_size * sizeof (int) - 2)
|
||||
/ (sizeof (WORD) +
|
||||
sizeof (SCRIPT_GLYPHPROP) +
|
||||
sizeof (int) +
|
||||
sizeof (GOFFSET) +
|
||||
sizeof (uint32_t));
|
||||
|
||||
ALLOCATE_ARRAY (WORD, glyphs, glyphs_size);
|
||||
ALLOCATE_ARRAY (SCRIPT_GLYPHPROP, glyph_props, glyphs_size);
|
||||
|
@ -38,9 +38,9 @@ HB_BEGIN_DECLS
|
||||
|
||||
#define HB_VERSION_MAJOR 0
|
||||
#define HB_VERSION_MINOR 9
|
||||
#define HB_VERSION_MICRO 24
|
||||
#define HB_VERSION_MICRO 25
|
||||
|
||||
#define HB_VERSION_STRING "0.9.24"
|
||||
#define HB_VERSION_STRING "0.9.25"
|
||||
|
||||
#define HB_VERSION_CHECK(major,minor,micro) \
|
||||
((major)*10000+(minor)*100+(micro) >= \
|
||||
|
@ -12,6 +12,7 @@ EXPORTS.harfbuzz += [
|
||||
'hb-face.h',
|
||||
'hb-font.h',
|
||||
'hb-ot-layout.h',
|
||||
'hb-ot-shape.h',
|
||||
'hb-ot-tag.h',
|
||||
'hb-ot.h',
|
||||
'hb-set.h',
|
||||
@ -25,6 +26,7 @@ EXPORTS.harfbuzz += [
|
||||
SOURCES += [
|
||||
'hb-blob.cc', # error: use of undeclared identifier 'snprintf' (FreeBSD)
|
||||
'hb-common.cc', # error: use of undeclared identifier 'strdup'
|
||||
'hb-ot-shape-complex-hangul.cc', # error: redefinition of enumerator 'NONE'
|
||||
'hb-ot-shape-complex-indic.cc', # error: redefinition of enumerator 'INIT'
|
||||
'hb-ot-shape-complex-sea.cc', # error: redefinition of 'basic_features'
|
||||
'hb-ot-shape.cc', # error: functions that differ only in their return type cannot be overloaded
|
||||
@ -40,9 +42,11 @@ UNIFIED_SOURCES += [
|
||||
'hb-ot-map.cc',
|
||||
'hb-ot-shape-complex-arabic.cc',
|
||||
'hb-ot-shape-complex-default.cc',
|
||||
'hb-ot-shape-complex-hebrew.cc',
|
||||
'hb-ot-shape-complex-indic-table.cc',
|
||||
'hb-ot-shape-complex-myanmar.cc',
|
||||
'hb-ot-shape-complex-thai.cc',
|
||||
'hb-ot-shape-complex-tibetan.cc',
|
||||
'hb-ot-shape-fallback.cc',
|
||||
'hb-ot-shape-normalize.cc',
|
||||
'hb-ot-tag.cc',
|
||||
|
Loading…
Reference in New Issue
Block a user