Remove hb-old and hb-icu-le test shapers

They've been disabled for a while and no one cared.  We're past
the point to need them for testing, and if we ever need to
resurrect them again, well, they're in git graveyard somewhere.
This commit is contained in:
Behdad Esfahbod 2013-08-30 19:32:10 -04:00
parent b94243d6a9
commit ac1b723917
54 changed files with 2 additions and 25532 deletions

View file

@ -128,14 +128,6 @@ AM_CONDITIONAL(HAVE_OT, $have_ot)
dnl ===========================================================================
have_hb_old=false
if $have_hb_old; then
AC_DEFINE(HAVE_HB_OLD, 1, [Have Old HarfBuzz backend])
fi
AM_CONDITIONAL(HAVE_HB_OLD, $have_hb_old)
dnl ===========================================================================
AC_ARG_WITH(glib,
[AS_HELP_STRING([--with-glib=@<:@yes/no/auto@:>@],
[Use glib @<:@default=auto@:>@])],,
@ -269,15 +261,6 @@ AM_CONDITIONAL(HAVE_ICU, $have_icu)
dnl ==========================================================================
have_icu_le=false
dnl PKG_CHECK_MODULES(ICU_LE, icu-le icu-uc, have_icu_le=true, :)
if $have_icu_le; then
AC_DEFINE(HAVE_ICU_LE, 1, [Have ICU Layout Engine library])
fi
AM_CONDITIONAL(HAVE_ICU_LE, $have_icu_le)
dnl ==========================================================================
AC_ARG_WITH(graphite2,
[AS_HELP_STRING([--with-graphite2=@<:@yes/no/auto@:>@],
[Use the graphite2 library @<:@default=no@:>@])],,
@ -408,8 +391,6 @@ AC_CONFIG_FILES([
Makefile
src/Makefile
src/hb-version.h
src/hb-icu-le/Makefile
src/hb-old/Makefile
src/hb-ucdn/Makefile
util/Makefile
test/Makefile
@ -439,10 +420,8 @@ Tools used for command-line utilities:
Additional shapers (the more the better):
Graphite2: ${have_graphite2}
Test / platform shapers (not normally needed):
Platform shapers (not normally needed):
CoreText: ${have_coretext}
ICU Layout Engine: ${have_icu_le}
Old HarfBuzz: ${have_hb_old}
Uniscribe: ${have_uniscribe}
Other features:

View file

@ -154,22 +154,6 @@ HBSOURCES += hb-coretext.cc
HBHEADERS += hb-coretext.h
endif
if HAVE_HB_OLD
SUBDIRS += hb-old
HBCFLAGS += -I$(srcdir)/hb-old
HBLIBS += hb-old/libhb-old.la
HBSOURCES += hb-old.cc
endif
DIST_SUBDIRS += hb-old
if HAVE_ICU_LE
SUBDIRS += hb-icu-le
HBCFLAGS += -I$(srcdir)/hb-icu-le
HBLIBS += hb-icu-le/libhb-icu-le.la
HBSOURCES += hb-icu-le.cc
endif
DIST_SUBDIRS += hb-icu-le
if HAVE_UCDN
SUBDIRS += hb-ucdn
HBCFLAGS += -I$(srcdir)/hb-ucdn
@ -186,9 +170,6 @@ export_symbols = -export-symbols harfbuzz.def
harfbuzz_def_dependency = harfbuzz.def
libharfbuzz_la_LINK = $(CXXLINK) $(libharfbuzz_la_LDFLAGS)
else
if HAVE_ICU_LE
libharfbuzz_la_LINK = $(CXXLINK) $(libharfbuzz_la_LDFLAGS)
else
# Use a C linker for GCC, not C++; Don't link to libstdc++
if HAVE_GCC
libharfbuzz_la_LINK = $(LINK) $(libharfbuzz_la_LDFLAGS)
@ -196,7 +177,6 @@ else
libharfbuzz_la_LINK = $(CXXLINK) $(libharfbuzz_la_LDFLAGS)
endif
endif
endif
libharfbuzz_la_SOURCES = $(HBSOURCES) $(HBHEADERS) $(HBNODISTHEADERS)
nodist_libharfbuzz_la_SOURCES = $(nodist_HBSOURCES)
@ -352,16 +332,10 @@ dist_check_SCRIPTS = \
check-c-linkage-decls.sh \
check-header-guards.sh \
check-includes.sh \
check-symbols.sh \
$(NULL)
if HAVE_ICU_LE
else
dist_check_SCRIPTS += \
check-libstdc++.sh \
check-static-inits.sh \
check-symbols.sh \
$(NULL)
endif
TESTS = $(dist_check_SCRIPTS)
TESTS_ENVIRONMENT = \

View file

@ -1,265 +0,0 @@
/*
* Copyright © 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
*/
#define HB_SHAPER icu_le
#define hb_icu_le_shaper_font_data_t PortableFontInstance
#include "hb-shaper-impl-private.hh"
#include "hb-icu-le/PortableFontInstance.h"
#include <layout/LEScripts.h>
#include <layout/loengine.h>
#include <unicode/uscript.h>
#include <unicode/unistr.h>
/* Duplicated here so we don't depend on hb-icu. */
static hb_script_t
_hb_icu_script_to_script (UScriptCode script)
{
if (unlikely (script == USCRIPT_INVALID_CODE))
return HB_SCRIPT_INVALID;
return hb_script_from_string (uscript_getShortName (script), -1);
}
static UScriptCode
_hb_icu_script_from_script (hb_script_t script)
{
if (unlikely (script == HB_SCRIPT_INVALID))
return USCRIPT_INVALID_CODE;
for (unsigned int i = 0; i < USCRIPT_CODE_LIMIT; i++)
if (unlikely (_hb_icu_script_to_script ((UScriptCode) i) == script))
return (UScriptCode) i;
return USCRIPT_UNKNOWN;
}
/*
* shaper face data
*/
struct hb_icu_le_shaper_face_data_t {};
hb_icu_le_shaper_face_data_t *
_hb_icu_le_shaper_face_data_create (hb_face_t *face HB_UNUSED)
{
return (hb_icu_le_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_icu_le_shaper_face_data_destroy (hb_icu_le_shaper_face_data_t *data HB_UNUSED)
{
}
/*
* shaper font data
*/
hb_icu_le_shaper_font_data_t *
_hb_icu_le_shaper_font_data_create (hb_font_t *font)
{
LEErrorCode status = LE_NO_ERROR;
unsigned int x_ppem = font->x_ppem ? font->x_ppem : 72;
unsigned int y_ppem = font->y_ppem ? font->y_ppem : 72;
hb_icu_le_shaper_font_data_t *data = new PortableFontInstance (font->face,
font->x_scale / x_ppem,
font->y_scale / y_ppem,
x_ppem,
y_ppem,
status);
if (status != LE_NO_ERROR) {
delete (data);
return NULL;
}
return data;
}
void
_hb_icu_le_shaper_font_data_destroy (hb_icu_le_shaper_font_data_t *data)
{
delete (data);
}
/*
* shaper shape_plan data
*/
struct hb_icu_le_shaper_shape_plan_data_t {};
hb_icu_le_shaper_shape_plan_data_t *
_hb_icu_le_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features,
unsigned int num_user_features)
{
return (hb_icu_le_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_icu_le_shaper_shape_plan_data_destroy (hb_icu_le_shaper_shape_plan_data_t *data)
{
}
/*
* shaper
*/
hb_bool_t
_hb_icu_le_shape (hb_shape_plan_t *shape_plan,
hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
unsigned int num_features)
{
LEFontInstance *font_instance = HB_SHAPER_DATA_GET (font);
le_int32 script_code = _hb_icu_script_from_script (shape_plan->props.script);
le_int32 language_code = -1 /* TODO */;
le_int32 typography_flags = 3; /* Needed for ligatures and kerning */
LEErrorCode status = LE_NO_ERROR;
le_engine *le = le_create ((const le_font *) font_instance,
script_code,
language_code,
typography_flags,
&status);
if (status != LE_NO_ERROR)
{ le_close (le); return false; }
retry:
unsigned int scratch_size;
char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size);
LEUnicode *pchars = (LEUnicode *) scratch;
unsigned int chars_len = 0;
for (unsigned int i = 0; i < buffer->len; i++) {
hb_codepoint_t c = buffer->info[i].codepoint;
if (likely (c < 0x10000))
pchars[chars_len++] = c;
else if (unlikely (c >= 0x110000))
pchars[chars_len++] = 0xFFFD;
else {
pchars[chars_len++] = 0xD800 + ((c - 0x10000) >> 10);
pchars[chars_len++] = 0xDC00 + ((c - 0x10000) & ((1 << 10) - 1));
}
}
#define ALLOCATE_ARRAY(Type, name, len) \
Type *name = (Type *) scratch; \
scratch += (len) * sizeof ((name)[0]); \
scratch_size -= (len) * sizeof ((name)[0]);
ALLOCATE_ARRAY (LEUnicode, chars, chars_len);
ALLOCATE_ARRAY (unsigned int, clusters, chars_len);
chars_len = 0;
for (unsigned int i = 0; i < buffer->len; i++) {
hb_codepoint_t c = buffer->info[i].codepoint;
if (likely (c < 0x10000))
clusters[chars_len++] = buffer->info[i].cluster;
else if (unlikely (c >= 0x110000))
clusters[chars_len++] = buffer->info[i].cluster;
else {
clusters[chars_len++] = buffer->info[i].cluster;
clusters[chars_len++] = buffer->info[i].cluster;
}
}
unsigned int glyph_count = le_layoutChars (le,
chars,
0,
chars_len,
chars_len,
HB_DIRECTION_IS_BACKWARD (buffer->props.direction),
0., 0.,
&status);
if (status != LE_NO_ERROR)
{ le_close (le); return false; }
unsigned int num_glyphs = scratch_size / (sizeof (LEGlyphID) +
sizeof (le_int32) +
sizeof (float) * 2);
if (unlikely (glyph_count >= num_glyphs || glyph_count > buffer->allocated)) {
buffer->ensure (buffer->allocated * 2);
if (buffer->in_error)
{ le_close (le); return false; }
goto retry;
}
ALLOCATE_ARRAY (LEGlyphID, glyphs, glyph_count);
ALLOCATE_ARRAY (le_int32, indices, glyph_count);
ALLOCATE_ARRAY (float, positions, glyph_count * 2 + 2);
le_getGlyphs (le, glyphs, &status);
le_getCharIndices (le, indices, &status);
le_getGlyphPositions (le, positions, &status);
#undef ALLOCATE_ARRAY
/* Ok, we've got everything we need, now compose output buffer,
* very, *very*, carefully! */
unsigned int j = 0;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < glyph_count; i++)
{
if (glyphs[i] >= 0xFFFE)
continue;
info[j].codepoint = glyphs[i];
info[j].cluster = clusters[indices[i]];
/* icu-le doesn't seem to have separate advance values. */
info[j].mask = positions[2 * i + 2] - positions[2 * i];
info[j].var1.u32 = 0;
info[j].var2.u32 = -positions[2 * i + 1];
j++;
}
buffer->len = j;
buffer->clear_positions ();
for (unsigned int i = 0; i < buffer->len; i++) {
hb_glyph_info_t *info = &buffer->info[i];
hb_glyph_position_t *pos = &buffer->pos[i];
/* TODO vertical */
pos->x_advance = info->mask;
pos->x_offset = info->var1.u32;
pos->y_offset = info->var2.u32;
}
le_close (le);
return true;
}

View file

@ -1,2 +0,0 @@
The contents of this directory are licensed under the ICU license.
See file license.html.

View file

@ -1,91 +0,0 @@
/*
**********************************************************************
* Copyright (C) 2003-2008, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*/
#include "layout/LETypes.h"
#include "letest.h"
#include "FontTableCache.h"
#define TABLE_CACHE_INIT 5
#define TABLE_CACHE_GROW 5
struct FontTableCacheEntry
{
LETag tag;
hb_blob_t *blob;
};
FontTableCache::FontTableCache()
: fTableCacheCurr(0), fTableCacheSize(TABLE_CACHE_INIT)
{
fTableCache = NEW_ARRAY(FontTableCacheEntry, fTableCacheSize);
if (fTableCache == NULL) {
fTableCacheSize = 0;
return;
}
for (int i = 0; i < fTableCacheSize; i += 1) {
fTableCache[i].tag = 0;
fTableCache[i].blob = NULL;
}
}
FontTableCache::~FontTableCache()
{
for (int i = fTableCacheCurr - 1; i >= 0; i -= 1) {
hb_blob_destroy(fTableCache[i].blob);
fTableCache[i].tag = 0;
fTableCache[i].blob = NULL;
}
fTableCacheCurr = 0;
DELETE_ARRAY(fTableCache);
}
void FontTableCache::freeFontTable(hb_blob_t *blob) const
{
hb_blob_destroy(blob);
}
const void *FontTableCache::find(LETag tableTag) const
{
for (int i = 0; i < fTableCacheCurr; i += 1) {
if (fTableCache[i].tag == tableTag) {
return hb_blob_get_data(fTableCache[i].blob, NULL);
}
}
hb_blob_t *blob = readFontTable(tableTag);
((FontTableCache *) this)->add(tableTag, blob);
return hb_blob_get_data (blob, NULL);
}
void FontTableCache::add(LETag tableTag, hb_blob_t *blob)
{
if (fTableCacheCurr >= fTableCacheSize) {
le_int32 newSize = fTableCacheSize + TABLE_CACHE_GROW;
fTableCache = (FontTableCacheEntry *) GROW_ARRAY(fTableCache, newSize);
for (le_int32 i = fTableCacheSize; i < newSize; i += 1) {
fTableCache[i].tag = 0;
fTableCache[i].blob = NULL;
}
fTableCacheSize = newSize;
}
fTableCache[fTableCacheCurr].tag = tableTag;
fTableCache[fTableCacheCurr].blob = blob;
fTableCacheCurr += 1;
}

View file

@ -1,48 +0,0 @@
/*
**********************************************************************
* Copyright (C) 2003-2008, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*/
#ifndef __FONTTABLECACHE_H
#define __FONTTABLECACHE_H
#define HB_H_IN
#include <hb-blob.h>
#include "layout/LETypes.h"
#include "letest.h"
HB_BEGIN_VISIBILITY
U_NAMESPACE_USE
struct FontTableCacheEntry;
class FontTableCache
{
public:
FontTableCache();
virtual ~FontTableCache();
const void *find(LETag tableTag) const;
protected:
virtual hb_blob_t *readFontTable(LETag tableTag) const = 0;
virtual void freeFontTable(hb_blob_t *blob) const;
private:
void add(LETag tableTag, hb_blob_t *blob);
FontTableCacheEntry *fTableCache;
le_int32 fTableCacheCurr;
le_int32 fTableCacheSize;
};
HB_END_VISIBILITY
#endif

View file

@ -1,25 +0,0 @@
## Process this file with automake to produce Makefile.in
noinst_LTLIBRARIES = libhb-icu-le.la
libhb_icu_le_la_SOURCES = \
FontTableCache.cpp \
FontTableCache.h \
PortableFontInstance.cpp \
PortableFontInstance.h \
cmaps.cpp \
cmaps.h \
letest.h \
sfnt.h
libhb_icu_le_la_CPPFLAGS = \
-I$(top_srcdir) \
-I$(top_srcdir)/src \
-I$(top_builddir)/src \
$(ICU_LE_CFLAGS)
libhb_icu_le_la_LIBADD = \
$(ICU_LE_LIBS)
EXTRA_DIST = README license.html COPYING
-include $(top_srcdir)/git.mk

View file

@ -1,275 +0,0 @@
/*
*******************************************************************************
*
* Copyright (C) 1999-2008, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
* file name: PortableFontInstance.cpp
*
* created on: 11/22/1999
* created by: Eric R. Mader
*/
#include <stdio.h>
#include "layout/LETypes.h"
#include "layout/LEFontInstance.h"
#include "layout/LESwaps.h"
#include "PortableFontInstance.h"
#include "letest.h"
#include "sfnt.h"
#include <string.h>
PortableFontInstance::PortableFontInstance(hb_face_t *face,
float xScale,
float yScale,
unsigned int xPixelsPerEM,
unsigned int yPixelsPerEM,
LEErrorCode &status)
: fFace(face),
fXScale(xScale), fYScale(yScale),
fXPixelsPerEM(xPixelsPerEM), fYPixelsPerEM(yPixelsPerEM),
fUnitsPerEM(0), fAscent(0), fDescent(0), fLeading(0),
fNAMETable(NULL), fNameCount(0), fNameStringOffset(0), fCMAPMapper(NULL), fHMTXTable(NULL), fNumGlyphs(0), fNumLongHorMetrics(0)
{
if (LE_FAILURE(status)) {
return;
}
const LETag hheaTag = LE_HHEA_TABLE_TAG;
const HHEATable *hheaTable = NULL;
fUnitsPerEM = hb_face_get_upem (face);
hheaTable = (HHEATable *) getFontTable(hheaTag);
if (hheaTable == NULL) {
status = LE_MISSING_FONT_TABLE_ERROR;
return;
}
fAscent = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->ascent));
fDescent = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->descent));
fLeading = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->lineGap));
fNumLongHorMetrics = SWAPW(hheaTable->numOfLongHorMetrics);
fCMAPMapper = findUnicodeMapper();
if (fCMAPMapper == NULL) {
status = LE_MISSING_FONT_TABLE_ERROR;
return;
}
}
PortableFontInstance::~PortableFontInstance()
{
if (fCMAPMapper)
delete fCMAPMapper;
}
const void *PortableFontInstance::getFontTable(LETag tableTag) const
{
return FontTableCache::find(tableTag);
}
hb_blob_t *PortableFontInstance::readFontTable(LETag tableTag) const
{
return hb_face_reference_table(fFace, tableTag);
}
CMAPMapper *PortableFontInstance::findUnicodeMapper()
{
LETag cmapTag = LE_CMAP_TABLE_TAG;
const CMAPTable *cmap = (CMAPTable *) getFontTable(cmapTag);
if (cmap == NULL) {
return NULL;
}
return CMAPMapper::createUnicodeMapper(cmap);
}
const char *PortableFontInstance::getNameString(le_uint16 nameID, le_uint16 platformID, le_uint16 encodingID, le_uint16 languageID) const
{
if (fNAMETable == NULL) {
LETag nameTag = LE_NAME_TABLE_TAG;
PortableFontInstance *realThis = (PortableFontInstance *) this;
realThis->fNAMETable = (const NAMETable *) getFontTable(nameTag);
if (realThis->fNAMETable != NULL) {
realThis->fNameCount = SWAPW(realThis->fNAMETable->count);
realThis->fNameStringOffset = SWAPW(realThis->fNAMETable->stringOffset);
}
}
for(le_int32 i = 0; i < fNameCount; i += 1) {
const NameRecord *nameRecord = &fNAMETable->nameRecords[i];
if (SWAPW(nameRecord->platformID) == platformID && SWAPW(nameRecord->encodingID) == encodingID &&
SWAPW(nameRecord->languageID) == languageID && SWAPW(nameRecord->nameID) == nameID) {
char *name = ((char *) fNAMETable) + fNameStringOffset + SWAPW(nameRecord->offset);
le_uint16 length = SWAPW(nameRecord->length);
char *result = NEW_ARRAY(char, length + 2);
ARRAY_COPY(result, name, length);
result[length] = result[length + 1] = 0;
return result;
}
}
return NULL;
}
const LEUnicode16 *PortableFontInstance::getUnicodeNameString(le_uint16 nameID, le_uint16 platformID, le_uint16 encodingID, le_uint16 languageID) const
{
if (fNAMETable == NULL) {
LETag nameTag = LE_NAME_TABLE_TAG;
PortableFontInstance *realThis = (PortableFontInstance *) this;
realThis->fNAMETable = (const NAMETable *) getFontTable(nameTag);
if (realThis->fNAMETable != NULL) {
realThis->fNameCount = SWAPW(realThis->fNAMETable->count);
realThis->fNameStringOffset = SWAPW(realThis->fNAMETable->stringOffset);
}
}
for(le_int32 i = 0; i < fNameCount; i += 1) {
const NameRecord *nameRecord = &fNAMETable->nameRecords[i];
if (SWAPW(nameRecord->platformID) == platformID && SWAPW(nameRecord->encodingID) == encodingID &&
SWAPW(nameRecord->languageID) == languageID && SWAPW(nameRecord->nameID) == nameID) {
LEUnicode16 *name = (LEUnicode16 *) (((char *) fNAMETable) + fNameStringOffset + SWAPW(nameRecord->offset));
le_uint16 length = SWAPW(nameRecord->length) / 2;
LEUnicode16 *result = NEW_ARRAY(LEUnicode16, length + 2);
for (le_int32 c = 0; c < length; c += 1) {
result[c] = SWAPW(name[c]);
}
result[length] = 0;
return result;
}
}
return NULL;
}
void PortableFontInstance::deleteNameString(const char *name) const
{
DELETE_ARRAY(name);
}
void PortableFontInstance::deleteNameString(const LEUnicode16 *name) const
{
DELETE_ARRAY(name);
}
void PortableFontInstance::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const
{
TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(glyph);
if (fHMTXTable == NULL) {
LETag maxpTag = LE_MAXP_TABLE_TAG;
LETag hmtxTag = LE_HMTX_TABLE_TAG;
const MAXPTable *maxpTable = (MAXPTable *) getFontTable(maxpTag);
PortableFontInstance *realThis = (PortableFontInstance *) this;
if (maxpTable != NULL) {
realThis->fNumGlyphs = SWAPW(maxpTable->numGlyphs);
}
realThis->fHMTXTable = (const HMTXTable *) getFontTable(hmtxTag);
}
le_uint16 index = ttGlyph;
if (ttGlyph >= fNumGlyphs || fHMTXTable == NULL) {
advance.fX = advance.fY = 0;
return;
}
if (ttGlyph >= fNumLongHorMetrics) {
index = fNumLongHorMetrics - 1;
}
transformFunits (SWAPW(fHMTXTable->hMetrics[index].advanceWidth), 0, advance);
}
le_bool PortableFontInstance::getGlyphPoint(LEGlyphID /*glyph*/, le_int32 /*pointNumber*/, LEPoint &/*point*/) const
{
return FALSE;
}
le_int32 PortableFontInstance::getUnitsPerEM() const
{
return fUnitsPerEM;
}
le_uint32 PortableFontInstance::getFontChecksum() const
{
return 0;
}
le_int32 PortableFontInstance::getAscent() const
{
return fAscent;
}
le_int32 PortableFontInstance::getDescent() const
{
return fDescent;
}
le_int32 PortableFontInstance::getLeading() const
{
return fLeading;
}
// We really want to inherit this method from the superclass, but some compilers
// issue a warning if we don't implement it...
LEGlyphID PortableFontInstance::mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper, le_bool filterZeroWidth) const
{
return LEFontInstance::mapCharToGlyph(ch, mapper, filterZeroWidth);
}
// We really want to inherit this method from the superclass, but some compilers
// issue a warning if we don't implement it...
LEGlyphID PortableFontInstance::mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper) const
{
return LEFontInstance::mapCharToGlyph(ch, mapper);
}
LEGlyphID PortableFontInstance::mapCharToGlyph(LEUnicode32 ch) const
{
return fCMAPMapper->unicodeToGlyph(ch);
}
float PortableFontInstance::getXPixelsPerEm() const
{
return fXPixelsPerEM;
}
float PortableFontInstance::getYPixelsPerEm() const
{
return fYPixelsPerEM;
}
float PortableFontInstance::getScaleFactorX() const
{
return fXScale;
}
float PortableFontInstance::getScaleFactorY() const
{
return fYScale;
}

View file

@ -1,119 +0,0 @@
/*
*******************************************************************************
*
* Copyright (C) 1999-2008, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
* file name: PortableFontInstance.h
*
* created on: 11/12/1999
* created by: Eric R. Mader
*/
#ifndef __PORTABLEFONTINSTANCE_H
#define __PORTABLEFONTINSTANCE_H
#define HB_H_IN
#include <hb-font.h>
#include <hb-blob.h>
#include "layout/LETypes.h"
#include "layout/LEFontInstance.h"
#include "letest.h"
#include "FontTableCache.h"
#include "cmaps.h"
HB_BEGIN_VISIBILITY
class PortableFontInstance : public LEFontInstance, protected FontTableCache
{
private:
hb_face_t *fFace;
float fXScale;
float fYScale;
unsigned int fXPixelsPerEM;
unsigned int fYPixelsPerEM;
le_int32 fUnitsPerEM;
le_int32 fAscent;
le_int32 fDescent;
le_int32 fLeading;
const NAMETable *fNAMETable;
le_uint16 fNameCount;
le_uint16 fNameStringOffset;
CMAPMapper *fCMAPMapper;
const HMTXTable *fHMTXTable;
le_uint16 fNumGlyphs;
le_uint16 fNumLongHorMetrics;
void getMetrics();
CMAPMapper *findUnicodeMapper();
protected:
hb_blob_t *readFontTable(LETag tableTag) const;
public:
PortableFontInstance(hb_face_t *face,
float xScale,
float yScale,
unsigned int xPixelsPerEM,
unsigned int yPixelsPerEM,
LEErrorCode &status);
virtual ~PortableFontInstance();
virtual const void *getFontTable(LETag tableTag) const;
virtual const char *getNameString(le_uint16 nameID, le_uint16 platform, le_uint16 encoding, le_uint16 language) const;
virtual const LEUnicode16 *getUnicodeNameString(le_uint16 nameID, le_uint16 platform, le_uint16 encoding, le_uint16 language) const;
virtual void deleteNameString(const char *name) const;
virtual void deleteNameString(const LEUnicode16 *name) const;
virtual le_int32 getUnitsPerEM() const;
virtual le_uint32 getFontChecksum() const;
virtual le_int32 getAscent() const;
virtual le_int32 getDescent() const;
virtual le_int32 getLeading() const;
// We really want to inherit this method from the superclass, but some compilers
// issue a warning if we don't implement it...
virtual LEGlyphID mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper, le_bool filterZeroWidth) const;
// We really want to inherit this method from the superclass, but some compilers
// issue a warning if we don't implement it...
virtual LEGlyphID mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper) const;
virtual LEGlyphID mapCharToGlyph(LEUnicode32 ch) const;
virtual void getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const;
virtual le_bool getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point) const;
virtual float getXPixelsPerEm() const;
virtual float getYPixelsPerEm() const;
virtual float getScaleFactorX() const;
virtual float getScaleFactorY() const;
};
HB_END_VISIBILITY
#endif

View file

@ -1,3 +0,0 @@
This is PortableFontInstance from icu/test/testle of ICU50.
Modified to use a hb_face_t.
For license information, see the file license.html.

View file

@ -1,200 +0,0 @@
/***************************************************************************
*
* Copyright (C) 1998-2003, International Business Machines
* Corporation and others. All Rights Reserved.
*
************************************************************************/
#include "layout/LETypes.h"
#include "layout/LESwaps.h"
#include "sfnt.h"
#include "cmaps.h"
#define SWAPU16(code) ((LEUnicode16) SWAPW(code))
#define SWAPU32(code) ((LEUnicode32) SWAPL(code))
//
// Finds the high bit by binary searching
// through the bits in value.
//
static inline le_int8 highBit(le_uint32 value)
{
le_uint8 bit = 0;
if (value >= 1 << 16) {
value >>= 16;
bit += 16;
}
if (value >= 1 << 8) {
value >>= 8;
bit += 8;
}
if (value >= 1 << 4) {
value >>= 4;
bit += 4;
}
if (value >= 1 << 2) {
value >>= 2;
bit += 2;
}
if (value >= 1 << 1) {
value >>= 1;
bit += 1;
}
return bit;
}
CMAPMapper *CMAPMapper::createUnicodeMapper(const CMAPTable *cmap)
{
le_uint16 i;
le_uint16 nSubtables = SWAPW(cmap->numberSubtables);
const CMAPEncodingSubtable *subtable = NULL;
le_uint32 offset1 = 0, offset10 = 0;
for (i = 0; i < nSubtables; i += 1) {
const CMAPEncodingSubtableHeader *esh = &cmap->encodingSubtableHeaders[i];
if (SWAPW(esh->platformID) == 3) {
switch (SWAPW(esh->platformSpecificID)) {
case 1:
offset1 = SWAPL(esh->encodingOffset);
break;
case 10:
offset10 = SWAPL(esh->encodingOffset);
break;
}
}
}
if (offset10 != 0)
{
subtable = (const CMAPEncodingSubtable *) ((const char *) cmap + offset10);
} else if (offset1 != 0) {
subtable = (const CMAPEncodingSubtable *) ((const char *) cmap + offset1);
} else {
return NULL;
}
switch (SWAPW(subtable->format)) {
case 4:
return new CMAPFormat4Mapper(cmap, (const CMAPFormat4Encoding *) subtable);
case 12:
{
const CMAPFormat12Encoding *encoding = (const CMAPFormat12Encoding *) subtable;
return new CMAPGroupMapper(cmap, encoding->groups, SWAPL(encoding->nGroups));
}
default:
break;
}
return NULL;
}
CMAPFormat4Mapper::CMAPFormat4Mapper(const CMAPTable *cmap, const CMAPFormat4Encoding *header)
: CMAPMapper(cmap)
{
le_uint16 segCount = SWAPW(header->segCountX2) / 2;
fEntrySelector = SWAPW(header->entrySelector);
fRangeShift = SWAPW(header->rangeShift) / 2;
fEndCodes = &header->endCodes[0];
fStartCodes = &header->endCodes[segCount + 1]; // + 1 for reservedPad...
fIdDelta = &fStartCodes[segCount];
fIdRangeOffset = &fIdDelta[segCount];
}
LEGlyphID CMAPFormat4Mapper::unicodeToGlyph(LEUnicode32 unicode32) const
{
if (unicode32 >= 0x10000) {
return 0;
}
LEUnicode16 unicode = (LEUnicode16) unicode32;
le_uint16 index = 0;
le_uint16 probe = 1 << fEntrySelector;
TTGlyphID result = 0;
if (SWAPU16(fStartCodes[fRangeShift]) <= unicode) {
index = fRangeShift;
}
while (probe > (1 << 0)) {
probe >>= 1;
if (SWAPU16(fStartCodes[index + probe]) <= unicode) {
index += probe;
}
}
if (unicode >= SWAPU16(fStartCodes[index]) && unicode <= SWAPU16(fEndCodes[index])) {
if (fIdRangeOffset[index] == 0) {
result = (TTGlyphID) unicode;
} else {
le_uint16 offset = unicode - SWAPU16(fStartCodes[index]);
le_uint16 rangeOffset = SWAPW(fIdRangeOffset[index]);
le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &fIdRangeOffset[index] + rangeOffset);
result = SWAPW(glyphIndexTable[offset]);
}
result += SWAPW(fIdDelta[index]);
} else {
result = 0;
}
return LE_SET_GLYPH(0, result);
}
CMAPFormat4Mapper::~CMAPFormat4Mapper()
{
// parent destructor does it all
}
CMAPGroupMapper::CMAPGroupMapper(const CMAPTable *cmap, const CMAPGroup *groups, le_uint32 nGroups)
: CMAPMapper(cmap), fGroups(groups)
{
le_uint8 bit = highBit(nGroups);
fPower = 1 << bit;
fRangeOffset = nGroups - fPower;
}
LEGlyphID CMAPGroupMapper::unicodeToGlyph(LEUnicode32 unicode32) const
{
le_int32 probe = fPower;
le_int32 range = 0;
if (SWAPU32(fGroups[fRangeOffset].startCharCode) <= unicode32) {
range = fRangeOffset;
}
while (probe > (1 << 0)) {
probe >>= 1;
if (SWAPU32(fGroups[range + probe].startCharCode) <= unicode32) {
range += probe;
}
}
if (SWAPU32(fGroups[range].startCharCode) <= unicode32 && SWAPU32(fGroups[range].endCharCode) >= unicode32) {
return (LEGlyphID) (SWAPU32(fGroups[range].startGlyphCode) + unicode32 - SWAPU32(fGroups[range].startCharCode));
}
return 0;
}
CMAPGroupMapper::~CMAPGroupMapper()
{
// parent destructor does it all
}

View file

@ -1,87 +0,0 @@
/***************************************************************************
*
* Copyright (C) 1998-2006, International Business Machines
* Corporation and others. All Rights Reserved.
*
************************************************************************/
#ifndef __CMAPS_H
#define __CMAPS_H
#include "layout/LETypes.h"
#include "letest.h"
#include "sfnt.h"
HB_BEGIN_VISIBILITY
class CMAPMapper
{
public:
virtual LEGlyphID unicodeToGlyph(LEUnicode32 unicode32) const = 0;
virtual ~CMAPMapper();
static CMAPMapper *createUnicodeMapper(const CMAPTable *cmap);
protected:
CMAPMapper(const CMAPTable *cmap);
CMAPMapper() {};
private:
const CMAPTable *fcmap;
};
class CMAPFormat4Mapper : public CMAPMapper
{
public:
CMAPFormat4Mapper(const CMAPTable *cmap, const CMAPFormat4Encoding *header);
virtual ~CMAPFormat4Mapper();
virtual LEGlyphID unicodeToGlyph(LEUnicode32 unicode32) const;
protected:
CMAPFormat4Mapper() {};
private:
le_uint16 fEntrySelector;
le_uint16 fRangeShift;
const le_uint16 *fEndCodes;
const le_uint16 *fStartCodes;
const le_uint16 *fIdDelta;
const le_uint16 *fIdRangeOffset;
};
class CMAPGroupMapper : public CMAPMapper
{
public:
CMAPGroupMapper(const CMAPTable *cmap, const CMAPGroup *groups, le_uint32 nGroups);
virtual ~CMAPGroupMapper();
virtual LEGlyphID unicodeToGlyph(LEUnicode32 unicode32) const;
protected:
CMAPGroupMapper() {};
private:
le_int32 fPower;
le_int32 fRangeOffset;
const CMAPGroup *fGroups;
};
inline CMAPMapper::CMAPMapper(const CMAPTable *cmap)
: fcmap(cmap)
{
// nothing else to do
}
inline CMAPMapper::~CMAPMapper()
{
}
HB_END_VISIBILITY
#endif

View file

@ -1,63 +0,0 @@
/*
*******************************************************************************
*
* Copyright (C) 1999-2011, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
* file name: letest.h
*
* created on: 11/06/2000
* created by: Eric R. Mader
*/
#ifndef __LETEST_H
#define __LETEST_H
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)
# define HB_BEGIN_VISIBILITY _Pragma ("GCC visibility push(hidden)")
# define HB_END_VISIBILITY _Pragma ("GCC visibility pop")
#else
# define HB_BEGIN_VISIBILITY
# define HB_END_VISIBILITY
#endif
#include "layout/LETypes.h"
/*#include "unicode/ctest.h"*/
#include <stdlib.h>
#include <string.h>
HB_BEGIN_VISIBILITY
U_NAMESPACE_USE
#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
#define ARRAY_COPY(dst, src, count) memcpy((void *) (dst), (void *) (src), (count) * sizeof (src)[0])
#define NEW_ARRAY(type,count) (type *) malloc((count) * sizeof(type))
#define DELETE_ARRAY(array) free((void *) (array))
#define GROW_ARRAY(array,newSize) realloc((void *) (array), (newSize) * sizeof (array)[0])
struct TestResult
{
le_int32 glyphCount;
LEGlyphID *glyphs;
le_int32 *indices;
float *positions;
};
#ifndef __cplusplus
typedef struct TestResult TestResult;
#endif
//U_CFUNC void addCTests(TestNode **root);
HB_END_VISIBILITY
#endif

View file

@ -1,51 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></meta>
<title>ICU License - ICU 1.8.1 and later</title>
</head>
<body BGCOLOR="#ffffff">
<h2>ICU License - ICU 1.8.1 and later</h2>
<p>COPYRIGHT AND PERMISSION NOTICE</p>
<p>
Copyright (c) 1995-2012 International Business Machines Corporation and others
</p>
<p>
All rights reserved.
</p>
<p>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, and/or sell
copies of the Software, and to permit persons
to whom the Software is furnished to do so, provided that the above
copyright notice(s) and this permission notice appear in all copies
of the Software and that both the above copyright notice(s) and this
permission notice appear in supporting documentation.
</p>
<p>
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL
THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM,
OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
USE OR PERFORMANCE OF THIS SOFTWARE.
</p>
<p>
Except as contained in this notice, the name of a copyright holder shall not be
used in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization of the copyright holder.
</p>
<hr>
<p><small>
All trademarks and registered trademarks mentioned herein are the property of their respective owners.
</small></p>
</body>
</html>

View file

@ -1,453 +0,0 @@
/***************************************************************************
*
* Copyright (C) 1998-2011, International Business Machines
* Corporation and others. All Rights Reserved.
*
************************************************************************/
#ifndef __SFNT_H
#define __SFNT_H
#include "layout/LETypes.h"
#include "letest.h"
HB_BEGIN_VISIBILITY
U_NAMESPACE_USE
#ifndef ANY_NUMBER
#define ANY_NUMBER 1
#endif
struct DirectoryEntry
{
le_uint32 tag;
le_uint32 checksum;
le_uint32 offset;
le_uint32 length;
};
#ifndef __cplusplus
typedef struct DirectoryEntry DirectoryEntry;
#endif
struct SFNTDirectory
{
le_uint32 scalerType;
le_uint16 numTables;
le_uint16 searchRange;
le_uint16 entrySelector;
le_uint16 rangeShift;
DirectoryEntry tableDirectory[ANY_NUMBER];
};
#ifndef __cplusplus
typedef struct SFNTDirectory SFNTDirectory;
#endif
struct CMAPEncodingSubtableHeader
{
le_uint16 platformID;
le_uint16 platformSpecificID;
le_uint32 encodingOffset;
};
#ifndef __cplusplus
typedef struct CMAPEncodingSubtableHeader CMAPEncodingSubtableHeader;
#endif
struct CMAPTable
{
le_uint16 version;
le_uint16 numberSubtables;
CMAPEncodingSubtableHeader encodingSubtableHeaders[ANY_NUMBER];
};
#ifndef __cplusplus
typedef struct CMAPTable CMAPTable;
#endif
struct CMAPEncodingSubtable
{
le_uint16 format;
le_uint16 length;
le_uint16 language;
};
#ifndef __cplusplus
typedef struct CMAPEncodingSubtable CMAPEncodingSubtable;
#endif
#ifdef __cplusplus
struct CMAPFormat0Encoding : CMAPEncodingSubtable
{
le_uint8 glyphIndexArray[256];
};
#else
struct CMAPFormat0Encoding
{
CMAPEncodingSubtable base;
le_uint8 glyphIndexArray[256];
};
typedef struct CMAPFormat0Encoding CMAPFormat0Encoding;
#endif
struct CMAPFormat2Subheader
{
le_uint16 firstCode;
le_uint16 entryCount;
le_int16 idDelta;
le_uint16 idRangeOffset;
};
#ifndef __cplusplus
typedef struct CMAPFormat2Subheader CMAPFormat2Subheader;
#endif
#ifdef __cplusplus
struct CMAPFormat2Encoding : CMAPEncodingSubtable
{
le_uint16 subHeadKeys[256];
CMAPFormat2Subheader subheaders[ANY_NUMBER];
};
#else
struct CMAPFormat2Encoding
{
CMAPEncodingSubtable base;
le_uint16 subHeadKeys[256];
CMAPFormat2Subheader subheaders[ANY_NUMBER];
};
typedef struct CMAPFormat2Encoding CMAPFormat2Encoding;
#endif
#ifdef __cplusplus
struct CMAPFormat4Encoding : CMAPEncodingSubtable
{
le_uint16 segCountX2;
le_uint16 searchRange;
le_uint16 entrySelector;
le_uint16 rangeShift;
le_uint16 endCodes[ANY_NUMBER];
/*
le_uint16 reservedPad;
le_uint16 startCodes[ANY_NUMBER];
le_uint16 idDelta[ANY_NUMBER];
le_uint16 idRangeOffset[ANY_NUMBER];
le_uint16 glyphIndexArray[ANY_NUMBER];
*/
};
#else
struct CMAPFormat4Encoding
{
CMAPEncodingSubtable base;
le_uint16 segCountX2;
le_uint16 searchRange;
le_uint16 entrySelector;
le_uint16 rangeShift;
le_uint16 endCodes[ANY_NUMBER];
/*
// le_uint16 reservedPad;
// le_uint16 startCodes[ANY_NUMBER];
// le_uint16 idDelta[ANY_NUMBER];
// le_uint16 idRangeOffset[ANY_NUMBER];
// le_uint16 glyphIndexArray[ANY_NUMBER];
*/
};
typedef struct CMAPFormat4Encoding CMAPFormat4Encoding;
#endif
#ifdef __cplusplus
struct CMAPFormat6Encoding : CMAPEncodingSubtable
{
le_uint16 firstCode;
le_uint16 entryCount;
le_uint16 glyphIndexArray[ANY_NUMBER];
};
#else
struct CMAPFormat6Encoding
{
CMAPEncodingSubtable base;
le_uint16 firstCode;
le_uint16 entryCount;
le_uint16 glyphIndexArray[ANY_NUMBER];
};
typedef struct CMAPFormat6Encoding CMAPFormat6Encoding;
#endif
struct CMAPEncodingSubtable32
{
le_uint32 format;
le_uint32 length;
le_uint32 language;
};
#ifndef __cplusplus
typedef struct CMAPEncodingSubtable32 CMAPEncodingSubtable32;
#endif
struct CMAPGroup
{
le_uint32 startCharCode;
le_uint32 endCharCode;
le_uint32 startGlyphCode;
};
#ifndef __cplusplus
typedef struct CMAPGroup CMAPGroup;
#endif
#ifdef __cplusplus
struct CMAPFormat8Encoding : CMAPEncodingSubtable32
{
le_uint32 is32[65536/32];
le_uint32 nGroups;
CMAPGroup groups[ANY_NUMBER];
};
#else
struct CMAPFormat8Encoding
{
CMAPEncodingSubtable32 base;
le_uint32 is32[65536/32];
le_uint32 nGroups;
CMAPGroup groups[ANY_NUMBER];
};
typedef struct CMAPFormat8Encoding CMAPFormat8Encoding;
#endif
#ifdef __cplusplus
struct CMAPFormat10Encoding : CMAPEncodingSubtable32
{
le_uint32 startCharCode;
le_uint32 numCharCodes;
le_uint16 glyphs[ANY_NUMBER];
};
#else
struct CMAPFormat10Encoding
{
CMAPEncodingSubtable32 base;
le_uint32 startCharCode;
le_uint32 numCharCodes;
le_uint16 glyphs[ANY_NUMBER];
};
typedef struct CMAPFormat10Encoding CMAPFormat10Encoding;
#endif
#ifdef __cplusplus
struct CMAPFormat12Encoding : CMAPEncodingSubtable32
{
le_uint32 nGroups;
CMAPGroup groups[ANY_NUMBER];
};
#else
struct CMAPFormat12Encoding
{
CMAPEncodingSubtable32 base;
le_uint32 nGroups;
CMAPGroup groups[ANY_NUMBER];
};
typedef struct CMAPFormat12Encoding CMAPFormat12Encoding;
#endif
typedef le_int32 fixed;
struct BigDate
{
le_uint32 bc;
le_uint32 ad;
};
#ifndef __cplusplus
typedef struct BigDate BigDate;
#endif
struct HEADTable
{
fixed version;
fixed fontRevision;
le_uint32 checksumAdjustment;
le_uint32 magicNumber;
le_uint16 flags;
le_uint16 unitsPerEm;
BigDate created;
BigDate modified;
le_int16 xMin;
le_int16 yMin;
le_int16 xMax;
le_int16 yMax;
le_int16 lowestRecPPEM;
le_int16 fontDirectionHint;
le_int16 indexToLocFormat;
le_int16 glyphDataFormat;
};
#ifndef __cplusplus
typedef struct HEADTable HEADTable;
#endif
struct MAXPTable
{
fixed version;
le_uint16 numGlyphs;
le_uint16 maxPoints;
le_uint16 maxContours;
le_uint16 maxComponentPoints;
le_uint16 maxComponentContours;
le_uint16 maxZones;
le_uint16 maxTwilightPoints;
le_uint16 maxStorage;
le_uint16 maxFunctionDefs;
le_uint16 maxInstructionDefs;
le_uint16 maxStackElements;
le_uint16 maxSizeOfInstructions;
le_uint16 maxComponentElements;
le_uint16 maxComponentDepth;
};
#ifndef __cplusplus
typedef struct MAXPTable MAXPTable;
#endif
struct HHEATable
{
fixed version;
le_int16 ascent;
le_int16 descent;
le_int16 lineGap;
le_uint16 advanceWidthMax;
le_int16 minLeftSideBearing;
le_int16 minRightSideBearing;
le_int16 xMaxExtent;
le_int16 caretSlopeRise;
le_int16 caretSlopeRun;
le_int16 caretOffset;
le_int16 reserved1;
le_int16 reserved2;
le_int16 reserved3;
le_int16 reserved4;
le_int16 metricDataFormat;
le_uint16 numOfLongHorMetrics;
};
#ifndef __cplusplus
typedef struct HHEATable HHEATable;
#endif
struct LongHorMetric
{
le_uint16 advanceWidth;
le_int16 leftSideBearing;
};
#ifndef __cplusplus
typedef struct LongHorMetric LongHorMetric;
#endif
struct HMTXTable
{
LongHorMetric hMetrics[ANY_NUMBER]; /* ANY_NUMBER = numOfLongHorMetrics from hhea table */
/* le_int16 leftSideBearing[ANY_NUMBER]; ANY_NUMBER = numGlyphs - numOfLongHorMetrics */
};
#ifndef __cplusplus
typedef struct HMTXTable HMTXTable;
#endif
enum PlatformID
{
PLATFORM_UNICODE = 0,
PLATFORM_MACINTOSH = 1,
PLATFORM_ISO = 2,
PLATFORM_MICROSOFT = 3,
PLATFORM_CUSTOM = 4
};
enum MacintoshEncodingID
{
MACINTOSH_ROMAN = 0
};
enum MacintoshLanguageID
{
MACINTOSH_ENGLISH = 0
};
enum MicrosoftEncodingID
{
MICROSOFT_UNICODE_BMP = 1,
MICROSOFT_UNICODE_FULL = 10
};
enum MicrosoftLanguageID
{
MICROSOFT_ENGLISH = 0x409
};
enum NameID
{
NAME_COPYRIGHT_NOTICE = 0,
NAME_FONT_FAMILY = 1,
NAME_FONT_SUB_FAMILY = 2,
NAME_UNIQUE_FONT_ID = 3,
NAME_FULL_FONT_NAME = 4,
NAME_VERSION_STRING = 5,
NAME_POSTSCRIPT_NAME = 6,
NAME_TRADEMARK = 7,
NAME_MANUFACTURER = 8,
NAME_DESIGNER = 9,
NAME_DESCRIPTION = 10,
NAME_VENDOR_URL = 11,
NAME_DESIGNER_URL = 12,
NAME_LICENSE_DESCRIPTION = 13,
NAME_LICENSE_URL = 14,
NAME_RESERVED = 15,
NAME_PREFERRED_FAMILY = 16,
NAME_PREFERRED_SUB_FAMILY = 17,
NAME_COMPATIBLE_FULL = 18,
NAME_SAMPLE_TEXT = 19,
NAME_POSTSCRIPT_CID = 20
};
struct NameRecord
{
le_uint16 platformID;
le_uint16 encodingID;
le_uint16 languageID;
le_uint16 nameID;
le_uint16 length;
le_uint16 offset;
};
#ifndef __cplusplus
typedef struct NameRecord NameRecord;
#endif
struct NAMETable
{
le_uint16 version;
le_uint16 count;
le_uint16 stringOffset;
NameRecord nameRecords[ANY_NUMBER];
};
#ifndef __cplusplus
typedef struct NAMETable NAMETable;
#endif
HB_END_VISIBILITY
#endif

View file

@ -1,410 +0,0 @@
/*
* Copyright © 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
*/
#define HB_SHAPER old
#define hb_old_shaper_face_data_t HB_FaceRec_
#define hb_old_shaper_font_data_t HB_Font_
#include "hb-shaper-impl-private.hh"
#include <harfbuzz.h>
#ifndef HB_DEBUG_OLD
#define HB_DEBUG_OLD (HB_DEBUG+0)
#endif
static HB_Script
hb_old_script_from_script (hb_script_t script)
{
switch ((hb_tag_t) script)
{
default:
case HB_SCRIPT_COMMON: return HB_Script_Common;
case HB_SCRIPT_GREEK: return HB_Script_Greek;
case HB_SCRIPT_CYRILLIC: return HB_Script_Cyrillic;
case HB_SCRIPT_ARMENIAN: return HB_Script_Armenian;
case HB_SCRIPT_HEBREW: return HB_Script_Hebrew;
case HB_SCRIPT_ARABIC: return HB_Script_Arabic;
case HB_SCRIPT_SYRIAC: return HB_Script_Syriac;
case HB_SCRIPT_THAANA: return HB_Script_Thaana;
case HB_SCRIPT_DEVANAGARI: return HB_Script_Devanagari;
case HB_SCRIPT_BENGALI: return HB_Script_Bengali;
case HB_SCRIPT_GURMUKHI: return HB_Script_Gurmukhi;
case HB_SCRIPT_GUJARATI: return HB_Script_Gujarati;
case HB_SCRIPT_ORIYA: return HB_Script_Oriya;
case HB_SCRIPT_TAMIL: return HB_Script_Tamil;
case HB_SCRIPT_TELUGU: return HB_Script_Telugu;
case HB_SCRIPT_KANNADA: return HB_Script_Kannada;
case HB_SCRIPT_MALAYALAM: return HB_Script_Malayalam;
case HB_SCRIPT_SINHALA: return HB_Script_Sinhala;
case HB_SCRIPT_THAI: return HB_Script_Thai;
case HB_SCRIPT_LAO: return HB_Script_Lao;
case HB_SCRIPT_TIBETAN: return HB_Script_Tibetan;
case HB_SCRIPT_MYANMAR: return HB_Script_Myanmar;
case HB_SCRIPT_GEORGIAN: return HB_Script_Georgian;
case HB_SCRIPT_HANGUL: return HB_Script_Hangul;
case HB_SCRIPT_OGHAM: return HB_Script_Ogham;
case HB_SCRIPT_RUNIC: return HB_Script_Runic;
case HB_SCRIPT_KHMER: return HB_Script_Khmer;
case HB_SCRIPT_NKO: return HB_Script_Nko;
case HB_SCRIPT_INHERITED: return HB_Script_Inherited;
}
}
static HB_Bool
hb_old_convertStringToGlyphIndices (HB_Font old_font,
const HB_UChar16 *string,
hb_uint32 length,
HB_Glyph *glyphs,
hb_uint32 *numGlyphs,
HB_Bool rightToLeft)
{
hb_font_t *font = (hb_font_t *) old_font->userData;
for (unsigned int i = 0; i < length; i++)
{
hb_codepoint_t u;
/* XXX Handle UTF-16. Ugh */
u = string[i];
if (rightToLeft)
u = hb_unicode_funcs_get_default ()->mirroring (u);
font->get_glyph (u, 0, &u); /* TODO Variation selectors */
glyphs[i] = u;
}
*numGlyphs = length; /* XXX */
return true;
}
static void
hb_old_getGlyphAdvances (HB_Font old_font,
const HB_Glyph *glyphs,
hb_uint32 numGlyphs,
HB_Fixed *advances,
int flags /*HB_ShaperFlag*/ HB_UNUSED)
{
hb_font_t *font = (hb_font_t *) old_font->userData;
for (unsigned int i = 0; i < numGlyphs; i++)
advances[i] = font->get_glyph_h_advance (glyphs[i]);
}
static HB_Bool
hb_old_canRender (HB_Font old_font,
const HB_UChar16 *string,
hb_uint32 length)
{
return true; /* TODO */
}
static HB_Error
hb_old_getPointInOutline (HB_Font old_font,
HB_Glyph glyph,
int flags /*HB_ShaperFlag*/,
hb_uint32 point,
HB_Fixed *xpos,
HB_Fixed *ypos,
hb_uint32 *nPoints)
{
return HB_Err_Ok; /* TODO */
}
static void
hb_old_getGlyphMetrics (HB_Font old_font,
HB_Glyph glyph,
HB_GlyphMetrics *metrics)
{
hb_font_t *font = (hb_font_t *) old_font->userData;
hb_glyph_extents_t extents;
font->get_glyph_extents (glyph, &extents);
metrics->x = extents.x_bearing;
metrics->y = extents.y_bearing;
metrics->width = extents.width;
metrics->height = extents.height;
metrics->xOffset = font->get_glyph_h_advance (glyph);
metrics->yOffset = 0;
}
static HB_Fixed
hb_old_getFontMetric (HB_Font old_font,
HB_FontMetric metric)
{
hb_font_t *font = (hb_font_t *) old_font->userData;
switch (metric)
{
case HB_FontAscent:
return font->y_scale; /* XXX We don't have ascent data yet. */
default:
return 0;
}
}
static const HB_FontClass hb_old_font_class = {
hb_old_convertStringToGlyphIndices,
hb_old_getGlyphAdvances,
hb_old_canRender,
hb_old_getPointInOutline,
hb_old_getGlyphMetrics,
hb_old_getFontMetric
};
static HB_Error
table_func (void *font, HB_Tag tag, HB_Byte *buffer, HB_UInt *length)
{
hb_face_t *face = (hb_face_t *) font;
hb_blob_t *blob = face->reference_table ((hb_tag_t) tag);
unsigned int capacity = *length;
*length = hb_blob_get_length (blob);
memcpy (buffer, hb_blob_get_data (blob, NULL), MIN (capacity, *length));
hb_blob_destroy (blob);
return HB_Err_Ok;
}
/*
* shaper face data
*/
hb_old_shaper_face_data_t *
_hb_old_shaper_face_data_create (hb_face_t *face)
{
return HB_NewFace (face, table_func);
}
void
_hb_old_shaper_face_data_destroy (hb_old_shaper_face_data_t *data)
{
HB_FreeFace (data);
}
/*
* shaper font data
*/
hb_old_shaper_font_data_t *
_hb_old_shaper_font_data_create (hb_font_t *font)
{
HB_FontRec *data = (HB_FontRec *) calloc (1, sizeof (HB_FontRec));
if (unlikely (!data)) {
DEBUG_MSG (OLD, font, "malloc()ing HB_Font failed");
return NULL;
}
data->klass = &hb_old_font_class;
data->x_ppem = font->x_ppem;
data->y_ppem = font->y_ppem;
data->x_scale = font->x_scale; /* XXX */
data->y_scale = font->y_scale; /* XXX */
data->userData = font;
return data;
}
void
_hb_old_shaper_font_data_destroy (hb_old_shaper_font_data_t *data)
{
free (data);
}
/*
* shaper shape_plan data
*/
struct hb_old_shaper_shape_plan_data_t {};
hb_old_shaper_shape_plan_data_t *
_hb_old_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED)
{
return (hb_old_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_old_shaper_shape_plan_data_destroy (hb_old_shaper_shape_plan_data_t *data HB_UNUSED)
{
}
/*
* shaper
*/
hb_bool_t
_hb_old_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
unsigned int num_features)
{
hb_face_t *face = font->face;
HB_Face old_face = HB_SHAPER_DATA_GET (face);
HB_Font old_font = HB_SHAPER_DATA_GET (font);
bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
retry:
unsigned int scratch_size;
char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size);
#define utf16_index() var1.u32
HB_UChar16 *pchars = (HB_UChar16 *) scratch;
unsigned int chars_len = 0;
for (unsigned int i = 0; i < buffer->len; i++) {
hb_codepoint_t c = buffer->info[i].codepoint;
buffer->info[i].utf16_index() = chars_len;
if (likely (c < 0x10000))
pchars[chars_len++] = c;
else if (unlikely (c >= 0x110000))
pchars[chars_len++] = 0xFFFD;
else {
pchars[chars_len++] = 0xD800 + ((c - 0x10000) >> 10);
pchars[chars_len++] = 0xDC00 + ((c - 0x10000) & ((1 << 10) - 1));
}
}
#define ALLOCATE_ARRAY(Type, name, len) \
name = (Type *) scratch; \
scratch += (len) * sizeof ((name)[0]); \
scratch_size -= (len) * sizeof ((name)[0]);
HB_ShaperItem item = {0};
ALLOCATE_ARRAY (const HB_UChar16, item.string, chars_len);
ALLOCATE_ARRAY (unsigned short, item.log_clusters, chars_len + 2);
item.stringLength = chars_len;
item.item.pos = 0;
item.item.length = item.stringLength;
item.item.script = hb_old_script_from_script (buffer->props.script);
item.item.bidiLevel = backward ? 1 : 0;
item.font = old_font;
item.face = old_face;
item.shaperFlags = 0;
item.glyphIndicesPresent = false;
/* TODO Alignment. */
unsigned int num_glyphs = scratch_size / (sizeof (HB_Glyph) +
sizeof (HB_GlyphAttributes) +
sizeof (HB_Fixed) +
sizeof (HB_FixedPoint) +
sizeof (uint32_t));
item.num_glyphs = num_glyphs;
ALLOCATE_ARRAY (HB_Glyph, item.glyphs, num_glyphs);
ALLOCATE_ARRAY (HB_GlyphAttributes, item.attributes, num_glyphs);
ALLOCATE_ARRAY (HB_Fixed, item.advances, num_glyphs);
ALLOCATE_ARRAY (HB_FixedPoint, item.offsets, num_glyphs);
/* Apparently in some cases the offsets array will not be fully assigned to.
* Clear it. */
memset (item.offsets, 0, num_glyphs * sizeof (item.offsets[0]));
uint32_t *vis_clusters;
ALLOCATE_ARRAY (uint32_t, vis_clusters, num_glyphs);
#undef ALLOCATE_ARRAY
if (!HB_ShapeItem (&item))
{
if (unlikely (item.num_glyphs > num_glyphs))
{
buffer->ensure (buffer->allocated * 2);
if (buffer->in_error)
return false;
goto retry;
}
return false;
}
num_glyphs = item.num_glyphs;
/* Ok, we've got everything we need, now compose output buffer,
* very, *very*, carefully! */
/* Calculate visual-clusters. That's what we ship. */
for (unsigned int i = 0; i < num_glyphs; i++)
vis_clusters[i] = -1;
for (unsigned int i = 0; i < buffer->len; i++) {
uint32_t *p = &vis_clusters[item.log_clusters[buffer->info[i].utf16_index()]];
*p = MIN (*p, buffer->info[i].cluster);
}
for (unsigned int i = 1; i < num_glyphs; i++)
if (vis_clusters[i] == (uint32_t) -1)
vis_clusters[i] = vis_clusters[i - 1];
#undef utf16_index
buffer->ensure (num_glyphs);
if (buffer->in_error)
return false;
buffer->len = num_glyphs;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < num_glyphs; i++)
{
info[i].codepoint = item.glyphs[i];
info[i].cluster = vis_clusters[i];
info[i].mask = item.advances[i];
info[i].var1.u32 = item.offsets[i].x;
info[i].var2.u32 = item.offsets[i].y;
}
buffer->clear_positions ();
for (unsigned int i = 0; i < num_glyphs; ++i) {
hb_glyph_info_t *info = &buffer->info[i];
hb_glyph_position_t *pos = &buffer->pos[i];
/* TODO vertical */
pos->x_advance = info->mask;
pos->x_offset = info->var1.u32;
pos->y_offset = info->var2.u32;
}
if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
buffer->reverse ();
return true;
}

View file

@ -1,24 +0,0 @@
HarfBuzz-old was previously licensed under different licenses. This was
changed in January 2008. If you need to relicense your old copies,
consult the announcement of the license change on the internet.
Other than that, each copy of HarfBuzz-old is licensed under the COPYING
file included with it. The actual license follows:
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.

View file

@ -1,56 +0,0 @@
## Process this file with automake to produce Makefile.in
noinst_LTLIBRARIES = libhb-old.la
MAINSOURCES = \
harfbuzz-buffer.c \
harfbuzz-stream.c \
harfbuzz-gdef.c \
harfbuzz-gpos.c \
harfbuzz-gsub.c \
harfbuzz-impl.c \
harfbuzz-open.c \
harfbuzz-shaper.cpp \
harfbuzz-greek.c \
harfbuzz-tibetan.c \
harfbuzz-khmer.c \
harfbuzz-indic.cpp \
harfbuzz-hebrew.c \
harfbuzz-arabic.c \
harfbuzz-hangul.c \
harfbuzz-myanmar.c
PUBLICHEADERS = \
harfbuzz.h \
harfbuzz-buffer.h \
harfbuzz-gdef.h \
harfbuzz-gpos.h \
harfbuzz-gsub.h \
harfbuzz-open.h \
harfbuzz-global.h \
harfbuzz-external.h \
harfbuzz-shaper.h \
harfbuzz-stream.h
PRIVATEHEADERS = \
harfbuzz-impl.h \
harfbuzz-buffer-private.h \
harfbuzz-stream-private.h \
harfbuzz-gdef-private.h \
harfbuzz-gpos-private.h \
harfbuzz-gsub-private.h \
harfbuzz-open-private.h \
harfbuzz-shaper-private.h
libhb_old_la_SOURCES = \
$(MAINSOURCES) \
$(PUBLICHEADERS) \
$(PRIVATEHEADERS)
libhb_old_la_CPPFLAGS = \
-I$(top_srcdir) \
-I$(top_srcdir)/src \
-I$(top_builddir)/src
EXTRA_DIST = README COPYING
-include $(top_srcdir)/git.mk

View file

@ -1,7 +0,0 @@
This is HarfBuzz-old, an OpenType Layout engine library.
To report bugs or post to discussion mailing list, see:
http://freedesktop.org/wiki/Software/HarfBuzz
For license information, see the file COPYING.

File diff suppressed because it is too large Load diff

View file

@ -1,107 +0,0 @@
/*
* Copyright (C) 1998-2004 David Turner and Werner Lemberg
* Copyright (C) 2004,2007 Red Hat, Inc.
*
* This is part of HarfBuzz, an OpenType Layout engine 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): Owen Taylor, Behdad Esfahbod
*/
#ifndef HARFBUZZ_BUFFER_PRIVATE_H
#define HARFBUZZ_BUFFER_PRIVATE_H
#include "harfbuzz-impl.h"
#include "harfbuzz-buffer.h"
HB_BEGIN_HEADER
#define HB_GLYPH_PROPERTIES_UNKNOWN 0xFFFF
HB_INTERNAL void
_hb_buffer_swap( HB_Buffer buffer );
HB_INTERNAL void
_hb_buffer_clear_output( HB_Buffer buffer );
HB_INTERNAL HB_Error
_hb_buffer_clear_positions( HB_Buffer buffer );
HB_INTERNAL HB_Error
_hb_buffer_add_output_glyphs( HB_Buffer buffer,
HB_UShort num_in,
HB_UShort num_out,
HB_UShort *glyph_data,
HB_UShort component,
HB_UShort ligID );
HB_INTERNAL HB_Error
_hb_buffer_add_output_glyph ( HB_Buffer buffer,
HB_UInt glyph_index,
HB_UShort component,
HB_UShort ligID );
HB_INTERNAL HB_Error
_hb_buffer_copy_output_glyph ( HB_Buffer buffer );
HB_INTERNAL HB_Error
_hb_buffer_replace_output_glyph ( HB_Buffer buffer,
HB_UInt glyph_index,
HB_Bool inplace );
HB_INTERNAL HB_UShort
_hb_buffer_allocate_ligid( HB_Buffer buffer );
/* convenience macros */
#define IN_GLYPH( pos ) (buffer->in_string[(pos)].gindex)
#define IN_ITEM( pos ) (&buffer->in_string[(pos)])
#define IN_CURGLYPH() (buffer->in_string[buffer->in_pos].gindex)
#define IN_CURITEM() (&buffer->in_string[buffer->in_pos])
#define IN_PROPERTIES( pos ) (buffer->in_string[(pos)].properties)
#define IN_LIGID( pos ) (buffer->in_string[(pos)].ligID)
#define IN_COMPONENT( pos ) (buffer->in_string[(pos)].component)
#define POSITION( pos ) (&buffer->positions[(pos)])
#define OUT_GLYPH( pos ) (buffer->out_string[(pos)].gindex)
#define OUT_ITEM( pos ) (&buffer->out_string[(pos)])
#define CHECK_Property( gdef, index, flags, property ) \
( ( error = _HB_GDEF_Check_Property( (gdef), (index), (flags), \
(property) ) ) != HB_Err_Ok )
#define ADD_String( buffer, num_in, num_out, glyph_data, component, ligID ) \
( ( error = _hb_buffer_add_output_glyphs( (buffer), \
(num_in), (num_out), \
(glyph_data), (component), (ligID) \
) ) != HB_Err_Ok )
#define ADD_Glyph( buffer, glyph_index, component, ligID ) \
( ( error = _hb_buffer_add_output_glyph( (buffer), \
(glyph_index), (component), (ligID) \
) ) != HB_Err_Ok )
#define REPLACE_Glyph( buffer, glyph_index, nesting_level ) \
( ( error = _hb_buffer_replace_output_glyph( (buffer), (glyph_index), \
(nesting_level) == 1 ) ) != HB_Err_Ok )
#define COPY_Glyph( buffer ) \
( (error = _hb_buffer_copy_output_glyph ( buffer ) ) != HB_Err_Ok )
HB_END_HEADER
#endif /* HARFBUZZ_BUFFER_PRIVATE_H */

View file

@ -1,383 +0,0 @@
/*
* Copyright (C) 1998-2004 David Turner and Werner Lemberg
* Copyright (C) 2004,2007 Red Hat, Inc.
*
* This is part of HarfBuzz, an OpenType Layout engine 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): Owen Taylor, Behdad Esfahbod
*/
#include "harfbuzz-impl.h"
#include "harfbuzz-buffer-private.h"
#include "harfbuzz-gsub-private.h"
#include "harfbuzz-gpos-private.h"
/* Here is how the buffer works internally:
*
* There are two string pointers: in_string and out_string. They
* always have same allocated size, but different length and positions.
*
* As an optimization, both in_string and out_string may point to the
* same piece of memory, which is owned by in_string. This remains the
* case as long as:
*
* - copy_glyph() is called
* - replace_glyph() is called with inplace=TRUE
* - add_output_glyph() and add_output_glyphs() are not called
*
* In that case swap(), and copy_glyph(), and replace_glyph() are all
* mostly no-op.
*
* As soon an add_output_glyph[s]() or replace_glyph() with inplace=FALSE is
* called, out_string is moved over to an alternate buffer (alt_string), and
* its current contents (out_length entries) are copied to the alt buffer.
* This should all remain transparent to the user. swap() then switches
* in_string and alt_string. alt_string is not allocated until its needed,
* but after that it's grown with in_string unconditionally.
*
* The buffer->separate_out boolean keeps status of whether out_string points
* to in_string (FALSE) or alt_string (TRUE).
*/
/* Internal API */
static HB_Error
HB_Buffer_ensure( HB_Buffer buffer,
HB_UInt size )
{
HB_UInt new_allocated = buffer->allocated;
if (size > new_allocated)
{
HB_Error error;
while (size > new_allocated)
new_allocated += (new_allocated >> 1) + 8;
if ( buffer->positions )
{
if ( REALLOC_ARRAY( buffer->positions, new_allocated, HB_PositionRec ) )
return error;
}
if ( REALLOC_ARRAY( buffer->in_string, new_allocated, HB_GlyphItemRec ) )
return error;
if ( buffer->separate_out )
{
if ( REALLOC_ARRAY( buffer->alt_string, new_allocated, HB_GlyphItemRec ) )
return error;
buffer->out_string = buffer->alt_string;
}
else
{
buffer->out_string = buffer->in_string;
if ( buffer->alt_string )
{
if ( REALLOC_ARRAY( buffer->alt_string, new_allocated, HB_GlyphItemRec ) )
return error;
}
}
buffer->allocated = new_allocated;
}
return HB_Err_Ok;
}
static HB_Error
HB_Buffer_duplicate_out_buffer( HB_Buffer buffer )
{
if ( !buffer->alt_string )
{
HB_Error error;
if ( ALLOC_ARRAY( buffer->alt_string, buffer->allocated, HB_GlyphItemRec ) )
return error;
}
buffer->out_string = buffer->alt_string;
memcpy( buffer->out_string, buffer->in_string, buffer->out_length * sizeof (buffer->out_string[0]) );
buffer->separate_out = TRUE;
return HB_Err_Ok;
}
/* Public API */
HB_Error
HB_Buffer_new( HB_Buffer *pbuffer )
{
HB_Buffer buffer;
HB_Error error;
if ( ALLOC( buffer, sizeof( HB_BufferRec ) ) )
return error;
buffer->allocated = 0;
buffer->in_string = NULL;
buffer->alt_string = NULL;
buffer->positions = NULL;
HB_Buffer_clear( buffer );
*pbuffer = buffer;
return HB_Err_Ok;
}
void
HB_Buffer_free( HB_Buffer buffer )
{
FREE( buffer->in_string );
FREE( buffer->alt_string );
buffer->out_string = NULL;
FREE( buffer->positions );
FREE( buffer );
}
void
HB_Buffer_clear( HB_Buffer buffer )
{
buffer->in_length = 0;
buffer->out_length = 0;
buffer->in_pos = 0;
buffer->out_pos = 0;
buffer->out_string = buffer->in_string;
buffer->separate_out = FALSE;
buffer->max_ligID = 0;
}
HB_Error
HB_Buffer_add_glyph( HB_Buffer buffer,
HB_UInt glyph_index,
HB_UInt properties,
HB_UInt cluster )
{
HB_Error error;
HB_GlyphItem glyph;
error = HB_Buffer_ensure( buffer, buffer->in_length + 1 );
if ( error )
return error;
glyph = &buffer->in_string[buffer->in_length];
glyph->gindex = glyph_index;
glyph->properties = properties;
glyph->cluster = cluster;
glyph->component = 0;
glyph->ligID = 0;
glyph->gproperties = HB_GLYPH_PROPERTIES_UNKNOWN;
buffer->in_length++;
return HB_Err_Ok;
}
/* HarfBuzz-Internal API */
HB_INTERNAL void
_hb_buffer_clear_output( HB_Buffer buffer )
{
buffer->out_length = 0;
buffer->out_pos = 0;
buffer->out_string = buffer->in_string;
buffer->separate_out = FALSE;
}
HB_INTERNAL HB_Error
_hb_buffer_clear_positions( HB_Buffer buffer )
{
if ( !buffer->positions )
{
HB_Error error;
if ( ALLOC_ARRAY( buffer->positions, buffer->allocated, HB_PositionRec ) )
return error;
}
memset (buffer->positions, 0, sizeof (buffer->positions[0]) * buffer->in_length);
return HB_Err_Ok;
}
HB_INTERNAL void
_hb_buffer_swap( HB_Buffer buffer )
{
HB_GlyphItem tmp_string;
int tmp_length;
int tmp_pos;
if ( buffer->separate_out )
{
tmp_string = buffer->in_string;
buffer->in_string = buffer->out_string;
buffer->out_string = tmp_string;
buffer->alt_string = buffer->out_string;
}
tmp_length = buffer->in_length;
buffer->in_length = buffer->out_length;
buffer->out_length = tmp_length;
tmp_pos = buffer->in_pos;
buffer->in_pos = buffer->out_pos;
buffer->out_pos = tmp_pos;
}
/* The following function copies `num_out' elements from `glyph_data'
to `buffer->out_string', advancing the in array pointer in the structure
by `num_in' elements, and the out array pointer by `num_out' elements.
Finally, it sets the `length' field of `out' equal to
`pos' of the `out' structure.
If `component' is 0xFFFF, the component value from buffer->in_pos
will copied `num_out' times, otherwise `component' itself will
be used to fill the `component' fields.
If `ligID' is 0xFFFF, the ligID value from buffer->in_pos
will copied `num_out' times, otherwise `ligID' itself will
be used to fill the `ligID' fields.
The properties for all replacement glyphs are taken
from the glyph at position `buffer->in_pos'.
The cluster value for the glyph at position buffer->in_pos is used
for all replacement glyphs */
HB_INTERNAL HB_Error
_hb_buffer_add_output_glyphs( HB_Buffer buffer,
HB_UShort num_in,
HB_UShort num_out,
HB_UShort *glyph_data,
HB_UShort component,
HB_UShort ligID )
{
HB_Error error;
HB_UShort i;
HB_UInt properties;
HB_UInt cluster;
error = HB_Buffer_ensure( buffer, buffer->out_pos + num_out );
if ( error )
return error;
if ( !buffer->separate_out )
{
error = HB_Buffer_duplicate_out_buffer( buffer );
if ( error )
return error;
}
properties = buffer->in_string[buffer->in_pos].properties;
cluster = buffer->in_string[buffer->in_pos].cluster;
if ( component == 0xFFFF )
component = buffer->in_string[buffer->in_pos].component;
if ( ligID == 0xFFFF )
ligID = buffer->in_string[buffer->in_pos].ligID;
for ( i = 0; i < num_out; i++ )
{
HB_GlyphItem item = &buffer->out_string[buffer->out_pos + i];
item->gindex = glyph_data[i];
item->properties = properties;
item->cluster = cluster;
item->component = component;
item->ligID = ligID;
item->gproperties = HB_GLYPH_PROPERTIES_UNKNOWN;
}
buffer->in_pos += num_in;
buffer->out_pos += num_out;
buffer->out_length = buffer->out_pos;
return HB_Err_Ok;
}
HB_INTERNAL HB_Error
_hb_buffer_add_output_glyph( HB_Buffer buffer,
HB_UInt glyph_index,
HB_UShort component,
HB_UShort ligID )
{
HB_UShort glyph_data = glyph_index;
return _hb_buffer_add_output_glyphs ( buffer, 1, 1,
&glyph_data, component, ligID );
}
HB_INTERNAL HB_Error
_hb_buffer_copy_output_glyph ( HB_Buffer buffer )
{
HB_Error error;
error = HB_Buffer_ensure( buffer, buffer->out_pos + 1 );
if ( error )
return error;
if ( buffer->separate_out )
{
buffer->out_string[buffer->out_pos] = buffer->in_string[buffer->in_pos];
}
buffer->in_pos++;
buffer->out_pos++;
buffer->out_length = buffer->out_pos;
return HB_Err_Ok;
}
HB_INTERNAL HB_Error
_hb_buffer_replace_output_glyph( HB_Buffer buffer,
HB_UInt glyph_index,
HB_Bool inplace )
{
HB_Error error;
if ( inplace )
{
error = _hb_buffer_copy_output_glyph ( buffer );
if ( error )
return error;
buffer->out_string[buffer->out_pos-1].gindex = glyph_index;
}
else
{
return _hb_buffer_add_output_glyph( buffer, glyph_index, 0xFFFF, 0xFFFF );
}
return HB_Err_Ok;
}
HB_INTERNAL HB_UShort
_hb_buffer_allocate_ligid( HB_Buffer buffer )
{
buffer->max_ligID++;
if (HB_UNLIKELY (buffer->max_ligID == 0))
buffer->max_ligID++;
return buffer->max_ligID;
}

View file

@ -1,102 +0,0 @@
/*
* Copyright (C) 1998-2004 David Turner and Werner Lemberg
* Copyright (C) 2004,2007 Red Hat, Inc.
*
* This is part of HarfBuzz, an OpenType Layout engine 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): Owen Taylor, Behdad Esfahbod
*/
#ifndef HARFBUZZ_BUFFER_H
#define HARFBUZZ_BUFFER_H
#include "harfbuzz-global.h"
HB_BEGIN_HEADER
#ifdef HB_USE_PACKED_STRUCTS
#pragma pack(push, 1)
#endif
typedef struct HB_GlyphItemRec_ {
HB_UInt gindex;
HB_UInt properties;
HB_UInt cluster;
HB_UShort component;
HB_UShort ligID;
HB_UShort gproperties;
} HB_GlyphItemRec, *HB_GlyphItem;
typedef struct HB_PositionRec_ {
HB_Fixed x_pos;
HB_Fixed y_pos;
HB_Fixed x_advance;
HB_Fixed y_advance;
HB_UShort back; /* number of glyphs to go back
for drawing current glyph */
HB_Short cursive_chain; /* character to which this connects,
may be positive or negative; used
only internally */
HB_Bool new_advance; /* if set, the advance width values are
absolute, i.e., they won't be
added to the original glyph's value
but rather replace them. */
} HB_PositionRec, *HB_Position;
typedef struct HB_BufferRec_{
HB_UInt allocated;
HB_UInt in_length;
HB_UInt out_length;
HB_UInt in_pos;
HB_UInt out_pos;
HB_GlyphItem in_string;
HB_GlyphItem out_string;
HB_GlyphItem alt_string;
HB_Position positions;
HB_UShort max_ligID;
HB_Bool separate_out;
} HB_BufferRec, *HB_Buffer;
HB_Error
HB_Buffer_new( HB_Buffer *buffer );
void
HB_Buffer_free( HB_Buffer buffer );
void
HB_Buffer_clear( HB_Buffer buffer );
HB_Error
HB_Buffer_add_glyph( HB_Buffer buffer,
HB_UInt glyph_index,
HB_UInt properties,
HB_UInt cluster );
#ifdef HB_USE_PACKED_STRUCTS
#pragma pack(pop)
#endif
HB_END_HEADER
#endif /* HARFBUZZ_BUFFER_H */

View file

@ -1,106 +0,0 @@
/*
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#ifndef HARFBUZZ_EXTERNAL_H
#define HARFBUZZ_EXTERNAL_H
#define HB_H_IN
#include <hb-unicode.h>
#include "harfbuzz-global.h"
HB_BEGIN_HEADER
/* This header contains some methods that are not part of
Harfbuzz itself, but referenced by it.
They need to be provided by the application/library
*/
typedef enum
{
HB_Mark_NonSpacing = HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK, /* Mn */
HB_Mark_SpacingCombining = HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK, /* Mc */
HB_Mark_Enclosing = HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK, /* Me */
HB_Number_DecimalDigit = HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER, /* Nd */
HB_Number_Letter = HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER, /* Nl */
HB_Number_Other = HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER, /* No */
HB_Separator_Space = HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR, /* Zs */
HB_Separator_Line = HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR, /* Zl */
HB_Separator_Paragraph = HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR, /* Zp */
HB_Other_Control = HB_UNICODE_GENERAL_CATEGORY_CONTROL, /* Cc */
HB_Other_Format = HB_UNICODE_GENERAL_CATEGORY_FORMAT, /* Cf */
HB_Other_Surrogate = HB_UNICODE_GENERAL_CATEGORY_SURROGATE, /* Cs */
HB_Other_PrivateUse = HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE, /* Co */
HB_Other_NotAssigned = HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED, /* Cn */
HB_Letter_Uppercase = HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER, /* Lu */
HB_Letter_Lowercase = HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER, /* Ll */
HB_Letter_Titlecase = HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER, /* Lt */
HB_Letter_Modifier = HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER, /* Lm */
HB_Letter_Other = HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER, /* Lo */
HB_Punctuation_Connector = HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION, /* Pc */
HB_Punctuation_Dash = HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION, /* Pd */
HB_Punctuation_Open = HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION, /* Ps */
HB_Punctuation_Close = HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION, /* Pe */
HB_Punctuation_InitialQuote = HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION, /* Pi */
HB_Punctuation_FinalQuote = HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION, /* Pf */
HB_Punctuation_Other = HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION, /* Po */
HB_Symbol_Math = HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL, /* Sm */
HB_Symbol_Currency = HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL, /* Sc */
HB_Symbol_Modifier = HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL, /* Sk */
HB_Symbol_Other = HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL /* So */
} HB_CharCategory;
static inline HB_CharCategory HB_GetUnicodeCharCategory(hb_unicode_funcs_t *funcs, HB_UChar32 ch)
{
return (HB_CharCategory) hb_unicode_general_category (funcs, ch);
}
static inline int HB_GetUnicodeCharCombiningClass(hb_unicode_funcs_t *funcs, HB_UChar32 ch)
{
return hb_unicode_combining_class (funcs, ch);
}
static inline HB_UChar16 HB_GetMirroredChar(hb_unicode_funcs_t *funcs, HB_UChar16 ch)
{
return hb_unicode_mirroring (funcs, ch);
}
static inline void HB_GetUnicodeCharProperties(hb_unicode_funcs_t *funcs, HB_UChar32 ch, HB_CharCategory *category, int *combiningClass)
{
if (category)
*category = HB_GetUnicodeCharCategory (funcs, ch);
if (combiningClass)
*combiningClass = HB_GetUnicodeCharCombiningClass (funcs, ch);
}
HB_END_HEADER
#endif

View file

@ -1,135 +0,0 @@
/*
* Copyright (C) 1998-2004 David Turner and Werner Lemberg
* Copyright (C) 2006 Behdad Esfahbod
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#ifndef HARFBUZZ_GDEF_PRIVATE_H
#define HARFBUZZ_GDEF_PRIVATE_H
#include "harfbuzz-impl.h"
#include "harfbuzz-stream-private.h"
#include "harfbuzz-buffer-private.h"
#include "harfbuzz-gdef.h"
HB_BEGIN_HEADER
#ifdef HB_USE_PACKED_STRUCTS
#pragma pack(push, 1)
#endif
/* Attachment related structures */
struct HB_AttachPoint_
{
HB_UShort* PointIndex; /* array of contour points */
HB_UShort PointCount; /* size of the PointIndex array */
};
/* Ligature Caret related structures */
struct HB_CaretValueFormat1_
{
HB_Short Coordinate; /* x or y value (in design units) */
};
typedef struct HB_CaretValueFormat1_ HB_CaretValueFormat1;
struct HB_CaretValueFormat2_
{
HB_UShort CaretValuePoint; /* contour point index on glyph */
};
typedef struct HB_CaretValueFormat2_ HB_CaretValueFormat2;
struct HB_CaretValueFormat3_
{
HB_Device* Device; /* Device table for x or y value */
HB_Short Coordinate; /* x or y value (in design units) */
};
typedef struct HB_CaretValueFormat3_ HB_CaretValueFormat3;
#ifdef HB_SUPPORT_MULTIPLE_MASTER
struct HB_CaretValueFormat4_
{
HB_UShort IdCaretValue; /* metric ID */
};
typedef struct HB_CaretValueFormat4_ HB_CaretValueFormat4;
#endif
struct HB_CaretValue_
{
union
{
HB_CaretValueFormat1 cvf1;
HB_CaretValueFormat2 cvf2;
HB_CaretValueFormat3 cvf3;
#ifdef HB_SUPPORT_MULTIPLE_MASTER
HB_CaretValueFormat4 cvf4;
#endif
} cvf;
HB_Byte CaretValueFormat; /* 1, 2, 3, or 4 */
};
typedef struct HB_CaretValue_ HB_CaretValue;
struct HB_LigGlyph_
{
HB_CaretValue* CaretValue; /* array of caret values */
HB_UShort CaretCount; /* number of caret values */
HB_Bool loaded;
};
HB_INTERNAL HB_Error
_HB_GDEF_Add_Glyph_Property( HB_GDEFHeader* gdef,
HB_UShort glyphID,
HB_UShort property );
HB_INTERNAL HB_Error
_HB_GDEF_Check_Property( HB_GDEFHeader* gdef,
HB_GlyphItem item,
HB_UShort flags,
HB_UShort* property );
HB_INTERNAL HB_Error
_HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( HB_GDEFHeader* gdef,
HB_Stream input,
HB_Lookup* lo,
HB_UShort num_lookups );
#ifdef HB_USE_PACKED_STRUCTS
#pragma pack(pop)
#endif
HB_END_HEADER
#endif /* HARFBUZZ_GDEF_PRIVATE_H */

File diff suppressed because it is too large Load diff

View file

@ -1,140 +0,0 @@
/*
* Copyright (C) 1998-2004 David Turner and Werner Lemberg
* Copyright (C) 2006 Behdad Esfahbod
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#ifndef HARFBUZZ_GDEF_H
#define HARFBUZZ_GDEF_H
#include "harfbuzz-open.h"
#include "harfbuzz-stream.h"
HB_BEGIN_HEADER
#ifdef HB_USE_PACKED_STRUCTS
#pragma pack(push, 1)
#endif
/* GDEF glyph properties. Note that HB_GDEF_COMPONENT has no corresponding
* flag in the LookupFlag field. */
#define HB_GDEF_BASE_GLYPH 0x0002
#define HB_GDEF_LIGATURE 0x0004
#define HB_GDEF_MARK 0x0008
#define HB_GDEF_COMPONENT 0x0010
typedef struct HB_AttachPoint_ HB_AttachPoint;
struct HB_AttachList_
{
HB_AttachPoint* AttachPoint; /* array of AttachPoint tables */
HB_Coverage Coverage; /* Coverage table */
HB_UShort GlyphCount; /* number of glyphs with
attachments */
HB_Bool loaded;
};
typedef struct HB_AttachList_ HB_AttachList;
typedef struct HB_LigGlyph_ HB_LigGlyph;
struct HB_LigCaretList_
{
HB_LigGlyph* LigGlyph; /* array of LigGlyph tables */
HB_Coverage Coverage; /* Coverage table */
HB_UShort LigGlyphCount; /* number of ligature glyphs */
HB_Bool loaded;
};
typedef struct HB_LigCaretList_ HB_LigCaretList;
/* The `NewGlyphClasses' field is not defined in the TTO specification.
We use it for fonts with a constructed `GlyphClassDef' structure
(i.e., which don't have a GDEF table) to collect glyph classes
assigned during the lookup process. The number of arrays in this
pointer array is GlyphClassDef->cd.cd2.ClassRangeCount+1; the nth
array then contains the glyph class values of the glyphs not covered
by the ClassRangeRecords structures with index n-1 and n. We store
glyph class values for four glyphs in a single array element.
`LastGlyph' is identical to the number of glyphs minus one in the
font; we need it only if `NewGlyphClasses' is not NULL (to have an
upper bound for the last array).
Note that we first store the file offset to the `MarkAttachClassDef'
field (which has been introduced in OpenType 1.2) -- since the
`Version' field value hasn't been increased to indicate that we have
one more field for some obscure reason, we must parse the GSUB table
to find out whether class values refer to this table. Only then we
can finally load the MarkAttachClassDef structure if necessary. */
struct HB_GDEFHeader_
{
HB_UShort** NewGlyphClasses;
HB_UInt offset;
HB_UInt MarkAttachClassDef_offset;
HB_16Dot16 Version;
HB_ClassDefinition GlyphClassDef;
HB_AttachList AttachList;
HB_LigCaretList LigCaretList;
HB_ClassDefinition MarkAttachClassDef; /* new in OT 1.2 */
HB_UShort LastGlyph;
};
typedef struct HB_GDEFHeader_ HB_GDEFHeader;
typedef struct HB_GDEFHeader_* HB_GDEF;
HB_Error HB_New_GDEF_Table( HB_GDEFHeader** retptr );
HB_Error HB_Load_GDEF_Table( HB_Stream stream,
HB_GDEFHeader** gdef );
HB_Error HB_Done_GDEF_Table ( HB_GDEFHeader* gdef );
HB_Error HB_GDEF_Get_Glyph_Property( HB_GDEFHeader* gdef,
HB_UShort glyphID,
HB_UShort* property );
HB_Error HB_GDEF_Build_ClassDefinition( HB_GDEFHeader* gdef,
HB_UShort num_glyphs,
HB_UShort glyph_count,
HB_UShort* glyph_array,
HB_UShort* class_array );
#ifdef HB_USE_PACKED_STRUCTS
#pragma pack(pop)
#endif
HB_END_HEADER
#endif /* HARFBUZZ_GDEF_H */

View file

@ -1,125 +0,0 @@
/*
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
* Copyright (C) 2007 Red Hat, Inc.
*
* This is part of HarfBuzz, an OpenType Layout engine 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 HARFBUZZ_GLOBAL_H
#define HARFBUZZ_GLOBAL_H
#include <stdlib.h>
#include <string.h>
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)
# define HB_BEGIN_VISIBILITY _Pragma ("GCC visibility push(hidden)")
# define HB_END_VISIBILITY _Pragma ("GCC visibility pop")
#else
# define HB_BEGIN_VISIBILITY
# define HB_END_VISIBILITY
#endif
#ifdef __cplusplus
# define HB_BEGIN_HEADER extern "C" { HB_BEGIN_VISIBILITY
# define HB_END_HEADER HB_END_VISIBILITY }
#else
# define HB_BEGIN_HEADER HB_BEGIN_VISIBILITY
# define HB_END_HEADER HB_END_VISIBILITY
#endif
HB_BEGIN_HEADER
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
#define HB_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
( ( (HB_UInt)_x1 << 24 ) | \
( (HB_UInt)_x2 << 16 ) | \
( (HB_UInt)_x3 << 8 ) | \
(HB_UInt)_x4 )
typedef char hb_int8;
typedef unsigned char hb_uint8;
typedef short hb_int16;
typedef unsigned short hb_uint16;
typedef int hb_int32;
typedef unsigned int hb_uint32;
typedef hb_uint8 HB_Bool;
typedef hb_uint8 HB_Byte;
typedef hb_uint16 HB_UShort;
typedef hb_uint32 HB_UInt;
typedef hb_int8 HB_Char;
typedef hb_int16 HB_Short;
typedef hb_int32 HB_Int;
typedef hb_uint16 HB_UChar16;
typedef hb_uint32 HB_UChar32;
typedef hb_uint32 HB_Glyph;
typedef hb_int32 HB_Fixed; /* 26.6 */
#define HB_FIXED_CONSTANT(v) ((v) * 64)
#define HB_FIXED_ROUND(v) (((v)+32) & -64)
typedef hb_int32 HB_16Dot16; /* 16.16 */
typedef void * HB_Pointer;
typedef hb_uint32 HB_Tag;
typedef enum {
/* no error */
HB_Err_Ok = 0x0000,
HB_Err_Not_Covered = 0xFFFF,
/* _hb_err() is called whenever returning the following errors,
* and in a couple places for HB_Err_Not_Covered too. */
/* programmer error */
HB_Err_Invalid_Argument = 0x1A66,
/* font error */
HB_Err_Invalid_SubTable_Format = 0x157F,
HB_Err_Invalid_SubTable = 0x1570,
HB_Err_Read_Error = 0x6EAD,
/* system error */
HB_Err_Out_Of_Memory = 0xDEAD
} HB_Error;
typedef struct {
HB_Fixed x;
HB_Fixed y;
} HB_FixedPoint;
typedef struct HB_Font_ *HB_Font;
typedef struct HB_StreamRec_ *HB_Stream;
typedef struct HB_FaceRec_ *HB_Face;
HB_END_HEADER
#endif

View file

@ -1,729 +0,0 @@
/*
* Copyright (C) 1998-2004 David Turner and Werner Lemberg
* Copyright (C) 2006 Behdad Esfahbod
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#ifndef HARFBUZZ_GPOS_PRIVATE_H
#define HARFBUZZ_GPOS_PRIVATE_H
#include "harfbuzz-impl.h"
#include "harfbuzz-stream-private.h"
#include "harfbuzz-gpos.h"
HB_BEGIN_HEADER
#ifdef HB_USE_PACKED_STRUCTS
#pragma pack(push, 1)
#endif
/* shared tables */
#define VR_X_PLACEMENT_DEVICE 0
#define VR_Y_PLACEMENT_DEVICE 1
#define VR_X_ADVANCE_DEVICE 2
#define VR_Y_ADVANCE_DEVICE 3
struct HB_ValueRecord_
{
HB_Short XPlacement; /* horizontal adjustment for
placement */
HB_Short YPlacement; /* vertical adjustment for
placement */
HB_Short XAdvance; /* horizontal adjustment for
advance */
HB_Short YAdvance; /* vertical adjustment for
advance */
HB_Device** DeviceTables; /* device tables for placement
and advance */
#ifdef HB_SUPPORT_MULTIPLE_MASTER
HB_UShort XIdPlacement; /* horizontal placement metric ID */
HB_UShort YIdPlacement; /* vertical placement metric ID */
HB_UShort XIdAdvance; /* horizontal advance metric ID */
HB_UShort YIdAdvance; /* vertical advance metric ID */
#endif
};
typedef struct HB_ValueRecord_ HB_ValueRecord;
/* Mask values to scan the value format of the ValueRecord structure.
We always expand compressed ValueRecords of the font. */
#define HB_GPOS_FORMAT_HAVE_DEVICE_TABLES 0x00F0
#define HB_GPOS_FORMAT_HAVE_X_PLACEMENT 0x0001
#define HB_GPOS_FORMAT_HAVE_Y_PLACEMENT 0x0002
#define HB_GPOS_FORMAT_HAVE_X_ADVANCE 0x0004
#define HB_GPOS_FORMAT_HAVE_Y_ADVANCE 0x0008
#define HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE 0x0010
#define HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE 0x0020
#define HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE 0x0040
#define HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE 0x0080
#define HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT 0x0100
#define HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT 0x0200
#define HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE 0x0400
#define HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE 0x0800
struct HB_AnchorFormat1_
{
HB_Short XCoordinate; /* horizontal value */
HB_Short YCoordinate; /* vertical value */
};
typedef struct HB_AnchorFormat1_ HB_AnchorFormat1;
struct HB_AnchorFormat2_
{
HB_Short XCoordinate; /* horizontal value */
HB_Short YCoordinate; /* vertical value */
HB_UShort AnchorPoint; /* index to glyph contour point */
};
typedef struct HB_AnchorFormat2_ HB_AnchorFormat2;
#define AF3_X_DEVICE_TABLE 0
#define AF3_Y_DEVICE_TABLE 1
struct HB_AnchorFormat3_
{
HB_Short XCoordinate; /* horizontal value */
HB_Short YCoordinate; /* vertical value */
HB_Device** DeviceTables; /* device tables for coordinates */
};
typedef struct HB_AnchorFormat3_ HB_AnchorFormat3;
#ifdef HB_SUPPORT_MULTIPLE_MASTER
struct HB_AnchorFormat4_
{
HB_UShort XIdAnchor; /* horizontal metric ID */
HB_UShort YIdAnchor; /* vertical metric ID */
};
typedef struct HB_AnchorFormat4_ HB_AnchorFormat4;
#endif
struct HB_Anchor_
{
HB_Byte PosFormat; /* 1, 2, 3, or 4 -- 0 indicates
that there is no Anchor table */
union
{
HB_AnchorFormat1 af1;
HB_AnchorFormat2 af2;
HB_AnchorFormat3 af3;
#ifdef HB_SUPPORT_MULTIPLE_MASTER
HB_AnchorFormat4 af4;
#endif
} af;
};
typedef struct HB_Anchor_ HB_Anchor;
struct HB_MarkRecord_
{
HB_UShort Class; /* mark class */
HB_Anchor MarkAnchor; /* anchor table */
};
typedef struct HB_MarkRecord_ HB_MarkRecord;
struct HB_MarkArray_
{
HB_UShort MarkCount; /* number of MarkRecord tables */
HB_MarkRecord* MarkRecord; /* array of MarkRecord tables */
};
typedef struct HB_MarkArray_ HB_MarkArray;
/* LookupType 1 */
struct HB_SinglePosFormat1_
{
HB_ValueRecord Value; /* ValueRecord for all covered
glyphs */
};
typedef struct HB_SinglePosFormat1_ HB_SinglePosFormat1;
struct HB_SinglePosFormat2_
{
HB_UShort ValueCount; /* number of ValueRecord tables */
HB_ValueRecord* Value; /* array of ValueRecord tables */
};
typedef struct HB_SinglePosFormat2_ HB_SinglePosFormat2;
struct HB_SinglePos_
{
HB_Byte PosFormat; /* 1 or 2 */
HB_Coverage Coverage; /* Coverage table */
HB_UShort ValueFormat; /* format of ValueRecord table */
union
{
HB_SinglePosFormat1 spf1;
HB_SinglePosFormat2 spf2;
} spf;
};
typedef struct HB_SinglePos_ HB_SinglePos;
/* LookupType 2 */
struct HB_PairValueRecord_
{
HB_UShort SecondGlyph; /* glyph ID for second glyph */
HB_ValueRecord Value1; /* pos. data for first glyph */
HB_ValueRecord Value2; /* pos. data for second glyph */
};
typedef struct HB_PairValueRecord_ HB_PairValueRecord;
struct HB_PairSet_
{
HB_UShort PairValueCount;
/* number of PairValueRecord tables */
HB_PairValueRecord* PairValueRecord;
/* array of PairValueRecord tables */
};
typedef struct HB_PairSet_ HB_PairSet;
struct HB_PairPosFormat1_
{
HB_UShort PairSetCount; /* number of PairSet tables */
HB_PairSet* PairSet; /* array of PairSet tables */
};
typedef struct HB_PairPosFormat1_ HB_PairPosFormat1;
struct HB_Class2Record_
{
HB_ValueRecord Value1; /* pos. data for first glyph */
HB_ValueRecord Value2; /* pos. data for second glyph */
};
typedef struct HB_Class2Record_ HB_Class2Record;
struct HB_Class1Record_
{
HB_Class2Record* Class2Record; /* array of Class2Record tables */
};
typedef struct HB_Class1Record_ HB_Class1Record;
struct HB_PairPosFormat2_
{
HB_ClassDefinition ClassDef1; /* class def. for first glyph */
HB_ClassDefinition ClassDef2; /* class def. for second glyph */
HB_UShort Class1Count; /* number of classes in ClassDef1
table */
HB_UShort Class2Count; /* number of classes in ClassDef2
table */
HB_Class1Record* Class1Record; /* array of Class1Record tables */
};
typedef struct HB_PairPosFormat2_ HB_PairPosFormat2;
struct HB_PairPos_
{
HB_Byte PosFormat; /* 1 or 2 */
HB_Coverage Coverage; /* Coverage table */
HB_UShort ValueFormat1; /* format of ValueRecord table
for first glyph */
HB_UShort ValueFormat2; /* format of ValueRecord table
for second glyph */
union
{
HB_PairPosFormat1 ppf1;
HB_PairPosFormat2 ppf2;
} ppf;
};
typedef struct HB_PairPos_ HB_PairPos;
/* LookupType 3 */
struct HB_EntryExitRecord_
{
HB_Anchor EntryAnchor; /* entry Anchor table */
HB_Anchor ExitAnchor; /* exit Anchor table */
};
typedef struct HB_EntryExitRecord_ HB_EntryExitRecord;
struct HB_CursivePos_
{
HB_UShort PosFormat; /* always 1 */
HB_Coverage Coverage; /* Coverage table */
HB_UShort EntryExitCount;
/* number of EntryExitRecord tables */
HB_EntryExitRecord* EntryExitRecord;
/* array of EntryExitRecord tables */
};
typedef struct HB_CursivePos_ HB_CursivePos;
/* LookupType 4 */
struct HB_BaseRecord_
{
HB_Anchor* BaseAnchor; /* array of base glyph anchor
tables */
};
typedef struct HB_BaseRecord_ HB_BaseRecord;
struct HB_BaseArray_
{
HB_UShort BaseCount; /* number of BaseRecord tables */
HB_BaseRecord* BaseRecord; /* array of BaseRecord tables */
};
typedef struct HB_BaseArray_ HB_BaseArray;
struct HB_MarkBasePos_
{
HB_UShort PosFormat; /* always 1 */
HB_Coverage MarkCoverage; /* mark glyph coverage table */
HB_Coverage BaseCoverage; /* base glyph coverage table */
HB_UShort ClassCount; /* number of mark classes */
HB_MarkArray MarkArray; /* mark array table */
HB_BaseArray BaseArray; /* base array table */
};
typedef struct HB_MarkBasePos_ HB_MarkBasePos;
/* LookupType 5 */
struct HB_ComponentRecord_
{
HB_Anchor* LigatureAnchor; /* array of ligature glyph anchor
tables */
};
typedef struct HB_ComponentRecord_ HB_ComponentRecord;
struct HB_LigatureAttach_
{
HB_UShort ComponentCount;
/* number of ComponentRecord tables */
HB_ComponentRecord* ComponentRecord;
/* array of ComponentRecord tables */
};
typedef struct HB_LigatureAttach_ HB_LigatureAttach;
struct HB_LigatureArray_
{
HB_UShort LigatureCount; /* number of LigatureAttach tables */
HB_LigatureAttach* LigatureAttach;
/* array of LigatureAttach tables */
};
typedef struct HB_LigatureArray_ HB_LigatureArray;
struct HB_MarkLigPos_
{
HB_UShort PosFormat; /* always 1 */
HB_Coverage MarkCoverage; /* mark glyph coverage table */
HB_Coverage LigatureCoverage;
/* ligature glyph coverage table */
HB_UShort ClassCount; /* number of mark classes */
HB_MarkArray MarkArray; /* mark array table */
HB_LigatureArray LigatureArray; /* ligature array table */
};
typedef struct HB_MarkLigPos_ HB_MarkLigPos;
/* LookupType 6 */
struct HB_Mark2Record_
{
HB_Anchor* Mark2Anchor; /* array of mark glyph anchor
tables */
};
typedef struct HB_Mark2Record_ HB_Mark2Record;
struct HB_Mark2Array_
{
HB_UShort Mark2Count; /* number of Mark2Record tables */
HB_Mark2Record* Mark2Record; /* array of Mark2Record tables */
};
typedef struct HB_Mark2Array_ HB_Mark2Array;
struct HB_MarkMarkPos_
{
HB_UShort PosFormat; /* always 1 */
HB_Coverage Mark1Coverage; /* first mark glyph coverage table */
HB_Coverage Mark2Coverage; /* second mark glyph coverave table */
HB_UShort ClassCount; /* number of combining mark classes */
HB_MarkArray Mark1Array; /* MarkArray table for first mark */
HB_Mark2Array Mark2Array; /* MarkArray table for second mark */
};
typedef struct HB_MarkMarkPos_ HB_MarkMarkPos;
/* needed by both lookup type 7 and 8 */
struct HB_PosLookupRecord_
{
HB_UShort SequenceIndex; /* index into current
glyph sequence */
HB_UShort LookupListIndex; /* Lookup to apply to that pos. */
};
typedef struct HB_PosLookupRecord_ HB_PosLookupRecord;
/* LookupType 7 */
struct HB_PosRule_
{
HB_UShort GlyphCount; /* total number of input glyphs */
HB_UShort PosCount; /* number of PosLookupRecord tables */
HB_UShort* Input; /* array of input glyph IDs */
HB_PosLookupRecord* PosLookupRecord;
/* array of PosLookupRecord tables */
};
typedef struct HB_PosRule_ HB_PosRule;
struct HB_PosRuleSet_
{
HB_UShort PosRuleCount; /* number of PosRule tables */
HB_PosRule* PosRule; /* array of PosRule tables */
};
typedef struct HB_PosRuleSet_ HB_PosRuleSet;
struct HB_ContextPosFormat1_
{
HB_Coverage Coverage; /* Coverage table */
HB_UShort PosRuleSetCount; /* number of PosRuleSet tables */
HB_PosRuleSet* PosRuleSet; /* array of PosRuleSet tables */
};
typedef struct HB_ContextPosFormat1_ HB_ContextPosFormat1;
struct HB_PosClassRule_
{
HB_UShort GlyphCount; /* total number of context classes */
HB_UShort PosCount; /* number of PosLookupRecord tables */
HB_UShort* Class; /* array of classes */
HB_PosLookupRecord* PosLookupRecord;
/* array of PosLookupRecord tables */
};
typedef struct HB_PosClassRule_ HB_PosClassRule;
struct HB_PosClassSet_
{
HB_UShort PosClassRuleCount;
/* number of PosClassRule tables */
HB_PosClassRule* PosClassRule; /* array of PosClassRule tables */
};
typedef struct HB_PosClassSet_ HB_PosClassSet;
/* The `MaxContextLength' field is not defined in the TTO specification
but simplifies the implementation of this format. It holds the
maximal context length used in the context rules. */
struct HB_ContextPosFormat2_
{
HB_UShort MaxContextLength;
/* maximal context length */
HB_Coverage Coverage; /* Coverage table */
HB_ClassDefinition ClassDef; /* ClassDef table */
HB_UShort PosClassSetCount;
/* number of PosClassSet tables */
HB_PosClassSet* PosClassSet; /* array of PosClassSet tables */
};
typedef struct HB_ContextPosFormat2_ HB_ContextPosFormat2;
struct HB_ContextPosFormat3_
{
HB_UShort GlyphCount; /* number of input glyphs */
HB_UShort PosCount; /* number of PosLookupRecord tables */
HB_Coverage* Coverage; /* array of Coverage tables */
HB_PosLookupRecord* PosLookupRecord;
/* array of PosLookupRecord tables */
};
typedef struct HB_ContextPosFormat3_ HB_ContextPosFormat3;
struct HB_ContextPos_
{
HB_Byte PosFormat; /* 1, 2, or 3 */
union
{
HB_ContextPosFormat1 cpf1;
HB_ContextPosFormat2 cpf2;
HB_ContextPosFormat3 cpf3;
} cpf;
};
typedef struct HB_ContextPos_ HB_ContextPos;
/* LookupType 8 */
struct HB_ChainPosRule_
{
HB_UShort* Backtrack; /* array of backtrack glyph IDs */
HB_UShort* Input; /* array of input glyph IDs */
HB_UShort* Lookahead; /* array of lookahead glyph IDs */
HB_PosLookupRecord* PosLookupRecord;
/* array of PosLookupRecords */
HB_UShort BacktrackGlyphCount;
/* total number of backtrack glyphs */
HB_UShort InputGlyphCount;
/* total number of input glyphs */
HB_UShort LookaheadGlyphCount;
/* total number of lookahead glyphs */
HB_UShort PosCount; /* number of PosLookupRecords */
};
typedef struct HB_ChainPosRule_ HB_ChainPosRule;
struct HB_ChainPosRuleSet_
{
HB_UShort ChainPosRuleCount;
/* number of ChainPosRule tables */
HB_ChainPosRule* ChainPosRule; /* array of ChainPosRule tables */
};
typedef struct HB_ChainPosRuleSet_ HB_ChainPosRuleSet;
struct HB_ChainContextPosFormat1_
{
HB_Coverage Coverage; /* Coverage table */
HB_UShort ChainPosRuleSetCount;
/* number of ChainPosRuleSet tables */
HB_ChainPosRuleSet* ChainPosRuleSet;
/* array of ChainPosRuleSet tables */
};
typedef struct HB_ChainContextPosFormat1_ HB_ChainContextPosFormat1;
struct HB_ChainPosClassRule_
{
HB_UShort* Backtrack; /* array of backtrack classes */
HB_UShort* Input; /* array of context classes */
HB_UShort* Lookahead; /* array of lookahead classes */
HB_PosLookupRecord* PosLookupRecord;
/* array of substitution lookups */
HB_UShort BacktrackGlyphCount;
/* total number of backtrack
classes */
HB_UShort InputGlyphCount;
/* total number of context classes */
HB_UShort LookaheadGlyphCount;
/* total number of lookahead
classes */
HB_UShort PosCount; /* number of PosLookupRecords */
};
typedef struct HB_ChainPosClassRule_ HB_ChainPosClassRule;
struct HB_ChainPosClassSet_
{
HB_UShort ChainPosClassRuleCount;
/* number of ChainPosClassRule
tables */
HB_ChainPosClassRule* ChainPosClassRule;
/* array of ChainPosClassRule
tables */
};
typedef struct HB_ChainPosClassSet_ HB_ChainPosClassSet;
/* The `MaxXXXLength' fields are not defined in the TTO specification
but simplifies the implementation of this format. It holds the
maximal context length used in the specific context rules. */
struct HB_ChainContextPosFormat2_
{
HB_Coverage Coverage; /* Coverage table */
HB_UShort MaxBacktrackLength;
/* maximal backtrack length */
HB_ClassDefinition BacktrackClassDef;
/* BacktrackClassDef table */
HB_UShort MaxInputLength;
/* maximal input length */
HB_ClassDefinition InputClassDef;
/* InputClassDef table */
HB_UShort MaxLookaheadLength;
/* maximal lookahead length */
HB_ClassDefinition LookaheadClassDef;
/* LookaheadClassDef table */
HB_UShort ChainPosClassSetCount;
/* number of ChainPosClassSet
tables */
HB_ChainPosClassSet* ChainPosClassSet;
/* array of ChainPosClassSet
tables */
};
typedef struct HB_ChainContextPosFormat2_ HB_ChainContextPosFormat2;
struct HB_ChainContextPosFormat3_
{
HB_UShort BacktrackGlyphCount;
/* number of backtrack glyphs */
HB_Coverage* BacktrackCoverage;
/* array of backtrack Coverage
tables */
HB_UShort InputGlyphCount;
/* number of input glyphs */
HB_Coverage* InputCoverage;
/* array of input coverage
tables */
HB_UShort LookaheadGlyphCount;
/* number of lookahead glyphs */
HB_Coverage* LookaheadCoverage;
/* array of lookahead coverage
tables */
HB_UShort PosCount; /* number of PosLookupRecords */
HB_PosLookupRecord* PosLookupRecord;
/* array of substitution lookups */
};
typedef struct HB_ChainContextPosFormat3_ HB_ChainContextPosFormat3;
struct HB_ChainContextPos_
{
HB_Byte PosFormat; /* 1, 2, or 3 */
union
{
HB_ChainContextPosFormat1 ccpf1;
HB_ChainContextPosFormat2 ccpf2;
HB_ChainContextPosFormat3 ccpf3;
} ccpf;
};
typedef struct HB_ChainContextPos_ HB_ChainContextPos;
#if 0
/* LookupType 10 */
struct HB_ExtensionPos_
{
HB_UShort PosFormat; /* always 1 */
HB_UShort LookuptType; /* lookup-type of referenced subtable */
HB_GPOS_SubTable *subtable; /* referenced subtable */
};
typedef struct HB_ExtensionPos_ HB_ExtensionPos;
#endif
union HB_GPOS_SubTable_
{
HB_SinglePos single;
HB_PairPos pair;
HB_CursivePos cursive;
HB_MarkBasePos markbase;
HB_MarkLigPos marklig;
HB_MarkMarkPos markmark;
HB_ContextPos context;
HB_ChainContextPos chain;
};
typedef union HB_GPOS_SubTable_ HB_GPOS_SubTable;
HB_INTERNAL HB_Error
_HB_GPOS_Load_SubTable( HB_GPOS_SubTable* st,
HB_Stream stream,
HB_UShort lookup_type );
HB_INTERNAL void
_HB_GPOS_Free_SubTable( HB_GPOS_SubTable* st,
HB_UShort lookup_type );
#ifdef HB_USE_PACKED_STRUCTS
#pragma pack(pop)
#endif
HB_END_HEADER
#endif /* HARFBUZZ_GPOS_PRIVATE_H */

File diff suppressed because it is too large Load diff

View file

@ -1,155 +0,0 @@
/*
* Copyright (C) 1998-2004 David Turner and Werner Lemberg
* Copyright (C) 2006 Behdad Esfahbod
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#ifndef HARFBUZZ_GPOS_H
#define HARFBUZZ_GPOS_H
#include "harfbuzz-gdef.h"
#include "harfbuzz-buffer.h"
HB_BEGIN_HEADER
/* Lookup types for glyph positioning */
#define HB_GPOS_LOOKUP_SINGLE 1
#define HB_GPOS_LOOKUP_PAIR 2
#define HB_GPOS_LOOKUP_CURSIVE 3
#define HB_GPOS_LOOKUP_MARKBASE 4
#define HB_GPOS_LOOKUP_MARKLIG 5
#define HB_GPOS_LOOKUP_MARKMARK 6
#define HB_GPOS_LOOKUP_CONTEXT 7
#define HB_GPOS_LOOKUP_CHAIN 8
#define HB_GPOS_LOOKUP_EXTENSION 9
#ifdef HB_SUPPORT_MULTIPLE_MASTER
/* A pointer to a function which accesses the PostScript interpreter.
Multiple Master fonts need this interface to convert a metric ID
(as stored in an OpenType font version 1.2 or higher) `metric_id'
into a metric value (returned in `metric_value').
`data' points to the user-defined structure specified during a
call to HB_GPOS_Register_MM_Function().
`metric_value' must be returned as a scaled value (but shouldn't
be rounded). */
typedef HB_Error (*HB_MMFunction)(HB_Font font,
HB_UShort metric_id,
HB_Fixed* metric_value,
void* data );
#endif
struct HB_GPOSHeader_
{
HB_16Dot16 Version;
HB_ScriptList ScriptList;
HB_FeatureList FeatureList;
HB_LookupList LookupList;
HB_GDEFHeader* gdef;
#ifdef HB_SUPPORT_MULTIPLE_MASTER
/* this is OpenType 1.2 -- Multiple Master fonts need this
callback function to get various metric values from the
PostScript interpreter. */
HB_MMFunction mmfunc;
void* data;
#endif
};
typedef struct HB_GPOSHeader_ HB_GPOSHeader;
typedef HB_GPOSHeader* HB_GPOS;
HB_Error HB_Load_GPOS_Table( HB_Stream stream,
HB_GPOSHeader** gpos,
HB_GDEFHeader* gdef,
HB_Stream gdefStream );
HB_Error HB_Done_GPOS_Table( HB_GPOSHeader* gpos );
HB_Error HB_GPOS_Select_Script( HB_GPOSHeader* gpos,
HB_UInt script_tag,
HB_UShort* script_index );
HB_Error HB_GPOS_Select_Language( HB_GPOSHeader* gpos,
HB_UInt language_tag,
HB_UShort script_index,
HB_UShort* language_index,
HB_UShort* req_feature_index );
HB_Error HB_GPOS_Select_Feature( HB_GPOSHeader* gpos,
HB_UInt feature_tag,
HB_UShort script_index,
HB_UShort language_index,
HB_UShort* feature_index );
HB_Error HB_GPOS_Query_Scripts( HB_GPOSHeader* gpos,
HB_UInt** script_tag_list );
HB_Error HB_GPOS_Query_Languages( HB_GPOSHeader* gpos,
HB_UShort script_index,
HB_UInt** language_tag_list );
HB_Error HB_GPOS_Query_Features( HB_GPOSHeader* gpos,
HB_UShort script_index,
HB_UShort language_index,
HB_UInt** feature_tag_list );
HB_Error HB_GPOS_Add_Feature( HB_GPOSHeader* gpos,
HB_UShort feature_index,
HB_UInt property );
HB_Error HB_GPOS_Clear_Features( HB_GPOSHeader* gpos );
#ifdef HB_SUPPORT_MULTIPLE_MASTER
HB_Error HB_GPOS_Register_MM_Function( HB_GPOSHeader* gpos,
HB_MMFunction mmfunc,
void* data );
#endif
/* If `dvi' is TRUE, glyph contour points for anchor points and device
tables are ignored -- you will get device independent values. */
HB_Error HB_GPOS_Apply_String( HB_Font font,
HB_GPOSHeader* gpos,
HB_UShort load_flags,
HB_Buffer buffer,
HB_Bool dvi,
HB_Bool r2l );
HB_END_HEADER
#endif /* HARFBUZZ_GPOS_H */

View file

@ -1,447 +0,0 @@
/*
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#include "harfbuzz-shaper.h"
#include "harfbuzz-shaper-private.h"
#include <assert.h>
#ifndef NO_OPENTYPE
static const HB_OpenTypeFeature greek_features[] = {
{ HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },
{ HB_MAKE_TAG('l', 'i', 'g', 'a'), CcmpProperty },
{ HB_MAKE_TAG('c', 'l', 'i', 'g'), CcmpProperty },
{0, 0}
};
#endif
/*
Greek decompositions
*/
typedef struct _hb_greek_decomposition {
HB_UChar16 composed;
HB_UChar16 base;
} hb_greek_decomposition;
static const hb_greek_decomposition decompose_0x300[] = {
{ 0x1FBA, 0x0391 },
{ 0x1FC8, 0x0395 },
{ 0x1FCA, 0x0397 },
{ 0x1FDA, 0x0399 },
{ 0x1FF8, 0x039F },
{ 0x1FEA, 0x03A5 },
{ 0x1FFA, 0x03A9 },
{ 0x1F70, 0x03B1 },
{ 0x1F72, 0x03B5 },
{ 0x1F74, 0x03B7 },
{ 0x1F76, 0x03B9 },
{ 0x1F78, 0x03BF },
{ 0x1F7A, 0x03C5 },
{ 0x1F7C, 0x03C9 },
{ 0x1FD2, 0x03CA },
{ 0x1FE2, 0x03CB },
{ 0x1F02, 0x1F00 },
{ 0, 0 }
};
static HB_UChar16 compose_0x300(HB_UChar16 base)
{
if ((base ^ 0x1f00) < 0x100) {
if (base <= 0x1f69 && !(base & 0x6))
return base + 2;
if (base == 0x1fbf)
return 0x1fcd;
if (base == 0x1ffe)
return 0x1fdd;
return 0;
}
{
const hb_greek_decomposition *d = decompose_0x300;
while (d->base && d->base != base)
++d;
return d->composed;
}
}
static const hb_greek_decomposition decompose_0x301[] = {
{ 0x0386, 0x0391 },
{ 0x0388, 0x0395 },
{ 0x0389, 0x0397 },
{ 0x038A, 0x0399 },
{ 0x038C, 0x039F },
{ 0x038E, 0x03A5 },
{ 0x038F, 0x03A9 },
{ 0x03AC, 0x03B1 },
{ 0x03AD, 0x03B5 },
{ 0x03AE, 0x03B7 },
{ 0x03AF, 0x03B9 },
{ 0x03CC, 0x03BF },
{ 0x03CD, 0x03C5 },
{ 0x03CE, 0x03C9 },
{ 0x0390, 0x03CA },
{ 0x03B0, 0x03CB },
{ 0x03D3, 0x03D2 },
{ 0, 0 }
};
static HB_UChar16 compose_0x301(HB_UChar16 base)
{
if ((base ^ 0x1f00) < 0x100) {
if (base <= 0x1f69 && !(base & 0x6))
return base + 4;
if (base == 0x1fbf)
return 0x1fce;
if (base == 0x1ffe)
return 0x1fde;
}
{
const hb_greek_decomposition *d = decompose_0x301;
while (d->base && d->base != base)
++d;
return d->composed;
}
}
static const hb_greek_decomposition decompose_0x304[] = {
{ 0x1FB9, 0x0391 },
{ 0x1FD9, 0x0399 },
{ 0x1FE9, 0x03A5 },
{ 0x1FB1, 0x03B1 },
{ 0x1FD1, 0x03B9 },
{ 0x1FE1, 0x03C5 },
{ 0, 0 }
};
static HB_UChar16 compose_0x304(HB_UChar16 base)
{
const hb_greek_decomposition *d = decompose_0x304;
while (d->base && d->base != base)
++d;
return d->composed;
}
static const hb_greek_decomposition decompose_0x306[] = {
{ 0x1FB8, 0x0391 },
{ 0x1FD8, 0x0399 },
{ 0x1FE8, 0x03A5 },
{ 0x1FB0, 0x03B1 },
{ 0x1FD0, 0x03B9 },
{ 0x1FE0, 0x03C5 },
{ 0, 0 }
};
static HB_UChar16 compose_0x306(HB_UChar16 base)
{
const hb_greek_decomposition *d = decompose_0x306;
while (d->base && d->base != base)
++d;
return d->composed;
}
static const hb_greek_decomposition decompose_0x308[] = {
{ 0x03AA, 0x0399 },
{ 0x03AB, 0x03A5 },
{ 0x03CA, 0x03B9 },
{ 0x03CB, 0x03C5 },
{ 0x03D4, 0x03D2 },
{ 0, 0 }
};
static HB_UChar16 compose_0x308(HB_UChar16 base)
{
const hb_greek_decomposition *d = decompose_0x308;
while (d->base && d->base != base)
++d;
return d->composed;
}
static const hb_greek_decomposition decompose_0x313[] = {
{ 0x1F08, 0x0391 },
{ 0x1F18, 0x0395 },
{ 0x1F28, 0x0397 },
{ 0x1F38, 0x0399 },
{ 0x1F48, 0x039F },
{ 0x1F68, 0x03A9 },
{ 0x1F00, 0x03B1 },
{ 0x1F10, 0x03B5 },
{ 0x1F20, 0x03B7 },
{ 0x1F30, 0x03B9 },
{ 0x1F40, 0x03BF },
{ 0x1FE4, 0x03C1 },
{ 0x1F50, 0x03C5 },
{ 0x1F60, 0x03C9 },
{ 0, 0 }
};
static HB_UChar16 compose_0x313(HB_UChar16 base)
{
const hb_greek_decomposition *d = decompose_0x313;
while (d->base && d->base != base)
++d;
return d->composed;
}
static const hb_greek_decomposition decompose_0x314[] = {
{ 0x1F09, 0x0391 },
{ 0x1F19, 0x0395 },
{ 0x1F29, 0x0397 },
{ 0x1F39, 0x0399 },
{ 0x1F49, 0x039F },
{ 0x1FEC, 0x03A1 },
{ 0x1F59, 0x03A5 },
{ 0x1F69, 0x03A9 },
{ 0x1F01, 0x03B1 },
{ 0x1F11, 0x03B5 },
{ 0x1F21, 0x03B7 },
{ 0x1F31, 0x03B9 },
{ 0x1F41, 0x03BF },
{ 0x1FE5, 0x03C1 },
{ 0x1F51, 0x03C5 },
{ 0x1F61, 0x03C9 },
{ 0, 0 }
};
static HB_UChar16 compose_0x314(HB_UChar16 base)
{
const hb_greek_decomposition *d = decompose_0x314;
while (d->base && d->base != base)
++d;
return d->composed;
}
static const hb_greek_decomposition decompose_0x342[] = {
{ 0x1FB6, 0x03B1 },
{ 0x1FC6, 0x03B7 },
{ 0x1FD6, 0x03B9 },
{ 0x1FE6, 0x03C5 },
{ 0x1FF6, 0x03C9 },
{ 0x1FD7, 0x03CA },
{ 0x1FE7, 0x03CB },
{ 0x1F06, 0x1F00 },
{ 0x1F07, 0x1F01 },
{ 0x1F0E, 0x1F08 },
{ 0x1F0F, 0x1F09 },
{ 0x1F26, 0x1F20 },
{ 0x1F27, 0x1F21 },
{ 0x1F2E, 0x1F28 },
{ 0x1F2F, 0x1F29 },
{ 0x1F36, 0x1F30 },
{ 0x1F37, 0x1F31 },
{ 0x1F3E, 0x1F38 },
{ 0x1F3F, 0x1F39 },
{ 0x1F56, 0x1F50 },
{ 0x1F57, 0x1F51 },
{ 0x1F5F, 0x1F59 },
{ 0x1F66, 0x1F60 },
{ 0x1F67, 0x1F61 },
{ 0x1F6E, 0x1F68 },
{ 0x1F6F, 0x1F69 },
{ 0x1FCF, 0x1FBF },
{ 0x1FDF, 0x1FFE },
{ 0, 0 }
};
static HB_UChar16 compose_0x342(HB_UChar16 base)
{
const hb_greek_decomposition *d = decompose_0x342;
while (d->base && d->base != base)
++d;
return d->composed;
}
static const hb_greek_decomposition decompose_0x345[] = {
{ 0x1FBC, 0x0391 },
{ 0x1FCC, 0x0397 },
{ 0x1FFC, 0x03A9 },
{ 0x1FB4, 0x03AC },
{ 0x1FC4, 0x03AE },
{ 0x1FB3, 0x03B1 },
{ 0x1FC3, 0x03B7 },
{ 0x1FF3, 0x03C9 },
{ 0x1FF4, 0x03CE },
{ 0x1F80, 0x1F00 },
{ 0x1F81, 0x1F01 },
{ 0x1F82, 0x1F02 },
{ 0x1F83, 0x1F03 },
{ 0x1F84, 0x1F04 },
{ 0x1F85, 0x1F05 },
{ 0x1F86, 0x1F06 },
{ 0x1F87, 0x1F07 },
{ 0x1F88, 0x1F08 },
{ 0x1F89, 0x1F09 },
{ 0x1F8A, 0x1F0A },
{ 0x1F8B, 0x1F0B },
{ 0x1F8C, 0x1F0C },
{ 0x1F8D, 0x1F0D },
{ 0x1F8E, 0x1F0E },
{ 0x1F8F, 0x1F0F },
{ 0x1F90, 0x1F20 },
{ 0x1F91, 0x1F21 },
{ 0x1F92, 0x1F22 },
{ 0x1F93, 0x1F23 },
{ 0x1F94, 0x1F24 },
{ 0x1F95, 0x1F25 },
{ 0x1F96, 0x1F26 },
{ 0x1F97, 0x1F27 },
{ 0x1F98, 0x1F28 },
{ 0x1F99, 0x1F29 },
{ 0x1F9A, 0x1F2A },
{ 0x1F9B, 0x1F2B },
{ 0x1F9C, 0x1F2C },
{ 0x1F9D, 0x1F2D },
{ 0x1F9E, 0x1F2E },
{ 0x1F9F, 0x1F2F },
{ 0x1FA0, 0x1F60 },
{ 0x1FA1, 0x1F61 },
{ 0x1FA2, 0x1F62 },
{ 0x1FA3, 0x1F63 },
{ 0x1FA4, 0x1F64 },
{ 0x1FA5, 0x1F65 },
{ 0x1FA6, 0x1F66 },
{ 0x1FA7, 0x1F67 },
{ 0x1FA8, 0x1F68 },
{ 0x1FA9, 0x1F69 },
{ 0x1FAA, 0x1F6A },
{ 0x1FAB, 0x1F6B },
{ 0x1FAC, 0x1F6C },
{ 0x1FAD, 0x1F6D },
{ 0x1FAE, 0x1F6E },
{ 0x1FAF, 0x1F6F },
{ 0x1FB2, 0x1F70 },
{ 0x1FC2, 0x1F74 },
{ 0x1FF2, 0x1F7C },
{ 0x1FB7, 0x1FB6 },
{ 0x1FC7, 0x1FC6 },
{ 0x1FF7, 0x1FF6 },
{ 0, 0 }
};
static HB_UChar16 compose_0x345(HB_UChar16 base)
{
const hb_greek_decomposition *d = decompose_0x345;
while (d->base && d->base != base)
++d;
return d->composed;
}
/*
Greek shaping. Heuristic positioning can't render polytonic greek correctly. We're a lot
better off mapping greek chars with diacritics to the characters in the extended greek
region in Unicode if possible.
*/
HB_Bool HB_GreekShape(HB_ShaperItem *shaper_item)
{
const int availableGlyphs = shaper_item->num_glyphs;
const HB_UChar16 *uc = shaper_item->string + shaper_item->item.pos;
unsigned short *logClusters = shaper_item->log_clusters;
HB_GlyphAttributes *attributes = shaper_item->attributes;
HB_Bool haveGlyphs;
int slen = 1;
int cluster_start = 0;
hb_uint32 i;
HB_STACKARRAY(HB_UChar16, shapedChars, 2 * shaper_item->item.length);
assert(shaper_item->item.script == HB_Script_Greek);
*shapedChars = *uc;
logClusters[0] = 0;
for (i = 1; i < shaper_item->item.length; ++i) {
hb_uint16 base = shapedChars[slen-1];
hb_uint16 shaped = 0;
if (uc[i] == 0x300)
shaped = compose_0x300(base);
else if (uc[i] == 0x301)
shaped = compose_0x301(base);
else if (uc[i] == 0x304)
shaped = compose_0x304(base);
else if (uc[i] == 0x306)
shaped = compose_0x306(base);
else if (uc[i] == 0x308)
shaped = compose_0x308(base);
else if (uc[i] == 0x313)
shaped = compose_0x313(base);
else if (uc[i] == 0x314)
shaped = compose_0x314(base);
else if (uc[i] == 0x342)
shaped = compose_0x342(base);
else if (uc[i] == 0x345)
shaped = compose_0x345(base);
if (shaped) {
if (shaper_item->font->klass->canRender(shaper_item->font, (HB_UChar16 *)&shaped, 1)) {
shapedChars[slen-1] = shaped;
} else {
shaped = 0;
}
}
if (!shaped) {
HB_CharCategory category;
int cmb;
shapedChars[slen] = uc[i];
HB_GetUnicodeCharProperties(shaper_item->ufuncs, uc[i], &category, &cmb);
if (category != HB_Mark_NonSpacing) {
attributes[slen].clusterStart = TRUE;
attributes[slen].mark = FALSE;
attributes[slen].combiningClass = 0;
attributes[slen].dontPrint = HB_IsControlChar(uc[i]);
cluster_start = slen;
} else {
attributes[slen].clusterStart = FALSE;
attributes[slen].mark = TRUE;
attributes[slen].combiningClass = cmb;
}
++slen;
}
logClusters[i] = cluster_start;
}
haveGlyphs = shaper_item->font->klass
->convertStringToGlyphIndices(shaper_item->font,
shapedChars, slen,
shaper_item->glyphs, &shaper_item->num_glyphs,
shaper_item->item.bidiLevel % 2);
HB_FREE_STACKARRAY(shapedChars);
if (!haveGlyphs)
return FALSE;
#ifndef NO_OPENTYPE
if (HB_SelectScript(shaper_item, greek_features)) {
HB_OpenTypeShape(shaper_item, /*properties*/0);
return HB_OpenTypePosition(shaper_item, availableGlyphs, /*doLogClusters*/TRUE);
}
#endif
HB_HeuristicPosition(shaper_item);
return TRUE;
}

View file

@ -1,483 +0,0 @@
/*
* Copyright (C) 1998-2004 David Turner and Werner Lemberg
* Copyright (C) 2006 Behdad Esfahbod
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#ifndef HARFBUZZ_GSUB_PRIVATE_H
#define HARFBUZZ_GSUB_PRIVATE_H
#include "harfbuzz-impl.h"
#include "harfbuzz-stream-private.h"
#include "harfbuzz-gsub.h"
HB_BEGIN_HEADER
#ifdef HB_USE_PACKED_STRUCTS
#pragma pack(push, 1)
#endif
typedef union HB_GSUB_SubTable_ HB_GSUB_SubTable;
/* LookupType 1 */
struct HB_SingleSubstFormat1_
{
HB_Short DeltaGlyphID; /* constant added to get
substitution glyph index */
};
typedef struct HB_SingleSubstFormat1_ HB_SingleSubstFormat1;
struct HB_SingleSubstFormat2_
{
HB_UShort* Substitute; /* array of substitute glyph IDs */
HB_UShort GlyphCount; /* number of glyph IDs in
Substitute array */
};
typedef struct HB_SingleSubstFormat2_ HB_SingleSubstFormat2;
struct HB_SingleSubst_
{
union
{
HB_SingleSubstFormat1 ssf1;
HB_SingleSubstFormat2 ssf2;
} ssf;
HB_Coverage Coverage; /* Coverage table */
HB_Byte SubstFormat; /* 1 or 2 */
};
typedef struct HB_SingleSubst_ HB_SingleSubst;
/* LookupType 2 */
struct HB_Sequence_
{
HB_UShort* Substitute; /* string of glyph IDs to
substitute */
HB_UShort GlyphCount; /* number of glyph IDs in the
Substitute array */
};
typedef struct HB_Sequence_ HB_Sequence;
struct HB_MultipleSubst_
{
HB_Sequence* Sequence; /* array of Sequence tables */
HB_Coverage Coverage; /* Coverage table */
HB_UShort SubstFormat; /* always 1 */
HB_UShort SequenceCount; /* number of Sequence tables */
};
typedef struct HB_MultipleSubst_ HB_MultipleSubst;
/* LookupType 3 */
struct HB_AlternateSet_
{
HB_UShort* Alternate; /* array of alternate glyph IDs */
HB_UShort GlyphCount; /* number of glyph IDs in the
Alternate array */
};
typedef struct HB_AlternateSet_ HB_AlternateSet;
struct HB_AlternateSubst_
{
HB_AlternateSet* AlternateSet; /* array of AlternateSet tables */
HB_Coverage Coverage; /* Coverage table */
HB_UShort SubstFormat; /* always 1 */
HB_UShort AlternateSetCount;
/* number of AlternateSet tables */
};
typedef struct HB_AlternateSubst_ HB_AlternateSubst;
/* LookupType 4 */
struct HB_Ligature_
{
HB_UShort* Component; /* array of component glyph IDs */
HB_UShort LigGlyph; /* glyphID of ligature
to substitute */
HB_UShort ComponentCount; /* number of components in ligature */
};
typedef struct HB_Ligature_ HB_Ligature;
struct HB_LigatureSet_
{
HB_Ligature* Ligature; /* array of Ligature tables */
HB_UShort LigatureCount; /* number of Ligature tables */
};
typedef struct HB_LigatureSet_ HB_LigatureSet;
struct HB_LigatureSubst_
{
HB_LigatureSet* LigatureSet; /* array of LigatureSet tables */
HB_Coverage Coverage; /* Coverage table */
HB_UShort SubstFormat; /* always 1 */
HB_UShort LigatureSetCount; /* number of LigatureSet tables */
};
typedef struct HB_LigatureSubst_ HB_LigatureSubst;
/* needed by both lookup type 5 and 6 */
struct HB_SubstLookupRecord_
{
HB_UShort SequenceIndex; /* index into current
glyph sequence */
HB_UShort LookupListIndex; /* Lookup to apply to that pos. */
};
typedef struct HB_SubstLookupRecord_ HB_SubstLookupRecord;
/* LookupType 5 */
struct HB_SubRule_
{
HB_UShort* Input; /* array of input glyph IDs */
HB_SubstLookupRecord* SubstLookupRecord;
/* array of SubstLookupRecord
tables */
HB_UShort GlyphCount; /* total number of input glyphs */
HB_UShort SubstCount; /* number of SubstLookupRecord
tables */
};
typedef struct HB_SubRule_ HB_SubRule;
struct HB_SubRuleSet_
{
HB_SubRule* SubRule; /* array of SubRule tables */
HB_UShort SubRuleCount; /* number of SubRule tables */
};
typedef struct HB_SubRuleSet_ HB_SubRuleSet;
struct HB_ContextSubstFormat1_
{
HB_SubRuleSet* SubRuleSet; /* array of SubRuleSet tables */
HB_Coverage Coverage; /* Coverage table */
HB_UShort SubRuleSetCount; /* number of SubRuleSet tables */
};
typedef struct HB_ContextSubstFormat1_ HB_ContextSubstFormat1;
struct HB_SubClassRule_
{
HB_UShort* Class; /* array of classes */
HB_SubstLookupRecord* SubstLookupRecord;
/* array of SubstLookupRecord
tables */
HB_UShort GlyphCount; /* total number of context classes */
HB_UShort SubstCount; /* number of SubstLookupRecord
tables */
};
typedef struct HB_SubClassRule_ HB_SubClassRule;
struct HB_SubClassSet_
{
HB_SubClassRule* SubClassRule; /* array of SubClassRule tables */
HB_UShort SubClassRuleCount;
/* number of SubClassRule tables */
};
typedef struct HB_SubClassSet_ HB_SubClassSet;
/* The `MaxContextLength' field is not defined in the TTO specification
but simplifies the implementation of this format. It holds the
maximal context length used in the context rules. */
struct HB_ContextSubstFormat2_
{
HB_SubClassSet* SubClassSet; /* array of SubClassSet tables */
HB_Coverage Coverage; /* Coverage table */
HB_ClassDefinition ClassDef; /* ClassDef table */
HB_UShort SubClassSetCount;
/* number of SubClassSet tables */
HB_UShort MaxContextLength;
/* maximal context length */
};
typedef struct HB_ContextSubstFormat2_ HB_ContextSubstFormat2;
struct HB_ContextSubstFormat3_
{
HB_Coverage* Coverage; /* array of Coverage tables */
HB_SubstLookupRecord* SubstLookupRecord;
/* array of substitution lookups */
HB_UShort GlyphCount; /* number of input glyphs */
HB_UShort SubstCount; /* number of SubstLookupRecords */
};
typedef struct HB_ContextSubstFormat3_ HB_ContextSubstFormat3;
struct HB_ContextSubst_
{
union
{
HB_ContextSubstFormat1 csf1;
HB_ContextSubstFormat2 csf2;
HB_ContextSubstFormat3 csf3;
} csf;
HB_Byte SubstFormat; /* 1, 2, or 3 */
};
typedef struct HB_ContextSubst_ HB_ContextSubst;
/* LookupType 6 */
struct HB_ChainSubRule_
{
HB_UShort* Backtrack; /* array of backtrack glyph IDs */
HB_UShort* Input; /* array of input glyph IDs */
HB_UShort* Lookahead; /* array of lookahead glyph IDs */
HB_SubstLookupRecord* SubstLookupRecord;
/* array of SubstLookupRecords */
HB_UShort BacktrackGlyphCount;
/* total number of backtrack glyphs */
HB_UShort InputGlyphCount;
/* total number of input glyphs */
HB_UShort LookaheadGlyphCount;
/* total number of lookahead glyphs */
HB_UShort SubstCount; /* number of SubstLookupRecords */
};
typedef struct HB_ChainSubRule_ HB_ChainSubRule;
struct HB_ChainSubRuleSet_
{
HB_ChainSubRule* ChainSubRule; /* array of ChainSubRule tables */
HB_UShort ChainSubRuleCount;
/* number of ChainSubRule tables */
};
typedef struct HB_ChainSubRuleSet_ HB_ChainSubRuleSet;
struct HB_ChainContextSubstFormat1_
{
HB_ChainSubRuleSet* ChainSubRuleSet;
/* array of ChainSubRuleSet tables */
HB_Coverage Coverage; /* Coverage table */
HB_UShort ChainSubRuleSetCount;
/* number of ChainSubRuleSet tables */
};
typedef struct HB_ChainContextSubstFormat1_ HB_ChainContextSubstFormat1;
struct HB_ChainSubClassRule_
{
HB_UShort* Backtrack; /* array of backtrack classes */
HB_UShort* Input; /* array of context classes */
HB_UShort* Lookahead; /* array of lookahead classes */
HB_SubstLookupRecord* SubstLookupRecord;
/* array of substitution lookups */
HB_UShort BacktrackGlyphCount;
/* total number of backtrack
classes */
HB_UShort InputGlyphCount;
/* total number of context classes */
HB_UShort LookaheadGlyphCount;
/* total number of lookahead
classes */
HB_UShort SubstCount; /* number of SubstLookupRecords */
};
typedef struct HB_ChainSubClassRule_ HB_ChainSubClassRule;
struct HB_ChainSubClassSet_
{
HB_ChainSubClassRule* ChainSubClassRule;
/* array of ChainSubClassRule
tables */
HB_UShort ChainSubClassRuleCount;
/* number of ChainSubClassRule
tables */
};
typedef struct HB_ChainSubClassSet_ HB_ChainSubClassSet;
/* The `MaxXXXLength' fields are not defined in the TTO specification
but simplifies the implementation of this format. It holds the
maximal context length used in the specific context rules. */
struct HB_ChainContextSubstFormat2_
{
HB_ChainSubClassSet* ChainSubClassSet;
/* array of ChainSubClassSet
tables */
HB_Coverage Coverage; /* Coverage table */
HB_ClassDefinition BacktrackClassDef;
/* BacktrackClassDef table */
HB_ClassDefinition InputClassDef;
/* InputClassDef table */
HB_ClassDefinition LookaheadClassDef;
/* LookaheadClassDef table */
HB_UShort ChainSubClassSetCount;
/* number of ChainSubClassSet
tables */
HB_UShort MaxBacktrackLength;
/* maximal backtrack length */
HB_UShort MaxLookaheadLength;
/* maximal lookahead length */
HB_UShort MaxInputLength;
/* maximal input length */
};
typedef struct HB_ChainContextSubstFormat2_ HB_ChainContextSubstFormat2;
struct HB_ChainContextSubstFormat3_
{
HB_Coverage* BacktrackCoverage;
/* array of backtrack Coverage
tables */
HB_Coverage* InputCoverage;
/* array of input coverage
tables */
HB_Coverage* LookaheadCoverage;
/* array of lookahead coverage
tables */
HB_SubstLookupRecord* SubstLookupRecord;
/* array of substitution lookups */
HB_UShort BacktrackGlyphCount;
/* number of backtrack glyphs */
HB_UShort InputGlyphCount;
/* number of input glyphs */
HB_UShort LookaheadGlyphCount;
/* number of lookahead glyphs */
HB_UShort SubstCount; /* number of SubstLookupRecords */
};
typedef struct HB_ChainContextSubstFormat3_ HB_ChainContextSubstFormat3;
struct HB_ChainContextSubst_
{
union
{
HB_ChainContextSubstFormat1 ccsf1;
HB_ChainContextSubstFormat2 ccsf2;
HB_ChainContextSubstFormat3 ccsf3;
} ccsf;
HB_Byte SubstFormat; /* 1, 2, or 3 */
};
typedef struct HB_ChainContextSubst_ HB_ChainContextSubst;
#if 0
/* LookupType 7 */
struct HB_ExtensionSubst_
{
HB_GSUB_SubTable *subtable; /* referenced subtable */
HB_UShort SubstFormat; /* always 1 */
HB_UShort LookuptType; /* lookup-type of referenced subtable */
};
typedef struct HB_ExtensionSubst_ HB_ExtensionSubst;
#endif
/* LookupType 8 */
struct HB_ReverseChainContextSubst_
{
HB_Coverage* LookaheadCoverage; /* array of lookahead Coverage
tables */
HB_UShort* Substitute; /* array of substitute Glyph ID */
HB_Coverage* BacktrackCoverage; /* array of backtrack Coverage
tables */
HB_Coverage Coverage; /* coverage table for input glyphs */
HB_UShort SubstFormat; /* always 1 */
HB_UShort BacktrackGlyphCount; /* number of backtrack glyphs */
HB_UShort LookaheadGlyphCount; /* number of lookahead glyphs */
HB_UShort GlyphCount; /* number of Glyph IDs */
};
typedef struct HB_ReverseChainContextSubst_ HB_ReverseChainContextSubst;
union HB_GSUB_SubTable_
{
HB_SingleSubst single;
HB_MultipleSubst multiple;
HB_AlternateSubst alternate;
HB_LigatureSubst ligature;
HB_ContextSubst context;
HB_ChainContextSubst chain;
HB_ReverseChainContextSubst reverse;
};
HB_INTERNAL HB_Error
_HB_GSUB_Load_SubTable( HB_GSUB_SubTable* st,
HB_Stream stream,
HB_UShort lookup_type );
HB_INTERNAL void
_HB_GSUB_Free_SubTable( HB_GSUB_SubTable* st,
HB_UShort lookup_type );
#ifdef HB_USE_PACKED_STRUCTS
#pragma pack(pop)
#endif
HB_END_HEADER
#endif /* HARFBUZZ_GSUB_PRIVATE_H */

File diff suppressed because it is too large Load diff

View file

@ -1,148 +0,0 @@
/*
* Copyright (C) 1998-2004 David Turner and Werner Lemberg
* Copyright (C) 2006 Behdad Esfahbod
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#ifndef HARFBUZZ_GSUB_H
#define HARFBUZZ_GSUB_H
#include "harfbuzz-gdef.h"
#include "harfbuzz-buffer.h"
HB_BEGIN_HEADER
#ifdef HB_USE_PACKED_STRUCTS
#pragma pack(push, 1)
#endif
/* Lookup types for glyph substitution */
#define HB_GSUB_LOOKUP_SINGLE 1
#define HB_GSUB_LOOKUP_MULTIPLE 2
#define HB_GSUB_LOOKUP_ALTERNATE 3
#define HB_GSUB_LOOKUP_LIGATURE 4
#define HB_GSUB_LOOKUP_CONTEXT 5
#define HB_GSUB_LOOKUP_CHAIN 6
#define HB_GSUB_LOOKUP_EXTENSION 7
#define HB_GSUB_LOOKUP_REVERSE_CHAIN 8
/* A pointer to a function which selects the alternate glyph. `pos' is
the position of the glyph with index `glyphID', `num_alternates'
gives the number of alternates in the `alternates' array. `data'
points to the user-defined structure specified during a call to
HB_GSUB_Register_Alternate_Function(). The function must return an
index into the `alternates' array. */
typedef HB_UShort (*HB_AltFunction)(HB_UInt pos,
HB_UShort glyphID,
HB_UShort num_alternates,
HB_UShort* alternates,
void* data );
struct HB_GSUBHeader_
{
HB_GDEFHeader* gdef;
/* the next two fields are used for an alternate substitution callback
function to select the proper alternate glyph. */
void* data;
HB_AltFunction altfunc;
HB_UInt offset;
HB_16Dot16 Version;
HB_ScriptList ScriptList;
HB_FeatureList FeatureList;
HB_LookupList LookupList;
};
typedef struct HB_GSUBHeader_ HB_GSUBHeader;
typedef HB_GSUBHeader* HB_GSUB;
HB_Error HB_Load_GSUB_Table( HB_Stream stream,
HB_GSUBHeader** gsub,
HB_GDEFHeader* gdef,
HB_Stream gdefStream );
HB_Error HB_Done_GSUB_Table( HB_GSUBHeader* gsub );
HB_Error HB_GSUB_Select_Script( HB_GSUBHeader* gsub,
HB_UInt script_tag,
HB_UShort* script_index );
HB_Error HB_GSUB_Select_Language( HB_GSUBHeader* gsub,
HB_UInt language_tag,
HB_UShort script_index,
HB_UShort* language_index,
HB_UShort* req_feature_index );
HB_Error HB_GSUB_Select_Feature( HB_GSUBHeader* gsub,
HB_UInt feature_tag,
HB_UShort script_index,
HB_UShort language_index,
HB_UShort* feature_index );
HB_Error HB_GSUB_Query_Scripts( HB_GSUBHeader* gsub,
HB_UInt** script_tag_list );
HB_Error HB_GSUB_Query_Languages( HB_GSUBHeader* gsub,
HB_UShort script_index,
HB_UInt** language_tag_list );
HB_Error HB_GSUB_Query_Features( HB_GSUBHeader* gsub,
HB_UShort script_index,
HB_UShort language_index,
HB_UInt** feature_tag_list );
HB_Error HB_GSUB_Add_Feature( HB_GSUBHeader* gsub,
HB_UShort feature_index,
HB_UInt property );
HB_Error HB_GSUB_Clear_Features( HB_GSUBHeader* gsub );
HB_Error HB_GSUB_Register_Alternate_Function( HB_GSUBHeader* gsub,
HB_AltFunction altfunc,
void* data );
HB_Error HB_GSUB_Apply_String( HB_GSUBHeader* gsub,
HB_Buffer buffer );
#ifdef HB_USE_PACKED_STRUCTS
#pragma pack(pop)
#endif
HB_END_HEADER
#endif /* HARFBUZZ_GSUB_H */

View file

@ -1,268 +0,0 @@
/*
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#include "harfbuzz-shaper.h"
#include "harfbuzz-shaper-private.h"
#include <assert.h>
/*
// Hangul is a syllable based script. Unicode reserves a large range
// for precomposed hangul, where syllables are already precomposed to
// their final glyph shape. In addition, a so called jamo range is
// defined, that can be used to express old Hangul. Modern hangul
// syllables can also be expressed as jamo, and should be composed
// into syllables. The operation is rather simple and mathematical.
// Every hangul jamo is classified as being either a Leading consonant
// (L), and intermediat Vowel (V) or a trailing consonant (T). Modern
// hangul syllables (the ones in the precomposed area can be of type
// LV or LVT.
//
// Syllable breaks do _not_ occur between:
//
// L L, V or precomposed
// V, LV V, T
// LVT, T T
//
// A standard syllable is of the form L+V+T*. The above rules allow
// nonstandard syllables L*V*T*. To transform them into standard
// syllables fill characters L_f and V_f can be inserted.
*/
enum {
Hangul_SBase = 0xac00,
Hangul_LBase = 0x1100,
Hangul_VBase = 0x1161,
Hangul_TBase = 0x11a7,
Hangul_SCount = 11172,
Hangul_LCount = 19,
Hangul_VCount = 21,
Hangul_TCount = 28,
Hangul_NCount = 21*28
};
#define hangul_isPrecomposed(uc) \
(uc >= Hangul_SBase && uc < Hangul_SBase + Hangul_SCount)
#define hangul_isLV(uc) \
((uc - Hangul_SBase) % Hangul_TCount == 0)
typedef enum {
L,
V,
T,
LV,
LVT,
X
} HangulType;
static HangulType hangul_type(unsigned short uc) {
if (uc > Hangul_SBase && uc < Hangul_SBase + Hangul_SCount)
return hangul_isLV(uc) ? LV : LVT;
if (uc < Hangul_LBase || uc > 0x11ff)
return X;
if (uc < Hangul_VBase)
return L;
if (uc < Hangul_TBase)
return V;
return T;
}
static int hangul_nextSyllableBoundary(const HB_UChar16 *s, int start, int end)
{
const HB_UChar16 *uc = s + start;
HangulType state = hangul_type(*uc);
int pos = 1;
while (pos < end - start) {
HangulType newState = hangul_type(uc[pos]);
switch(newState) {
case X:
goto finish;
case L:
case V:
case T:
if (state > newState)
goto finish;
state = newState;
break;
case LV:
if (state > L)
goto finish;
state = V;
break;
case LVT:
if (state > L)
goto finish;
state = T;
}
++pos;
}
finish:
return start+pos;
}
#ifndef NO_OPENTYPE
static const HB_OpenTypeFeature hangul_features [] = {
{ HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },
{ HB_MAKE_TAG('l', 'j', 'm', 'o'), CcmpProperty },
{ HB_MAKE_TAG('v', 'j', 'm', 'o'), CcmpProperty },
{ HB_MAKE_TAG('t', 'j', 'm', 'o'), CcmpProperty },
{ 0, 0 }
};
#endif
static HB_Bool hangul_shape_syllable(HB_ShaperItem *item, HB_Bool openType)
{
const HB_UChar16 *ch = item->string + item->item.pos;
int len = item->item.length;
#ifndef NO_OPENTYPE
const int availableGlyphs = item->num_glyphs;
#endif
int i;
HB_UChar16 composed = 0;
/* see if we can compose the syllable into a modern hangul */
if (item->item.length == 2) {
int LIndex = ch[0] - Hangul_LBase;
int VIndex = ch[1] - Hangul_VBase;
if (LIndex >= 0 && LIndex < Hangul_LCount &&
VIndex >= 0 && VIndex < Hangul_VCount)
composed = (LIndex * Hangul_VCount + VIndex) * Hangul_TCount + Hangul_SBase;
} else if (item->item.length == 3) {
int LIndex = ch[0] - Hangul_LBase;
int VIndex = ch[1] - Hangul_VBase;
int TIndex = ch[2] - Hangul_TBase;
if (LIndex >= 0 && LIndex < Hangul_LCount &&
VIndex >= 0 && VIndex < Hangul_VCount &&
TIndex >= 0 && TIndex < Hangul_TCount)
composed = (LIndex * Hangul_VCount + VIndex) * Hangul_TCount + TIndex + Hangul_SBase;
}
/* if we have a modern hangul use the composed form */
if (composed) {
ch = &composed;
len = 1;
}
if (!item->font->klass->convertStringToGlyphIndices(item->font,
ch, len,
item->glyphs, &item->num_glyphs,
item->item.bidiLevel % 2))
return FALSE;
for (i = 0; i < len; i++) {
item->attributes[i].mark = FALSE;
item->attributes[i].clusterStart = FALSE;
item->attributes[i].justification = 0;
item->attributes[i].zeroWidth = FALSE;
/*IDEBUG(" %d: %4x", i, ch[i].unicode()); */
}
#ifndef NO_OPENTYPE
if (!composed && openType) {
HB_Bool positioned;
HB_STACKARRAY(unsigned short, logClusters, len);
for (i = 0; i < len; ++i)
logClusters[i] = i;
item->log_clusters = logClusters;
HB_OpenTypeShape(item, /*properties*/0);
positioned = HB_OpenTypePosition(item, availableGlyphs, /*doLogClusters*/FALSE);
HB_FREE_STACKARRAY(logClusters);
if (!positioned)
return FALSE;
} else {
HB_HeuristicPosition(item);
}
#endif
item->attributes[0].clusterStart = TRUE;
return TRUE;
}
HB_Bool HB_HangulShape(HB_ShaperItem *item)
{
const HB_UChar16 *uc = item->string + item->item.pos;
HB_Bool allPrecomposed = TRUE;
int i;
assert(item->item.script == HB_Script_Hangul);
for (i = 0; i < (int)item->item.length; ++i) {
if (!hangul_isPrecomposed(uc[i])) {
allPrecomposed = FALSE;
break;
}
}
if (!allPrecomposed) {
HB_Bool openType = FALSE;
unsigned short *logClusters = item->log_clusters;
HB_ShaperItem syllable;
int first_glyph = 0;
int sstart = item->item.pos;
int end = sstart + item->item.length;
#ifndef NO_OPENTYPE
openType = HB_SelectScript(item, hangul_features);
#endif
syllable = *item;
while (sstart < end) {
int send = hangul_nextSyllableBoundary(item->string, sstart, end);
syllable.item.pos = sstart;
syllable.item.length = send-sstart;
syllable.glyphs = item->glyphs + first_glyph;
syllable.attributes = item->attributes + first_glyph;
syllable.offsets = item->offsets + first_glyph;
syllable.advances = item->advances + first_glyph;
syllable.num_glyphs = item->num_glyphs - first_glyph;
if (!hangul_shape_syllable(&syllable, openType)) {
item->num_glyphs += syllable.num_glyphs;
return FALSE;
}
/* fix logcluster array */
for (i = sstart; i < send; ++i)
logClusters[i-item->item.pos] = first_glyph;
sstart = send;
first_glyph += syllable.num_glyphs;
}
item->num_glyphs = first_glyph;
return TRUE;
}
return HB_BasicShape(item);
}

View file

@ -1,187 +0,0 @@
/*
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#include "harfbuzz-shaper.h"
#include "harfbuzz-shaper-private.h"
#include <assert.h>
/*
// Uniscribe also defines dlig for Hebrew, but we leave this out for now, as it's mostly
// ligatures one does not want in modern Hebrew (as lam-alef ligatures).
*/
#ifndef NO_OPENTYPE
static const HB_OpenTypeFeature hebrew_features[] = {
{ HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },
{0, 0}
};
#endif
/* Hebrew shaping. In the non opentype case we try to use the
presentation forms specified for Hebrew. Especially for the
ligatures with Dagesh this gives much better results than we could
achieve manually.
*/
HB_Bool HB_HebrewShape(HB_ShaperItem *shaper_item)
{
enum {
Dagesh = 0x5bc,
ShinDot = 0x5c1,
SinDot = 0x5c2,
Patah = 0x5b7,
Qamats = 0x5b8,
Holam = 0x5b9,
Rafe = 0x5bf
};
assert(shaper_item->item.script == HB_Script_Hebrew);
#ifndef NO_OPENTYPE
if (HB_SelectScript(shaper_item, hebrew_features)) {
const int availableGlyphs = shaper_item->num_glyphs;
if (!HB_ConvertStringToGlyphIndices(shaper_item))
return FALSE;
HB_HeuristicSetGlyphAttributes(shaper_item);
HB_OpenTypeShape(shaper_item, /*properties*/0);
return HB_OpenTypePosition(shaper_item, availableGlyphs, /*doLogClusters*/TRUE);
}
#endif
{
const HB_UChar16 *uc = shaper_item->string + shaper_item->item.pos;
unsigned short *logClusters = shaper_item->log_clusters;
HB_GlyphAttributes *attributes = shaper_item->attributes;
HB_Bool haveGlyphs;
int slen = 1;
int cluster_start = 0;
hb_uint32 i;
HB_STACKARRAY(HB_UChar16, shapedChars, 2 * shaper_item->item.length);
*shapedChars = *uc;
logClusters[0] = 0;
for (i = 1; i < shaper_item->item.length; ++i) {
hb_uint16 base = shapedChars[cluster_start];
hb_uint16 shaped = 0;
HB_Bool invalid = FALSE;
if (uc[i] == Dagesh) {
if (base >= 0x5d0
&& base <= 0x5ea
&& base != 0x5d7
&& base != 0x5dd
&& base != 0x5df
&& base != 0x5e2
&& base != 0x5e5) {
shaped = base - 0x5d0 + 0xfb30;
} else if (base == 0xfb2a || base == 0xfb2b /* Shin with Shin or Sin dot */) {
shaped = base + 2;
} else {
invalid = TRUE;
}
} else if (uc[i] == ShinDot) {
if (base == 0x05e9)
shaped = 0xfb2a;
else if (base == 0xfb49)
shaped = 0xfb2c;
else
invalid = TRUE;
} else if (uc[i] == SinDot) {
if (base == 0x05e9)
shaped = 0xfb2b;
else if (base == 0xfb49)
shaped = 0xfb2d;
else
invalid = TRUE;
} else if (uc[i] == Patah) {
if (base == 0x5d0)
shaped = 0xfb2e;
} else if (uc[i] == Qamats) {
if (base == 0x5d0)
shaped = 0xfb2f;
} else if (uc[i] == Holam) {
if (base == 0x5d5)
shaped = 0xfb4b;
} else if (uc[i] == Rafe) {
if (base == 0x5d1)
shaped = 0xfb4c;
else if (base == 0x5db)
shaped = 0xfb4d;
else if (base == 0x5e4)
shaped = 0xfb4e;
}
if (invalid) {
shapedChars[slen] = 0x25cc;
attributes[slen].clusterStart = TRUE;
attributes[slen].mark = FALSE;
attributes[slen].combiningClass = 0;
cluster_start = slen;
++slen;
}
if (shaped) {
if (shaper_item->font->klass->canRender(shaper_item->font, (HB_UChar16 *)&shaped, 1)) {
shapedChars[cluster_start] = shaped;
} else
shaped = 0;
}
if (!shaped) {
HB_CharCategory category;
int cmb;
shapedChars[slen] = uc[i];
HB_GetUnicodeCharProperties(shaper_item->ufuncs, uc[i], &category, &cmb);
if (category != HB_Mark_NonSpacing) {
attributes[slen].clusterStart = TRUE;
attributes[slen].mark = FALSE;
attributes[slen].combiningClass = 0;
attributes[slen].dontPrint = HB_IsControlChar(uc[i]);
cluster_start = slen;
} else {
attributes[slen].clusterStart = FALSE;
attributes[slen].mark = TRUE;
attributes[slen].combiningClass = cmb;
}
++slen;
}
logClusters[i] = cluster_start;
}
haveGlyphs = shaper_item->font->klass
->convertStringToGlyphIndices(shaper_item->font,
shapedChars, slen,
shaper_item->glyphs, &shaper_item->num_glyphs,
shaper_item->item.bidiLevel % 2);
HB_FREE_STACKARRAY(shapedChars);
if (!haveGlyphs)
return FALSE;
HB_HeuristicPosition(shaper_item);
}
return TRUE;
}

View file

@ -1,84 +0,0 @@
/*
* Copyright (C) 1998-2004 David Turner and Werner Lemberg
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
* Copyright (C) 2007 Red Hat, Inc.
*
* This is part of HarfBuzz, an OpenType Layout engine 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
*/
#include "harfbuzz-impl.h"
HB_INTERNAL HB_Pointer
_hb_alloc(size_t size,
HB_Error *perror )
{
HB_Error error = (HB_Error)0;
HB_Pointer block = NULL;
if ( size > 0 )
{
block = calloc( 1, size );
if ( !block )
error = ERR(HB_Err_Out_Of_Memory);
}
*perror = error;
return block;
}
HB_INTERNAL HB_Pointer
_hb_realloc(HB_Pointer block,
size_t new_size,
HB_Error *perror )
{
HB_Pointer block2 = NULL;
HB_Error error = (HB_Error)0;
block2 = realloc( block, new_size );
if ( block2 == NULL && new_size != 0 )
error = ERR(HB_Err_Out_Of_Memory);
if ( !error )
block = block2;
*perror = error;
return block;
}
HB_INTERNAL void
_hb_free( HB_Pointer block )
{
if ( block )
free( block );
}
/* helper func to set a breakpoint on */
HB_INTERNAL HB_Error
_hb_err (HB_Error code)
{
return code;
}

View file

@ -1,135 +0,0 @@
/*
* Copyright (C) 1998-2004 David Turner and Werner Lemberg
* Copyright (C) 2006 Behdad Esfahbod
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#ifndef HARFBUZZ_IMPL_H
#define HARFBUZZ_IMPL_H
#include "harfbuzz-global.h"
#include <stdlib.h>
HB_BEGIN_HEADER
#ifndef HB_INTERNAL
# ifndef __MINGW32__
# define HB_INTERNAL __attribute__((__visibility__("hidden")))
# else
# define HB_INTERNAL
# endif
#endif
#ifndef NULL
# define NULL ((void *)0)
#endif
#ifndef FALSE
# define FALSE 0
#endif
#ifndef TRUE
# define TRUE 1
#endif
#ifndef TTAG_GDEF
# define TTAG_GDEF HB_MAKE_TAG( 'G', 'D', 'E', 'F' )
#endif
#ifndef TTAG_GPOS
# define TTAG_GPOS HB_MAKE_TAG( 'G', 'P', 'O', 'S' )
#endif
#ifndef TTAG_GSUB
# define TTAG_GSUB HB_MAKE_TAG( 'G', 'S', 'U', 'B' )
#endif
#ifndef HB_UNUSED
# define HB_UNUSED(arg) ((arg) = (arg))
#endif
#define HB_LIKELY(cond) (cond)
#define HB_UNLIKELY(cond) (cond)
#define ARRAY_LEN(Array) ((int)(sizeof (Array) / sizeof (Array)[0]))
#define HB_IsHighSurrogate(ucs) \
(((ucs) & 0xfc00) == 0xd800)
#define HB_IsLowSurrogate(ucs) \
(((ucs) & 0xfc00) == 0xdc00)
#define HB_SurrogateToUcs4(high, low) \
(((HB_UChar32)(high))<<10) + (low) - 0x35fdc00;
#define ALLOC(_ptr,_size) \
( (_ptr) = _hb_alloc( _size, &error ), error != 0 )
#define REALLOC(_ptr,_newsz) \
( (_ptr) = _hb_realloc( (_ptr), (_newsz), &error ), error != 0 )
#define FREE(_ptr) \
do { \
if ( (_ptr) ) \
{ \
_hb_free( _ptr ); \
_ptr = NULL; \
} \
} while (0)
#define ALLOC_ARRAY(_ptr,_count,_type) \
ALLOC(_ptr,(_count)*sizeof(_type))
#define REALLOC_ARRAY(_ptr,_newcnt,_type) \
REALLOC(_ptr,(_newcnt)*sizeof(_type))
#define MEM_Copy(dest,source,count) memcpy( (char*)(dest), (const char*)(source), (size_t)(count) )
#define ERR(err) _hb_err (err)
HB_INTERNAL HB_Pointer
_hb_alloc( size_t size,
HB_Error *perror_ );
HB_INTERNAL HB_Pointer
_hb_realloc( HB_Pointer block,
size_t new_size,
HB_Error *perror_ );
HB_INTERNAL void
_hb_free( HB_Pointer block );
/* helper func to set a breakpoint on */
HB_INTERNAL HB_Error
_hb_err (HB_Error code);
HB_END_HEADER
#endif /* HARFBUZZ_IMPL_H */

File diff suppressed because it is too large Load diff

View file

@ -1,642 +0,0 @@
/*
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#include "harfbuzz-shaper.h"
#include "harfbuzz-shaper-private.h"
#include <assert.h>
#include <stdio.h>
/*
// Vocabulary
// Base -> A consonant or an independent vowel in its full (not subscript) form. It is the
// center of the syllable, it can be surrounded by coeng (subscript) consonants, vowels,
// split vowels, signs... but there is only one base in a syllable, it has to be coded as
// the first character of the syllable.
// split vowel --> vowel that has two parts placed separately (e.g. Before and after the consonant).
// Khmer language has five of them. Khmer split vowels either have one part before the
// base and one after the base or they have a part before the base and a part above the base.
// The first part of all Khmer split vowels is the same character, identical to
// the glyph of Khmer dependent vowel SRA EI
// coeng --> modifier used in Khmer to construct coeng (subscript) consonants
// Differently than indian languages, the coeng modifies the consonant that follows it,
// not the one preceding it Each consonant has two forms, the base form and the subscript form
// the base form is the normal one (using the consonants code-point), the subscript form is
// displayed when the combination coeng + consonant is encountered.
// Consonant of type 1 -> A consonant which has subscript for that only occupies space under a base consonant
// Consonant of type 2.-> Its subscript form occupies space under and before the base (only one, RO)
// Consonant of Type 3 -> Its subscript form occupies space under and after the base (KHO, CHHO, THHO, BA, YO, SA)
// Consonant shifter -> Khmer has to series of consonants. The same dependent vowel has different sounds
// if it is attached to a consonant of the first series or a consonant of the second series
// Most consonants have an equivalent in the other series, but some of theme exist only in
// one series (for example SA). If we want to use the consonant SA with a vowel sound that
// can only be done with a vowel sound that corresponds to a vowel accompanying a consonant
// of the other series, then we need to use a consonant shifter: TRIISAP or MUSIKATOAN
// x17C9 y x17CA. TRIISAP changes a first series consonant to second series sound and
// MUSIKATOAN a second series consonant to have a first series vowel sound.
// Consonant shifter are both normally supercript marks, but, when they are followed by a
// superscript, they change shape and take the form of subscript dependent vowel SRA U.
// If they are in the same syllable as a coeng consonant, Unicode 3.0 says that they
// should be typed before the coeng. Unicode 4.0 breaks the standard and says that it should
// be placed after the coeng consonant.
// Dependent vowel -> In khmer dependent vowels can be placed above, below, before or after the base
// Each vowel has its own position. Only one vowel per syllable is allowed.
// Signs -> Khmer has above signs and post signs. Only one above sign and/or one post sign are
// Allowed in a syllable.
//
//
// order is important here! This order must be the same that is found in each horizontal
// line in the statetable for Khmer (see khmerStateTable) .
*/
enum KhmerCharClassValues {
CC_RESERVED = 0,
CC_CONSONANT = 1, /* Consonant of type 1 or independent vowel */
CC_CONSONANT2 = 2, /* Consonant of type 2 */
CC_CONSONANT3 = 3, /* Consonant of type 3 */
CC_ZERO_WIDTH_NJ_MARK = 4, /* Zero Width non joiner character (0x200C) */
CC_CONSONANT_SHIFTER = 5,
CC_ROBAT = 6, /* Khmer special diacritic accent -treated differently in state table */
CC_COENG = 7, /* Subscript consonant combining character */
CC_DEPENDENT_VOWEL = 8,
CC_SIGN_ABOVE = 9,
CC_SIGN_AFTER = 10,
CC_ZERO_WIDTH_J_MARK = 11, /* Zero width joiner character */
CC_COUNT = 12 /* This is the number of character classes */
};
enum KhmerCharClassFlags {
CF_CLASS_MASK = 0x0000FFFF,
CF_CONSONANT = 0x01000000, /* flag to speed up comparing */
CF_SPLIT_VOWEL = 0x02000000, /* flag for a split vowel -> the first part is added in front of the syllable */
CF_DOTTED_CIRCLE = 0x04000000, /* add a dotted circle if a character with this flag is the first in a syllable */
CF_COENG = 0x08000000, /* flag to speed up comparing */
CF_SHIFTER = 0x10000000, /* flag to speed up comparing */
CF_ABOVE_VOWEL = 0x20000000, /* flag to speed up comparing */
/* position flags */
CF_POS_BEFORE = 0x00080000,
CF_POS_BELOW = 0x00040000,
CF_POS_ABOVE = 0x00020000,
CF_POS_AFTER = 0x00010000,
CF_POS_MASK = 0x000f0000
};
/* Characters that get referred to by name */
enum KhmerChar {
C_SIGN_ZWNJ = 0x200C,
C_SIGN_ZWJ = 0x200D,
C_RO = 0x179A,
C_VOWEL_AA = 0x17B6,
C_SIGN_NIKAHIT = 0x17C6,
C_VOWEL_E = 0x17C1,
C_COENG = 0x17D2
};
/*
// simple classes, they are used in the statetable (in this file) to control the length of a syllable
// they are also used to know where a character should be placed (location in reference to the base character)
// and also to know if a character, when independently displayed, should be displayed with a dotted-circle to
// indicate error in syllable construction
*/
enum {
_xx = CC_RESERVED,
_sa = CC_SIGN_ABOVE | CF_DOTTED_CIRCLE | CF_POS_ABOVE,
_sp = CC_SIGN_AFTER | CF_DOTTED_CIRCLE| CF_POS_AFTER,
_c1 = CC_CONSONANT | CF_CONSONANT,
_c2 = CC_CONSONANT2 | CF_CONSONANT,
_c3 = CC_CONSONANT3 | CF_CONSONANT,
_rb = CC_ROBAT | CF_POS_ABOVE | CF_DOTTED_CIRCLE,
_cs = CC_CONSONANT_SHIFTER | CF_DOTTED_CIRCLE | CF_SHIFTER,
_dl = CC_DEPENDENT_VOWEL | CF_POS_BEFORE | CF_DOTTED_CIRCLE,
_db = CC_DEPENDENT_VOWEL | CF_POS_BELOW | CF_DOTTED_CIRCLE,
_da = CC_DEPENDENT_VOWEL | CF_POS_ABOVE | CF_DOTTED_CIRCLE | CF_ABOVE_VOWEL,
_dr = CC_DEPENDENT_VOWEL | CF_POS_AFTER | CF_DOTTED_CIRCLE,
_co = CC_COENG | CF_COENG | CF_DOTTED_CIRCLE,
/* split vowel */
_va = _da | CF_SPLIT_VOWEL,
_vr = _dr | CF_SPLIT_VOWEL
};
/*
// Character class: a character class value
// ORed with character class flags.
*/
typedef unsigned long KhmerCharClass;
/*
// Character class tables
// _xx character does not combine into syllable, such as numbers, puntuation marks, non-Khmer signs...
// _sa Sign placed above the base
// _sp Sign placed after the base
// _c1 Consonant of type 1 or independent vowel (independent vowels behave as type 1 consonants)
// _c2 Consonant of type 2 (only RO)
// _c3 Consonant of type 3
// _rb Khmer sign robat u17CC. combining mark for subscript consonants
// _cd Consonant-shifter
// _dl Dependent vowel placed before the base (left of the base)
// _db Dependent vowel placed below the base
// _da Dependent vowel placed above the base
// _dr Dependent vowel placed behind the base (right of the base)
// _co Khmer combining mark COENG u17D2, combines with the consonant or independent vowel following
// it to create a subscript consonant or independent vowel
// _va Khmer split vowel in which the first part is before the base and the second one above the base
// _vr Khmer split vowel in which the first part is before the base and the second one behind (right of) the base
*/
static const KhmerCharClass khmerCharClasses[] = {
_c1, _c1, _c1, _c3, _c1, _c1, _c1, _c1, _c3, _c1, _c1, _c1, _c1, _c3, _c1, _c1, /* 1780 - 178F */
_c1, _c1, _c1, _c1, _c3, _c1, _c1, _c1, _c1, _c3, _c2, _c1, _c1, _c1, _c3, _c3, /* 1790 - 179F */
_c1, _c3, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, /* 17A0 - 17AF */
_c1, _c1, _c1, _c1, _dr, _dr, _dr, _da, _da, _da, _da, _db, _db, _db, _va, _vr, /* 17B0 - 17BF */
_vr, _dl, _dl, _dl, _vr, _vr, _sa, _sp, _sp, _cs, _cs, _sa, _rb, _sa, _sa, _sa, /* 17C0 - 17CF */
_sa, _sa, _co, _sa, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _sa, _xx, _xx /* 17D0 - 17DF */
};
/* this enum must reflect the range of khmerCharClasses */
enum KhmerCharClassesRange {
KhmerFirstChar = 0x1780,
KhmerLastChar = 0x17df
};
/*
// Below we define how a character in the input string is either in the khmerCharClasses table
// (in which case we get its type back), a ZWJ or ZWNJ (two characters that may appear
// within the syllable, but are not in the table) we also get their type back, or an unknown object
// in which case we get _xx (CC_RESERVED) back
*/
static KhmerCharClass getKhmerCharClass(HB_UChar16 uc)
{
if (uc == C_SIGN_ZWJ) {
return CC_ZERO_WIDTH_J_MARK;
}
if (uc == C_SIGN_ZWNJ) {
return CC_ZERO_WIDTH_NJ_MARK;
}
if (uc < KhmerFirstChar || uc > KhmerLastChar) {
return CC_RESERVED;
}
return khmerCharClasses[uc - KhmerFirstChar];
}
/*
// The stateTable is used to calculate the end (the length) of a well
// formed Khmer Syllable.
//
// Each horizontal line is ordered exactly the same way as the values in KhmerClassTable
// CharClassValues. This coincidence of values allows the follow up of the table.
//
// Each line corresponds to a state, which does not necessarily need to be a type
// of component... for example, state 2 is a base, with is always a first character
// in the syllable, but the state could be produced a consonant of any type when
// it is the first character that is analysed (in ground state).
//
// Differentiating 3 types of consonants is necessary in order to
// forbid the use of certain combinations, such as having a second
// coeng after a coeng RO,
// The inexistent possibility of having a type 3 after another type 3 is permitted,
// eliminating it would very much complicate the table, and it does not create typing
// problems, as the case above.
//
// The table is quite complex, in order to limit the number of coeng consonants
// to 2 (by means of the table).
//
// There a peculiarity, as far as Unicode is concerned:
// - The consonant-shifter is considered in two possible different
// locations, the one considered in Unicode 3.0 and the one considered in
// Unicode 4.0. (there is a backwards compatibility problem in this standard).
//
//
// xx independent character, such as a number, punctuation sign or non-khmer char
//
// c1 Khmer consonant of type 1 or an independent vowel
// that is, a letter in which the subscript for is only under the
// base, not taking any space to the right or to the left
//
// c2 Khmer consonant of type 2, the coeng form takes space under
// and to the left of the base (only RO is of this type)
//
// c3 Khmer consonant of type 3. Its subscript form takes space under
// and to the right of the base.
//
// cs Khmer consonant shifter
//
// rb Khmer robat
//
// co coeng character (u17D2)
//
// dv dependent vowel (including split vowels, they are treated in the same way).
// even if dv is not defined above, the component that is really tested for is
// KhmerClassTable::CC_DEPENDENT_VOWEL, which is common to all dependent vowels
//
// zwj Zero Width joiner
//
// zwnj Zero width non joiner
//
// sa above sign
//
// sp post sign
//
// there are lines with equal content but for an easier understanding
// (and maybe change in the future) we did not join them
*/
static const signed char khmerStateTable[][CC_COUNT] =
{
/* xx c1 c2 c3 zwnj cs rb co dv sa sp zwj */
{ 1, 2, 2, 2, 1, 1, 1, 6, 1, 1, 1, 2}, /* 0 - ground state */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 1 - exit state (or sign to the right of the syllable) */
{-1, -1, -1, -1, 3, 4, 5, 6, 16, 17, 1, -1}, /* 2 - Base consonant */
{-1, -1, -1, -1, -1, 4, -1, -1, 16, -1, -1, -1}, /* 3 - First ZWNJ before a register shifter It can only be followed by a shifter or a vowel */
{-1, -1, -1, -1, 15, -1, -1, 6, 16, 17, 1, 14}, /* 4 - First register shifter */
{-1, -1, -1, -1, -1, -1, -1, -1, 20, -1, 1, -1}, /* 5 - Robat */
{-1, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1}, /* 6 - First Coeng */
{-1, -1, -1, -1, 12, 13, -1, 10, 16, 17, 1, 14}, /* 7 - First consonant of type 1 after coeng */
{-1, -1, -1, -1, 12, 13, -1, -1, 16, 17, 1, 14}, /* 8 - First consonant of type 2 after coeng */
{-1, -1, -1, -1, 12, 13, -1, 10, 16, 17, 1, 14}, /* 9 - First consonant or type 3 after ceong */
{-1, 11, 11, 11, -1, -1, -1, -1, -1, -1, -1, -1}, /* 10 - Second Coeng (no register shifter before) */
{-1, -1, -1, -1, 15, -1, -1, -1, 16, 17, 1, 14}, /* 11 - Second coeng consonant (or ind. vowel) no register shifter before */
{-1, -1, -1, -1, -1, 13, -1, -1, 16, -1, -1, -1}, /* 12 - Second ZWNJ before a register shifter */
{-1, -1, -1, -1, 15, -1, -1, -1, 16, 17, 1, 14}, /* 13 - Second register shifter */
{-1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1}, /* 14 - ZWJ before vowel */
{-1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1}, /* 15 - ZWNJ before vowel */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 1, 18}, /* 16 - dependent vowel */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 18}, /* 17 - sign above */
{-1, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1}, /* 18 - ZWJ after vowel */
{-1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 19 - Third coeng */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1}, /* 20 - dependent vowel after a Robat */
};
/* #define KHMER_DEBUG */
#ifdef KHMER_DEBUG
#define KHDEBUG qDebug
#else
#define KHDEBUG if(0) printf
#endif
/*
// Given an input string of characters and a location in which to start looking
// calculate, using the state table, which one is the last character of the syllable
// that starts in the starting position.
*/
static int khmer_nextSyllableBoundary(const HB_UChar16 *s, int start, int end, HB_Bool *invalid)
{
const HB_UChar16 *uc = s + start;
int state = 0;
int pos = start;
*invalid = FALSE;
while (pos < end) {
KhmerCharClass charClass = getKhmerCharClass(*uc);
if (pos == start) {
*invalid = (charClass > 0) && ! (charClass & CF_CONSONANT);
}
state = khmerStateTable[state][charClass & CF_CLASS_MASK];
KHDEBUG("state[%d]=%d class=%8lx (uc=%4x)", pos - start, state,
charClass, *uc );
if (state < 0) {
break;
}
++uc;
++pos;
}
return pos;
}
#ifndef NO_OPENTYPE
static const HB_OpenTypeFeature khmer_features[] = {
{ HB_MAKE_TAG( 'p', 'r', 'e', 'f' ), PreFormProperty },
{ HB_MAKE_TAG( 'b', 'l', 'w', 'f' ), BelowFormProperty },
{ HB_MAKE_TAG( 'a', 'b', 'v', 'f' ), AboveFormProperty },
{ HB_MAKE_TAG( 'p', 's', 't', 'f' ), PostFormProperty },
{ HB_MAKE_TAG( 'p', 'r', 'e', 's' ), PreSubstProperty },
{ HB_MAKE_TAG( 'b', 'l', 'w', 's' ), BelowSubstProperty },
{ HB_MAKE_TAG( 'a', 'b', 'v', 's' ), AboveSubstProperty },
{ HB_MAKE_TAG( 'p', 's', 't', 's' ), PostSubstProperty },
{ HB_MAKE_TAG( 'c', 'l', 'i', 'g' ), CligProperty },
{ 0, 0 }
};
#endif
static HB_Bool khmer_shape_syllable(HB_Bool openType, HB_ShaperItem *item)
{
/* KHDEBUG("syllable from %d len %d, str='%s'", item->from, item->length,
item->string->mid(item->from, item->length).toUtf8().data()); */
int len = 0;
int syllableEnd = item->item.pos + item->item.length;
unsigned short reordered[16];
unsigned char properties[16];
enum {
AboveForm = 0x01,
PreForm = 0x02,
PostForm = 0x04,
BelowForm = 0x08
};
#ifndef NO_OPENTYPE
const int availableGlyphs = item->num_glyphs;
#endif
int coengRo;
int i;
/* according to the specs this is the max length one can get
### the real value should be smaller */
assert(item->item.length < 13);
memset(properties, 0, 16*sizeof(unsigned char));
#ifdef KHMER_DEBUG
qDebug("original:");
for (int i = from; i < syllableEnd; i++) {
qDebug(" %d: %4x", i, string[i]);
}
#endif
/*
// write a pre vowel or the pre part of a split vowel first
// and look out for coeng + ro. RO is the only vowel of type 2, and
// therefore the only one that requires saving space before the base.
*/
coengRo = -1; /* There is no Coeng Ro, if found this value will change */
for (i = item->item.pos; i < syllableEnd; i += 1) {
KhmerCharClass charClass = getKhmerCharClass(item->string[i]);
/* if a split vowel, write the pre part. In Khmer the pre part
is the same for all split vowels, same glyph as pre vowel C_VOWEL_E */
if (charClass & CF_SPLIT_VOWEL) {
reordered[len] = C_VOWEL_E;
properties[len] = PreForm;
++len;
break; /* there can be only one vowel */
}
/* if a vowel with pos before write it out */
if (charClass & CF_POS_BEFORE) {
reordered[len] = item->string[i];
properties[len] = PreForm;
++len;
break; /* there can be only one vowel */
}
/* look for coeng + ro and remember position
works because coeng + ro is always in front of a vowel (if there is a vowel)
and because CC_CONSONANT2 is enough to identify it, as it is the only consonant
with this flag */
if ( (charClass & CF_COENG) && (i + 1 < syllableEnd) &&
( (getKhmerCharClass(item->string[i+1]) & CF_CLASS_MASK) == CC_CONSONANT2) ) {
coengRo = i;
}
}
/* write coeng + ro if found */
if (coengRo > -1) {
reordered[len] = C_COENG;
properties[len] = PreForm;
++len;
reordered[len] = C_RO;
properties[len] = PreForm;
++len;
}
/*
shall we add a dotted circle?
If in the position in which the base should be (first char in the string) there is
a character that has the Dotted circle flag (a character that cannot be a base)
then write a dotted circle */
if (getKhmerCharClass(item->string[item->item.pos]) & CF_DOTTED_CIRCLE) {
reordered[len] = C_DOTTED_CIRCLE;
++len;
}
/* copy what is left to the output, skipping before vowels and
coeng Ro if they are present */
for (i = item->item.pos; i < syllableEnd; i += 1) {
HB_UChar16 uc = item->string[i];
KhmerCharClass charClass = getKhmerCharClass(uc);
/* skip a before vowel, it was already processed */
if (charClass & CF_POS_BEFORE) {
continue;
}
/* skip coeng + ro, it was already processed */
if (i == coengRo) {
i += 1;
continue;
}
switch (charClass & CF_POS_MASK)
{
case CF_POS_ABOVE :
reordered[len] = uc;
properties[len] = AboveForm;
++len;
break;
case CF_POS_AFTER :
reordered[len] = uc;
properties[len] = PostForm;
++len;
break;
case CF_POS_BELOW :
reordered[len] = uc;
properties[len] = BelowForm;
++len;
break;
default:
/* assign the correct flags to a coeng consonant
Consonants of type 3 are taged as Post forms and those type 1 as below forms */
if ( (charClass & CF_COENG) && i + 1 < syllableEnd ) {
unsigned char property = (getKhmerCharClass(item->string[i+1]) & CF_CLASS_MASK) == CC_CONSONANT3 ?
PostForm : BelowForm;
reordered[len] = uc;
properties[len] = property;
++len;
i += 1;
reordered[len] = item->string[i];
properties[len] = property;
++len;
break;
}
/* if a shifter is followed by an above vowel change the shifter to below form,
an above vowel can have two possible positions i + 1 or i + 3
(position i+1 corresponds to unicode 3, position i+3 to Unicode 4)
and there is an extra rule for C_VOWEL_AA + C_SIGN_NIKAHIT also for two
different positions, right after the shifter or after a vowel (Unicode 4) */
if ( (charClass & CF_SHIFTER) && (i + 1 < syllableEnd) ) {
if (getKhmerCharClass(item->string[i+1]) & CF_ABOVE_VOWEL ) {
reordered[len] = uc;
properties[len] = BelowForm;
++len;
break;
}
if (i + 2 < syllableEnd &&
(item->string[i+1] == C_VOWEL_AA) &&
(item->string[i+2] == C_SIGN_NIKAHIT) )
{
reordered[len] = uc;
properties[len] = BelowForm;
++len;
break;
}
if (i + 3 < syllableEnd && (getKhmerCharClass(item->string[i+3]) & CF_ABOVE_VOWEL) ) {
reordered[len] = uc;
properties[len] = BelowForm;
++len;
break;
}
if (i + 4 < syllableEnd &&
(item->string[i+3] == C_VOWEL_AA) &&
(item->string[i+4] == C_SIGN_NIKAHIT) )
{
reordered[len] = uc;
properties[len] = BelowForm;
++len;
break;
}
}
/* default - any other characters */
reordered[len] = uc;
++len;
break;
} /* switch */
} /* for */
if (!item->font->klass->convertStringToGlyphIndices(item->font,
reordered, len,
item->glyphs, &item->num_glyphs,
item->item.bidiLevel % 2))
return FALSE;
KHDEBUG("after shaping: len=%d", len);
for (i = 0; i < len; i++) {
item->attributes[i].mark = FALSE;
item->attributes[i].clusterStart = FALSE;
item->attributes[i].justification = 0;
item->attributes[i].zeroWidth = FALSE;
KHDEBUG(" %d: %4x property=%x", i, reordered[i], properties[i]);
}
/* now we have the syllable in the right order, and can start running it through open type. */
#ifndef NO_OPENTYPE
if (openType) {
hb_uint32 where[16];
for (i = 0; i < len; ++i) {
where[i] = ~(PreSubstProperty
| BelowSubstProperty
| AboveSubstProperty
| PostSubstProperty
| CligProperty
| PositioningProperties);
if (properties[i] == PreForm)
where[i] &= ~PreFormProperty;
else if (properties[i] == BelowForm)
where[i] &= ~BelowFormProperty;
else if (properties[i] == AboveForm)
where[i] &= ~AboveFormProperty;
else if (properties[i] == PostForm)
where[i] &= ~PostFormProperty;
}
HB_OpenTypeShape(item, where);
if (!HB_OpenTypePosition(item, availableGlyphs, /*doLogClusters*/FALSE))
return FALSE;
} else
#endif
{
KHDEBUG("Not using openType");
HB_HeuristicPosition(item);
}
item->attributes[0].clusterStart = TRUE;
return TRUE;
}
HB_Bool HB_KhmerShape(HB_ShaperItem *item)
{
HB_Bool openType = FALSE;
unsigned short *logClusters = item->log_clusters;
int i;
HB_ShaperItem syllable = *item;
int first_glyph = 0;
int sstart = item->item.pos;
int end = sstart + item->item.length;
assert(item->item.script == HB_Script_Khmer);
#ifndef NO_OPENTYPE
openType = HB_SelectScript(item, khmer_features);
#endif
KHDEBUG("khmer_shape: from %d length %d", item->item.pos, item->item.length);
while (sstart < end) {
HB_Bool invalid;
int send = khmer_nextSyllableBoundary(item->string, sstart, end, &invalid);
KHDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart,
invalid ? "TRUE" : "FALSE");
syllable.item.pos = sstart;
syllable.item.length = send-sstart;
syllable.glyphs = item->glyphs + first_glyph;
syllable.attributes = item->attributes + first_glyph;
syllable.offsets = item->offsets + first_glyph;
syllable.advances = item->advances + first_glyph;
syllable.num_glyphs = item->num_glyphs - first_glyph;
if (!khmer_shape_syllable(openType, &syllable)) {
KHDEBUG("syllable shaping failed, syllable requests %d glyphs", syllable.num_glyphs);
item->num_glyphs += syllable.num_glyphs;
return FALSE;
}
/* fix logcluster array */
KHDEBUG("syllable:");
for (i = first_glyph; i < first_glyph + (int)syllable.num_glyphs; ++i)
KHDEBUG(" %d -> glyph %x", i, item->glyphs[i]);
KHDEBUG(" logclusters:");
for (i = sstart; i < send; ++i) {
KHDEBUG(" %d -> glyph %d", i, first_glyph);
logClusters[i-item->item.pos] = first_glyph;
}
sstart = send;
first_glyph += syllable.num_glyphs;
}
item->num_glyphs = first_glyph;
return TRUE;
}

View file

@ -1,511 +0,0 @@
/*
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#include "harfbuzz-shaper.h"
#include "harfbuzz-shaper-private.h"
#include <assert.h>
#include <stdio.h>
enum MymrCharClassValues
{
Mymr_CC_RESERVED = 0,
Mymr_CC_CONSONANT = 1, /* Consonant of type 1, that has subscript form */
Mymr_CC_CONSONANT2 = 2, /* Consonant of type 2, that has no subscript form */
Mymr_CC_NGA = 3, /* Consonant NGA */
Mymr_CC_YA = 4, /* Consonant YA */
Mymr_CC_RA = 5, /* Consonant RA */
Mymr_CC_WA = 6, /* Consonant WA */
Mymr_CC_HA = 7, /* Consonant HA */
Mymr_CC_IND_VOWEL = 8, /* Independent vowel */
Mymr_CC_ZERO_WIDTH_NJ_MARK = 9, /* Zero Width non joiner character (0x200C) */
Mymr_CC_VIRAMA = 10, /* Subscript consonant combining character */
Mymr_CC_PRE_VOWEL = 11, /* Dependent vowel, prebase (Vowel e) */
Mymr_CC_BELOW_VOWEL = 12, /* Dependent vowel, prebase (Vowel u, uu) */
Mymr_CC_ABOVE_VOWEL = 13, /* Dependent vowel, prebase (Vowel i, ii, ai) */
Mymr_CC_POST_VOWEL = 14, /* Dependent vowel, prebase (Vowel aa) */
Mymr_CC_SIGN_ABOVE = 15,
Mymr_CC_SIGN_BELOW = 16,
Mymr_CC_SIGN_AFTER = 17,
Mymr_CC_ZERO_WIDTH_J_MARK = 18, /* Zero width joiner character */
Mymr_CC_COUNT = 19 /* This is the number of character classes */
};
enum MymrCharClassFlags
{
Mymr_CF_CLASS_MASK = 0x0000FFFF,
Mymr_CF_CONSONANT = 0x01000000, /* flag to speed up comparing */
Mymr_CF_MEDIAL = 0x02000000, /* flag to speed up comparing */
Mymr_CF_IND_VOWEL = 0x04000000, /* flag to speed up comparing */
Mymr_CF_DEP_VOWEL = 0x08000000, /* flag to speed up comparing */
Mymr_CF_DOTTED_CIRCLE = 0x10000000, /* add a dotted circle if a character with this flag is the first in a syllable */
Mymr_CF_VIRAMA = 0x20000000, /* flag to speed up comparing */
/* position flags */
Mymr_CF_POS_BEFORE = 0x00080000,
Mymr_CF_POS_BELOW = 0x00040000,
Mymr_CF_POS_ABOVE = 0x00020000,
Mymr_CF_POS_AFTER = 0x00010000,
Mymr_CF_POS_MASK = 0x000f0000,
Mymr_CF_AFTER_KINZI = 0x00100000
};
/* Characters that get refrered to by name */
enum MymrChar
{
Mymr_C_SIGN_ZWNJ = 0x200C,
Mymr_C_SIGN_ZWJ = 0x200D,
Mymr_C_DOTTED_CIRCLE = 0x25CC,
Mymr_C_RA = 0x101B,
Mymr_C_YA = 0x101A,
Mymr_C_NGA = 0x1004,
Mymr_C_VOWEL_E = 0x1031,
Mymr_C_VIRAMA = 0x1039
};
enum
{
Mymr_xx = Mymr_CC_RESERVED,
Mymr_c1 = Mymr_CC_CONSONANT | Mymr_CF_CONSONANT | Mymr_CF_POS_BELOW,
Mymr_c2 = Mymr_CC_CONSONANT2 | Mymr_CF_CONSONANT,
Mymr_ng = Mymr_CC_NGA | Mymr_CF_CONSONANT | Mymr_CF_POS_ABOVE,
Mymr_ya = Mymr_CC_YA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_AFTER | Mymr_CF_AFTER_KINZI,
Mymr_ra = Mymr_CC_RA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_BEFORE,
Mymr_wa = Mymr_CC_WA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_BELOW,
Mymr_ha = Mymr_CC_HA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_BELOW,
Mymr_id = Mymr_CC_IND_VOWEL | Mymr_CF_IND_VOWEL,
Mymr_vi = Mymr_CC_VIRAMA | Mymr_CF_VIRAMA | Mymr_CF_POS_ABOVE | Mymr_CF_DOTTED_CIRCLE,
Mymr_dl = Mymr_CC_PRE_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_BEFORE | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI,
Mymr_db = Mymr_CC_BELOW_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_BELOW | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI,
Mymr_da = Mymr_CC_ABOVE_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_ABOVE | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI,
Mymr_dr = Mymr_CC_POST_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_AFTER | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI,
Mymr_sa = Mymr_CC_SIGN_ABOVE | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_POS_ABOVE | Mymr_CF_AFTER_KINZI,
Mymr_sb = Mymr_CC_SIGN_BELOW | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_POS_BELOW | Mymr_CF_AFTER_KINZI,
Mymr_sp = Mymr_CC_SIGN_AFTER | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI
};
typedef int MymrCharClass;
static const MymrCharClass mymrCharClasses[] =
{
Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_ng, Mymr_c1, Mymr_c1, Mymr_c1,
Mymr_c1, Mymr_c1, Mymr_c2, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, /* 1000 - 100F */
Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1,
Mymr_c1, Mymr_c1, Mymr_ya, Mymr_ra, Mymr_c1, Mymr_wa, Mymr_c1, Mymr_ha, /* 1010 - 101F */
Mymr_c2, Mymr_c2, Mymr_xx, Mymr_id, Mymr_id, Mymr_id, Mymr_id, Mymr_id,
Mymr_xx, Mymr_id, Mymr_id, Mymr_xx, Mymr_dr, Mymr_da, Mymr_da, Mymr_db, /* 1020 - 102F */
Mymr_db, Mymr_dl, Mymr_da, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_sa, Mymr_sb,
Mymr_sp, Mymr_vi, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, /* 1030 - 103F */
Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx,
Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, /* 1040 - 104F */
Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx,
Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, /* 1050 - 105F */
};
static MymrCharClass
getMyanmarCharClass (HB_UChar16 ch)
{
if (ch == Mymr_C_SIGN_ZWJ)
return Mymr_CC_ZERO_WIDTH_J_MARK;
if (ch == Mymr_C_SIGN_ZWNJ)
return Mymr_CC_ZERO_WIDTH_NJ_MARK;
if (ch < 0x1000 || ch > 0x105f)
return Mymr_CC_RESERVED;
return mymrCharClasses[ch - 0x1000];
}
static const signed char mymrStateTable[][Mymr_CC_COUNT] =
{
/* xx c1, c2 ng ya ra wa ha id zwnj vi dl db da dr sa sb sp zwj */
{ 1, 4, 4, 2, 4, 4, 4, 4, 24, 1, 27, 17, 18, 19, 20, 21, 1, 1, 4}, /* 0 - ground state */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 1 - exit state (or sp to the right of the syllable) */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 17, 18, 19, 20, 21, -1, -1, 4}, /* 2 - NGA */
{-1, 4, 4, 4, 4, 4, 4, 4, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 3 - Virama after NGA */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, 17, 18, 19, 20, 21, 1, 1, -1}, /* 4 - Base consonant */
{-2, 6, -2, -2, 7, 8, 9, 10, -2, 23, -2, -2, -2, -2, -2, -2, -2, -2, -2}, /* 5 - First virama */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25, 17, 18, 19, 20, 21, -1, -1, -1}, /* 6 - c1 after virama */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, -1, -1}, /* 7 - ya after virama */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, -1, -1}, /* 8 - ra after virama */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, -1, -1}, /* 9 - wa after virama */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 18, 19, 20, 21, -1, -1, -1}, /* 10 - ha after virama */
{-1, -1, -1, -1, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 11 - Virama after NGA+zwj */
{-2, -2, -2, -2, -2, -2, 13, 14, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}, /* 12 - Second virama */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, 17, 18, 19, 20, 21, -1, -1, -1}, /* 13 - wa after virama */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 18, 19, 20, 21, -1, -1, -1}, /* 14 - ha after virama */
{-2, -2, -2, -2, -2, -2, -2, 16, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}, /* 15 - Third virama */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 18, 19, 20, 21, -1, -1, -1}, /* 16 - ha after virama */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, 21, 1, 1, -1}, /* 17 - dl, Dependent vowel e */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, -1, 21, 1, 1, -1}, /* 18 - db, Dependent vowel u,uu */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1}, /* 19 - da, Dependent vowel i,ii,ai */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, 1, 1, -1}, /* 20 - dr, Dependent vowel aa */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1}, /* 21 - sa, Sign anusvara */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 22 - atha */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1}, /* 23 - zwnj for atha */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1}, /* 24 - Independent vowel */
{-2, -2, -2, -2, 26, 26, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}, /* 25 - Virama after subscript consonant */
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, 1, -1}, /* 26 - ra/ya after subscript consonant + virama */
{-1, 6, -1, -1, 7, 8, 9, 10, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 - Virama after ground state */
/* exit state -2 is for invalid order of medials and combination of invalids
with virama where virama should treat as start of next syllable
*/
};
/*#define MYANMAR_DEBUG */
#ifdef MYANMAR_DEBUG
#define MMDEBUG qDebug
#else
#define MMDEBUG if(0) printf
#endif
/*
// Given an input string of characters and a location in which to start looking
// calculate, using the state table, which one is the last character of the syllable
// that starts in the starting position.
*/
static int myanmar_nextSyllableBoundary(const HB_UChar16 *s, int start, int end, HB_Bool *invalid)
{
const HB_UChar16 *uc = s + start;
int state = 0;
int pos = start;
*invalid = FALSE;
while (pos < end) {
MymrCharClass charClass = getMyanmarCharClass(*uc);
state = mymrStateTable[state][charClass & Mymr_CF_CLASS_MASK];
if (pos == start)
*invalid = (HB_Bool)(charClass & Mymr_CF_DOTTED_CIRCLE);
MMDEBUG("state[%d]=%d class=%8x (uc=%4x)", pos - start, state, charClass, *uc);
if (state < 0) {
if (state < -1)
--pos;
break;
}
++uc;
++pos;
}
return pos;
}
#ifndef NO_OPENTYPE
/* ###### might have to change order of above and below forms and substitutions,
but according to Unicode below comes before above */
static const HB_OpenTypeFeature myanmar_features[] = {
{ HB_MAKE_TAG('p', 'r', 'e', 'f'), PreFormProperty },
{ HB_MAKE_TAG('b', 'l', 'w', 'f'), BelowFormProperty },
{ HB_MAKE_TAG('a', 'b', 'v', 'f'), AboveFormProperty },
{ HB_MAKE_TAG('p', 's', 't', 'f'), PostFormProperty },
{ HB_MAKE_TAG('p', 'r', 'e', 's'), PreSubstProperty },
{ HB_MAKE_TAG('b', 'l', 'w', 's'), BelowSubstProperty },
{ HB_MAKE_TAG('a', 'b', 'v', 's'), AboveSubstProperty },
{ HB_MAKE_TAG('p', 's', 't', 's'), PostSubstProperty },
{ HB_MAKE_TAG('r', 'l', 'i', 'g'), CligProperty }, /* Myanmar1 uses this instead of the other features */
{ 0, 0 }
};
#endif
/*
// Visual order before shaping should be:
//
// [Vowel Mark E]
// [Virama + Medial Ra]
// [Base]
// [Virama + Consonant]
// [Nga + Virama] (Kinzi) ### should probably come before post forms (medial ya)
// [Vowels]
// [Marks]
//
// This means that we can keep the logical order apart from having to
// move the pre vowel, medial ra and kinzi
*/
static HB_Bool myanmar_shape_syllable(HB_Bool openType, HB_ShaperItem *item, HB_Bool invalid)
{
/*
// MMDEBUG("\nsyllable from %d len %d, str='%s'", item->item.pos, item->item.length,
// item->string->mid(item->from, item->length).toUtf8().data());
*/
#ifndef NO_OPENTYPE
const int availableGlyphs = item->num_glyphs;
#endif
const HB_UChar16 *uc = item->string + item->item.pos;
int vowel_e = -1;
int kinzi = -1;
int medial_ra = -1;
int base = -1;
int i;
int len = 0;
unsigned short reordered[32];
unsigned char properties[32];
enum {
AboveForm = 0x01,
PreForm = 0x02,
PostForm = 0x04,
BelowForm = 0x08
};
HB_Bool lastWasVirama = FALSE;
int basePos = -1;
memset(properties, 0, 32*sizeof(unsigned char));
/* according to the table the max length of a syllable should be around 14 chars */
assert(item->item.length < 32);
#ifdef MYANMAR_DEBUG
printf("original:");
for (i = 0; i < (int)item->item.length; i++) {
printf(" %d: %4x", i, uc[i]);
}
#endif
for (i = 0; i < (int)item->item.length; ++i) {
HB_UChar16 chr = uc[i];
if (chr == Mymr_C_VOWEL_E) {
vowel_e = i;
continue;
}
if (i == 0
&& chr == Mymr_C_NGA
&& i + 2 < (int)item->item.length
&& uc[i+1] == Mymr_C_VIRAMA) {
int mc = getMyanmarCharClass(uc[i+2]);
/*MMDEBUG("maybe kinzi: mc=%x", mc);*/
if ((mc & Mymr_CF_CONSONANT) == Mymr_CF_CONSONANT) {
kinzi = i;
continue;
}
}
if (base >= 0
&& chr == Mymr_C_VIRAMA
&& i + 1 < (int)item->item.length
&& uc[i+1] == Mymr_C_RA) {
medial_ra = i;
continue;
}
if (base < 0)
base = i;
}
MMDEBUG("\n base=%d, vowel_e=%d, kinzi=%d, medial_ra=%d", base, vowel_e, kinzi, medial_ra);
/* write vowel_e if found */
if (vowel_e >= 0) {
reordered[0] = Mymr_C_VOWEL_E;
len = 1;
}
/* write medial_ra */
if (medial_ra >= 0) {
reordered[len] = Mymr_C_VIRAMA;
reordered[len+1] = Mymr_C_RA;
properties[len] = PreForm;
properties[len+1] = PreForm;
len += 2;
}
/* shall we add a dotted circle?
If in the position in which the base should be (first char in the string) there is
a character that has the Dotted circle flag (a character that cannot be a base)
then write a dotted circle */
if (invalid) {
reordered[len] = C_DOTTED_CIRCLE;
++len;
}
/* copy the rest of the syllable to the output, inserting the kinzi
at the correct place */
for (i = 0; i < (int)item->item.length; ++i) {
hb_uint16 chr = uc[i];
MymrCharClass cc;
if (i == vowel_e)
continue;
if (i == medial_ra || i == kinzi) {
++i;
continue;
}
cc = getMyanmarCharClass(uc[i]);
if (kinzi >= 0 && i > base && (cc & Mymr_CF_AFTER_KINZI)) {
reordered[len] = Mymr_C_NGA;
reordered[len+1] = Mymr_C_VIRAMA;
if (len > 0)
properties[len-1] = AboveForm;
properties[len] = AboveForm;
len += 2;
kinzi = -1;
}
if (lastWasVirama) {
int prop = 0;
switch(cc & Mymr_CF_POS_MASK) {
case Mymr_CF_POS_BEFORE:
prop = PreForm;
break;
case Mymr_CF_POS_BELOW:
prop = BelowForm;
break;
case Mymr_CF_POS_ABOVE:
prop = AboveForm;
break;
case Mymr_CF_POS_AFTER:
prop = PostForm;
break;
default:
break;
}
properties[len-1] = prop;
properties[len] = prop;
if(basePos >= 0 && basePos == len-2)
properties[len-2] = prop;
}
lastWasVirama = (chr == Mymr_C_VIRAMA);
if(i == base)
basePos = len;
if ((chr != Mymr_C_SIGN_ZWNJ && chr != Mymr_C_SIGN_ZWJ) || !len) {
reordered[len] = chr;
++len;
}
}
if (kinzi >= 0) {
reordered[len] = Mymr_C_NGA;
reordered[len+1] = Mymr_C_VIRAMA;
properties[len] = AboveForm;
properties[len+1] = AboveForm;
len += 2;
}
if (!item->font->klass->convertStringToGlyphIndices(item->font,
reordered, len,
item->glyphs, &item->num_glyphs,
item->item.bidiLevel % 2))
return FALSE;
MMDEBUG("after shaping: len=%d", len);
for (i = 0; i < len; i++) {
item->attributes[i].mark = FALSE;
item->attributes[i].clusterStart = FALSE;
item->attributes[i].justification = 0;
item->attributes[i].zeroWidth = FALSE;
MMDEBUG(" %d: %4x property=%x", i, reordered[i], properties[i]);
}
/* now we have the syllable in the right order, and can start running it through open type. */
#ifndef NO_OPENTYPE
if (openType) {
hb_uint32 where[32];
for (i = 0; i < len; ++i) {
where[i] = ~(PreSubstProperty
| BelowSubstProperty
| AboveSubstProperty
| PostSubstProperty
| CligProperty
| PositioningProperties);
if (properties[i] & PreForm)
where[i] &= ~PreFormProperty;
if (properties[i] & BelowForm)
where[i] &= ~BelowFormProperty;
if (properties[i] & AboveForm)
where[i] &= ~AboveFormProperty;
if (properties[i] & PostForm)
where[i] &= ~PostFormProperty;
}
HB_OpenTypeShape(item, where);
if (!HB_OpenTypePosition(item, availableGlyphs, /*doLogClusters*/FALSE))
return FALSE;
} else
#endif
{
MMDEBUG("Not using openType");
HB_HeuristicPosition(item);
}
item->attributes[0].clusterStart = TRUE;
return TRUE;
}
HB_Bool HB_MyanmarShape(HB_ShaperItem *item)
{
HB_Bool openType = FALSE;
unsigned short *logClusters = item->log_clusters;
HB_ShaperItem syllable = *item;
int first_glyph = 0;
int sstart = item->item.pos;
int end = sstart + item->item.length;
int i = 0;
assert(item->item.script == HB_Script_Myanmar);
#ifndef NO_OPENTYPE
openType = HB_SelectScript(item, myanmar_features);
#endif
MMDEBUG("myanmar_shape: from %d length %d", item->item.pos, item->item.length);
while (sstart < end) {
HB_Bool invalid;
int send = myanmar_nextSyllableBoundary(item->string, sstart, end, &invalid);
MMDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart,
invalid ? "TRUE" : "FALSE");
syllable.item.pos = sstart;
syllable.item.length = send-sstart;
syllable.glyphs = item->glyphs + first_glyph;
syllable.attributes = item->attributes + first_glyph;
syllable.advances = item->advances + first_glyph;
syllable.offsets = item->offsets + first_glyph;
syllable.num_glyphs = item->num_glyphs - first_glyph;
if (!myanmar_shape_syllable(openType, &syllable, invalid)) {
MMDEBUG("syllable shaping failed, syllable requests %d glyphs", syllable.num_glyphs);
item->num_glyphs += syllable.num_glyphs;
return FALSE;
}
/* fix logcluster array */
MMDEBUG("syllable:");
for (i = first_glyph; i < first_glyph + (int)syllable.num_glyphs; ++i)
MMDEBUG(" %d -> glyph %x", i, item->glyphs[i]);
MMDEBUG(" logclusters:");
for (i = sstart; i < send; ++i) {
MMDEBUG(" %d -> glyph %d", i, first_glyph);
logClusters[i-item->item.pos] = first_glyph;
}
sstart = send;
first_glyph += syllable.num_glyphs;
}
item->num_glyphs = first_glyph;
return TRUE;
}

View file

@ -1,102 +0,0 @@
/*
* Copyright (C) 1998-2004 David Turner and Werner Lemberg
* Copyright (C) 2006 Behdad Esfahbod
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#ifndef HARFBUZZ_OPEN_PRIVATE_H
#define HARFBUZZ_OPEN_PRIVATE_H
#include "harfbuzz-impl.h"
#include "harfbuzz-open.h"
#include "harfbuzz-gsub-private.h"
#include "harfbuzz-gpos-private.h"
HB_BEGIN_HEADER
struct HB_SubTable_
{
union
{
HB_GSUB_SubTable gsub;
HB_GPOS_SubTable gpos;
} st;
};
HB_INTERNAL HB_Error
_HB_OPEN_Load_ScriptList( HB_ScriptList* sl,
HB_Stream input );
HB_INTERNAL HB_Error
_HB_OPEN_Load_FeatureList( HB_FeatureList* fl,
HB_Stream input );
HB_INTERNAL HB_Error
_HB_OPEN_Load_LookupList( HB_LookupList* ll,
HB_Stream input,
HB_Type type );
HB_INTERNAL HB_Error
_HB_OPEN_Load_Coverage( HB_Coverage* c,
HB_Stream input );
HB_INTERNAL HB_Error
_HB_OPEN_Load_ClassDefinition( HB_ClassDefinition* cd,
HB_UShort limit,
HB_Stream input );
HB_INTERNAL HB_Error
_HB_OPEN_Load_EmptyOrClassDefinition( HB_ClassDefinition* cd,
HB_UShort limit,
HB_UInt class_offset,
HB_UInt base_offset,
HB_Stream input );
HB_INTERNAL HB_Error
_HB_OPEN_Load_Device( HB_Device** d,
HB_Stream input );
HB_INTERNAL void _HB_OPEN_Free_ScriptList( HB_ScriptList* sl );
HB_INTERNAL void _HB_OPEN_Free_FeatureList( HB_FeatureList* fl );
HB_INTERNAL void _HB_OPEN_Free_LookupList( HB_LookupList* ll,
HB_Type type );
HB_INTERNAL void _HB_OPEN_Free_Coverage( HB_Coverage* c );
HB_INTERNAL void _HB_OPEN_Free_ClassDefinition( HB_ClassDefinition* cd );
HB_INTERNAL void _HB_OPEN_Free_Device( HB_Device* d );
HB_INTERNAL HB_Error
_HB_OPEN_Coverage_Index( HB_Coverage* c,
HB_UShort glyphID,
HB_UShort* index );
HB_INTERNAL HB_Error
_HB_OPEN_Get_Class( HB_ClassDefinition* cd,
HB_UShort glyphID,
HB_UShort* klass,
HB_UShort* index );
HB_INTERNAL HB_Error
_HB_OPEN_Get_Device( HB_Device* d,
HB_UShort size,
HB_Short* value );
HB_END_HEADER
#endif /* HARFBUZZ_OPEN_PRIVATE_H */

File diff suppressed because it is too large Load diff

View file

@ -1,288 +0,0 @@
/*
* Copyright (C) 1998-2004 David Turner and Werner Lemberg
* Copyright (C) 2006 Behdad Esfahbod
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#ifndef HARFBUZZ_OPEN_H
#define HARFBUZZ_OPEN_H
#include "harfbuzz-global.h"
HB_BEGIN_HEADER
#ifdef HB_USE_PACKED_STRUCTS
#pragma pack(push, 1)
#endif
/* Use this if a feature applies to all glyphs */
#define HB_ALL_GLYPHS 0xFFFF
#define HB_DEFAULT_LANGUAGE 0xFFFF
#define HB_MAX_NESTING_LEVEL 100
/* Script list related structures */
struct HB_LangSys_
{
HB_UShort* FeatureIndex; /* array of Feature indices */
HB_UShort LookupOrderOffset; /* always 0 for TT Open 1.0 */
HB_UShort ReqFeatureIndex; /* required FeatureIndex */
HB_UShort FeatureCount; /* number of Feature indices */
};
typedef struct HB_LangSys_ HB_LangSys;
struct HB_LangSysRecord_
{
HB_LangSys LangSys; /* LangSys table */
HB_UInt LangSysTag; /* LangSysTag identifier */
};
typedef struct HB_LangSysRecord_ HB_LangSysRecord;
struct HB_ScriptTable_
{
HB_LangSysRecord* LangSysRecord; /* array of LangSysRecords */
HB_LangSys DefaultLangSys; /* DefaultLangSys table */
HB_UShort LangSysCount; /* number of LangSysRecords */
};
typedef struct HB_ScriptTable_ HB_ScriptTable;
struct HB_ScriptRecord_
{
HB_UInt ScriptTag; /* ScriptTag identifier */
HB_ScriptTable Script; /* Script table */
};
typedef struct HB_ScriptRecord_ HB_ScriptRecord;
struct HB_ScriptList_
{
HB_ScriptRecord* ScriptRecord; /* array of ScriptRecords */
HB_UShort ScriptCount; /* number of ScriptRecords */
};
typedef struct HB_ScriptList_ HB_ScriptList;
/* Feature list related structures */
struct HB_Feature_
{
HB_UShort* LookupListIndex; /* array of LookupList indices */
HB_UShort FeatureParams; /* always 0 for TT Open 1.0 */
HB_UShort LookupListCount; /* number of LookupList indices */
};
typedef struct HB_Feature_ HB_Feature;
struct HB_FeatureRecord_
{
HB_UInt FeatureTag; /* FeatureTag identifier */
HB_Feature Feature; /* Feature table */
};
typedef struct HB_FeatureRecord_ HB_FeatureRecord;
struct HB_FeatureList_
{
HB_UShort* ApplyOrder; /* order to apply features */
HB_FeatureRecord* FeatureRecord; /* array of FeatureRecords */
HB_UShort FeatureCount; /* number of FeatureRecords */
HB_UShort ApplyCount; /* number of elements in ApplyOrder */
};
typedef struct HB_FeatureList_ HB_FeatureList;
/* Lookup list related structures */
typedef struct HB_SubTable_ HB_SubTable;
struct HB_Lookup_
{
HB_SubTable* SubTable; /* array of SubTables */
HB_UShort LookupType; /* Lookup type */
HB_UShort LookupFlag; /* Lookup qualifiers */
HB_UShort SubTableCount; /* number of SubTables */
};
typedef struct HB_Lookup_ HB_Lookup;
/* The `Properties' field is not defined in the OpenType specification but
is needed for processing lookups. If properties[n] is > 0, the
functions HB_GSUB_Apply_String() resp. HB_GPOS_Apply_String() will
process Lookup[n] for glyphs which have the specific bit not set in
the `properties' field of the input string object. */
struct HB_LookupList_
{
HB_Lookup* Lookup; /* array of Lookup records */
HB_UInt* Properties; /* array of flags */
HB_UShort LookupCount; /* number of Lookups */
};
typedef struct HB_LookupList_ HB_LookupList;
/* Possible LookupFlag bit masks. `HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS' comes from the
OpenType 1.2 specification; HB_LOOKUP_FLAG_RIGHT_TO_LEFT has been (re)introduced in
OpenType 1.3 -- if set, the last glyph in a cursive attachment
sequence has to be positioned on the baseline -- regardless of the
writing direction. */
#define HB_LOOKUP_FLAG_RIGHT_TO_LEFT 0x0001
#define HB_LOOKUP_FLAG_IGNORE_BASE_GLYPHS 0x0002
#define HB_LOOKUP_FLAG_IGNORE_LIGATURES 0x0004
#define HB_LOOKUP_FLAG_IGNORE_MARKS 0x0008
#define HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS 0xFF00
struct HB_CoverageFormat1_
{
HB_UShort* GlyphArray; /* array of glyph IDs */
HB_UShort GlyphCount; /* number of glyphs in GlyphArray */
};
typedef struct HB_CoverageFormat1_ HB_CoverageFormat1;
struct HB_RangeRecord_
{
HB_UShort Start; /* first glyph ID in the range */
HB_UShort End; /* last glyph ID in the range */
HB_UShort StartCoverageIndex; /* coverage index of first
glyph ID in the range */
};
typedef struct HB_RangeRecord_ HB_RangeRecord;
struct HB_CoverageFormat2_
{
HB_RangeRecord* RangeRecord; /* array of RangeRecords */
HB_UShort RangeCount; /* number of RangeRecords */
};
typedef struct HB_CoverageFormat2_ HB_CoverageFormat2;
struct HB_Coverage_
{
HB_Byte CoverageFormat; /* 1 or 2 */
union
{
HB_CoverageFormat1 cf1;
HB_CoverageFormat2 cf2;
} cf;
};
typedef struct HB_Coverage_ HB_Coverage;
struct HB_ClassDefFormat1_
{
HB_UShort* ClassValueArray; /* array of class values */
HB_UShort StartGlyph; /* first glyph ID of the
ClassValueArray */
HB_UShort GlyphCount; /* size of the ClassValueArray */
};
typedef struct HB_ClassDefFormat1_ HB_ClassDefFormat1;
struct HB_ClassRangeRecord_
{
HB_UShort Start; /* first glyph ID in the range */
HB_UShort End; /* last glyph ID in the range */
HB_UShort Class; /* applied to all glyphs in range */
};
typedef struct HB_ClassRangeRecord_ HB_ClassRangeRecord;
struct HB_ClassDefFormat2_
{
HB_ClassRangeRecord* ClassRangeRecord;
/* array of ClassRangeRecords */
HB_UShort ClassRangeCount;
/* number of ClassRangeRecords */
};
typedef struct HB_ClassDefFormat2_ HB_ClassDefFormat2;
struct HB_ClassDefinition_
{
union
{
HB_ClassDefFormat1 cd1;
HB_ClassDefFormat2 cd2;
} cd;
HB_Byte ClassFormat; /* 1 or 2 */
HB_Bool loaded;
};
typedef struct HB_ClassDefinition_ HB_ClassDefinition;
struct HB_Device_
{
HB_UShort* DeltaValue; /* array of compressed data */
HB_UShort StartSize; /* smallest size to correct */
HB_UShort EndSize; /* largest size to correct */
HB_Byte DeltaFormat; /* DeltaValue array data format:
1, 2, or 3 */
};
typedef struct HB_Device_ HB_Device;
enum HB_Type_
{
HB_Type_GSUB,
HB_Type_GPOS
};
typedef enum HB_Type_ HB_Type;
#ifdef HB_USE_PACKED_STRUCTS
#pragma pack(pop)
#endif
HB_END_HEADER
#endif /* HARFBUZZ_OPEN_H */

View file

@ -1,37 +0,0 @@
/*
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#include "harfbuzz-shaper.cpp"
#include "harfbuzz-indic.cpp"
extern "C" {
#include "harfbuzz-greek.c"
#include "harfbuzz-tibetan.c"
#include "harfbuzz-khmer.c"
#include "harfbuzz-hebrew.c"
#include "harfbuzz-arabic.c"
#include "harfbuzz-hangul.c"
#include "harfbuzz-myanmar.c"
#include "harfbuzz-thai.c"
}

View file

@ -1,159 +0,0 @@
/*
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#ifndef HARFBUZZ_SHAPER_PRIVATE_H
#define HARFBUZZ_SHAPER_PRIVATE_H
HB_BEGIN_HEADER
enum {
C_DOTTED_CIRCLE = 0x25CC
};
typedef enum
{
HB_Combining_BelowLeftAttached = 200,
HB_Combining_BelowAttached = 202,
HB_Combining_BelowRightAttached = 204,
HB_Combining_LeftAttached = 208,
HB_Combining_RightAttached = 210,
HB_Combining_AboveLeftAttached = 212,
HB_Combining_AboveAttached = 214,
HB_Combining_AboveRightAttached = 216,
HB_Combining_BelowLeft = 218,
HB_Combining_Below = 220,
HB_Combining_BelowRight = 222,
HB_Combining_Left = 224,
HB_Combining_Right = 226,
HB_Combining_AboveLeft = 228,
HB_Combining_Above = 230,
HB_Combining_AboveRight = 232,
HB_Combining_DoubleBelow = 233,
HB_Combining_DoubleAbove = 234,
HB_Combining_IotaSubscript = 240
} HB_CombiningClass;
typedef enum {
LocaProperty = 0x1,
CcmpProperty = 0x2,
InitProperty = 0x4,
IsolProperty = 0x8,
FinaProperty = 0x10,
MediProperty = 0x20,
RligProperty = 0x40,
CaltProperty = 0x80,
LigaProperty = 0x100,
DligProperty = 0x200,
CswhProperty = 0x400,
MsetProperty = 0x800,
/* used by indic and myanmar shaper */
NuktaProperty = 0x8,
AkhantProperty = 0x10,
RephProperty = 0x20,
PreFormProperty = 0x40,
BelowFormProperty = 0x80,
AboveFormProperty = 0x100,
HalfFormProperty = 0x200,
PostFormProperty = 0x400,
ConjunctFormProperty = 0x800,
VattuProperty = 0x1000,
PreSubstProperty = 0x2000,
BelowSubstProperty = 0x4000,
AboveSubstProperty = 0x8000,
PostSubstProperty = 0x10000,
HalantProperty = 0x20000,
CligProperty = 0x40000,
IndicCaltProperty = 0x80000
} HB_OpenTypeProperty;
/* return true if ok. */
typedef HB_Bool (*HB_ShapeFunction)(HB_ShaperItem *shaper_item);
typedef struct {
HB_ShapeFunction shape;
} HB_ScriptEngine;
extern const HB_ScriptEngine hb_scriptEngines[];
extern HB_Bool HB_BasicShape(HB_ShaperItem *shaper_item);
extern HB_Bool HB_GreekShape(HB_ShaperItem *shaper_item);
extern HB_Bool HB_TibetanShape(HB_ShaperItem *shaper_item);
extern HB_Bool HB_HebrewShape(HB_ShaperItem *shaper_item);
extern HB_Bool HB_ArabicShape(HB_ShaperItem *shaper_item);
extern HB_Bool HB_HangulShape(HB_ShaperItem *shaper_item);
extern HB_Bool HB_MyanmarShape(HB_ShaperItem *shaper_item);
extern HB_Bool HB_KhmerShape(HB_ShaperItem *shaper_item);
extern HB_Bool HB_IndicShape(HB_ShaperItem *shaper_item);
typedef struct {
hb_uint32 tag;
hb_uint32 property;
} HB_OpenTypeFeature;
#define PositioningProperties 0x80000000
HB_Bool HB_SelectScript(HB_ShaperItem *item, const HB_OpenTypeFeature *features);
HB_Bool HB_OpenTypeShape(HB_ShaperItem *item, const hb_uint32 *properties);
HB_Bool HB_OpenTypePosition(HB_ShaperItem *item, int availableGlyphs, HB_Bool doLogClusters);
void HB_HeuristicPosition(HB_ShaperItem *item);
void HB_HeuristicSetGlyphAttributes(HB_ShaperItem *item);
#define HB_IsControlChar(uc) \
((uc >= 0x200b && uc <= 0x200f /* ZW Space, ZWNJ, ZWJ, LRM and RLM */) \
|| (uc >= 0x2028 && uc <= 0x202f /* LS, PS, LRE, RLE, PDF, LRO, RLO, NNBSP */) \
|| (uc >= 0x206a && uc <= 0x206f /* ISS, ASS, IAFS, AFS, NADS, NODS */))
HB_Bool HB_ConvertStringToGlyphIndices(HB_ShaperItem *shaper_item);
#define HB_GetGlyphAdvances(shaper_item) \
shaper_item->font->klass->getGlyphAdvances(shaper_item->font, \
shaper_item->glyphs, shaper_item->num_glyphs, \
shaper_item->advances, \
shaper_item->face->current_flags);
#define HB_DECLARE_STACKARRAY(Type, Name) \
Type stack##Name[512]; \
Type *Name = stack##Name;
#define HB_INIT_STACKARRAY(Type, Name, Length) \
if ((Length) >= 512) \
Name = (Type *)malloc((Length) * sizeof(Type));
#define HB_STACKARRAY(Type, Name, Length) \
HB_DECLARE_STACKARRAY(Type, Name) \
HB_INIT_STACKARRAY(Type, Name, Length)
#define HB_FREE_STACKARRAY(Name) \
if (stack##Name != Name) \
free(Name);
HB_END_HEADER
#endif

View file

@ -1,996 +0,0 @@
/*
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#include "harfbuzz-shaper.h"
#include "harfbuzz-shaper-private.h"
#include "harfbuzz-stream-private.h"
#include <assert.h>
#include <stdio.h>
#define HB_MIN(a, b) ((a) < (b) ? (a) : (b))
#define HB_MAX(a, b) ((a) > (b) ? (a) : (b))
// --------------------------------------------------------------------------------------------------------------------------------------------
//
// Basic processing
//
// --------------------------------------------------------------------------------------------------------------------------------------------
static inline void positionCluster(HB_ShaperItem *item, int gfrom, int glast)
{
int nmarks = glast - gfrom;
assert(nmarks > 0);
HB_Glyph *glyphs = item->glyphs;
HB_GlyphAttributes *attributes = item->attributes;
HB_GlyphMetrics baseMetrics;
item->font->klass->getGlyphMetrics(item->font, glyphs[gfrom], &baseMetrics);
if (item->item.script == HB_Script_Hebrew
&& (-baseMetrics.y) > baseMetrics.height)
// we need to attach below the baseline, because of the hebrew iud.
baseMetrics.height = -baseMetrics.y;
// qDebug("---> positionCluster: cluster from %d to %d", gfrom, glast);
// qDebug("baseInfo: %f/%f (%f/%f) off=%f/%f", baseInfo.x, baseInfo.y, baseInfo.width, baseInfo.height, baseInfo.xoff, baseInfo.yoff);
HB_Fixed size = item->font->klass->getFontMetric(item->font, HB_FontAscent) / 10;
HB_Fixed offsetBase = HB_FIXED_CONSTANT(1) + (size - HB_FIXED_CONSTANT(4)) / 4;
if (size > HB_FIXED_CONSTANT(4))
offsetBase += HB_FIXED_CONSTANT(4);
else
offsetBase += size;
offsetBase = -offsetBase;
//qreal offsetBase = (size - 4) / 4 + qMin<qreal>(size, 4) + 1;
// qDebug("offset = %f", offsetBase);
bool rightToLeft = item->item.bidiLevel % 2;
int i;
unsigned char lastCmb = 0;
HB_GlyphMetrics attachmentRect;
memset(&attachmentRect, 0, sizeof(attachmentRect));
for(i = 1; i <= nmarks; i++) {
HB_Glyph mark = glyphs[gfrom+i];
HB_GlyphMetrics markMetrics;
item->font->klass->getGlyphMetrics(item->font, mark, &markMetrics);
HB_FixedPoint p;
p.x = p.y = 0;
// qDebug("markInfo: %f/%f (%f/%f) off=%f/%f", markInfo.x, markInfo.y, markInfo.width, markInfo.height, markInfo.xoff, markInfo.yoff);
HB_Fixed offset = offsetBase;
unsigned char cmb = attributes[gfrom+i].combiningClass;
// ### maybe the whole position determination should move down to heuristicSetGlyphAttributes. Would save some
// bits in the glyphAttributes structure.
if (cmb < 200) {
// fixed position classes. We approximate by mapping to one of the others.
// currently I added only the ones for arabic, hebrew, lao and thai.
// for Lao and Thai marks with class 0, see below (heuristicSetGlyphAttributes)
// add a bit more offset to arabic, a bit hacky
if (cmb >= 27 && cmb <= 36 && offset < 3)
offset +=1;
// below
if ((cmb >= 10 && cmb <= 18) ||
cmb == 20 || cmb == 22 ||
cmb == 29 || cmb == 32)
cmb = HB_Combining_Below;
// above
else if (cmb == 23 || cmb == 27 || cmb == 28 ||
cmb == 30 || cmb == 31 || (cmb >= 33 && cmb <= 36))
cmb = HB_Combining_Above;
//below-right
else if (cmb == 9 || cmb == 103 || cmb == 118)
cmb = HB_Combining_BelowRight;
// above-right
else if (cmb == 24 || cmb == 107 || cmb == 122)
cmb = HB_Combining_AboveRight;
else if (cmb == 25)
cmb = HB_Combining_AboveLeft;
// fixed:
// 19 21
}
// combining marks of different class don't interact. Reset the rectangle.
if (cmb != lastCmb) {
//qDebug("resetting rect");
attachmentRect = baseMetrics;
}
switch(cmb) {
case HB_Combining_DoubleBelow:
// ### wrong in rtl context!
case HB_Combining_BelowLeft:
p.y += offset;
case HB_Combining_BelowLeftAttached:
p.x += attachmentRect.x - markMetrics.x;
p.y += (attachmentRect.y + attachmentRect.height) - markMetrics.y;
break;
case HB_Combining_Below:
p.y += offset;
case HB_Combining_BelowAttached:
p.x += attachmentRect.x - markMetrics.x;
p.y += (attachmentRect.y + attachmentRect.height) - markMetrics.y;
p.x += (attachmentRect.width - markMetrics.width) / 2;
break;
case HB_Combining_BelowRight:
p.y += offset;
case HB_Combining_BelowRightAttached:
p.x += attachmentRect.x + attachmentRect.width - markMetrics.width - markMetrics.x;
p.y += attachmentRect.y + attachmentRect.height - markMetrics.y;
break;
case HB_Combining_Left:
p.x -= offset;
case HB_Combining_LeftAttached:
break;
case HB_Combining_Right:
p.x += offset;
case HB_Combining_RightAttached:
break;
case HB_Combining_DoubleAbove:
// ### wrong in RTL context!
case HB_Combining_AboveLeft:
p.y -= offset;
case HB_Combining_AboveLeftAttached:
p.x += attachmentRect.x - markMetrics.x;
p.y += attachmentRect.y - markMetrics.y - markMetrics.height;
break;
case HB_Combining_Above:
p.y -= offset;
case HB_Combining_AboveAttached:
p.x += attachmentRect.x - markMetrics.x;
p.y += attachmentRect.y - markMetrics.y - markMetrics.height;
p.x += (attachmentRect.width - markMetrics.width) / 2;
break;
case HB_Combining_AboveRight:
p.y -= offset;
case HB_Combining_AboveRightAttached:
p.x += attachmentRect.x + attachmentRect.width - markMetrics.x - markMetrics.width;
p.y += attachmentRect.y - markMetrics.y - markMetrics.height;
break;
case HB_Combining_IotaSubscript:
default:
break;
}
// qDebug("char=%x combiningClass = %d offset=%f/%f", mark, cmb, p.x(), p.y());
markMetrics.x += p.x;
markMetrics.y += p.y;
HB_GlyphMetrics unitedAttachmentRect = attachmentRect;
unitedAttachmentRect.x = HB_MIN(attachmentRect.x, markMetrics.x);
unitedAttachmentRect.y = HB_MIN(attachmentRect.y, markMetrics.y);
unitedAttachmentRect.width = HB_MAX(attachmentRect.x + attachmentRect.width, markMetrics.x + markMetrics.width) - unitedAttachmentRect.x;
unitedAttachmentRect.height = HB_MAX(attachmentRect.y + attachmentRect.height, markMetrics.y + markMetrics.height) - unitedAttachmentRect.y;
attachmentRect = unitedAttachmentRect;
lastCmb = cmb;
if (rightToLeft) {
item->offsets[gfrom+i].x = p.x;
item->offsets[gfrom+i].y = p.y;
} else {
item->offsets[gfrom+i].x = p.x - baseMetrics.xOffset;
item->offsets[gfrom+i].y = p.y - baseMetrics.yOffset;
}
item->advances[gfrom+i] = 0;
}
}
void HB_HeuristicPosition(HB_ShaperItem *item)
{
HB_GetGlyphAdvances(item);
HB_GlyphAttributes *attributes = item->attributes;
int cEnd = -1;
int i = item->num_glyphs;
while (i--) {
if (cEnd == -1 && attributes[i].mark) {
cEnd = i;
} else if (cEnd != -1 && !attributes[i].mark) {
positionCluster(item, i, cEnd);
cEnd = -1;
}
}
}
// set the glyph attributes heuristically. Assumes a 1 to 1 relationship between chars and glyphs
// and no reordering.
// also computes logClusters heuristically
void HB_HeuristicSetGlyphAttributes(HB_ShaperItem *item)
{
const HB_UChar16 *uc = item->string + item->item.pos;
hb_uint32 length = item->item.length;
// ### zeroWidth and justification are missing here!!!!!
assert(item->num_glyphs <= length);
// qDebug("QScriptEngine::heuristicSetGlyphAttributes, num_glyphs=%d", item->num_glyphs);
HB_GlyphAttributes *attributes = item->attributes;
unsigned short *logClusters = item->log_clusters;
hb_uint32 glyph_pos = 0;
hb_uint32 i;
for (i = 0; i < length; i++) {
if (HB_IsHighSurrogate(uc[i]) && i < length - 1
&& HB_IsLowSurrogate(uc[i + 1])) {
logClusters[i] = glyph_pos;
logClusters[++i] = glyph_pos;
} else {
logClusters[i] = glyph_pos;
}
++glyph_pos;
}
assert(glyph_pos == item->num_glyphs);
// first char in a run is never (treated as) a mark
int cStart = 0;
const bool symbolFont = item->face->isSymbolFont;
attributes[0].mark = false;
attributes[0].clusterStart = true;
attributes[0].dontPrint = (!symbolFont && uc[0] == 0x00ad) || HB_IsControlChar(uc[0]);
int pos = 0;
HB_CharCategory lastCat;
int dummy;
HB_GetUnicodeCharProperties(item->ufuncs, uc[0], &lastCat, &dummy);
for (i = 1; i < length; ++i) {
if (logClusters[i] == pos)
// same glyph
continue;
++pos;
while (pos < logClusters[i]) {
attributes[pos] = attributes[pos-1];
++pos;
}
// hide soft-hyphens by default
if ((!symbolFont && uc[i] == 0x00ad) || HB_IsControlChar(uc[i]))
attributes[pos].dontPrint = true;
HB_CharCategory cat;
int cmb;
HB_GetUnicodeCharProperties(item->ufuncs, uc[i], &cat, &cmb);
if (cat != HB_Mark_NonSpacing) {
attributes[pos].mark = false;
attributes[pos].clusterStart = true;
attributes[pos].combiningClass = 0;
cStart = logClusters[i];
} else {
if (cmb == 0) {
// Fix 0 combining classes
if ((uc[pos] & 0xff00) == 0x0e00) {
// thai or lao
if (uc[pos] == 0xe31 ||
uc[pos] == 0xe34 ||
uc[pos] == 0xe35 ||
uc[pos] == 0xe36 ||
uc[pos] == 0xe37 ||
uc[pos] == 0xe47 ||
uc[pos] == 0xe4c ||
uc[pos] == 0xe4d ||
uc[pos] == 0xe4e) {
cmb = HB_Combining_AboveRight;
} else if (uc[pos] == 0xeb1 ||
uc[pos] == 0xeb4 ||
uc[pos] == 0xeb5 ||
uc[pos] == 0xeb6 ||
uc[pos] == 0xeb7 ||
uc[pos] == 0xebb ||
uc[pos] == 0xecc ||
uc[pos] == 0xecd) {
cmb = HB_Combining_Above;
} else if (uc[pos] == 0xebc) {
cmb = HB_Combining_Below;
}
}
}
attributes[pos].mark = true;
attributes[pos].clusterStart = false;
attributes[pos].combiningClass = cmb;
logClusters[i] = cStart;
}
// one gets an inter character justification point if the current char is not a non spacing mark.
// as then the current char belongs to the last one and one gets a space justification point
// after the space char.
if (lastCat == HB_Separator_Space)
attributes[pos-1].justification = HB_Space;
else if (cat != HB_Mark_NonSpacing)
attributes[pos-1].justification = HB_Character;
else
attributes[pos-1].justification = HB_NoJustification;
lastCat = cat;
}
pos = logClusters[length-1];
if (lastCat == HB_Separator_Space)
attributes[pos].justification = HB_Space;
else
attributes[pos].justification = HB_Character;
}
#ifndef NO_OPENTYPE
static const HB_OpenTypeFeature basic_features[] = {
{ HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },
{ HB_MAKE_TAG('l', 'i', 'g', 'a'), CcmpProperty },
{ HB_MAKE_TAG('c', 'l', 'i', 'g'), CcmpProperty },
{0, 0}
};
#endif
HB_Bool HB_ConvertStringToGlyphIndices(HB_ShaperItem *shaper_item)
{
if (shaper_item->glyphIndicesPresent) {
shaper_item->num_glyphs = shaper_item->initialGlyphCount;
shaper_item->glyphIndicesPresent = false;
return true;
}
return shaper_item->font->klass
->convertStringToGlyphIndices(shaper_item->font,
shaper_item->string + shaper_item->item.pos, shaper_item->item.length,
shaper_item->glyphs, &shaper_item->num_glyphs,
shaper_item->item.bidiLevel % 2);
}
HB_Bool HB_BasicShape(HB_ShaperItem *shaper_item)
{
#ifndef NO_OPENTYPE
const int availableGlyphs = shaper_item->num_glyphs;
#endif
if (!HB_ConvertStringToGlyphIndices(shaper_item))
return false;
HB_HeuristicSetGlyphAttributes(shaper_item);
#ifndef NO_OPENTYPE
if (HB_SelectScript(shaper_item, basic_features)) {
HB_OpenTypeShape(shaper_item, /*properties*/0);
return HB_OpenTypePosition(shaper_item, availableGlyphs, /*doLogClusters*/true);
}
#endif
HB_HeuristicPosition(shaper_item);
return true;
}
const HB_ScriptEngine HB_ScriptEngines[] = {
// Common
{ HB_BasicShape},
// Greek
{ HB_GreekShape},
// Cyrillic
{ HB_BasicShape},
// Armenian
{ HB_BasicShape},
// Hebrew
{ HB_HebrewShape},
// Arabic
{ HB_ArabicShape},
// Syriac
{ HB_ArabicShape},
// Thaana
{ HB_BasicShape},
// Devanagari
{ HB_IndicShape},
// Bengali
{ HB_IndicShape},
// Gurmukhi
{ HB_IndicShape},
// Gujarati
{ HB_IndicShape},
// Oriya
{ HB_IndicShape},
// Tamil
{ HB_IndicShape},
// Telugu
{ HB_IndicShape},
// Kannada
{ HB_IndicShape},
// Malayalam
{ HB_IndicShape},
// Sinhala
{ HB_IndicShape},
// Thai
{ HB_BasicShape},
// Lao
{ HB_BasicShape},
// Tibetan
{ HB_TibetanShape},
// Myanmar
{ HB_MyanmarShape},
// Georgian
{ HB_BasicShape},
// Hangul
{ HB_HangulShape},
// Ogham
{ HB_BasicShape},
// Runic
{ HB_BasicShape},
// Khmer
{ HB_KhmerShape},
// N'Ko
{ HB_ArabicShape}
};
static inline char *tag_to_string(HB_UInt tag)
{
static char string[5];
string[0] = (tag >> 24)&0xff;
string[1] = (tag >> 16)&0xff;
string[2] = (tag >> 8)&0xff;
string[3] = tag&0xff;
string[4] = 0;
return string;
}
#ifdef OT_DEBUG
static void dump_string(HB_Buffer buffer)
{
for (uint i = 0; i < buffer->in_length; ++i) {
qDebug(" %x: cluster=%d", buffer->in_string[i].gindex, buffer->in_string[i].cluster);
}
}
#define DEBUG printf
#else
#define DEBUG if (1) ; else printf
#endif
#if 0
#define DefaultLangSys 0xffff
#define DefaultScript HB_MAKE_TAG('D', 'F', 'L', 'T')
#endif
enum {
RequiresGsub = 1,
RequiresGpos = 2
};
struct OTScripts {
unsigned int tag;
int flags;
};
static const OTScripts ot_scripts [] = {
// Common
{ HB_MAKE_TAG('l', 'a', 't', 'n'), 0 },
// Greek
{ HB_MAKE_TAG('g', 'r', 'e', 'k'), 0 },
// Cyrillic
{ HB_MAKE_TAG('c', 'y', 'r', 'l'), 0 },
// Armenian
{ HB_MAKE_TAG('a', 'r', 'm', 'n'), 0 },
// Hebrew
{ HB_MAKE_TAG('h', 'e', 'b', 'r'), 1 },
// Arabic
{ HB_MAKE_TAG('a', 'r', 'a', 'b'), 1 },
// Syriac
{ HB_MAKE_TAG('s', 'y', 'r', 'c'), 1 },
// Thaana
{ HB_MAKE_TAG('t', 'h', 'a', 'a'), 1 },
// Devanagari
{ HB_MAKE_TAG('d', 'e', 'v', 'a'), 1 },
// Bengali
{ HB_MAKE_TAG('b', 'e', 'n', 'g'), 1 },
// Gurmukhi
{ HB_MAKE_TAG('g', 'u', 'r', 'u'), 1 },
// Gujarati
{ HB_MAKE_TAG('g', 'u', 'j', 'r'), 1 },
// Oriya
{ HB_MAKE_TAG('o', 'r', 'y', 'a'), 1 },
// Tamil
{ HB_MAKE_TAG('t', 'a', 'm', 'l'), 1 },
// Telugu
{ HB_MAKE_TAG('t', 'e', 'l', 'u'), 1 },
// Kannada
{ HB_MAKE_TAG('k', 'n', 'd', 'a'), 1 },
// Malayalam
{ HB_MAKE_TAG('m', 'l', 'y', 'm'), 1 },
// Sinhala
{ HB_MAKE_TAG('s', 'i', 'n', 'h'), 1 },
// Thai
{ HB_MAKE_TAG('t', 'h', 'a', 'i'), 1 },
// Lao
{ HB_MAKE_TAG('l', 'a', 'o', ' '), 1 },
// Tibetan
{ HB_MAKE_TAG('t', 'i', 'b', 't'), 1 },
// Myanmar
{ HB_MAKE_TAG('m', 'y', 'm', 'r'), 1 },
// Georgian
{ HB_MAKE_TAG('g', 'e', 'o', 'r'), 0 },
// Hangul
{ HB_MAKE_TAG('h', 'a', 'n', 'g'), 1 },
// Ogham
{ HB_MAKE_TAG('o', 'g', 'a', 'm'), 0 },
// Runic
{ HB_MAKE_TAG('r', 'u', 'n', 'r'), 0 },
// Khmer
{ HB_MAKE_TAG('k', 'h', 'm', 'r'), 1 },
// N'Ko
{ HB_MAKE_TAG('n', 'k', 'o', ' '), 1 }
};
enum { NumOTScripts = sizeof(ot_scripts)/sizeof(OTScripts) };
static HB_Bool checkScript(HB_Face face, int script)
{
assert(script < HB_ScriptCount);
if (!face->gsub && !face->gpos)
return false;
unsigned int tag = ot_scripts[script].tag;
int requirements = ot_scripts[script].flags;
if (requirements & RequiresGsub) {
if (!face->gsub)
return false;
HB_UShort script_index;
HB_Error error = HB_GSUB_Select_Script(face->gsub, tag, &script_index);
if (error) {
DEBUG("could not select script %d in GSub table: %d", (int)script, error);
error = HB_GSUB_Select_Script(face->gsub, HB_MAKE_TAG('D', 'F', 'L', 'T'), &script_index);
if (error)
return false;
}
}
if (requirements & RequiresGpos) {
if (!face->gpos)
return false;
HB_UShort script_index;
HB_Error error = HB_GPOS_Select_Script(face->gpos, script, &script_index);
if (error) {
DEBUG("could not select script in gpos table: %d", error);
error = HB_GPOS_Select_Script(face->gpos, HB_MAKE_TAG('D', 'F', 'L', 'T'), &script_index);
if (error)
return false;
}
}
return true;
}
static HB_Stream getTableStream(void *font, HB_GetFontTableFunc tableFunc, HB_Tag tag)
{
HB_Error error;
HB_UInt length = 0;
HB_Stream stream = 0;
if (!font)
return 0;
error = tableFunc(font, tag, 0, &length);
if (error)
return 0;
stream = (HB_Stream)malloc(sizeof(HB_StreamRec));
if (!stream)
return 0;
stream->base = (HB_Byte*)malloc(length);
if (!stream->base) {
free(stream);
return 0;
}
error = tableFunc(font, tag, stream->base, &length);
if (error) {
_hb_close_stream(stream);
return 0;
}
stream->size = length;
stream->pos = 0;
stream->cursor = NULL;
return stream;
}
HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc)
{
HB_Face face = (HB_Face )malloc(sizeof(HB_FaceRec));
if (!face)
return 0;
face->isSymbolFont = false;
face->gdef = 0;
face->gpos = 0;
face->gsub = 0;
face->current_script = HB_ScriptCount;
face->current_flags = HB_ShaperFlag_Default;
face->has_opentype_kerning = false;
face->tmpAttributes = 0;
face->tmpLogClusters = 0;
face->glyphs_substituted = false;
face->buffer = 0;
HB_Error error = HB_Err_Ok;
HB_Stream stream;
HB_Stream gdefStream;
gdefStream = getTableStream(font, tableFunc, TTAG_GDEF);
error = HB_Err_Not_Covered;
if (!gdefStream || (error = HB_Load_GDEF_Table(gdefStream, &face->gdef))) {
//DEBUG("error loading gdef table: %d", error);
face->gdef = 0;
}
//DEBUG() << "trying to load gsub table";
stream = getTableStream(font, tableFunc, TTAG_GSUB);
error = HB_Err_Not_Covered;
if (!stream || (error = HB_Load_GSUB_Table(stream, &face->gsub, face->gdef, gdefStream))) {
face->gsub = 0;
if (error != HB_Err_Not_Covered) {
//DEBUG("error loading gsub table: %d", error);
} else {
//DEBUG("face doesn't have a gsub table");
}
}
_hb_close_stream(stream);
stream = getTableStream(font, tableFunc, TTAG_GPOS);
error = HB_Err_Not_Covered;
if (!stream || (error = HB_Load_GPOS_Table(stream, &face->gpos, face->gdef, gdefStream))) {
face->gpos = 0;
DEBUG("error loading gpos table: %d", error);
}
_hb_close_stream(stream);
_hb_close_stream(gdefStream);
for (unsigned int i = 0; i < HB_ScriptCount; ++i)
face->supported_scripts[i] = checkScript(face, i);
if (HB_Buffer_new(&face->buffer) != HB_Err_Ok) {
HB_FreeFace(face);
return 0;
}
return face;
}
void HB_FreeFace(HB_Face face)
{
if (!face)
return;
if (face->gpos)
HB_Done_GPOS_Table(face->gpos);
if (face->gsub)
HB_Done_GSUB_Table(face->gsub);
if (face->gdef)
HB_Done_GDEF_Table(face->gdef);
if (face->buffer)
HB_Buffer_free(face->buffer);
if (face->tmpAttributes)
free(face->tmpAttributes);
if (face->tmpLogClusters)
free(face->tmpLogClusters);
free(face);
}
HB_Bool HB_SelectScript(HB_ShaperItem *shaper_item, const HB_OpenTypeFeature *features)
{
HB_Script script = shaper_item->item.script;
if (!shaper_item->face->supported_scripts[script])
return false;
HB_Face face = shaper_item->face;
if (face->current_script == script && face->current_flags == shaper_item->shaperFlags)
return true;
face->current_script = script;
face->current_flags = shaper_item->shaperFlags;
assert(script < HB_ScriptCount);
// find script in our list of supported scripts.
unsigned int tag = ot_scripts[script].tag;
if (face->gsub && features) {
#ifdef OT_DEBUG
{
HB_FeatureList featurelist = face->gsub->FeatureList;
int numfeatures = featurelist.FeatureCount;
DEBUG("gsub table has %d features", numfeatures);
for (int i = 0; i < numfeatures; i++) {
HB_FeatureRecord *r = featurelist.FeatureRecord + i;
DEBUG(" feature '%s'", tag_to_string(r->FeatureTag));
}
}
#endif
HB_GSUB_Clear_Features(face->gsub);
HB_UShort script_index;
HB_Error error = HB_GSUB_Select_Script(face->gsub, tag, &script_index);
if (!error) {
DEBUG("script %s has script index %d", tag_to_string(script), script_index);
while (features->tag) {
HB_UShort feature_index;
error = HB_GSUB_Select_Feature(face->gsub, features->tag, script_index, 0xffff, &feature_index);
if (!error) {
DEBUG(" adding feature %s", tag_to_string(features->tag));
HB_GSUB_Add_Feature(face->gsub, feature_index, features->property);
}
++features;
}
}
}
// reset
face->has_opentype_kerning = false;
if (face->gpos) {
HB_GPOS_Clear_Features(face->gpos);
HB_UShort script_index;
HB_Error error = HB_GPOS_Select_Script(face->gpos, tag, &script_index);
if (!error) {
#ifdef OT_DEBUG
{
HB_FeatureList featurelist = face->gpos->FeatureList;
int numfeatures = featurelist.FeatureCount;
DEBUG("gpos table has %d features", numfeatures);
for(int i = 0; i < numfeatures; i++) {
HB_FeatureRecord *r = featurelist.FeatureRecord + i;
HB_UShort feature_index;
HB_GPOS_Select_Feature(face->gpos, r->FeatureTag, script_index, 0xffff, &feature_index);
DEBUG(" feature '%s'", tag_to_string(r->FeatureTag));
}
}
#endif
HB_UInt *feature_tag_list_buffer;
error = HB_GPOS_Query_Features(face->gpos, script_index, 0xffff, &feature_tag_list_buffer);
if (!error) {
HB_UInt *feature_tag_list = feature_tag_list_buffer;
while (*feature_tag_list) {
HB_UShort feature_index;
if (*feature_tag_list == HB_MAKE_TAG('k', 'e', 'r', 'n')) {
if (face->current_flags & HB_ShaperFlag_NoKerning) {
++feature_tag_list;
continue;
}
face->has_opentype_kerning = true;
}
error = HB_GPOS_Select_Feature(face->gpos, *feature_tag_list, script_index, 0xffff, &feature_index);
if (!error)
HB_GPOS_Add_Feature(face->gpos, feature_index, PositioningProperties);
++feature_tag_list;
}
FREE(feature_tag_list_buffer);
}
}
}
return true;
}
HB_Bool HB_OpenTypeShape(HB_ShaperItem *item, const hb_uint32 *properties)
{
HB_GlyphAttributes *tmpAttributes;
unsigned int *tmpLogClusters;
HB_Face face = item->face;
face->length = item->num_glyphs;
HB_Buffer_clear(face->buffer);
tmpAttributes = (HB_GlyphAttributes *) realloc(face->tmpAttributes, face->length*sizeof(HB_GlyphAttributes));
if (!tmpAttributes)
return false;
face->tmpAttributes = tmpAttributes;
tmpLogClusters = (unsigned int *) realloc(face->tmpLogClusters, face->length*sizeof(unsigned int));
if (!tmpLogClusters)
return false;
face->tmpLogClusters = tmpLogClusters;
for (int i = 0; i < face->length; ++i) {
HB_Buffer_add_glyph(face->buffer, item->glyphs[i], properties ? properties[i] : 0, i);
face->tmpAttributes[i] = item->attributes[i];
face->tmpLogClusters[i] = item->log_clusters[i];
}
#ifdef OT_DEBUG
DEBUG("-----------------------------------------");
// DEBUG("log clusters before shaping:");
// for (int j = 0; j < length; j++)
// DEBUG(" log[%d] = %d", j, item->log_clusters[j]);
DEBUG("original glyphs: %p", item->glyphs);
for (int i = 0; i < length; ++i)
DEBUG(" glyph=%4x", hb_buffer->in_string[i].gindex);
// dump_string(hb_buffer);
#endif
face->glyphs_substituted = false;
if (face->gsub) {
unsigned int error = HB_GSUB_Apply_String(face->gsub, face->buffer);
if (error && error != HB_Err_Not_Covered)
return false;
face->glyphs_substituted = (error != HB_Err_Not_Covered);
}
#ifdef OT_DEBUG
// DEBUG("log clusters before shaping:");
// for (int j = 0; j < length; j++)
// DEBUG(" log[%d] = %d", j, item->log_clusters[j]);
DEBUG("shaped glyphs:");
for (int i = 0; i < length; ++i)
DEBUG(" glyph=%4x", hb_buffer->in_string[i].gindex);
DEBUG("-----------------------------------------");
// dump_string(hb_buffer);
#endif
return true;
}
HB_Bool HB_OpenTypePosition(HB_ShaperItem *item, int availableGlyphs, HB_Bool doLogClusters)
{
HB_Face face = item->face;
bool glyphs_positioned = false;
if (face->gpos) {
if (face->buffer->positions)
memset(face->buffer->positions, 0, face->buffer->in_length*sizeof(HB_PositionRec));
// #### check that passing "false,false" is correct
glyphs_positioned = HB_GPOS_Apply_String(item->font, face->gpos, face->current_flags, face->buffer, false, false) != HB_Err_Not_Covered;
}
if (!face->glyphs_substituted && !glyphs_positioned) {
HB_GetGlyphAdvances(item);
return true; // nothing to do for us
}
// make sure we have enough space to write everything back
if (availableGlyphs < (int)face->buffer->in_length) {
item->num_glyphs = face->buffer->in_length;
return false;
}
HB_Glyph *glyphs = item->glyphs;
HB_GlyphAttributes *attributes = item->attributes;
for (unsigned int i = 0; i < face->buffer->in_length; ++i) {
glyphs[i] = face->buffer->in_string[i].gindex;
attributes[i] = face->tmpAttributes[face->buffer->in_string[i].cluster];
if (i && face->buffer->in_string[i].cluster == face->buffer->in_string[i-1].cluster)
attributes[i].clusterStart = false;
}
item->num_glyphs = face->buffer->in_length;
if (doLogClusters && face->glyphs_substituted) {
// we can't do this for indic, as we pass the stuf in syllables and it's easier to do it in the shaper.
unsigned short *logClusters = item->log_clusters;
int clusterStart = 0;
int oldCi = 0;
// #### the reconstruction of the logclusters currently does not work if the original string
// contains surrogate pairs
for (unsigned int i = 0; i < face->buffer->in_length; ++i) {
int ci = face->buffer->in_string[i].cluster;
// DEBUG(" ci[%d] = %d mark=%d, cmb=%d, cs=%d",
// i, ci, glyphAttributes[i].mark, glyphAttributes[i].combiningClass, glyphAttributes[i].clusterStart);
if (!attributes[i].mark && attributes[i].clusterStart && ci != oldCi) {
for (int j = oldCi; j < ci; j++)
logClusters[j] = clusterStart;
clusterStart = i;
oldCi = ci;
}
}
for (int j = oldCi; j < face->length; j++)
logClusters[j] = clusterStart;
}
// calulate the advances for the shaped glyphs
// DEBUG("unpositioned: ");
// positioning code:
if (glyphs_positioned) {
HB_GetGlyphAdvances(item);
HB_Position positions = face->buffer->positions;
HB_Fixed *advances = item->advances;
// DEBUG("positioned glyphs:");
for (unsigned int i = 0; i < face->buffer->in_length; i++) {
// DEBUG(" %d:\t orig advance: (%d/%d)\tadv=(%d/%d)\tpos=(%d/%d)\tback=%d\tnew_advance=%d", i,
// glyphs[i].advance.x.toInt(), glyphs[i].advance.y.toInt(),
// (int)(positions[i].x_advance >> 6), (int)(positions[i].y_advance >> 6),
// (int)(positions[i].x_pos >> 6), (int)(positions[i].y_pos >> 6),
// positions[i].back, positions[i].new_advance);
HB_Fixed adjustment = positions[i].x_advance;
if (!(face->current_flags & HB_ShaperFlag_UseDesignMetrics))
adjustment = HB_FIXED_ROUND(adjustment);
if (positions[i].new_advance) {
; //advances[i] = adjustment;
} else {
advances[i] += adjustment;
}
int back = 0;
HB_FixedPoint *offsets = item->offsets;
offsets[i].x = positions[i].x_pos;
offsets[i].y = positions[i].y_pos;
while (positions[i - back].back) {
back += positions[i - back].back;
offsets[i].x += positions[i - back].x_pos;
offsets[i].y += positions[i - back].y_pos;
}
offsets[i].y = -offsets[i].y;
if (item->item.bidiLevel % 2) {
// ### may need to go back multiple glyphs like in ltr
back = positions[i].back;
while (back--)
offsets[i].x -= advances[i-back];
} else {
back = 0;
while (positions[i - back].back) {
back += positions[i - back].back;
offsets[i].x -= advances[i-back];
}
}
// DEBUG(" ->\tadv=%d\tpos=(%d/%d)",
// glyphs[i].advance.x.toInt(), glyphs[i].offset.x.toInt(), glyphs[i].offset.y.toInt());
}
item->kerning_applied = face->has_opentype_kerning;
} else {
HB_HeuristicPosition(item);
}
#ifdef OT_DEBUG
if (doLogClusters) {
DEBUG("log clusters after shaping:");
for (int j = 0; j < length; j++)
DEBUG(" log[%d] = %d", j, item->log_clusters[j]);
}
DEBUG("final glyphs:");
for (int i = 0; i < (int)hb_buffer->in_length; ++i)
DEBUG(" glyph=%4x char_index=%d mark: %d cmp: %d, clusterStart: %d advance=%d/%d offset=%d/%d",
glyphs[i].glyph, hb_buffer->in_string[i].cluster, glyphs[i].attributes.mark,
glyphs[i].attributes.combiningClass, glyphs[i].attributes.clusterStart,
glyphs[i].advance.x.toInt(), glyphs[i].advance.y.toInt(),
glyphs[i].offset.x.toInt(), glyphs[i].offset.y.toInt());
DEBUG("-----------------------------------------");
#endif
return true;
}
HB_Bool HB_ShapeItem(HB_ShaperItem *shaper_item)
{
HB_Bool result = false;
if (shaper_item->num_glyphs < shaper_item->item.length) {
shaper_item->num_glyphs = shaper_item->item.length;
return false;
}
assert(shaper_item->item.script < HB_ScriptCount);
if (!shaper_item->ufuncs)
shaper_item->ufuncs = hb_unicode_funcs_get_default ();
result = HB_ScriptEngines[shaper_item->item.script].shape(shaper_item);
shaper_item->glyphIndicesPresent = false;
return result;
}

View file

@ -1,265 +0,0 @@
/*
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#ifndef HARFBUZZ_SHAPER_H
#define HARFBUZZ_SHAPER_H
#include "harfbuzz-global.h"
#include "harfbuzz-gdef.h"
#include "harfbuzz-gpos.h"
#include "harfbuzz-gsub.h"
#include "harfbuzz-external.h"
#include "harfbuzz-stream-private.h"
HB_BEGIN_HEADER
#ifdef HB_USE_PACKED_STRUCTS
#pragma pack(push, 1)
#endif
/*
using anything else than signed or unsigned for bitfields in C is non standard,
but accepted by almost all compilers. And it gives a significant reduction in
memory consumption as HB_CharAttributes and HB_GlyphAttributes will not have
a 4 byte alignment
*/
#ifdef __xlC__
typedef unsigned hb_bitfield;
#else
typedef hb_uint8 hb_bitfield;
#endif
typedef enum {
HB_Script_Common,
HB_Script_Greek,
HB_Script_Cyrillic,
HB_Script_Armenian,
HB_Script_Hebrew,
HB_Script_Arabic,
HB_Script_Syriac,
HB_Script_Thaana,
HB_Script_Devanagari,
HB_Script_Bengali,
HB_Script_Gurmukhi,
HB_Script_Gujarati,
HB_Script_Oriya,
HB_Script_Tamil,
HB_Script_Telugu,
HB_Script_Kannada,
HB_Script_Malayalam,
HB_Script_Sinhala,
HB_Script_Thai,
HB_Script_Lao,
HB_Script_Tibetan,
HB_Script_Myanmar,
HB_Script_Georgian,
HB_Script_Hangul,
HB_Script_Ogham,
HB_Script_Runic,
HB_Script_Khmer,
HB_Script_Nko,
HB_Script_Inherited,
HB_ScriptCount = HB_Script_Inherited
/*
HB_Script_Latin = Common,
HB_Script_Ethiopic = Common,
HB_Script_Cherokee = Common,
HB_Script_CanadianAboriginal = Common,
HB_Script_Mongolian = Common,
HB_Script_Hiragana = Common,
HB_Script_Katakana = Common,
HB_Script_Bopomofo = Common,
HB_Script_Han = Common,
HB_Script_Yi = Common,
HB_Script_OldItalic = Common,
HB_Script_Gothic = Common,
HB_Script_Deseret = Common,
HB_Script_Tagalog = Common,
HB_Script_Hanunoo = Common,
HB_Script_Buhid = Common,
HB_Script_Tagbanwa = Common,
HB_Script_Limbu = Common,
HB_Script_TaiLe = Common,
HB_Script_LinearB = Common,
HB_Script_Ugaritic = Common,
HB_Script_Shavian = Common,
HB_Script_Osmanya = Common,
HB_Script_Cypriot = Common,
HB_Script_Braille = Common,
HB_Script_Buginese = Common,
HB_Script_Coptic = Common,
HB_Script_NewTaiLue = Common,
HB_Script_Glagolitic = Common,
HB_Script_Tifinagh = Common,
HB_Script_SylotiNagri = Common,
HB_Script_OldPersian = Common,
HB_Script_Kharoshthi = Common,
HB_Script_Balinese = Common,
HB_Script_Cuneiform = Common,
HB_Script_Phoenician = Common,
HB_Script_PhagsPa = Common,
*/
} HB_Script;
typedef struct
{
hb_uint32 pos;
hb_uint32 length;
HB_Script script;
hb_uint8 bidiLevel;
} HB_ScriptItem;
typedef enum {
HB_LeftToRight = 0,
HB_RightToLeft = 1
} HB_StringToGlyphsFlags;
typedef enum {
HB_ShaperFlag_Default = 0,
HB_ShaperFlag_NoKerning = 1,
HB_ShaperFlag_UseDesignMetrics = 2
} HB_ShaperFlag;
/*
highest value means highest priority for justification. Justification is done by first inserting kashidas
starting with the highest priority positions, then stretching spaces, afterwards extending inter char
spacing, and last spacing between arabic words.
NoJustification is for example set for arabic where no Kashida can be inserted or for diacritics.
*/
typedef enum {
HB_NoJustification= 0, /* Justification can't be applied after this glyph */
HB_Arabic_Space = 1, /* This glyph represents a space inside arabic text */
HB_Character = 2, /* Inter-character justification point follows this glyph */
HB_Space = 4, /* This glyph represents a blank outside an Arabic run */
HB_Arabic_Normal = 7, /* Normal Middle-Of-Word glyph that connects to the right (begin) */
HB_Arabic_Waw = 8, /* Next character is final form of Waw/Ain/Qaf/Fa */
HB_Arabic_BaRa = 9, /* Next two chars are Ba + Ra/Ya/AlefMaksura */
HB_Arabic_Alef = 10, /* Next character is final form of Alef/Tah/Lam/Kaf/Gaf */
HB_Arabic_HaaDal = 11, /* Next character is final form of Haa/Dal/Taa Marbutah */
HB_Arabic_Seen = 12, /* Initial or Medial form Of Seen/Sad */
HB_Arabic_Kashida = 13 /* Kashida(U+640) in middle of word */
} HB_JustificationClass;
/* This structure is binary compatible with Uniscribe's SCRIPT_VISATTR. Would be nice to keep
* it like that. If this is a problem please tell Trolltech :)
*/
typedef struct {
hb_bitfield justification :4; /* Justification class */
hb_bitfield clusterStart :1; /* First glyph of representation of cluster */
hb_bitfield mark :1; /* needs to be positioned around base char */
hb_bitfield zeroWidth :1; /* ZWJ, ZWNJ etc, with no width */
hb_bitfield dontPrint :1;
hb_bitfield combiningClass :8;
} HB_GlyphAttributes;
typedef struct HB_FaceRec_ {
HB_Bool isSymbolFont;
HB_GDEF gdef;
HB_GSUB gsub;
HB_GPOS gpos;
HB_Bool supported_scripts[HB_ScriptCount];
HB_Buffer buffer;
HB_Script current_script;
int current_flags; /* HB_ShaperFlags */
HB_Bool has_opentype_kerning;
HB_Bool glyphs_substituted;
HB_GlyphAttributes *tmpAttributes;
unsigned int *tmpLogClusters;
int length;
int orig_nglyphs;
} HB_FaceRec;
typedef HB_Error (*HB_GetFontTableFunc)(void *font, HB_Tag tag, HB_Byte *buffer, HB_UInt *length);
HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc);
void HB_FreeFace(HB_Face face);
typedef struct {
HB_Fixed x, y;
HB_Fixed width, height;
HB_Fixed xOffset, yOffset;
} HB_GlyphMetrics;
typedef enum {
HB_FontAscent
} HB_FontMetric;
typedef struct {
HB_Bool (*convertStringToGlyphIndices)(HB_Font font, const HB_UChar16 *string, hb_uint32 length, HB_Glyph *glyphs, hb_uint32 *numGlyphs, HB_Bool rightToLeft);
void (*getGlyphAdvances)(HB_Font font, const HB_Glyph *glyphs, hb_uint32 numGlyphs, HB_Fixed *advances, int flags /*HB_ShaperFlag*/);
HB_Bool (*canRender)(HB_Font font, const HB_UChar16 *string, hb_uint32 length);
/* implementation needs to make sure to load a scaled glyph, so /no/ FT_LOAD_NO_SCALE */
HB_Error (*getPointInOutline)(HB_Font font, HB_Glyph glyph, int flags /*HB_ShaperFlag*/, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints);
void (*getGlyphMetrics)(HB_Font font, HB_Glyph glyph, HB_GlyphMetrics *metrics);
HB_Fixed (*getFontMetric)(HB_Font font, HB_FontMetric metric);
} HB_FontClass;
typedef struct HB_Font_ {
const HB_FontClass *klass;
/* Metrics */
HB_UShort x_ppem, y_ppem;
HB_16Dot16 x_scale, y_scale;
void *userData;
} HB_FontRec;
#ifdef HB_USE_PACKED_STRUCTS
#pragma pack(pop)
#endif
typedef struct HB_ShaperItem_ HB_ShaperItem;
struct HB_ShaperItem_ {
hb_unicode_funcs_t *ufuncs;
const HB_UChar16 *string; /* input: the Unicode UTF16 text to be shaped */
hb_uint32 stringLength; /* input: the length of the input in 16-bit words */
HB_ScriptItem item; /* input: the current run to be shaped: a run of text all in the same script that is a substring of <string> */
HB_Font font; /* input: the font: scale, units and function pointers supplying glyph indices and metrics */
HB_Face face; /* input: the shaper state; current script, access to the OpenType tables , etc. */
int shaperFlags; /* input (unused) should be set to 0; intended to support flags defined in HB_ShaperFlag */
HB_Bool glyphIndicesPresent; /* input: true if the <glyphs> array contains glyph indices ready to be shaped */
hb_uint32 initialGlyphCount; /* input: if glyphIndicesPresent is true, the number of glyph indices in the <glyphs> array */
hb_uint32 num_glyphs; /* input: capacity of output arrays <glyphs>, <attributes>, <advances>, <offsets>, and <log_clusters>; */
/* output: required capacity (may be larger than actual capacity) */
HB_Glyph *glyphs; /* output: <num_glyphs> indices of shaped glyphs */
HB_GlyphAttributes *attributes; /* output: <num_glyphs> glyph attributes */
HB_Fixed *advances; /* output: <num_glyphs> advances */
HB_FixedPoint *offsets; /* output: <num_glyphs> offsets */
unsigned short *log_clusters; /* output: for each output glyph, the index in the input of the start of its logical cluster */
/* XXX the discription for log_clusters is wrong. It maps each input position to output glyph position! */
/* internal */
HB_Bool kerning_applied; /* output: true if kerning was applied by the shaper */
};
HB_Bool HB_ShapeItem(HB_ShaperItem *item);
HB_END_HEADER
#endif

View file

@ -1,81 +0,0 @@
/*
* Copyright (C) 1998-2004 David Turner and Werner Lemberg
* Copyright (C) 2006 Behdad Esfahbod
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#ifndef HARFBUZZ_STREAM_PRIVATE_H
#define HARFBUZZ_STREAM_PRIVATE_H
#include "harfbuzz-impl.h"
#include "harfbuzz-stream.h"
HB_BEGIN_HEADER
HB_INTERNAL void
_hb_close_stream( HB_Stream stream );
HB_INTERNAL HB_Int
_hb_stream_pos( HB_Stream stream );
HB_INTERNAL HB_Error
_hb_stream_seek( HB_Stream stream,
HB_UInt pos );
HB_INTERNAL HB_Error
_hb_stream_frame_enter( HB_Stream stream,
HB_UInt size );
HB_INTERNAL void
_hb_stream_frame_exit( HB_Stream stream );
/* convenience macros */
#define SET_ERR(c) ( (error = (c)) != 0 )
#define GOTO_Table(tag) (0)
#define FILE_Pos() _hb_stream_pos( stream )
#define FILE_Seek(pos) SET_ERR( _hb_stream_seek( stream, pos ) )
#define ACCESS_Frame(size) SET_ERR( _hb_stream_frame_enter( stream, size ) )
#define FORGET_Frame() _hb_stream_frame_exit( stream )
#define GET_Byte() (*stream->cursor++)
#define GET_Short() (stream->cursor += 2, (HB_Short)( \
(*(((HB_Byte*)stream->cursor)-2) << 8) | \
*(((HB_Byte*)stream->cursor)-1) \
))
#define GET_Long() (stream->cursor += 4, (HB_Int)( \
(*(((HB_Byte*)stream->cursor)-4) << 24) | \
(*(((HB_Byte*)stream->cursor)-3) << 16) | \
(*(((HB_Byte*)stream->cursor)-2) << 8) | \
*(((HB_Byte*)stream->cursor)-1) \
))
#define GET_Char() ((HB_Char)GET_Byte())
#define GET_UShort() ((HB_UShort)GET_Short())
#define GET_ULong() ((HB_UInt)GET_Long())
#define GET_Tag4() GET_ULong()
HB_END_HEADER
#endif /* HARFBUZZ_STREAM_PRIVATE_H */

View file

@ -1,114 +0,0 @@
/*
* Copyright (C) 2005 David Turner
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
* Copyright (C) 2007 Red Hat, Inc.
*
* This is part of HarfBuzz, an OpenType Layout engine 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
*/
#include "harfbuzz-impl.h"
#include "harfbuzz-stream-private.h"
#include <stdlib.h>
#if 0
#include <stdio.h>
#define LOG(x) _hb_log x
static void
_hb_log( const char* format, ... )
{
va_list ap;
va_start( ap, format );
vfprintf( stderr, format, ap );
va_end( ap );
}
#else
#define LOG(x) do {} while (0)
#endif
HB_INTERNAL void
_hb_close_stream( HB_Stream stream )
{
if (!stream)
return;
free(stream->base);
free(stream);
}
HB_INTERNAL HB_Int
_hb_stream_pos( HB_Stream stream )
{
LOG(( "_hb_stream_pos() -> %ld\n", stream->pos ));
return stream->pos;
}
HB_INTERNAL HB_Error
_hb_stream_seek( HB_Stream stream,
HB_UInt pos )
{
HB_Error error = (HB_Error)0;
stream->pos = pos;
if (pos > stream->size)
error = ERR(HB_Err_Read_Error);
LOG(( "_hb_stream_seek(%ld) -> 0x%04X\n", pos, error ));
return error;
}
HB_INTERNAL HB_Error
_hb_stream_frame_enter( HB_Stream stream,
HB_UInt count )
{
HB_Error error = HB_Err_Ok;
/* check new position, watch for overflow */
if (HB_UNLIKELY (stream->pos + count > stream->size ||
stream->pos + count < stream->pos))
{
error = ERR(HB_Err_Read_Error);
goto Exit;
}
/* set cursor */
stream->cursor = stream->base + stream->pos;
stream->pos += count;
Exit:
LOG(( "_hb_stream_frame_enter(%ld) -> 0x%04X\n", count, error ));
return error;
}
HB_INTERNAL void
_hb_stream_frame_exit( HB_Stream stream )
{
stream->cursor = NULL;
LOG(( "_hb_stream_frame_exit()\n" ));
}

View file

@ -1,51 +0,0 @@
/*
* Copyright (C) 2005 David Turner
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#ifndef HARFBUZZ_STREAM_H
#define HARFBUZZ_STREAM_H
#include "harfbuzz-global.h"
HB_BEGIN_HEADER
#ifdef HB_USE_PACKED_STRUCTS
#pragma pack(push, 1)
#endif
typedef struct HB_StreamRec_
{
HB_Byte* base;
HB_Byte* cursor;
HB_UInt size;
HB_UInt pos;
} HB_StreamRec;
#ifdef HB_USE_PACKED_STRUCTS
#pragma pack(pop)
#endif
HB_END_HEADER
#endif

View file

@ -1,249 +0,0 @@
/*
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#include "harfbuzz-shaper.h"
#include "harfbuzz-shaper-private.h"
#include <assert.h>
/*
tibetan syllables are of the form:
head position consonant
first sub-joined consonant
....intermediate sub-joined consonants (if any)
last sub-joined consonant
sub-joined vowel (a-chung U+0F71)
standard or compound vowel sign (or 'virama' for devanagari transliteration)
*/
typedef enum {
TibetanOther,
TibetanHeadConsonant,
TibetanSubjoinedConsonant,
TibetanSubjoinedVowel,
TibetanVowel
} TibetanForm;
/* this table starts at U+0f40 */
static const unsigned char tibetanForm[0x80] = {
TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
TibetanOther, TibetanOther, TibetanOther, TibetanOther,
TibetanOther, TibetanVowel, TibetanVowel, TibetanVowel,
TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel,
TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel,
TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel,
TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel,
TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel,
TibetanOther, TibetanOther, TibetanOther, TibetanOther,
TibetanOther, TibetanOther, TibetanOther, TibetanOther,
TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
TibetanSubjoinedConsonant, TibetanOther, TibetanOther, TibetanOther
};
#define tibetan_form(c) \
((c) >= 0x0f40 && (c) < 0x0fc0 ? (TibetanForm)tibetanForm[(c) - 0x0f40] : TibetanOther)
static const HB_OpenTypeFeature tibetan_features[] = {
{ HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },
{ HB_MAKE_TAG('a', 'b', 'v', 's'), AboveSubstProperty },
{ HB_MAKE_TAG('b', 'l', 'w', 's'), BelowSubstProperty },
{ HB_MAKE_TAG('c', 'a', 'l', 't'), CaltProperty },
{0, 0}
};
static HB_Bool tibetan_shape_syllable(HB_Bool openType, HB_ShaperItem *item, HB_Bool invalid)
{
hb_uint32 i;
const HB_UChar16 *str = item->string + item->item.pos;
int len = item->item.length;
#ifndef NO_OPENTYPE
const int availableGlyphs = item->num_glyphs;
#endif
HB_Bool haveGlyphs;
HB_STACKARRAY(HB_UChar16, reordered, len + 4);
if (item->num_glyphs < item->item.length + 4) {
item->num_glyphs = item->item.length + 4;
HB_FREE_STACKARRAY(reordered);
return FALSE;
}
if (invalid) {
*reordered = 0x25cc;
memcpy(reordered+1, str, len*sizeof(HB_UChar16));
len++;
str = reordered;
}
haveGlyphs = item->font->klass->convertStringToGlyphIndices(item->font,
str, len,
item->glyphs, &item->num_glyphs,
item->item.bidiLevel % 2);
HB_FREE_STACKARRAY(reordered);
if (!haveGlyphs)
return FALSE;
for (i = 0; i < item->item.length; i++) {
item->attributes[i].mark = FALSE;
item->attributes[i].clusterStart = FALSE;
item->attributes[i].justification = 0;
item->attributes[i].zeroWidth = FALSE;
/* IDEBUG(" %d: %4x", i, str[i]); */
}
/* now we have the syllable in the right order, and can start running it through open type. */
#ifndef NO_OPENTYPE
if (openType) {
HB_OpenTypeShape(item, /*properties*/0);
if (!HB_OpenTypePosition(item, availableGlyphs, /*doLogClusters*/FALSE))
return FALSE;
} else {
HB_HeuristicPosition(item);
}
#endif
item->attributes[0].clusterStart = TRUE;
return TRUE;
}
static int tibetan_nextSyllableBoundary(const HB_UChar16 *s, int start, int end, HB_Bool *invalid)
{
const HB_UChar16 *uc = s + start;
int pos = 0;
TibetanForm state = tibetan_form(*uc);
/* qDebug("state[%d]=%d (uc=%4x)", pos, state, uc[pos]);*/
pos++;
if (state != TibetanHeadConsonant) {
if (state != TibetanOther)
*invalid = TRUE;
goto finish;
}
while (pos < end - start) {
TibetanForm newState = tibetan_form(uc[pos]);
switch(newState) {
case TibetanSubjoinedConsonant:
case TibetanSubjoinedVowel:
if (state != TibetanHeadConsonant &&
state != TibetanSubjoinedConsonant)
goto finish;
state = newState;
break;
case TibetanVowel:
if (state != TibetanHeadConsonant &&
state != TibetanSubjoinedConsonant &&
state != TibetanSubjoinedVowel)
goto finish;
break;
case TibetanOther:
case TibetanHeadConsonant:
goto finish;
}
pos++;
}
finish:
*invalid = FALSE;
return start+pos;
}
HB_Bool HB_TibetanShape(HB_ShaperItem *item)
{
HB_Bool openType = FALSE;
unsigned short *logClusters = item->log_clusters;
HB_ShaperItem syllable = *item;
int first_glyph = 0;
int sstart = item->item.pos;
int end = sstart + item->item.length;
assert(item->item.script == HB_Script_Tibetan);
#ifndef QT_NO_OPENTYPE
openType = HB_SelectScript(item, tibetan_features);
#endif
while (sstart < end) {
HB_Bool invalid;
int i;
int send = tibetan_nextSyllableBoundary(item->string, sstart, end, &invalid);
/* IDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart,
invalid ? "TRUE" : "FALSE"); */
syllable.item.pos = sstart;
syllable.item.length = send-sstart;
syllable.glyphs = item->glyphs + first_glyph;
syllable.attributes = item->attributes + first_glyph;
syllable.offsets = item->offsets + first_glyph;
syllable.advances = item->advances + first_glyph;
syllable.num_glyphs = item->num_glyphs - first_glyph;
if (!tibetan_shape_syllable(openType, &syllable, invalid)) {
item->num_glyphs += syllable.num_glyphs;
return FALSE;
}
/* fix logcluster array */
for (i = sstart; i < send; ++i)
logClusters[i-item->item.pos] = first_glyph;
sstart = send;
first_glyph += syllable.num_glyphs;
}
item->num_glyphs = first_glyph;
return TRUE;
}

View file

@ -1,38 +0,0 @@
/*
* Copyright (C) 1998-2004 David Turner and Werner Lemberg
* Copyright (C) 2006 Behdad Esfahbod
*
* This is part of HarfBuzz, an OpenType Layout engine 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.
*/
#ifndef HARFBUZZ_H
#define HARFBUZZ_H
#include "harfbuzz-external.h"
#include "harfbuzz-global.h"
#include "harfbuzz-buffer.h"
#include "harfbuzz-gdef.h"
#include "harfbuzz-gsub.h"
#include "harfbuzz-gpos.h"
#include "harfbuzz-open.h"
#include "harfbuzz-shaper.h"
#endif /* HARFBUZZ_OPEN_H */