mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-30 12:50:11 +00:00
8206428: Upgrade JDK11 to harfbuzz 1.8.2
Reviewed-by: serb
This commit is contained in:
parent
d9aa299526
commit
dd12703f56
@ -1,4 +1,4 @@
|
||||
## Harfbuzz v1.8.1
|
||||
## Harfbuzz v1.8.2
|
||||
|
||||
### Harfbuzz License
|
||||
|
||||
|
||||
@ -489,10 +489,10 @@ hb_blob_t::try_make_writable (void)
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifndef _O_BINARY
|
||||
# define _O_BINARY 0
|
||||
#else
|
||||
# ifndef _O_BINARY
|
||||
# define _O_BINARY 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef MAP_NORESERVE
|
||||
@ -517,7 +517,7 @@ _hb_mapped_file_destroy (hb_mapped_file_t *file)
|
||||
UnmapViewOfFile (file->contents);
|
||||
CloseHandle (file->mapping);
|
||||
#else
|
||||
free (file->contents);
|
||||
assert (0); // If we don't have mmap we shouldn't reach here
|
||||
#endif
|
||||
|
||||
free (file);
|
||||
@ -534,77 +534,103 @@ _hb_mapped_file_destroy (hb_mapped_file_t *file)
|
||||
hb_blob_t *
|
||||
hb_blob_create_from_file (const char *file_name)
|
||||
{
|
||||
// Adopted from glib's gmappedfile.c with Matthias Clasen and
|
||||
// Allison Lortie permission but changed a lot to suit our need.
|
||||
bool writable = false;
|
||||
hb_memory_mode_t mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
|
||||
/* Adopted from glib's gmappedfile.c with Matthias Clasen and
|
||||
Allison Lortie permission but changed a lot to suit our need. */
|
||||
#if defined(HAVE_MMAP) && !defined(HB_NO_MMAP)
|
||||
hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t));
|
||||
if (unlikely (!file)) return hb_blob_get_empty ();
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
int fd = open (file_name, (writable ? O_RDWR : O_RDONLY) | _O_BINARY, 0);
|
||||
# define CLOSE close
|
||||
int fd = open (file_name, O_RDONLY | _O_BINARY, 0);
|
||||
if (unlikely (fd == -1)) goto fail_without_close;
|
||||
|
||||
struct stat st;
|
||||
if (unlikely (fstat (fd, &st) == -1)) goto fail;
|
||||
|
||||
// See https://github.com/GNOME/glib/blob/f9faac7/glib/gmappedfile.c#L139-L142
|
||||
if (unlikely (st.st_size == 0 && S_ISREG (st.st_mode))) goto fail;
|
||||
|
||||
file->length = (unsigned long) st.st_size;
|
||||
file->contents = (char *) mmap (nullptr, file->length,
|
||||
writable ? PROT_READ|PROT_WRITE : PROT_READ,
|
||||
file->contents = (char *) mmap (nullptr, file->length, PROT_READ,
|
||||
MAP_PRIVATE | MAP_NORESERVE, fd, 0);
|
||||
|
||||
if (unlikely (file->contents == MAP_FAILED)) goto fail;
|
||||
|
||||
#elif defined(_WIN32) || defined(__CYGWIN__)
|
||||
HANDLE fd = CreateFile (file_name,
|
||||
writable ? GENERIC_READ|GENERIC_WRITE : GENERIC_READ,
|
||||
FILE_SHARE_READ, nullptr, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, nullptr);
|
||||
# define CLOSE CloseHandle
|
||||
close (fd);
|
||||
|
||||
return hb_blob_create (file->contents, file->length,
|
||||
HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file,
|
||||
(hb_destroy_func_t) _hb_mapped_file_destroy);
|
||||
|
||||
fail:
|
||||
close (fd);
|
||||
fail_without_close:
|
||||
free (file);
|
||||
|
||||
#elif (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_MMAP)
|
||||
hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t));
|
||||
if (unlikely (!file)) return hb_blob_get_empty ();
|
||||
|
||||
HANDLE fd = CreateFile (file_name, GENERIC_READ, FILE_SHARE_READ, nullptr,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
|
||||
nullptr);
|
||||
|
||||
if (unlikely (fd == INVALID_HANDLE_VALUE)) goto fail_without_close;
|
||||
|
||||
file->length = (unsigned long) GetFileSize (fd, nullptr);
|
||||
file->mapping = CreateFileMapping (fd, nullptr,
|
||||
writable ? PAGE_WRITECOPY : PAGE_READONLY,
|
||||
0, 0, nullptr);
|
||||
file->mapping = CreateFileMapping (fd, nullptr, PAGE_READONLY, 0, 0, nullptr);
|
||||
if (unlikely (file->mapping == nullptr)) goto fail;
|
||||
|
||||
file->contents = (char *) MapViewOfFile (file->mapping,
|
||||
writable ? FILE_MAP_COPY : FILE_MAP_READ,
|
||||
0, 0, 0);
|
||||
file->contents = (char *) MapViewOfFile (file->mapping, FILE_MAP_READ, 0, 0, 0);
|
||||
if (unlikely (file->contents == nullptr)) goto fail;
|
||||
|
||||
#else
|
||||
mm = HB_MEMORY_MODE_WRITABLE;
|
||||
|
||||
FILE *fd = fopen (file_name, "rb");
|
||||
# define CLOSE fclose
|
||||
if (unlikely (!fd)) goto fail_without_close;
|
||||
|
||||
fseek (fd, 0, SEEK_END);
|
||||
file->length = ftell (fd);
|
||||
rewind (fd);
|
||||
file->contents = (char *) malloc (file->length);
|
||||
if (unlikely (!file->contents)) goto fail;
|
||||
|
||||
if (unlikely (fread (file->contents, 1, file->length, fd) != file->length))
|
||||
goto fail;
|
||||
|
||||
#endif
|
||||
|
||||
CLOSE (fd);
|
||||
return hb_blob_create (file->contents, file->length, mm, (void *) file,
|
||||
CloseHandle (fd);
|
||||
return hb_blob_create (file->contents, file->length,
|
||||
HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file,
|
||||
(hb_destroy_func_t) _hb_mapped_file_destroy);
|
||||
|
||||
fail:
|
||||
CLOSE (fd);
|
||||
#undef CLOSE
|
||||
CloseHandle (fd);
|
||||
fail_without_close:
|
||||
free (file);
|
||||
|
||||
#endif
|
||||
|
||||
/* The following tries to read a file without knowing its size beforehand
|
||||
It's used as a fallback for systems without mmap or to read from pipes */
|
||||
unsigned long len = 0, allocated = BUFSIZ * 16;
|
||||
char *data = (char *) malloc (allocated);
|
||||
if (unlikely (data == nullptr)) return hb_blob_get_empty ();
|
||||
|
||||
FILE *fp = fopen (file_name, "rb");
|
||||
if (unlikely (fp == nullptr)) goto fread_fail_without_close;
|
||||
|
||||
while (!feof (fp))
|
||||
{
|
||||
if (allocated - len < BUFSIZ)
|
||||
{
|
||||
allocated *= 2;
|
||||
/* Don't allocate and go more than ~536MB, our mmap reader still
|
||||
can cover files like that but lets limit our fallback reader */
|
||||
if (unlikely (allocated > (2 << 28))) goto fread_fail;
|
||||
char *new_data = (char *) realloc (data, allocated);
|
||||
if (unlikely (new_data == nullptr)) goto fread_fail;
|
||||
data = new_data;
|
||||
}
|
||||
|
||||
unsigned long addition = fread (data + len, 1, allocated - len, fp);
|
||||
|
||||
int err = ferror (fp);
|
||||
#ifdef EINTR // armcc doesn't have it
|
||||
if (unlikely (err == EINTR)) continue;
|
||||
#endif
|
||||
if (unlikely (err)) goto fread_fail;
|
||||
|
||||
len += addition;
|
||||
}
|
||||
|
||||
return hb_blob_create (data, len, HB_MEMORY_MODE_WRITABLE, data,
|
||||
(hb_destroy_func_t) free);
|
||||
|
||||
fread_fail:
|
||||
fclose (fp);
|
||||
fread_fail_without_close:
|
||||
free (data);
|
||||
return hb_blob_get_empty ();
|
||||
}
|
||||
|
||||
@ -286,6 +286,197 @@ struct TTCHeader
|
||||
} u;
|
||||
};
|
||||
|
||||
/*
|
||||
* Mac Resource Fork
|
||||
*/
|
||||
|
||||
struct ResourceRefItem
|
||||
{
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
// actual data sanitization is done on ResourceForkHeader sanitizer
|
||||
return_trace (likely (c->check_struct (this)));
|
||||
}
|
||||
|
||||
HBINT16 id; /* Resource ID, is really should be signed? */
|
||||
HBINT16 nameOffset; /* Offset from beginning of resource name list
|
||||
* to resource name, minus means there is no */
|
||||
HBUINT8 attr; /* Resource attributes */
|
||||
HBUINT24 dataOffset; /* Offset from beginning of resource data to
|
||||
* data for this resource */
|
||||
HBUINT32 reserved; /* Reserved for handle to resource */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (12);
|
||||
};
|
||||
|
||||
struct ResourceTypeItem
|
||||
{
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
// RefList sanitization is done on ResourceMap sanitizer
|
||||
return_trace (likely (c->check_struct (this)));
|
||||
}
|
||||
|
||||
inline unsigned int get_resource_count () const
|
||||
{
|
||||
return numRes + 1;
|
||||
}
|
||||
|
||||
inline bool is_sfnt () const
|
||||
{
|
||||
return type == HB_TAG ('s','f','n','t');
|
||||
}
|
||||
|
||||
inline const ResourceRefItem& get_ref_item (const void *base,
|
||||
unsigned int i) const
|
||||
{
|
||||
return (base+refList)[i];
|
||||
}
|
||||
|
||||
protected:
|
||||
Tag type; /* Resource type */
|
||||
HBUINT16 numRes; /* Number of resource this type in map minus 1 */
|
||||
OffsetTo<UnsizedArrayOf<ResourceRefItem> >
|
||||
refList; /* Offset from beginning of resource type list
|
||||
* to reference list for this type */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
};
|
||||
|
||||
struct ResourceMap
|
||||
{
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!c->check_struct (this)))
|
||||
return_trace (false);
|
||||
for (unsigned int i = 0; i < get_types_count (); ++i)
|
||||
{
|
||||
const ResourceTypeItem& type = get_type (i);
|
||||
if (unlikely (!type.sanitize (c)))
|
||||
return_trace (false);
|
||||
for (unsigned int j = 0; j < type.get_resource_count (); ++j)
|
||||
if (unlikely (!get_ref_item (type, j).sanitize (c)))
|
||||
return_trace (false);
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
inline const ResourceTypeItem& get_type (unsigned int i) const
|
||||
{
|
||||
// Why offset from the second byte of the object? I'm not sure
|
||||
return ((&reserved[2])+typeList)[i];
|
||||
}
|
||||
|
||||
inline unsigned int get_types_count () const
|
||||
{
|
||||
return nTypes + 1;
|
||||
}
|
||||
|
||||
inline const ResourceRefItem &get_ref_item (const ResourceTypeItem &type,
|
||||
unsigned int i) const
|
||||
{
|
||||
return type.get_ref_item (&(this+typeList), i);
|
||||
}
|
||||
|
||||
inline const PString& get_name (const ResourceRefItem &item,
|
||||
unsigned int i) const
|
||||
{
|
||||
if (item.nameOffset == -1)
|
||||
return Null (PString);
|
||||
|
||||
return StructAtOffset<PString> (this, nameList + item.nameOffset);
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT8 reserved[16]; /* Reserved for copy of resource header */
|
||||
LOffsetTo<ResourceMap>
|
||||
reserved1; /* Reserved for handle to next resource map */
|
||||
HBUINT16 reserved2; /* Reserved for file reference number */
|
||||
HBUINT16 attr; /* Resource fork attribute */
|
||||
OffsetTo<UnsizedArrayOf<ResourceTypeItem> >
|
||||
typeList; /* Offset from beginning of map to
|
||||
* resource type list */
|
||||
HBUINT16 nameList; /* Offset from beginning of map to
|
||||
* resource name list */
|
||||
HBUINT16 nTypes; /* Number of types in the map minus 1 */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (30);
|
||||
};
|
||||
|
||||
struct ResourceForkHeader
|
||||
{
|
||||
inline unsigned int get_face_count () const
|
||||
{
|
||||
const ResourceMap &resource_map = this+map;
|
||||
for (unsigned int i = 0; i < resource_map.get_types_count (); ++i)
|
||||
{
|
||||
const ResourceTypeItem& type = resource_map.get_type (i);
|
||||
if (type.is_sfnt ())
|
||||
return type.get_resource_count ();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline const LArrayOf<HBUINT8>& get_data (const ResourceTypeItem& type,
|
||||
unsigned int idx) const
|
||||
{
|
||||
const ResourceMap &resource_map = this+map;
|
||||
unsigned int offset = dataOffset;
|
||||
offset += resource_map.get_ref_item (type, idx).dataOffset;
|
||||
return StructAtOffset<LArrayOf<HBUINT8> > (this, offset);
|
||||
}
|
||||
|
||||
inline const OpenTypeFontFace& get_face (unsigned int idx) const
|
||||
{
|
||||
const ResourceMap &resource_map = this+map;
|
||||
for (unsigned int i = 0; i < resource_map.get_types_count (); ++i)
|
||||
{
|
||||
const ResourceTypeItem& type = resource_map.get_type (i);
|
||||
if (type.is_sfnt () && idx < type.get_resource_count ())
|
||||
return (OpenTypeFontFace&) get_data (type, idx).arrayZ;
|
||||
}
|
||||
return Null (OpenTypeFontFace);
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!c->check_struct (this)))
|
||||
return_trace (false);
|
||||
|
||||
const ResourceMap &resource_map = this+map;
|
||||
if (unlikely (!resource_map.sanitize (c)))
|
||||
return_trace (false);
|
||||
|
||||
for (unsigned int i = 0; i < resource_map.get_types_count (); ++i)
|
||||
{
|
||||
const ResourceTypeItem& type = resource_map.get_type (i);
|
||||
for (unsigned int j = 0; j < type.get_resource_count (); ++j)
|
||||
{
|
||||
const LArrayOf<HBUINT8>& data = get_data (type, j);
|
||||
if (unlikely (!(data.sanitize (c) &&
|
||||
((OpenTypeFontFace&) data.arrayZ).sanitize (c))))
|
||||
return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT32 dataOffset; /* Offset from beginning of resource fork
|
||||
* to resource data */
|
||||
LOffsetTo<ResourceMap>
|
||||
map; /* Offset from beginning of resource fork
|
||||
* to resource map */
|
||||
HBUINT32 dataLen; /* Length of resource data */
|
||||
HBUINT32 mapLen; /* Length of resource map */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (16);
|
||||
};
|
||||
|
||||
/*
|
||||
* OpenType Font File
|
||||
@ -299,6 +490,7 @@ struct OpenTypeFontFile
|
||||
CFFTag = HB_TAG ('O','T','T','O'), /* OpenType with Postscript outlines */
|
||||
TrueTypeTag = HB_TAG ( 0 , 1 , 0 , 0 ), /* OpenType with TrueType outlines */
|
||||
TTCTag = HB_TAG ('t','t','c','f'), /* TrueType Collection */
|
||||
DFontTag = HB_TAG ( 0 , 0 , 1 , 0 ), /* DFont Mac Resource Fork */
|
||||
TrueTag = HB_TAG ('t','r','u','e'), /* Obsolete Apple TrueType */
|
||||
Typ1Tag = HB_TAG ('t','y','p','1') /* Obsolete Apple Type1 font in SFNT container */
|
||||
};
|
||||
@ -313,6 +505,7 @@ struct OpenTypeFontFile
|
||||
case Typ1Tag:
|
||||
case TrueTypeTag: return 1;
|
||||
case TTCTag: return u.ttcHeader.get_face_count ();
|
||||
// case DFontTag: return u.rfHeader.get_face_count ();
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
@ -327,6 +520,7 @@ struct OpenTypeFontFile
|
||||
case Typ1Tag:
|
||||
case TrueTypeTag: return u.fontFace;
|
||||
case TTCTag: return u.ttcHeader.get_face (i);
|
||||
// case DFontTag: return u.rfHeader.get_face (i);
|
||||
default: return Null(OpenTypeFontFace);
|
||||
}
|
||||
}
|
||||
@ -353,6 +547,7 @@ struct OpenTypeFontFile
|
||||
case Typ1Tag:
|
||||
case TrueTypeTag: return_trace (u.fontFace.sanitize (c));
|
||||
case TTCTag: return_trace (u.ttcHeader.sanitize (c));
|
||||
// case DFontTag: return_trace (u.rfHeader.sanitize (c));
|
||||
default: return_trace (true);
|
||||
}
|
||||
}
|
||||
@ -362,6 +557,7 @@ struct OpenTypeFontFile
|
||||
Tag tag; /* 4-byte identifier. */
|
||||
OpenTypeFontFace fontFace;
|
||||
TTCHeader ttcHeader;
|
||||
ResourceForkHeader rfHeader;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (4, tag);
|
||||
|
||||
@ -1033,6 +1033,7 @@ struct ArrayOf
|
||||
DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
|
||||
};
|
||||
template <typename Type> struct LArrayOf : ArrayOf<Type, HBUINT32> {};
|
||||
typedef ArrayOf<HBUINT8, HBUINT8> PString;
|
||||
|
||||
/* Array of Offset's */
|
||||
template <typename Type, typename OffsetType=HBUINT16>
|
||||
|
||||
@ -832,7 +832,12 @@ struct CoverageFormat2
|
||||
c = &c_;
|
||||
coverage = 0;
|
||||
i = 0;
|
||||
j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0;
|
||||
j = c->rangeRecord.len ? c->rangeRecord[0].start : 0;
|
||||
if (unlikely (c->rangeRecord[0].start > c->rangeRecord[0].end))
|
||||
{
|
||||
/* Broken table. Skip. */
|
||||
i = c->rangeRecord.len;
|
||||
}
|
||||
}
|
||||
inline bool more (void) { return i < c->rangeRecord.len; }
|
||||
inline void next (void)
|
||||
@ -842,7 +847,14 @@ struct CoverageFormat2
|
||||
i++;
|
||||
if (more ())
|
||||
{
|
||||
hb_codepoint_t old = j;
|
||||
j = c->rangeRecord[i].start;
|
||||
if (unlikely (j <= old))
|
||||
{
|
||||
/* Broken table. Skip. Important to avoid DoS. */
|
||||
i = c->rangeRecord.len;
|
||||
return;
|
||||
}
|
||||
coverage = c->rangeRecord[i].value;
|
||||
}
|
||||
return;
|
||||
@ -855,7 +867,8 @@ struct CoverageFormat2
|
||||
|
||||
private:
|
||||
const struct CoverageFormat2 *c;
|
||||
unsigned int i, j, coverage;
|
||||
unsigned int i, coverage;
|
||||
hb_codepoint_t j;
|
||||
};
|
||||
private:
|
||||
|
||||
|
||||
@ -1074,10 +1074,13 @@ struct MarkBasePosFormat1
|
||||
if (!skippy_iter.prev ()) return_trace (false);
|
||||
/* We only want to attach to the first of a MultipleSubst sequence.
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/740
|
||||
* Reject others. */
|
||||
* Reject others...
|
||||
* ...but stop if we find a mark in the MultipleSubst sequence:
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/1020 */
|
||||
if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) ||
|
||||
0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) ||
|
||||
(skippy_iter.idx == 0 ||
|
||||
_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx - 1]) ||
|
||||
_hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) !=
|
||||
_hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) ||
|
||||
_hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) !=
|
||||
|
||||
@ -668,8 +668,9 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
|
||||
*
|
||||
* Reports suggest that in some scripts Uniscribe does this only if there
|
||||
* is *not* a Halant after last consonant already (eg. Kannada), while it
|
||||
* does it unconditionally in other scripts (eg. Malayalam). We don't
|
||||
* currently know about other scripts, so we single out Malayalam for now.
|
||||
* does it unconditionally in other scripts (eg. Malayalam, Bengali). We
|
||||
* don't currently know about other scripts, so we whitelist Malayalam and
|
||||
* Bengali for now.
|
||||
*
|
||||
* Kannada test case:
|
||||
* U+0C9A,U+0CCD,U+0C9A,U+0CCD
|
||||
@ -679,10 +680,16 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
|
||||
* Malayalam test case:
|
||||
* U+0D38,U+0D4D,U+0D31,U+0D4D,U+0D31,U+0D4D
|
||||
* With lohit-ttf-20121122/Lohit-Malayalam.ttf
|
||||
*
|
||||
* Bengali test case
|
||||
* U+0998,U+09CD,U+09AF,U+09CD
|
||||
* With Windows XP vrinda.ttf
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/1073
|
||||
*/
|
||||
if (indic_plan->is_old_spec)
|
||||
{
|
||||
bool disallow_double_halants = buffer->props.script != HB_SCRIPT_MALAYALAM;
|
||||
bool disallow_double_halants = buffer->props.script != HB_SCRIPT_MALAYALAM &&
|
||||
buffer->props.script != HB_SCRIPT_BENGALI;
|
||||
for (unsigned int i = base + 1; i < end; i++)
|
||||
if (info[i].indic_category() == OT_H)
|
||||
{
|
||||
|
||||
@ -372,22 +372,25 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
|
||||
break;
|
||||
}
|
||||
|
||||
/* Note! syllable() is a one-byte field. */
|
||||
for (unsigned int i = base; i < end; i++)
|
||||
if (info[i].syllable() != 255)
|
||||
{
|
||||
unsigned int max = i;
|
||||
unsigned int j = start + info[i].syllable();
|
||||
while (j != i)
|
||||
if (unlikely (end - start >= 127))
|
||||
buffer->merge_clusters (start, end);
|
||||
else
|
||||
/* Note! syllable() is a one-byte field. */
|
||||
for (unsigned int i = base; i < end; i++)
|
||||
if (info[i].syllable() != 255)
|
||||
{
|
||||
max = MAX (max, j);
|
||||
unsigned int next = start + info[j].syllable();
|
||||
info[j].syllable() = 255; /* So we don't process j later again. */
|
||||
j = next;
|
||||
unsigned int max = i;
|
||||
unsigned int j = start + info[i].syllable();
|
||||
while (j != i)
|
||||
{
|
||||
max = MAX (max, j);
|
||||
unsigned int next = start + info[j].syllable();
|
||||
info[j].syllable() = 255; /* So we don't process j later again. */
|
||||
j = next;
|
||||
}
|
||||
if (i != max)
|
||||
buffer->merge_clusters (i, max + 1);
|
||||
}
|
||||
if (i != max)
|
||||
buffer->merge_clusters (i, max + 1);
|
||||
}
|
||||
|
||||
/* Put syllable back in. */
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
|
||||
@ -1228,13 +1228,14 @@ struct hb_bytes_t
|
||||
/* fallback for round() */
|
||||
#if !defined (HAVE_ROUND) && !defined (HAVE_DECL_ROUND)
|
||||
static inline double
|
||||
round (double x)
|
||||
_hb_round (double x)
|
||||
{
|
||||
if (x >= 0)
|
||||
return floor (x + 0.5);
|
||||
else
|
||||
return ceil (x - 0.5);
|
||||
}
|
||||
#define round(x) _hb_round(x)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@ -38,9 +38,9 @@ HB_BEGIN_DECLS
|
||||
|
||||
#define HB_VERSION_MAJOR 1
|
||||
#define HB_VERSION_MINOR 8
|
||||
#define HB_VERSION_MICRO 1
|
||||
#define HB_VERSION_MICRO 2
|
||||
|
||||
#define HB_VERSION_STRING "1.8.1"
|
||||
#define HB_VERSION_STRING "1.8.2"
|
||||
|
||||
#define HB_VERSION_ATLEAST(major,minor,micro) \
|
||||
((major)*10000+(minor)*100+(micro) <= \
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user