ICU-9868 morx support (contributed)

X-SVN-Rev: 33130
This commit is contained in:
Steven R. Loomis 2013-02-06 07:01:19 +00:00
parent bd47a9bba6
commit 3509164083
42 changed files with 3072 additions and 92 deletions

View File

@ -1,6 +1,6 @@
/*
/**
*
* (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
* (C) Copyright IBM Corp. and Others 1998-2013 - All Rights Reserved
*
*/
@ -24,6 +24,11 @@ struct ContextualGlyphInsertionHeader : MorphStateTableHeader
{
};
struct ContextualGlyphInsertionHeader2 : MorphStateTableHeader2
{
le_uint32 insertionTableOffset;
};
enum ContextualGlyphInsertionFlags
{
cgiSetMark = 0x8000,
@ -36,11 +41,17 @@ enum ContextualGlyphInsertionFlags
cgiMarkedInsertCountMask = 0x001F
};
struct LigatureSubstitutionStateEntry : StateEntry
struct ContextualGlyphInsertionStateEntry : StateEntry
{
ByteOffset currentInsertionListOffset;
ByteOffset markedInsertionListOffset;
};
struct ContextualGlyphInsertionStateEntry2 : StateEntry2
{
le_uint16 currentInsertionListIndex;
le_uint16 markedInsertionListIndex;
};
U_NAMESPACE_END
#endif

View File

@ -0,0 +1,143 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "StateTables.h"
#include "MorphStateTables.h"
#include "SubtableProcessor2.h"
#include "StateTableProcessor2.h"
#include "ContextualGlyphInsertionProc2.h"
#include "LEGlyphStorage.h"
#include "LESwaps.h"
U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphInsertionProcessor2)
ContextualGlyphInsertionProcessor2::ContextualGlyphInsertionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
: StateTableProcessor2(morphSubtableHeader)
{
contextualGlyphHeader = (const ContextualGlyphInsertionHeader2 *) morphSubtableHeader;
le_uint32 insertionTableOffset = SWAPL(contextualGlyphHeader->insertionTableOffset);
insertionTable = ((le_uint16 *) ((char *)&stateTableHeader->stHeader + insertionTableOffset));
entryTable = (const ContextualGlyphInsertionStateEntry2 *) ((char *) &stateTableHeader->stHeader + entryTableOffset);
}
ContextualGlyphInsertionProcessor2::~ContextualGlyphInsertionProcessor2()
{
}
void ContextualGlyphInsertionProcessor2::beginStateTable()
{
markGlyph = 0;
}
le_uint16 ContextualGlyphInsertionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index)
{
const ContextualGlyphInsertionStateEntry2 *entry = &entryTable[index];
le_uint16 newState = SWAPW(entry->newStateIndex);
le_uint16 flags = SWAPW(entry->flags);
le_int16 currIndex = SWAPW(entry->currentInsertionListIndex);
le_int16 markIndex = SWAPW(entry->markedInsertionListIndex);
int i = 0;
if (markIndex > 0) {
le_int16 count = (flags & cgiMarkedInsertCountMask) >> 5;
if (!(flags & cgiMarkedIsKashidaLike)) {
// extra glyph(s) will be added directly before/after the specified marked glyph
if (!(flags & cgiMarkInsertBefore)) {
LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1);
for (i = 0; i < count; i++, markIndex++) {
insertGlyphs[i] = insertionTable[markIndex];
}
insertGlyphs[i] = glyphStorage[markGlyph];
glyphStorage.applyInsertions();
} else {
LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1);
insertGlyphs[0] = glyphStorage[markGlyph];
for (i = 1; i < count + 1; i++, markIndex++) {
insertGlyphs[i] = insertionTable[markIndex];
}
glyphStorage.applyInsertions();
}
} else {
// inserted as a split-vowel-like insertion
// extra glyph(s) will be inserted some distance away from the marked glyph
if (!(flags & cgiMarkInsertBefore)) {
LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1);
for (i = 0; i < count; i++, markIndex++) {
insertGlyphs[i] = insertionTable[markIndex];
}
insertGlyphs[i] = glyphStorage[markGlyph];
glyphStorage.applyInsertions();
} else {
LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1);
insertGlyphs[0] = glyphStorage[markGlyph];
for (i = 1; i < count + 1; i++, markIndex++) {
insertGlyphs[i] = insertionTable[markIndex];
}
glyphStorage.applyInsertions();
}
}
}
if (currIndex > 0) {
le_int16 count = flags & cgiCurrentInsertCountMask;
if (!(flags & cgiCurrentIsKashidaLike)) {
// extra glyph(s) will be added directly before/after the specified current glyph
if (!(flags & cgiCurrentInsertBefore)) {
LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1);
for (i = 0; i < count; i++, currIndex++) {
insertGlyphs[i] = insertionTable[currIndex];
}
insertGlyphs[i] = glyphStorage[currGlyph];
glyphStorage.applyInsertions();
} else {
LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1);
insertGlyphs[0] = glyphStorage[currGlyph];
for (i = 1; i < count + 1; i++, currIndex++) {
insertGlyphs[i] = insertionTable[currIndex];
}
glyphStorage.applyInsertions();
}
} else {
// inserted as a split-vowel-like insertion
// extra glyph(s) will be inserted some distance away from the current glyph
if (!(flags & cgiCurrentInsertBefore)) {
LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1);
for (i = 0; i < count; i++, currIndex++) {
insertGlyphs[i] = insertionTable[currIndex];
}
insertGlyphs[i] = glyphStorage[currGlyph];
glyphStorage.applyInsertions();
} else {
LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1);
insertGlyphs[0] = glyphStorage[currGlyph];
for (i = 1; i < count + 1; i++, currIndex++) {
insertGlyphs[i] = insertionTable[currIndex];
}
glyphStorage.applyInsertions();
}
}
}
if (flags & cgiSetMark) {
markGlyph = currGlyph;
}
if (!(flags & cgiDontAdvance)) {
currGlyph += dir;
}
return newState;
}
void ContextualGlyphInsertionProcessor2::endStateTable()
{
}
U_NAMESPACE_END

View File

@ -0,0 +1,64 @@
/*
*
* (C) Copyright IBM Corp. and others 2013 - All Rights Reserved
*
*/
#ifndef __CONTEXTUALGLYPHINSERTIONPROCESSOR2_H
#define __CONTEXTUALGLYPHINSERTIONPROCESSOR2_H
/**
* \file
* \internal
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "SubtableProcessor2.h"
#include "StateTableProcessor2.h"
#include "ContextualGlyphInsertionProc2.h"
#include "ContextualGlyphInsertion.h"
U_NAMESPACE_BEGIN
class LEGlyphStorage;
class ContextualGlyphInsertionProcessor2 : public StateTableProcessor2
{
public:
virtual void beginStateTable();
virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index);
virtual void endStateTable();
ContextualGlyphInsertionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader);
virtual ~ContextualGlyphInsertionProcessor2();
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
*
* @stable ICU 2.8
*/
virtual UClassID getDynamicClassID() const;
/**
* ICU "poor man's RTTI", returns a UClassID for this class.
*
* @stable ICU 2.8
*/
static UClassID getStaticClassID();
private:
ContextualGlyphInsertionProcessor2();
protected:
le_int32 markGlyph;
const le_uint16* insertionTable;
const ContextualGlyphInsertionStateEntry2 *entryTable;
const ContextualGlyphInsertionHeader2 *contextualGlyphHeader;
};
U_NAMESPACE_END
#endif

View File

@ -0,0 +1,134 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "StateTables.h"
#include "MorphStateTables.h"
#include "SubtableProcessor2.h"
#include "StateTableProcessor2.h"
#include "ContextualGlyphSubstProc2.h"
#include "LEGlyphStorage.h"
#include "LESwaps.h"
#include <stdio.h>
U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphSubstitutionProcessor2)
ContextualGlyphSubstitutionProcessor2::ContextualGlyphSubstitutionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
: StateTableProcessor2(morphSubtableHeader)
{
contextualGlyphHeader = (const ContextualGlyphHeader2 *) morphSubtableHeader;
le_uint32 perGlyphTableOffset = SWAPL(contextualGlyphHeader->perGlyphTableOffset);
perGlyphTable = ((le_uint32 *) ((char *)&stateTableHeader->stHeader + perGlyphTableOffset));
entryTable = (const ContextualGlyphStateEntry2 *) ((char *) &stateTableHeader->stHeader + entryTableOffset);
}
ContextualGlyphSubstitutionProcessor2::~ContextualGlyphSubstitutionProcessor2()
{
}
void ContextualGlyphSubstitutionProcessor2::beginStateTable()
{
markGlyph = 0;
}
le_uint16 ContextualGlyphSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index)
{
const ContextualGlyphStateEntry2 *entry = &entryTable[index];
le_uint16 newState = SWAPW(entry->newStateIndex);
le_uint16 flags = SWAPW(entry->flags);
le_int16 markIndex = SWAPW(entry->markIndex);
le_int16 currIndex = SWAPW(entry->currIndex);
if (markIndex != -1) {
le_uint32 offset = SWAPL(perGlyphTable[markIndex]);
LEGlyphID mGlyph = glyphStorage[markGlyph];
TTGlyphID newGlyph = lookup(offset, mGlyph);
glyphStorage[markGlyph] = LE_SET_GLYPH(mGlyph, newGlyph);
}
if (currIndex != -1) {
le_uint32 offset = SWAPL(perGlyphTable[currIndex]);
LEGlyphID thisGlyph = glyphStorage[currGlyph];
TTGlyphID newGlyph = lookup(offset, thisGlyph);
glyphStorage[currGlyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
}
if (flags & cgsSetMark) {
markGlyph = currGlyph;
}
if (!(flags & cgsDontAdvance)) {
currGlyph += dir;
}
return newState;
}
TTGlyphID ContextualGlyphSubstitutionProcessor2::lookup(le_uint32 offset, LEGlyphID gid)
{
LookupTable *lookupTable = ((LookupTable *) ((char *)perGlyphTable + offset));
le_int16 format = SWAPW(lookupTable->format);
TTGlyphID newGlyph = 0xFFFF;
switch (format) {
case ltfSimpleArray: {
#ifdef TEST_FORMAT
// Disabled pending for design review
SimpleArrayLookupTable *lookupTable0 = (SimpleArrayLookupTable *) lookupTable;
TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
newGlyph = SWAPW(lookupTable0->valueArray[glyphCode]);
#endif
break;
}
case ltfSegmentSingle: {
#ifdef TEST_FORMAT
// Disabled pending for design review
SegmentSingleLookupTable *lookupTable2 = (SegmentSingleLookupTable *) lookupTable;
const LookupSegment *segment = lookupTable2->lookupSegment(lookupTable2->segments, gid);
if (segment != NULL) {
newGlyph = SWAPW(segment->value);
}
#endif
break;
}
case ltfSegmentArray: {
printf("Context Lookup Table Format4: specific interpretation needed!\n");
break;
}
case ltfSingleTable: {
#ifdef TEST_FORMAT
// Disabled pending for design review
SingleTableLookupTable *lookupTable6 = (SingleTableLookupTable *) lookupTable;
const LookupSingle *segment = lookupTable6->lookupSingle(lookupTable6->entries, gid);
if (segment != NULL) {
newGlyph = SWAPW(segment->value);
}
#endif
break;
}
case ltfTrimmedArray: {
TrimmedArrayLookupTable *lookupTable8 = (TrimmedArrayLookupTable *) lookupTable;
TTGlyphID firstGlyph = SWAPW(lookupTable8->firstGlyph);
TTGlyphID lastGlyph = firstGlyph + SWAPW(lookupTable8->glyphCount);
TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
if ((glyphCode >= firstGlyph) && (glyphCode < lastGlyph)) {
newGlyph = SWAPW(lookupTable8->valueArray[glyphCode - firstGlyph]);
}
}
default:
break;
}
return newGlyph;
}
void ContextualGlyphSubstitutionProcessor2::endStateTable()
{
}
U_NAMESPACE_END

View File

@ -0,0 +1,67 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#ifndef __CONTEXTUALGLYPHSUBSTITUTIONPROCESSOR2_H
#define __CONTEXTUALGLYPHSUBSTITUTIONPROCESSOR2_H
/**
* \file
* \internal
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "SubtableProcessor2.h"
#include "StateTableProcessor2.h"
#include "ContextualGlyphSubstitution.h"
U_NAMESPACE_BEGIN
class LEGlyphStorage;
class ContextualGlyphSubstitutionProcessor2 : public StateTableProcessor2
{
public:
virtual void beginStateTable();
virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index);
virtual void endStateTable();
ContextualGlyphSubstitutionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader);
virtual ~ContextualGlyphSubstitutionProcessor2();
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
*
* @stable ICU 2.8
*/
virtual UClassID getDynamicClassID() const;
/**
* ICU "poor man's RTTI", returns a UClassID for this class.
*
* @stable ICU 2.8
*/
static UClassID getStaticClassID();
private:
ContextualGlyphSubstitutionProcessor2();
TTGlyphID lookup(le_uint32 offset, LEGlyphID gid);
protected:
const le_uint32* perGlyphTable;
const ContextualGlyphStateEntry2 *entryTable;
le_int16 perGlyphTableFormat;
le_int32 markGlyph;
const ContextualGlyphHeader2 *contextualGlyphHeader;
};
U_NAMESPACE_END
#endif

View File

@ -1,6 +1,6 @@
/*
*
* (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
@ -24,6 +24,11 @@ struct ContextualGlyphSubstitutionHeader : MorphStateTableHeader
ByteOffset substitutionTableOffset;
};
struct ContextualGlyphHeader2 : MorphStateTableHeader2
{
le_uint32 perGlyphTableOffset; // no more substitution tables
};
enum ContextualGlyphSubstitutionFlags
{
cgsSetMark = 0x8000,
@ -37,5 +42,11 @@ struct ContextualGlyphSubstitutionStateEntry : StateEntry
WordOffset currOffset;
};
struct ContextualGlyphStateEntry2 : StateEntry2
{
le_uint16 markIndex;
le_uint16 currIndex;
};
U_NAMESPACE_END
#endif

View File

@ -0,0 +1,66 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "LayoutEngine.h"
#include "GXLayoutEngine2.h"
#include "LEGlyphStorage.h"
#include "MorphTables.h"
U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(GXLayoutEngine2)
GXLayoutEngine2::GXLayoutEngine2(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const MorphTableHeader2 *morphTable, le_int32 typoFlags, LEErrorCode &success)
: LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success), fMorphTable(morphTable)
{
// nothing else to do?
}
GXLayoutEngine2::~GXLayoutEngine2()
{
reset();
}
// apply 'morx' table
le_int32 GXLayoutEngine2::computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, LEGlyphStorage &glyphStorage, LEErrorCode &success)
{
if (LE_FAILURE(success)) {
return 0;
}
if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
success = LE_ILLEGAL_ARGUMENT_ERROR;
return 0;
}
mapCharsToGlyphs(chars, offset, count, rightToLeft, rightToLeft, glyphStorage, success);
if (LE_FAILURE(success)) {
return 0;
}
fMorphTable->process(glyphStorage, fTypoFlags);
return count;
}
// apply positional tables
void GXLayoutEngine2::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool /*reverse*/,
LEGlyphStorage &/*glyphStorage*/, LEErrorCode &success)
{
if (LE_FAILURE(success)) {
return;
}
if (chars == NULL || offset < 0 || count < 0) {
success = LE_ILLEGAL_ARGUMENT_ERROR;
return;
}
// FIXME: no positional processing yet...
}
U_NAMESPACE_END

View File

@ -0,0 +1,125 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#ifndef __GXLAYOUTENGINE2_H
#define __GXLAYOUTENGINE2_H
#include "LETypes.h"
#include "LayoutEngine.h"
#include "MorphTables.h"
U_NAMESPACE_BEGIN
class LEFontInstance;
class LEGlyphStorage;
/**
* This class implements layout for QuickDraw GX or Apple Advanced Typograyph (AAT)
* fonts. A font is a GX or AAT font if it contains a 'mort' table. See Apple's
* TrueType Reference Manual (http://fonts.apple.com/TTRefMan/index.html) for details.
* Information about 'mort' tables is in the chapter titled "Font Files."
*
* @internal
*/
class GXLayoutEngine2 : public LayoutEngine
{
public:
/**
* This is the main constructor. It constructs an instance of GXLayoutEngine for
* a particular font, script and language. It takes the 'mort' table as a parameter since
* LayoutEngine::layoutEngineFactory has to read the 'mort' table to know that it has a
* GX font.
*
* Note: GX and AAT fonts don't contain any script and language specific tables, so
* the script and language are ignored.
*
* @param fontInstance - the font
* @param scriptCode - the script
* @param langaugeCode - the language
* @param morphTable - the 'mort' table
* @param success - set to an error code if the operation fails
*
* @see LayoutEngine::layoutEngineFactory
* @see ScriptAndLangaugeTags.h for script and language codes
*
* @internal
*/
GXLayoutEngine2(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const MorphTableHeader2 *morphTable, le_int32 typoFlags, LEErrorCode &success);
/**
* The destructor, virtual for correct polymorphic invocation.
*
* @internal
*/
virtual ~GXLayoutEngine2();
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
*
* @stable ICU 2.8
*/
virtual UClassID getDynamicClassID() const;
/**
* ICU "poor man's RTTI", returns a UClassID for this class.
*
* @stable ICU 2.8
*/
static UClassID getStaticClassID();
protected:
/**
* The address of the 'mort' table
*
* @internal
*/
const MorphTableHeader2 *fMorphTable;
/**
* This method does GX layout using the font's 'mort' table. It converts the
* input character codes to glyph indices using mapCharsToGlyphs, and then
* applies the 'mort' table.
*
* Input parameters:
* @param chars - the input character context
* @param offset - the index of the first character to process
* @param count - the number of characters to process
* @param max - the number of characters in the input context
* @param rightToLeft - <code>TRUE</code> if the text is in a right to left directional run
* @param glyphStorage - the glyph storage object. The glyph and char index arrays will be set.
*
* Output parameters:
* @param success - set to an error code if the operation fails
*
* @return the number of glyphs in the glyph index array
*
* @internal
*/
virtual le_int32 computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
LEGlyphStorage &glyphStorage, LEErrorCode &success);
/**
* This method adjusts the glyph positions using the font's
* 'kern', 'trak', 'bsln', 'opbd' and 'just' tables.
*
* Input parameters:
* @param glyphStorage - the object holding the glyph storage. The positions will be updated as needed.
*
* Output parameters:
* @param success - set to an error code if the operation fails
*
* @internal
*/
virtual void adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
LEGlyphStorage &glyphStorage, LEErrorCode &success);
};
U_NAMESPACE_END
#endif

View File

@ -1,6 +1,6 @@
/*
*
* (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
* (C) Copyright IBM Corp. and Others 1998-2013 - All Rights Reserved
*
*/
@ -24,6 +24,10 @@ struct IndicRearrangementSubtableHeader : MorphStateTableHeader
{
};
struct IndicRearrangementSubtableHeader2 : MorphStateTableHeader2
{
};
enum IndicRearrangementFlags
{
irfMarkFirst = 0x8000,
@ -60,6 +64,10 @@ struct IndicRearrangementStateEntry : StateEntry
{
};
struct IndicRearrangementStateEntry2 : StateEntry2
{
};
U_NAMESPACE_END
#endif

View File

@ -0,0 +1,398 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "StateTables.h"
#include "MorphStateTables.h"
#include "SubtableProcessor2.h"
#include "StateTableProcessor2.h"
#include "IndicRearrangementProcessor2.h"
#include "LEGlyphStorage.h"
#include "LESwaps.h"
U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IndicRearrangementProcessor2)
IndicRearrangementProcessor2::IndicRearrangementProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
: StateTableProcessor2(morphSubtableHeader)
{
indicRearrangementSubtableHeader = (const IndicRearrangementSubtableHeader2 *) morphSubtableHeader;
entryTable = (const IndicRearrangementStateEntry2 *) ((char *) &stateTableHeader->stHeader + entryTableOffset);
}
IndicRearrangementProcessor2::~IndicRearrangementProcessor2()
{
}
void IndicRearrangementProcessor2::beginStateTable()
{
firstGlyph = 0;
lastGlyph = 0;
}
le_uint16 IndicRearrangementProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index)
{
const IndicRearrangementStateEntry2 *entry = &entryTable[index];
le_uint16 newState = SWAPW(entry->newStateIndex); // index to the new state
IndicRearrangementFlags flags = (IndicRearrangementFlags) SWAPW(entry->flags);
if (flags & irfMarkFirst) {
firstGlyph = currGlyph;
}
if (flags & irfMarkLast) {
lastGlyph = currGlyph;
}
doRearrangementAction(glyphStorage, (IndicRearrangementVerb) (flags & irfVerbMask));
if (!(flags & irfDontAdvance)) {
currGlyph += dir;
}
return newState; // index to new state
}
void IndicRearrangementProcessor2::endStateTable()
{
}
void IndicRearrangementProcessor2::doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb) const
{
LEGlyphID a, b, c, d;
le_int32 ia, ib, ic, id, ix, x;
LEErrorCode success = LE_NO_ERROR;
switch(verb)
{
case irvNoAction:
break;
case irvxA:
a = glyphStorage[firstGlyph];
ia = glyphStorage.getCharIndex(firstGlyph, success);
x = firstGlyph + 1;
while (x <= lastGlyph) {
glyphStorage[x - 1] = glyphStorage[x];
ix = glyphStorage.getCharIndex(x, success);
glyphStorage.setCharIndex(x - 1, ix, success);
x += 1;
}
glyphStorage[lastGlyph] = a;
glyphStorage.setCharIndex(lastGlyph, ia, success);
break;
case irvDx:
d = glyphStorage[lastGlyph];
id = glyphStorage.getCharIndex(lastGlyph, success);
x = lastGlyph - 1;
while (x >= firstGlyph) {
glyphStorage[x + 1] = glyphStorage[x];
ix = glyphStorage.getCharIndex(x, success);
glyphStorage.setCharIndex(x + 1, ix, success);
x -= 1;
}
glyphStorage[firstGlyph] = d;
glyphStorage.setCharIndex(firstGlyph, id, success);
break;
case irvDxA:
a = glyphStorage[firstGlyph];
ia = glyphStorage.getCharIndex(firstGlyph, success);
id = glyphStorage.getCharIndex(lastGlyph, success);
glyphStorage[firstGlyph] = glyphStorage[lastGlyph];
glyphStorage[lastGlyph] = a;
glyphStorage.setCharIndex(firstGlyph, id, success);
glyphStorage.setCharIndex(lastGlyph, ia, success);
break;
case irvxAB:
a = glyphStorage[firstGlyph];
b = glyphStorage[firstGlyph + 1];
ia = glyphStorage.getCharIndex(firstGlyph, success);
ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
x = firstGlyph + 2;
while (x <= lastGlyph) {
glyphStorage[x - 2] = glyphStorage[x];
ix = glyphStorage.getCharIndex(x, success);
glyphStorage.setCharIndex(x - 2, ix, success);
x += 1;
}
glyphStorage[lastGlyph - 1] = a;
glyphStorage[lastGlyph] = b;
glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
glyphStorage.setCharIndex(lastGlyph, ib, success);
break;
case irvxBA:
a = glyphStorage[firstGlyph];
b = glyphStorage[firstGlyph + 1];
ia = glyphStorage.getCharIndex(firstGlyph, success);
ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
x = firstGlyph + 2;
while (x <= lastGlyph) {
glyphStorage[x - 2] = glyphStorage[x];
ix = glyphStorage.getCharIndex(x, success);
glyphStorage.setCharIndex(x - 2, ix, success);
x += 1;
}
glyphStorage[lastGlyph - 1] = b;
glyphStorage[lastGlyph] = a;
glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
glyphStorage.setCharIndex(lastGlyph, ia, success);
break;
case irvCDx:
c = glyphStorage[lastGlyph - 1];
d = glyphStorage[lastGlyph];
ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
id = glyphStorage.getCharIndex(lastGlyph, success);
x = lastGlyph - 2;
while (x >= firstGlyph) {
glyphStorage[x + 2] = glyphStorage[x];
ix = glyphStorage.getCharIndex(x, success);
glyphStorage.setCharIndex(x + 2, ix, success);
x -= 1;
}
glyphStorage[firstGlyph] = c;
glyphStorage[firstGlyph + 1] = d;
glyphStorage.setCharIndex(firstGlyph, ic, success);
glyphStorage.setCharIndex(firstGlyph + 1, id, success);
break;
case irvDCx:
c = glyphStorage[lastGlyph - 1];
d = glyphStorage[lastGlyph];
ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
id = glyphStorage.getCharIndex(lastGlyph, success);
x = lastGlyph - 2;
while (x >= firstGlyph) {
glyphStorage[x + 2] = glyphStorage[x];
ix = glyphStorage.getCharIndex(x, success);
glyphStorage.setCharIndex(x + 2, ix, success);
x -= 1;
}
glyphStorage[firstGlyph] = d;
glyphStorage[firstGlyph + 1] = c;
glyphStorage.setCharIndex(firstGlyph, id, success);
glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
break;
case irvCDxA:
a = glyphStorage[firstGlyph];
c = glyphStorage[lastGlyph - 1];
d = glyphStorage[lastGlyph];
ia = glyphStorage.getCharIndex(firstGlyph, success);
ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
id = glyphStorage.getCharIndex(lastGlyph, success);
x = lastGlyph - 2;
while (x > firstGlyph) {
glyphStorage[x + 1] = glyphStorage[x];
ix = glyphStorage.getCharIndex(x, success);
glyphStorage.setCharIndex(x + 1, ix, success);
x -= 1;
}
glyphStorage[firstGlyph] = c;
glyphStorage[firstGlyph + 1] = d;
glyphStorage[lastGlyph] = a;
glyphStorage.setCharIndex(firstGlyph, ic, success);
glyphStorage.setCharIndex(firstGlyph + 1, id, success);
glyphStorage.setCharIndex(lastGlyph, ia, success);
break;
case irvDCxA:
a = glyphStorage[firstGlyph];
c = glyphStorage[lastGlyph - 1];
d = glyphStorage[lastGlyph];
ia = glyphStorage.getCharIndex(firstGlyph, success);
ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
id = glyphStorage.getCharIndex(lastGlyph, success);
x = lastGlyph - 2;
while (x > firstGlyph) {
glyphStorage[x + 1] = glyphStorage[x];
ix = glyphStorage.getCharIndex(x, success);
glyphStorage.setCharIndex(x + 1, ix, success);
x -= 1;
}
glyphStorage[firstGlyph] = d;
glyphStorage[firstGlyph + 1] = c;
glyphStorage[lastGlyph] = a;
glyphStorage.setCharIndex(firstGlyph, id, success);
glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
glyphStorage.setCharIndex(lastGlyph, ia, success);
break;
case irvDxAB:
a = glyphStorage[firstGlyph];
b = glyphStorage[firstGlyph + 1];
d = glyphStorage[lastGlyph];
ia = glyphStorage.getCharIndex(firstGlyph, success);
ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
id = glyphStorage.getCharIndex(lastGlyph, success);
x = firstGlyph + 2;
while (x < lastGlyph) {
glyphStorage[x - 2] = glyphStorage[x];
ix = glyphStorage.getCharIndex(x, success);
glyphStorage.setCharIndex(x - 2, ix, success);
x += 1;
}
glyphStorage[firstGlyph] = d;
glyphStorage[lastGlyph - 1] = a;
glyphStorage[lastGlyph] = b;
glyphStorage.setCharIndex(firstGlyph, id, success);
glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
glyphStorage.setCharIndex(lastGlyph, ib, success);
break;
case irvDxBA:
a = glyphStorage[firstGlyph];
b = glyphStorage[firstGlyph + 1];
d = glyphStorage[lastGlyph];
ia = glyphStorage.getCharIndex(firstGlyph, success);
ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
id = glyphStorage.getCharIndex(lastGlyph, success);
x = firstGlyph + 2;
while (x < lastGlyph) {
glyphStorage[x - 2] = glyphStorage[x];
ix = glyphStorage.getCharIndex(x, success);
glyphStorage.setCharIndex(x - 2, ix, success);
x += 1;
}
glyphStorage[firstGlyph] = d;
glyphStorage[lastGlyph - 1] = b;
glyphStorage[lastGlyph] = a;
glyphStorage.setCharIndex(firstGlyph, id, success);
glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
glyphStorage.setCharIndex(lastGlyph, ia, success);
break;
case irvCDxAB:
a = glyphStorage[firstGlyph];
b = glyphStorage[firstGlyph + 1];
glyphStorage[firstGlyph] = glyphStorage[lastGlyph - 1];
glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph];
glyphStorage[lastGlyph - 1] = a;
glyphStorage[lastGlyph] = b;
ia = glyphStorage.getCharIndex(firstGlyph, success);
ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
id = glyphStorage.getCharIndex(lastGlyph, success);
glyphStorage.setCharIndex(firstGlyph, ic, success);
glyphStorage.setCharIndex(firstGlyph + 1, id, success);
glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
glyphStorage.setCharIndex(lastGlyph, ib, success);
break;
case irvCDxBA:
a = glyphStorage[firstGlyph];
b = glyphStorage[firstGlyph + 1];
glyphStorage[firstGlyph] = glyphStorage[lastGlyph - 1];
glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph];
glyphStorage[lastGlyph - 1] = b;
glyphStorage[lastGlyph] = a;
ia = glyphStorage.getCharIndex(firstGlyph, success);
ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
id = glyphStorage.getCharIndex(lastGlyph, success);
glyphStorage.setCharIndex(firstGlyph, ic, success);
glyphStorage.setCharIndex(firstGlyph + 1, id, success);
glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
glyphStorage.setCharIndex(lastGlyph, ia, success);
break;
case irvDCxAB:
a = glyphStorage[firstGlyph];
b = glyphStorage[firstGlyph + 1];
glyphStorage[firstGlyph] = glyphStorage[lastGlyph];
glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph - 1];
glyphStorage[lastGlyph - 1] = a;
glyphStorage[lastGlyph] = b;
ia = glyphStorage.getCharIndex(firstGlyph, success);
ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
id = glyphStorage.getCharIndex(lastGlyph, success);
glyphStorage.setCharIndex(firstGlyph, id, success);
glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
glyphStorage.setCharIndex(lastGlyph, ib, success);
break;
case irvDCxBA:
a = glyphStorage[firstGlyph];
b = glyphStorage[firstGlyph + 1];
glyphStorage[firstGlyph] = glyphStorage[lastGlyph];
glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph - 1];
glyphStorage[lastGlyph - 1] = b;
glyphStorage[lastGlyph] = a;
ia = glyphStorage.getCharIndex(firstGlyph, success);
ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
id = glyphStorage.getCharIndex(lastGlyph, success);
glyphStorage.setCharIndex(firstGlyph, id, success);
glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
glyphStorage.setCharIndex(lastGlyph, ia, success);
break;
default:
break;
}
}
U_NAMESPACE_END

View File

@ -0,0 +1,63 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#ifndef __INDICREARRANGEMENTPROCESSOR2_H
#define __INDICREARRANGEMENTPROCESSOR2_H
/**
* \file
* \internal
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "SubtableProcessor.h"
#include "StateTableProcessor2.h"
#include "IndicRearrangement.h"
U_NAMESPACE_BEGIN
class LEGlyphStorage;
class IndicRearrangementProcessor2 : public StateTableProcessor2
{
public:
virtual void beginStateTable();
virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index);
virtual void endStateTable();
void doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb) const;
IndicRearrangementProcessor2(const MorphSubtableHeader2 *morphSubtableHeader);
virtual ~IndicRearrangementProcessor2();
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
*
* @stable ICU 2.8
*/
virtual UClassID getDynamicClassID() const;
/**
* ICU "poor man's RTTI", returns a UClassID for this class.
*
* @stable ICU 2.8
*/
static UClassID getStaticClassID();
protected:
le_int32 firstGlyph;
le_int32 lastGlyph;
const IndicRearrangementStateEntry2 *entryTable;
const IndicRearrangementSubtableHeader2 *indicRearrangementSubtableHeader;
};
U_NAMESPACE_END
#endif

View File

@ -1,6 +1,6 @@
/*
*
* (C) Copyright IBM Corp. 1998-2012 - All Rights Reserved
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
@ -454,7 +454,7 @@ enum LEFeatureTags {
LE_CALT_FEATURE_TAG = 0x63616C74UL, /**< 'calt' */
LE_CASE_FEATURE_TAG = 0x63617365UL, /**< 'case' */
LE_CCMP_FEATURE_TAG = 0x63636D70UL, /**< 'ccmp' */
LE_CJCT_FEATURE_TAG = 0x636A6374UL, /**< 'cjct' */
LE_CJCT_FEATURE_TAG = 0x636A6374UL, /**< 'cjct' */
LE_CLIG_FEATURE_TAG = 0x636C6967UL, /**< 'clig' */
LE_CPSP_FEATURE_TAG = 0x63707370UL, /**< 'cpsp' */
LE_CSWH_FEATURE_TAG = 0x63737768UL, /**< 'cswh' */
@ -518,7 +518,7 @@ enum LEFeatureTags {
LE_RAND_FEATURE_TAG = 0x72616E64UL, /**< 'rand' */
LE_RLIG_FEATURE_TAG = 0x726C6967UL, /**< 'rlig' */
LE_RPHF_FEATURE_TAG = 0x72706866UL, /**< 'rphf' */
LE_RKRF_FEATURE_TAG = 0x726B7266UL, /**< 'rkrf' */
LE_RKRF_FEATURE_TAG = 0x726B7266UL, /**< 'rkrf' */
LE_RTBD_FEATURE_TAG = 0x72746264UL, /**< 'rtbd' */
LE_RTLA_FEATURE_TAG = 0x72746C61UL, /**< 'rtla' */
LE_RUBY_FEATURE_TAG = 0x72756279UL, /**< 'ruby' */
@ -569,6 +569,64 @@ enum LEFeatureTags {
LE_ZERO_FEATURE_TAG = 0x7A65726FUL /**< 'zero' */
};
/**
* @internal
*/
enum LEFeatureENUMs {
LE_Kerning_FEATURE_ENUM = 0, /**< Requests Kerning. Formerly LayoutEngine::kTypoFlagKern */
LE_Ligatures_FEATURE_ENUM = 1, /**< Requests Ligatures. Formerly LayoutEngine::kTypoFlagLiga */
LE_CLIG_FEATURE_ENUM, /**< Feature specific enum */
LE_DLIG_FEATURE_ENUM, /**< Feature specific enum */
LE_HLIG_FEATURE_ENUM, /**< Feature specific enum */
LE_LIGA_FEATURE_ENUM, /**< Feature specific enum */
LE_RLIG_FEATURE_ENUM, /**< Feature specific enum */
LE_SMCP_FEATURE_ENUM, /**< Feature specific enum */
LE_FRAC_FEATURE_ENUM, /**< Feature specific enum */
LE_AFRC_FEATURE_ENUM, /**< Feature specific enum */
LE_ZERO_FEATURE_ENUM, /**< Feature specific enum */
LE_SWSH_FEATURE_ENUM, /**< Feature specific enum */
LE_CSWH_FEATURE_ENUM, /**< Feature specific enum */
LE_SALT_FEATURE_ENUM, /**< Feature specific enum */
LE_NALT_FEATURE_ENUM, /**< Feature specific enum */
LE_RUBY_FEATURE_ENUM, /**< Feature specific enum */
LE_SS01_FEATURE_ENUM, /**< Feature specific enum */
LE_SS02_FEATURE_ENUM, /**< Feature specific enum */
LE_SS03_FEATURE_ENUM, /**< Feature specific enum */
LE_SS04_FEATURE_ENUM, /**< Feature specific enum */
LE_SS05_FEATURE_ENUM, /**< Feature specific enum */
LE_SS06_FEATURE_ENUM, /**< Feature specific enum */
LE_SS07_FEATURE_ENUM, /**< Feature specific enum */
LE_CHAR_FILTER_FEATURE_ENUM = 31, /**< Apply CharSubstitutionFilter */
LE_FEATURE_ENUM_MAX = LE_CHAR_FILTER_FEATURE_ENUM
};
#define LE_Kerning_FEATURE_FLAG (1 << LE_Kerning_FEATURE_ENUM)
#define LE_Ligatures_FEATURE_FLAG (1 << LE_Ligatures_FEATURE_ENUM)
#define LE_CLIG_FEATURE_FLAG (1 << LE_CLIG_FEATURE_ENUM)
#define LE_DLIG_FEATURE_FLAG (1 << LE_DLIG_FEATURE_ENUM)
#define LE_HLIG_FEATURE_FLAG (1 << LE_HLIG_FEATURE_ENUM)
#define LE_LIGA_FEATURE_FLAG (1 << LE_LIGA_FEATURE_ENUM)
#define LE_RLIG_FEATURE_FLAG (1 << LE_RLIG_FEATURE_ENUM)
#define LE_SMCP_FEATURE_FLAG (1 << LE_SMCP_FEATURE_ENUM)
#define LE_FRAC_FEATURE_FLAG (1 << LE_FRAC_FEATURE_ENUM)
#define LE_AFRC_FEATURE_FLAG (1 << LE_AFRC_FEATURE_ENUM)
#define LE_ZERO_FEATURE_FLAG (1 << LE_ZERO_FEATURE_ENUM)
#define LE_SWSH_FEATURE_FLAG (1 << LE_SWSH_FEATURE_ENUM)
#define LE_CSWH_FEATURE_FLAG (1 << LE_CSWH_FEATURE_ENUM)
#define LE_SALT_FEATURE_FLAG (1 << LE_SALT_FEATURE_ENUM)
#define LE_NALT_FEATURE_FLAG (1 << LE_NALT_FEATURE_ENUM)
#define LE_RUBY_FEATURE_FLAG (1 << LE_RUBY_FEATURE_ENUM)
#define LE_SS01_FEATURE_FLAG (1 << LE_SS01_FEATURE_ENUM)
#define LE_SS02_FEATURE_FLAG (1 << LE_SS02_FEATURE_ENUM)
#define LE_SS03_FEATURE_FLAG (1 << LE_SS03_FEATURE_ENUM)
#define LE_SS04_FEATURE_FLAG (1 << LE_SS04_FEATURE_ENUM)
#define LE_SS05_FEATURE_FLAG (1 << LE_SS05_FEATURE_ENUM)
#define LE_SS06_FEATURE_FLAG (1 << LE_SS06_FEATURE_ENUM)
#define LE_SS07_FEATURE_FLAG (1 << LE_SS07_FEATURE_ENUM)
#define LE_CHAR_FILTER_FEATURE_FLAG (1 << LE_CHAR_FILTER_FEATURE_ENUM)
/**
* Error codes returned by the LayoutEngine.
*

View File

@ -1,10 +1,11 @@
/*
* (C) Copyright IBM Corp. 1998-2011 - All Rights Reserved
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*/
#include "LETypes.h"
#include "LEScripts.h"
#include "LELanguages.h"
#include "LESwaps.h"
#include "LayoutEngine.h"
#include "ArabicLayoutEngine.h"
@ -16,6 +17,8 @@
#include "ThaiLayoutEngine.h"
#include "TibetanLayoutEngine.h"
#include "GXLayoutEngine.h"
#include "GXLayoutEngine2.h"
#include "ScriptAndLanguageTags.h"
#include "CharSubstitutionFilter.h"
@ -35,8 +38,9 @@ U_NAMESPACE_BEGIN
/* Leave this copyright notice here! It needs to go somewhere in this library. */
static const char copyright[] = U_COPYRIGHT_STRING;
const le_int32 LayoutEngine::kTypoFlagKern = 0x1;
const le_int32 LayoutEngine::kTypoFlagLiga = 0x2;
/* TODO: remove these? */
const le_int32 LayoutEngine::kTypoFlagKern = LE_Kerning_FEATURE_FLAG;
const le_int32 LayoutEngine::kTypoFlagLiga = LE_Ligatures_FEATURE_FLAG;
const LEUnicode32 DefaultCharMapper::controlChars[] = {
0x0009, 0x000A, 0x000D,
@ -134,9 +138,9 @@ static const FeatureMap canonFeatureMap[] =
static const le_int32 canonFeatureMapCount = LE_ARRAY_SIZE(canonFeatureMap);
LayoutEngine::LayoutEngine(const LEFontInstance *fontInstance,
le_int32 scriptCode,
le_int32 languageCode,
LayoutEngine::LayoutEngine(const LEFontInstance *fontInstance,
le_int32 scriptCode,
le_int32 languageCode,
le_int32 typoFlags,
LEErrorCode &success)
: fGlyphStorage(NULL), fFontInstance(fontInstance), fScriptCode(scriptCode), fLanguageCode(languageCode),
@ -144,7 +148,7 @@ LayoutEngine::LayoutEngine(const LEFontInstance *fontInstance,
{
if (LE_FAILURE(success)) {
return;
}
}
fGlyphStorage = new LEGlyphStorage();
if (fGlyphStorage == NULL) {
@ -208,7 +212,7 @@ le_int32 LayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 off
if (canonGSUBTable->coversScript(scriptTag)) {
CharSubstitutionFilter *substitutionFilter = new CharSubstitutionFilter(fFontInstance);
if (substitutionFilter == NULL) {
if (substitutionFilter == NULL) {
success = LE_MEMORY_ALLOCATION_ERROR;
return 0;
}
@ -398,7 +402,7 @@ void LayoutEngine::adjustMarkGlyphs(LEGlyphStorage &glyphStorage, LEGlyphFilter
for (p = 0; p < glyphCount; p += 1) {
float next, xAdvance;
glyphStorage.getGlyphPosition(p + 1, next, ignore, success);
xAdvance = next - prev;
@ -440,7 +444,7 @@ void LayoutEngine::adjustMarkGlyphs(const LEUnicode chars[], le_int32 charCount,
for (p = 0; p < charCount; p += 1, c += direction) {
float next, xAdvance;
glyphStorage.getGlyphPosition(p + 1, next, ignore, success);
xAdvance = next - prev;
@ -495,7 +499,7 @@ le_int32 LayoutEngine::layoutChars(const LEUnicode chars[], le_int32 offset, le_
if (fGlyphStorage->getGlyphCount() > 0) {
fGlyphStorage->reset();
}
glyphCount = computeGlyphs(chars, offset, count, max, rightToLeft, *fGlyphStorage, success);
positionGlyphs(*fGlyphStorage, x, y, success);
adjustGlyphPositions(chars, offset, count, rightToLeft, *fGlyphStorage, success);
@ -507,17 +511,18 @@ void LayoutEngine::reset()
{
fGlyphStorage->reset();
}
LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, LEErrorCode &success)
{
// 3 -> kerning and ligatures
return LayoutEngine::layoutEngineFactory(fontInstance, scriptCode, languageCode, 3, success);
}
LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success)
{
static const le_uint32 gsubTableTag = LE_GSUB_TABLE_TAG;
static const le_uint32 mortTableTag = LE_MORT_TABLE_TAG;
static const le_uint32 morxTableTag = LE_MORX_TABLE_TAG;
if (LE_FAILURE(success)) {
return NULL;
@ -597,46 +602,63 @@ LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstan
break;
}
} else {
const MorphTableHeader *morphTable = (MorphTableHeader *) fontInstance->getFontTable(mortTableTag);
if (morphTable != NULL) {
result = new GXLayoutEngine(fontInstance, scriptCode, languageCode, morphTable, success);
} else {
switch (scriptCode) {
case bengScriptCode:
case devaScriptCode:
case gujrScriptCode:
case kndaScriptCode:
case mlymScriptCode:
case oryaScriptCode:
case guruScriptCode:
case tamlScriptCode:
case teluScriptCode:
case sinhScriptCode:
{
result = new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
break;
MorphTableHeader2 *table = (MorphTableHeader2 *)fontInstance->getFontTable(morxTableTag);
if (table != NULL) {
le_uint32 version = SWAPL(table->version);
switch (version) {
case 0x10000: { // mort e.g.:Skia Regular
const MorphTableHeader *mortTable = (MorphTableHeader *) fontInstance->getFontTable(mortTableTag);
if (mortTable != NULL) {
result = new GXLayoutEngine(fontInstance, scriptCode, languageCode, mortTable, success);
}
break;
}
case 0x20000: { // morx
result = new GXLayoutEngine2(fontInstance, scriptCode, languageCode, table, typoFlags, success);
break;
}
}
} else {
const MorphTableHeader *mortTable = (MorphTableHeader *) fontInstance->getFontTable(mortTableTag);
if (mortTable != NULL) { // mort
result = new GXLayoutEngine(fontInstance, scriptCode, languageCode, mortTable, success);
} else {
switch (scriptCode) {
case bengScriptCode:
case devaScriptCode:
case gujrScriptCode:
case kndaScriptCode:
case mlymScriptCode:
case oryaScriptCode:
case guruScriptCode:
case tamlScriptCode:
case teluScriptCode:
case sinhScriptCode:
{
result = new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
break;
}
case arabScriptCode:
//case hebrScriptCode:
result = new UnicodeArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
break;
case arabScriptCode:
//case hebrScriptCode:
result = new UnicodeArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
break;
//case hebrScriptCode:
// return new HebrewOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
//case hebrScriptCode:
// return new HebrewOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
case thaiScriptCode:
result = new ThaiLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
break;
case thaiScriptCode:
result = new ThaiLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
break;
case hangScriptCode:
result = new HangulOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
break;
case hangScriptCode:
result = new HangulOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
break;
default:
result = new LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
break;
default:
result = new LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
break;
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
* (C) Copyright IBM Corp. 1998-2011 - All Rights Reserved
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*/
#ifndef __LAYOUTENGINE_H
@ -64,10 +64,10 @@ class LEGlyphStorage;
class U_LAYOUT_API LayoutEngine : public UObject {
public:
#ifndef U_HIDE_INTERNAL_API
/** @internal Flag to request kerning. */
/** @internal Flag to request kerning. Use LE_Kerning_FEATURE_FLAG instead. */
static const le_int32 kTypoFlagKern;
/** @internal Flag to request ligatures. */
static const le_int32 kTypoFlagLiga;
/** @internal Flag to request ligatures. Use LE_Ligatures_FEATURE_FLAG instead. */
static const le_int32 kTypoFlagLiga;
#endif /* U_HIDE_INTERNAL_API */
protected:

View File

@ -0,0 +1,116 @@
/*
*
* (C) Copyright IBM Corp and Others. 1998-2013 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "StateTables.h"
#include "MorphStateTables.h"
#include "SubtableProcessor2.h"
#include "StateTableProcessor2.h"
#include "LigatureSubstProc2.h"
#include "LEGlyphStorage.h"
#include "LESwaps.h"
U_NAMESPACE_BEGIN
#define ExtendedComplement(m) ((le_int32) (~((le_uint32) (m))))
#define SignBit(m) ((ExtendedComplement(m) >> 1) & (le_int32)(m))
#define SignExtend(v,m) (((v) & SignBit(m))? ((v) | ExtendedComplement(m)): (v))
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LigatureSubstitutionProcessor2)
LigatureSubstitutionProcessor2::LigatureSubstitutionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
: StateTableProcessor2(morphSubtableHeader)
{
ligatureSubstitutionHeader = (const LigatureSubstitutionHeader2 *) morphSubtableHeader;
ligActionOffset = SWAPL(ligatureSubstitutionHeader->ligActionOffset);
componentOffset = SWAPL(ligatureSubstitutionHeader->componentOffset);
ligatureOffset = SWAPL(ligatureSubstitutionHeader->ligatureOffset);
entryTable = (const LigatureSubstitutionStateEntry2 *) ((char *) &stateTableHeader->stHeader + entryTableOffset);
}
LigatureSubstitutionProcessor2::~LigatureSubstitutionProcessor2()
{
}
void LigatureSubstitutionProcessor2::beginStateTable()
{
m = -1;
}
le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index)
{
const LigatureSubstitutionStateEntry2 *entry = &entryTable[index];
le_uint16 nextStateIndex = SWAPW(entry->nextStateIndex);
le_uint16 flags = SWAPW(entry->entryFlags);
le_uint16 ligActionIndex = SWAPW(entry->ligActionIndex);
if (flags & lsfSetComponent) {
if (++m >= nComponents) {
m = 0;
}
componentStack[m] = currGlyph;
}
ByteOffset actionOffset = flags & lsfPerformAction;
if (actionOffset != 0) {
const LigatureActionEntry *ap = (const LigatureActionEntry *) ((char *) &ligatureSubstitutionHeader->stHeader + ligActionOffset) + ligActionIndex;
const TTGlyphID *ligatureTable = (const TTGlyphID *) ((char *) &ligatureSubstitutionHeader->stHeader + ligatureOffset);
LigatureActionEntry action;
le_int32 offset, i = 0;
le_int32 stack[nComponents];
le_int16 mm = -1;
const le_uint16 *componentTable = (const le_uint16 *)((char *) &ligatureSubstitutionHeader->stHeader + componentOffset);
do {
le_uint32 componentGlyph = componentStack[m--]; // pop off
action = SWAPL(*ap++);
if (m < 0) {
m = nComponents - 1;
}
offset = action & lafComponentOffsetMask;
if (offset != 0) {
i += SWAPW(componentTable[LE_GET_GLYPH(glyphStorage[componentGlyph]) + (SignExtend(offset, lafComponentOffsetMask))]);
if (action & (lafLast | lafStore)) {
TTGlyphID ligatureGlyph = SWAPW(ligatureTable[i]);
glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph);
stack[++mm] = componentGlyph;
i = 0;
} else {
glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], 0xFFFF);
}
}
} while (!(action & lafLast));
while (mm >= 0) {
if (++m >= nComponents) {
m = 0;
}
componentStack[m] = stack[mm--];
}
}
if (!(flags & lsfDontAdvance)) {
currGlyph += dir;
}
return nextStateIndex;
}
void LigatureSubstitutionProcessor2::endStateTable()
{
}
U_NAMESPACE_END

View File

@ -0,0 +1,71 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#ifndef __LIGATURESUBSTITUTIONPROCESSOR2_H
#define __LIGATURESUBSTITUTIONPROCESSOR2_H
/**
* \file
* \internal
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "SubtableProcessor2.h"
#include "StateTableProcessor2.h"
#include "LigatureSubstitution.h"
U_NAMESPACE_BEGIN
class LEGlyphStorage;
#define nComponents 16
class LigatureSubstitutionProcessor2 : public StateTableProcessor2
{
public:
virtual void beginStateTable();
virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index);
virtual void endStateTable();
LigatureSubstitutionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader);
virtual ~LigatureSubstitutionProcessor2();
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
*
* @stable ICU 2.8
*/
virtual UClassID getDynamicClassID() const;
/**
* ICU "poor man's RTTI", returns a UClassID for this class.
*
* @stable ICU 2.8
*/
static UClassID getStaticClassID();
private:
LigatureSubstitutionProcessor2();
protected:
le_uint32 ligActionOffset;
le_uint32 componentOffset;
le_uint32 ligatureOffset;
const LigatureSubstitutionStateEntry2 *entryTable;
le_int32 componentStack[nComponents];
le_int16 m;
const LigatureSubstitutionHeader2 *ligatureSubstitutionHeader;
};
U_NAMESPACE_END
#endif

View File

@ -1,6 +1,6 @@
/*
*
* (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
* (C) Copyright IBM Corp. and Others 1998-2013 - All Rights Reserved
*
*/
@ -27,17 +27,32 @@ struct LigatureSubstitutionHeader : MorphStateTableHeader
ByteOffset ligatureTableOffset;
};
struct LigatureSubstitutionHeader2 : MorphStateTableHeader2
{
le_uint32 ligActionOffset;
le_uint32 componentOffset;
le_uint32 ligatureOffset;
};
enum LigatureSubstitutionFlags
{
lsfSetComponent = 0x8000,
lsfDontAdvance = 0x4000,
lsfActionOffsetMask = 0x3FFF
lsfActionOffsetMask = 0x3FFF, // N/A in morx
lsfPerformAction = 0x2000
};
struct LigatureSubstitutionStateEntry : StateEntry
{
};
struct LigatureSubstitutionStateEntry2
{
le_uint16 nextStateIndex;
le_uint16 entryFlags;
le_uint16 ligActionIndex;
};
typedef le_uint32 LigatureActionEntry;
enum LigatureActionFlags

View File

@ -1,6 +1,6 @@
/*
*
* (C) Copyright IBM Corp. 1998-2012 - All Rights Reserved
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
@ -99,6 +99,10 @@ le_uint32 LookupProcessor::applySingleLookup(le_uint16 lookupTableIndex, GlyphIt
}
const LookupTable *lookupTable = lookupListTable->getLookupTable(lookupTableIndex);
if (lookupTable == NULL) {
success = LE_INTERNAL_ERROR;
return 0;
}
le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags);
GlyphIterator tempIterator(*glyphIterator, lookupFlags);
le_uint32 delta = applyLookupTable(lookupTable, &tempIterator, fontInstance, success);

View File

@ -1,6 +1,6 @@
#******************************************************************************
#
# Copyright (C) 1999-2011, International Business Machines
# Copyright (C) 1999-2013, International Business Machines
# Corporation and others. All Rights Reserved.
#
#******************************************************************************
@ -130,7 +130,21 @@ TibetanLayoutEngine.o \
TibetanReordering.o \
HangulLayoutEngine.o \
KernTable.o \
loengine.o
loengine.o \
ContextualGlyphInsertionProc2.o \
ContextualGlyphSubstProc2.o \
GXLayoutEngine2.o \
IndicRearrangementProcessor2.o \
LigatureSubstProc2.o \
MorphTables2.o \
NonContextualGlyphSubstProc2.o \
SegmentArrayProcessor2.o \
SegmentSingleProcessor2.o \
SimpleArrayProcessor2.o \
SingleTableProcessor2.o \
StateTableProcessor2.o \
SubtableProcessor2.o \
TrimmedArrayProcessor2.o
## Header files to install
HEADERS= $(srcdir)/LayoutEngine.h $(srcdir)/LE*.h $(srcdir)/loengine.h
@ -237,4 +251,3 @@ ifneq ($(patsubst %clean,,$(MAKECMDGOALS)),)
-include $(DEPS)
endif
endif

View File

@ -1,6 +1,6 @@
/*
*
* (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
@ -24,5 +24,10 @@ struct MorphStateTableHeader : MorphSubtableHeader
StateTableHeader stHeader;
};
struct MorphStateTableHeader2 : MorphSubtableHeader2
{
StateTableHeader2 stHeader;
};
U_NAMESPACE_END
#endif

View File

@ -1,6 +1,6 @@
/*
*
* (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
@ -51,6 +51,7 @@ struct MorphTableHeader
};
typedef le_int16 SubtableCoverage;
typedef le_uint32 SubtableCoverage2;
enum SubtableCoverageFlags
{
@ -80,6 +81,302 @@ struct MorphSubtableHeader
void process(LEGlyphStorage &glyphStorage) const;
};
enum SubtableCoverageFlags2
{
scfVertical2 = 0x80000000,
scfReverse2 = 0x40000000,
scfIgnoreVt2 = 0x20000000,
scfReserved2 = 0x1FFFFF00,
scfTypeMask2 = 0x000000FF
};
struct MorphSubtableHeader2
{
le_uint32 length;
SubtableCoverage2 coverage;
FeatureFlags subtableFeatures;
void process(LEGlyphStorage &glyphStorage) const;
};
struct ChainHeader2
{
FeatureFlags defaultFlags;
le_uint32 chainLength;
le_uint32 nFeatureEntries;
le_uint32 nSubtables;
FeatureTableEntry featureTable[ANY_NUMBER];
};
struct MorphTableHeader2
{
le_int32 version;
le_uint32 nChains;
ChainHeader2 chains[ANY_NUMBER];
void process(LEGlyphStorage &glyphStorage, le_int32 typoFlags) const;
};
/*
* AAT Font Features
* source: https://developer.apple.com/fonts/registry/
* (plus addition from ATS/SFNTLayoutTypes.h)
*/
enum {
allTypographicFeaturesType = 0,
allTypeFeaturesOnSelector = 0,
allTypeFeaturesOffSelector = 1,
ligaturesType = 1,
requiredLigaturesOnSelector = 0,
requiredLigaturesOffSelector = 1,
commonLigaturesOnSelector = 2,
commonLigaturesOffSelector = 3,
rareLigaturesOnSelector = 4,
rareLigaturesOffSelector = 5,
logosOnSelector = 6,
logosOffSelector = 7,
rebusPicturesOnSelector = 8,
rebusPicturesOffSelector = 9,
diphthongLigaturesOnSelector = 10,
diphthongLigaturesOffSelector = 11,
squaredLigaturesOnSelector = 12,
squaredLigaturesOffSelector = 13,
abbrevSquaredLigaturesOnSelector = 14,
abbrevSquaredLigaturesOffSelector = 15,
symbolLigaturesOnSelector = 16,
symbolLigaturesOffSelector = 17,
contextualLigaturesOnSelector = 18,
contextualLigaturesOffSelector = 19,
historicalLigaturesOnSelector = 20,
historicalLigaturesOffSelector = 21,
cursiveConnectionType = 2,
unconnectedSelector = 0,
partiallyConnectedSelector = 1,
cursiveSelector = 2,
letterCaseType = 3,
upperAndLowerCaseSelector = 0,
allCapsSelector = 1,
allLowerCaseSelector = 2,
smallCapsSelector = 3,
initialCapsSelector = 4,
initialCapsAndSmallCapsSelector = 5,
verticalSubstitutionType = 4,
substituteVerticalFormsOnSelector = 0,
substituteVerticalFormsOffSelector = 1,
linguisticRearrangementType = 5,
linguisticRearrangementOnSelector = 0,
linguisticRearrangementOffSelector = 1,
numberSpacingType = 6,
monospacedNumbersSelector = 0,
proportionalNumbersSelector = 1,
/*
appleReserved1Type = 7,
*/
smartSwashType = 8,
wordInitialSwashesOnSelector = 0,
wordInitialSwashesOffSelector = 1,
wordFinalSwashesOnSelector = 2,
wordFinalSwashesOffSelector = 3,
lineInitialSwashesOnSelector = 4,
lineInitialSwashesOffSelector = 5,
lineFinalSwashesOnSelector = 6,
lineFinalSwashesOffSelector = 7,
nonFinalSwashesOnSelector = 8,
nonFinalSwashesOffSelector = 9,
diacriticsType = 9,
showDiacriticsSelector = 0,
hideDiacriticsSelector = 1,
decomposeDiacriticsSelector = 2,
verticalPositionType = 10,
normalPositionSelector = 0,
superiorsSelector = 1,
inferiorsSelector = 2,
ordinalsSelector = 3,
fractionsType = 11,
noFractionsSelector = 0,
verticalFractionsSelector = 1,
diagonalFractionsSelector = 2,
/*
appleReserved2Type = 12,
*/
overlappingCharactersType = 13,
preventOverlapOnSelector = 0,
preventOverlapOffSelector = 1,
typographicExtrasType = 14,
hyphensToEmDashOnSelector = 0,
hyphensToEmDashOffSelector = 1,
hyphenToEnDashOnSelector = 2,
hyphenToEnDashOffSelector = 3,
unslashedZeroOnSelector = 4,
slashedZeroOffSelector = 4,
unslashedZeroOffSelector = 5,
slashedZeroOnSelector = 5,
formInterrobangOnSelector = 6,
formInterrobangOffSelector = 7,
smartQuotesOnSelector = 8,
smartQuotesOffSelector = 9,
periodsToEllipsisOnSelector = 10,
periodsToEllipsisOffSelector = 11,
mathematicalExtrasType = 15,
hyphenToMinusOnSelector = 0,
hyphenToMinusOffSelector = 1,
asteriskToMultiplyOnSelector = 2,
asteriskToMultiplyOffSelector = 3,
slashToDivideOnSelector = 4,
slashToDivideOffSelector = 5,
inequalityLigaturesOnSelector = 6,
inequalityLigaturesOffSelector = 7,
exponentsOnSelector = 8,
exponentsOffSelector = 9,
ornamentSetsType = 16,
noOrnamentsSelector = 0,
dingbatsSelector = 1,
piCharactersSelector = 2,
fleuronsSelector = 3,
decorativeBordersSelector = 4,
internationalSymbolsSelector = 5,
mathSymbolsSelector = 6,
characterAlternativesType = 17,
noAlternatesSelector = 0,
designComplexityType = 18,
designLevel1Selector = 0,
designLevel2Selector = 1,
designLevel3Selector = 2,
designLevel4Selector = 3,
designLevel5Selector = 4,
designLevel6Selector = 5,
designLevel7Selector = 6,
styleOptionsType = 19,
noStyleOptionsSelector = 0,
displayTextSelector = 1,
engravedTextSelector = 2,
illuminatedCapsSelector = 3,
titlingCapsSelector = 4,
tallCapsSelector = 5,
characterShapeType = 20,
traditionalCharactersSelector = 0,
simplifiedCharactersSelector = 1,
jis1978CharactersSelector = 2,
jis1983CharactersSelector = 3,
jis1990CharactersSelector = 4,
traditionalAltOneSelector = 5,
traditionalAltTwoSelector = 6,
traditionalAltThreeSelector = 7,
traditionalAltFourSelector = 8,
traditionalAltFiveSelector = 9,
expertCharactersSelector = 10,
numberCaseType = 21,
lowerCaseNumbersSelector = 0,
upperCaseNumbersSelector = 1,
textSpacingType = 22,
proportionalTextSelector = 0,
monospacedTextSelector = 1,
halfWidthTextSelector = 2,
normallySpacedTextSelector = 3,
transliterationType = 23,
noTransliterationSelector = 0,
hanjaToHangulSelector = 1,
hiraganaToKatakanaSelector = 2,
katakanaToHiraganaSelector = 3,
kanaToRomanizationSelector = 4,
romanizationToHiraganaSelector = 5,
romanizationToKatakanaSelector = 6,
hanjaToHangulAltOneSelector = 7,
hanjaToHangulAltTwoSelector = 8,
hanjaToHangulAltThreeSelector = 9,
annotationType = 24,
noAnnotationSelector = 0,
boxAnnotationSelector = 1,
roundedBoxAnnotationSelector = 2,
circleAnnotationSelector = 3,
invertedCircleAnnotationSelector = 4,
parenthesisAnnotationSelector = 5,
periodAnnotationSelector = 6,
romanNumeralAnnotationSelector = 7,
diamondAnnotationSelector = 8,
kanaSpacingType = 25,
fullWidthKanaSelector = 0,
proportionalKanaSelector = 1,
ideographicSpacingType = 26,
fullWidthIdeographsSelector = 0,
proportionalIdeographsSelector = 1,
cjkRomanSpacingType = 103,
halfWidthCJKRomanSelector = 0,
proportionalCJKRomanSelector = 1,
defaultCJKRomanSelector = 2,
fullWidthCJKRomanSelector = 3,
rubyKanaType = 28,
rubyKanaOnSelector = 2,
rubyKanaOffSelector = 3,
/* The following types are provided for compatibility; note that
their use is deprecated. */
adobeCharacterSpacingType = 100, /* prefer 22 */
adobeKanaSpacingType = 101, /* prefer 25 */
adobeKanjiSpacingType = 102, /* prefer 26 */
adobeSquareLigatures = 104, /* prefer 1 */
lastFeatureType = -1
};
U_NAMESPACE_END
#endif

View File

@ -0,0 +1,204 @@
/*
* (C) Copyright IBM Corp. and others 1998 - 2013 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "LayoutTables.h"
#include "MorphTables.h"
#include "SubtableProcessor2.h"
#include "IndicRearrangementProcessor2.h"
#include "ContextualGlyphSubstProc2.h"
#include "LigatureSubstProc2.h"
#include "NonContextualGlyphSubstProc2.h"
#include "ContextualGlyphInsertionProc2.h"
#include "LEGlyphStorage.h"
#include "LESwaps.h"
U_NAMESPACE_BEGIN
void MorphTableHeader2::process(LEGlyphStorage &glyphStorage, le_int32 typoFlags) const
{
const ChainHeader2 *chainHeader = chains;
le_uint32 chainCount = SWAPL(this->nChains);
le_uint32 chain;
for (chain = 0; chain < chainCount; chain++) {
FeatureFlags flag = SWAPL(chainHeader->defaultFlags);
le_uint32 chainLength = SWAPL(chainHeader->chainLength);
le_uint32 nFeatureEntries = SWAPL(chainHeader->nFeatureEntries);
le_uint32 nSubtables = SWAPL(chainHeader->nSubtables);
const MorphSubtableHeader2 *subtableHeader =
(const MorphSubtableHeader2 *)&chainHeader->featureTable[nFeatureEntries];
le_uint32 subtable;
if (typoFlags != 0) {
le_uint32 featureEntry;
// Feature subtables
for (featureEntry = 0; featureEntry < nFeatureEntries; featureEntry++) {
FeatureTableEntry featureTableEntry = chains->featureTable[featureEntry];
le_int16 featureType = SWAPW(featureTableEntry.featureType);
le_int16 featureSetting = SWAPW(featureTableEntry.featureSetting);
le_uint32 enableFlags = SWAPL(featureTableEntry.enableFlags);
le_uint32 disableFlags = SWAPL(featureTableEntry.disableFlags);
switch (featureType) {
case ligaturesType:
if ((typoFlags & LE_Ligatures_FEATURE_ENUM ) && (featureSetting ^ 0x1)){
flag &= disableFlags;
flag |= enableFlags;
} else {
if (((typoFlags & LE_RLIG_FEATURE_FLAG) && featureSetting == requiredLigaturesOnSelector) ||
((typoFlags & LE_CLIG_FEATURE_FLAG) && featureSetting == contextualLigaturesOnSelector) ||
((typoFlags & LE_HLIG_FEATURE_FLAG) && featureSetting == historicalLigaturesOnSelector) ||
((typoFlags & LE_LIGA_FEATURE_FLAG) && featureSetting == commonLigaturesOnSelector)) {
flag &= disableFlags;
flag |= enableFlags;
}
}
break;
case letterCaseType:
if ((typoFlags & LE_SMCP_FEATURE_FLAG) && featureSetting == smallCapsSelector) {
flag &= disableFlags;
flag |= enableFlags;
}
break;
case verticalSubstitutionType:
break;
case linguisticRearrangementType:
break;
case numberSpacingType:
break;
case smartSwashType:
if ((typoFlags & LE_SWSH_FEATURE_FLAG) && (featureSetting ^ 0x1)){
flag &= disableFlags;
flag |= enableFlags;
}
break;
case diacriticsType:
break;
case verticalPositionType:
break;
case fractionsType:
if (((typoFlags & LE_FRAC_FEATURE_FLAG) && featureSetting == diagonalFractionsSelector) ||
((typoFlags & LE_AFRC_FEATURE_FLAG) && featureSetting == verticalFractionsSelector)) {
flag &= disableFlags;
flag |= enableFlags;
} else {
flag &= disableFlags;
}
break;
case typographicExtrasType:
if ((typoFlags & LE_ZERO_FEATURE_FLAG) && featureSetting == slashedZeroOnSelector) {
flag &= disableFlags;
flag |= enableFlags;
}
break;
case mathematicalExtrasType:
break;
case ornamentSetsType:
break;
case characterAlternativesType:
break;
case designComplexityType:
if (((typoFlags & LE_SS01_FEATURE_FLAG) && featureSetting == designLevel1Selector) ||
((typoFlags & LE_SS02_FEATURE_FLAG) && featureSetting == designLevel2Selector) ||
((typoFlags & LE_SS03_FEATURE_FLAG) && featureSetting == designLevel3Selector) ||
((typoFlags & LE_SS04_FEATURE_FLAG) && featureSetting == designLevel4Selector) ||
((typoFlags & LE_SS05_FEATURE_FLAG) && featureSetting == designLevel5Selector) ||
((typoFlags & LE_SS06_FEATURE_FLAG) && featureSetting == designLevel6Selector) ||
((typoFlags & LE_SS07_FEATURE_FLAG) && featureSetting == designLevel7Selector)) {
flag &= disableFlags;
flag |= enableFlags;
}
break;
case styleOptionsType:
break;
case characterShapeType:
break;
case numberCaseType:
break;
case textSpacingType:
break;
case transliterationType:
break;
case annotationType:
if ((typoFlags & LE_NALT_FEATURE_FLAG) && featureSetting == circleAnnotationSelector) {
flag &= disableFlags;
flag |= enableFlags;
}
break;
case kanaSpacingType:
break;
case ideographicSpacingType:
break;
case rubyKanaType:
if ((typoFlags & LE_RUBY_FEATURE_FLAG) && featureSetting == rubyKanaOnSelector) {
flag &= disableFlags;
flag |= enableFlags;
}
break;
case cjkRomanSpacingType:
break;
default:
break;
}
}
}
for (subtable = 0; subtable < nSubtables; subtable++) {
le_uint32 length = SWAPL(subtableHeader->length);
le_uint32 coverage = SWAPL(subtableHeader->coverage);
FeatureFlags subtableFeatures = SWAPL(subtableHeader->subtableFeatures);
// should check coverage more carefully...
if (((coverage & scfIgnoreVt2) || !(coverage & scfVertical2)) && (subtableFeatures & flag) != 0) {
subtableHeader->process(glyphStorage);
}
subtableHeader = (const MorphSubtableHeader2 *) ((char *)subtableHeader + length);
}
chainHeader = (const ChainHeader2 *)((char *)chainHeader + chainLength);
}
}
void MorphSubtableHeader2::process(LEGlyphStorage &glyphStorage) const
{
SubtableProcessor2 *processor = NULL;
switch (SWAPL(coverage) & scfTypeMask2)
{
case mstIndicRearrangement:
processor = new IndicRearrangementProcessor2(this);
break;
case mstContextualGlyphSubstitution:
processor = new ContextualGlyphSubstitutionProcessor2(this);
break;
case mstLigatureSubstitution:
processor = new LigatureSubstitutionProcessor2(this);
break;
case mstReservedUnused:
break;
case mstNonContextualGlyphSubstitution:
processor = NonContextualGlyphSubstitutionProcessor2::createInstance(this);
break;
case mstContextualGlyphInsertion:
processor = new ContextualGlyphInsertionProcessor2(this);
break;
default:
break;
}
if (processor != NULL) {
processor->process(glyphStorage);
delete processor;
}
}
U_NAMESPACE_END

View File

@ -1,7 +1,5 @@
/*
* %W% %E%
*
* (C) Copyright IBM Corp. 1998-2003 - All Rights Reserved
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
@ -25,6 +23,11 @@ struct NonContextualGlyphSubstitutionHeader : MorphSubtableHeader
LookupTable table;
};
struct NonContextualGlyphSubstitutionHeader2 : MorphSubtableHeader2
{
LookupTable table;
};
U_NAMESPACE_END
#endif

View File

@ -0,0 +1,60 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "SubtableProcessor2.h"
#include "NonContextualGlyphSubst.h"
#include "NonContextualGlyphSubstProc2.h"
#include "SimpleArrayProcessor2.h"
#include "SegmentSingleProcessor2.h"
#include "SegmentArrayProcessor2.h"
#include "SingleTableProcessor2.h"
#include "TrimmedArrayProcessor2.h"
#include "LESwaps.h"
U_NAMESPACE_BEGIN
NonContextualGlyphSubstitutionProcessor2::NonContextualGlyphSubstitutionProcessor2()
{
}
NonContextualGlyphSubstitutionProcessor2::NonContextualGlyphSubstitutionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
: SubtableProcessor2(morphSubtableHeader)
{
}
NonContextualGlyphSubstitutionProcessor2::~NonContextualGlyphSubstitutionProcessor2()
{
}
SubtableProcessor2 *NonContextualGlyphSubstitutionProcessor2::createInstance(const MorphSubtableHeader2 *morphSubtableHeader)
{
const NonContextualGlyphSubstitutionHeader2 *header = (const NonContextualGlyphSubstitutionHeader2 *) morphSubtableHeader;
switch (SWAPW(header->table.format))
{
case ltfSimpleArray:
return new SimpleArrayProcessor2(morphSubtableHeader);
case ltfSegmentSingle:
return new SegmentSingleProcessor2(morphSubtableHeader);
case ltfSegmentArray:
return new SegmentArrayProcessor2(morphSubtableHeader);
case ltfSingleTable:
return new SingleTableProcessor2(morphSubtableHeader);
case ltfTrimmedArray:
return new TrimmedArrayProcessor2(morphSubtableHeader);
default:
return NULL;
}
}
U_NAMESPACE_END

View File

@ -0,0 +1,43 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#ifndef __NONCONTEXTUALGLYPHSUBSTITUTIONPROCESSOR2_H
#define __NONCONTEXTUALGLYPHSUBSTITUTIONPROCESSOR2_H
/**
* \file
* \internal
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "SubtableProcessor2.h"
#include "NonContextualGlyphSubst.h"
U_NAMESPACE_BEGIN
class LEGlyphStorage;
class NonContextualGlyphSubstitutionProcessor2 : public SubtableProcessor2
{
public:
virtual void process(LEGlyphStorage &glyphStorage) = 0;
static SubtableProcessor2 *createInstance(const MorphSubtableHeader2 *morphSubtableHeader);
protected:
NonContextualGlyphSubstitutionProcessor2();
NonContextualGlyphSubstitutionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader);
virtual ~NonContextualGlyphSubstitutionProcessor2();
private:
NonContextualGlyphSubstitutionProcessor2(const NonContextualGlyphSubstitutionProcessor2 &other); // forbid copying of this class
NonContextualGlyphSubstitutionProcessor2 &operator=(const NonContextualGlyphSubstitutionProcessor2 &other); // forbid copying of this class
};
U_NAMESPACE_END
#endif

View File

@ -1,7 +1,7 @@
/*
*
* (C) Copyright IBM Corp. 1998-2012 - All Rights Reserved
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
@ -39,11 +39,27 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(OpenTypeLayoutEngine)
#define loclFeatureTag LE_LOCL_FEATURE_TAG
#define caltFeatureTag LE_CALT_FEATURE_TAG
// 'dlig' not used at the moment
#define dligFeatureTag 0x646C6967
#define dligFeatureTag LE_DLIG_FEATURE_TAG
#define rligFeatureTag LE_RLIG_FEATURE_TAG
#define paltFeatureTag LE_PALT_FEATURE_TAG
// 'palt'
#define paltFeatureTag 0x70616C74
#define hligFeatureTag LE_HLIG_FEATURE_TAG
#define smcpFeatureTag LE_SMCP_FEATURE_TAG
#define fracFeatureTag LE_FRAC_FEATURE_TAG
#define afrcFeatureTag LE_AFRC_FEATURE_TAG
#define zeroFeatureTag LE_ZERO_FEATURE_TAG
#define swshFeatureTag LE_SWSH_FEATURE_TAG
#define cswhFeatureTag LE_CSWH_FEATURE_TAG
#define saltFeatureTag LE_SALT_FEATURE_TAG
#define naltFeatureTag LE_NALT_FEATURE_TAG
#define rubyFeatureTag LE_RUBY_FEATURE_TAG
#define ss01FeatureTag LE_SS01_FEATURE_TAG
#define ss02FeatureTag LE_SS02_FEATURE_TAG
#define ss03FeatureTag LE_SS03_FEATURE_TAG
#define ss04FeatureTag LE_SS04_FEATURE_TAG
#define ss05FeatureTag LE_SS05_FEATURE_TAG
#define ss06FeatureTag LE_SS06_FEATURE_TAG
#define ss07FeatureTag LE_SS07_FEATURE_TAG
#define ccmpFeatureMask 0x80000000UL
#define ligaFeatureMask 0x40000000UL
@ -55,10 +71,27 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(OpenTypeLayoutEngine)
#define loclFeatureMask 0x01000000UL
#define caltFeatureMask 0x00800000UL
#define dligFeatureMask 0x00400000UL
#define rligFeatureMask 0x00200000UL
#define hligFeatureMask 0x00100000UL
#define smcpFeatureMask 0x00080000UL
#define fracFeatureMask 0x00040000UL
#define afrcFeatureMask 0x00020000UL
#define zeroFeatureMask 0x00010000UL
#define swshFeatureMask 0x00008000UL
#define cswhFeatureMask 0x00004000UL
#define saltFeatureMask 0x00002000UL
#define naltFeatureMask 0x00001000UL
#define rubyFeatureMask 0x00000800UL
#define ss01FeatureMask 0x00000400UL
#define ss02FeatureMask 0x00000200UL
#define ss03FeatureMask 0x00000100UL
#define ss04FeatureMask 0x00000080UL
#define ss05FeatureMask 0x00000040UL
#define ss06FeatureMask 0x00000020UL
#define ss07FeatureMask 0x00000010UL
#define minimalFeatures (ccmpFeatureMask | markFeatureMask | mkmkFeatureMask | loclFeatureMask | caltFeatureMask)
#define ligaFeatures (ligaFeatureMask | cligFeatureMask | minimalFeatures)
#define kernFeatures (kernFeatureMask | paltFeatureMask | minimalFeatures)
#define kernAndLigaFeatures (ligaFeatures | kernFeatures)
static const FeatureMap featureMap[] =
{
@ -70,7 +103,24 @@ static const FeatureMap featureMap[] =
{markFeatureTag, markFeatureMask},
{mkmkFeatureTag, mkmkFeatureMask},
{loclFeatureTag, loclFeatureMask},
{caltFeatureTag, caltFeatureMask}
{caltFeatureTag, caltFeatureMask},
{hligFeatureTag, hligFeatureMask},
{smcpFeatureTag, smcpFeatureMask},
{fracFeatureTag, fracFeatureMask},
{afrcFeatureTag, afrcFeatureMask},
{zeroFeatureTag, zeroFeatureMask},
{swshFeatureTag, swshFeatureMask},
{cswhFeatureTag, cswhFeatureMask},
{saltFeatureTag, saltFeatureMask},
{naltFeatureTag, naltFeatureMask},
{rubyFeatureTag, rubyFeatureMask},
{ss01FeatureTag, ss01FeatureMask},
{ss02FeatureTag, ss02FeatureMask},
{ss03FeatureTag, ss03FeatureMask},
{ss04FeatureTag, ss04FeatureMask},
{ss05FeatureTag, ss05FeatureMask},
{ss06FeatureTag, ss06FeatureMask},
{ss07FeatureTag, ss07FeatureMask}
};
static const le_int32 featureMapCount = LE_ARRAY_SIZE(featureMap);
@ -85,17 +135,65 @@ OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, l
static const le_uint32 gposTableTag = LE_GPOS_TABLE_TAG;
const GlyphPositioningTableHeader *gposTable = (const GlyphPositioningTableHeader *) getFontTable(gposTableTag);
// todo: switch to more flags and bitfield rather than list of feature tags?
switch (typoFlags & ~0x80000000L) {
case 0: break; // default
case 1: fFeatureMask = kernFeatures; break;
case 2: fFeatureMask = ligaFeatures; break;
case 3: fFeatureMask = kernAndLigaFeatures; break;
default: break;
switch (typoFlags & (LE_SS01_FEATURE_FLAG
| LE_SS02_FEATURE_FLAG
| LE_SS03_FEATURE_FLAG
| LE_SS04_FEATURE_FLAG
| LE_SS05_FEATURE_FLAG
| LE_SS06_FEATURE_FLAG
| LE_SS07_FEATURE_FLAG)) {
case LE_SS01_FEATURE_FLAG:
fFeatureMask |= ss01FeatureMask;
break;
case LE_SS02_FEATURE_FLAG:
fFeatureMask |= ss02FeatureMask;
break;
case LE_SS03_FEATURE_FLAG:
fFeatureMask |= ss03FeatureMask;
break;
case LE_SS04_FEATURE_FLAG:
fFeatureMask |= ss04FeatureMask;
break;
case LE_SS05_FEATURE_FLAG:
fFeatureMask |= ss05FeatureMask;
break;
case LE_SS06_FEATURE_FLAG:
fFeatureMask |= ss06FeatureMask;
break;
case LE_SS07_FEATURE_FLAG:
fFeatureMask |= ss07FeatureMask;
break;
}
if (typoFlags & 0x80000000L) {
fSubstitutionFilter = new CharSubstitutionFilter(fontInstance);
if (typoFlags & LE_Kerning_FEATURE_FLAG) {
fFeatureMask |= (kernFeatureMask | paltFeatureMask);
// Convenience.
}
if (typoFlags & LE_Ligatures_FEATURE_FLAG) {
fFeatureMask |= (ligaFeatureMask | cligFeatureMask);
// Convenience TODO: should add: .. dligFeatureMask | rligFeatureMask ?
}
if (typoFlags & LE_CLIG_FEATURE_FLAG) fFeatureMask |= cligFeatureMask;
if (typoFlags & LE_DLIG_FEATURE_FLAG) fFeatureMask |= dligFeatureMask;
if (typoFlags & LE_HLIG_FEATURE_FLAG) fFeatureMask |= hligFeatureMask;
if (typoFlags & LE_LIGA_FEATURE_FLAG) fFeatureMask |= ligaFeatureMask;
if (typoFlags & LE_RLIG_FEATURE_FLAG) fFeatureMask |= rligFeatureMask;
if (typoFlags & LE_SMCP_FEATURE_FLAG) fFeatureMask |= smcpFeatureMask;
if (typoFlags & LE_FRAC_FEATURE_FLAG) fFeatureMask |= fracFeatureMask;
if (typoFlags & LE_AFRC_FEATURE_FLAG) fFeatureMask |= afrcFeatureMask;
if (typoFlags & LE_ZERO_FEATURE_FLAG) fFeatureMask |= zeroFeatureMask;
if (typoFlags & LE_SWSH_FEATURE_FLAG) fFeatureMask |= swshFeatureMask;
if (typoFlags & LE_CSWH_FEATURE_FLAG) fFeatureMask |= cswhFeatureMask;
if (typoFlags & LE_SALT_FEATURE_FLAG) fFeatureMask |= saltFeatureMask;
if (typoFlags & LE_RUBY_FEATURE_FLAG) fFeatureMask |= rubyFeatureMask;
if (typoFlags & LE_NALT_FEATURE_FLAG) {
// Mutually exclusive with ALL other features. http://www.microsoft.com/typography/otspec/features_ko.htm
fFeatureMask = naltFeatureMask;
}
if (typoFlags & LE_CHAR_FILTER_FEATURE_FLAG) {
// This isn't a font feature, but requests a Char Substitution Filter
fSubstitutionFilter = new CharSubstitutionFilter(fontInstance);
}
setScriptAndLanguageTags();

View File

@ -0,0 +1,60 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "SubtableProcessor2.h"
#include "NonContextualGlyphSubst.h"
#include "NonContextualGlyphSubstProc2.h"
#include "SegmentArrayProcessor2.h"
#include "LEGlyphStorage.h"
#include "LESwaps.h"
U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SegmentArrayProcessor2)
SegmentArrayProcessor2::SegmentArrayProcessor2()
{
}
SegmentArrayProcessor2::SegmentArrayProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
: NonContextualGlyphSubstitutionProcessor2(morphSubtableHeader)
{
const NonContextualGlyphSubstitutionHeader2 *header = (const NonContextualGlyphSubstitutionHeader2 *) morphSubtableHeader;
segmentArrayLookupTable = (const SegmentArrayLookupTable *) &header->table;
}
SegmentArrayProcessor2::~SegmentArrayProcessor2()
{
}
void SegmentArrayProcessor2::process(LEGlyphStorage &glyphStorage)
{
const LookupSegment *segments = segmentArrayLookupTable->segments;
le_int32 glyphCount = glyphStorage.getGlyphCount();
le_int32 glyph;
for (glyph = 0; glyph < glyphCount; glyph += 1) {
LEGlyphID thisGlyph = glyphStorage[glyph];
const LookupSegment *lookupSegment = segmentArrayLookupTable->lookupSegment(segments, thisGlyph);
if (lookupSegment != NULL) {
TTGlyphID firstGlyph = SWAPW(lookupSegment->firstGlyph);
le_int16 offset = SWAPW(lookupSegment->value);
if (offset != 0) {
TTGlyphID *glyphArray = (TTGlyphID *) ((char *) subtableHeader + offset);
TTGlyphID newGlyph = SWAPW(glyphArray[LE_GET_GLYPH(thisGlyph) - firstGlyph]);
glyphStorage[glyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
}
}
}
}
U_NAMESPACE_END

View File

@ -0,0 +1,58 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#ifndef __SEGMENTARRAYPROCESSOR_H
#define __SEGMENTARRAYPROCESSOR_H
/**
* \file
* \internal
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "SubtableProcessor2.h"
#include "NonContextualGlyphSubst.h"
#include "NonContextualGlyphSubstProc2.h"
U_NAMESPACE_BEGIN
class LEGlyphStorage;
class SegmentArrayProcessor2 : public NonContextualGlyphSubstitutionProcessor2
{
public:
virtual void process(LEGlyphStorage &glyphStorage);
SegmentArrayProcessor2(const MorphSubtableHeader2 *morphSubtableHeader);
virtual ~SegmentArrayProcessor2();
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
*
* @stable ICU 2.8
*/
virtual UClassID getDynamicClassID() const;
/**
* ICU "poor man's RTTI", returns a UClassID for this class.
*
* @stable ICU 2.8
*/
static UClassID getStaticClassID();
private:
SegmentArrayProcessor2();
protected:
const SegmentArrayLookupTable *segmentArrayLookupTable;
};
U_NAMESPACE_END
#endif

View File

@ -0,0 +1,54 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "SubtableProcessor2.h"
#include "NonContextualGlyphSubst.h"
#include "NonContextualGlyphSubstProc2.h"
#include "SegmentSingleProcessor2.h"
#include "LEGlyphStorage.h"
#include "LESwaps.h"
U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SegmentSingleProcessor2)
SegmentSingleProcessor2::SegmentSingleProcessor2()
{
}
SegmentSingleProcessor2::SegmentSingleProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
: NonContextualGlyphSubstitutionProcessor2(morphSubtableHeader)
{
const NonContextualGlyphSubstitutionHeader2 *header = (const NonContextualGlyphSubstitutionHeader2 *) morphSubtableHeader;
segmentSingleLookupTable = (const SegmentSingleLookupTable *) &header->table;
}
SegmentSingleProcessor2::~SegmentSingleProcessor2()
{
}
void SegmentSingleProcessor2::process(LEGlyphStorage &glyphStorage)
{
const LookupSegment *segments = segmentSingleLookupTable->segments;
le_int32 glyphCount = glyphStorage.getGlyphCount();
le_int32 glyph;
for (glyph = 0; glyph < glyphCount; glyph += 1) {
LEGlyphID thisGlyph = glyphStorage[glyph];
const LookupSegment *lookupSegment = segmentSingleLookupTable->lookupSegment(segments, thisGlyph);
if (lookupSegment != NULL) {
TTGlyphID newGlyph = (TTGlyphID) LE_GET_GLYPH(thisGlyph) + SWAPW(lookupSegment->value);
glyphStorage[glyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
}
}
}
U_NAMESPACE_END

View File

@ -0,0 +1,58 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#ifndef __SEGMENTSINGLEPROCESSOR_H
#define __SEGMENTSINGLEPROCESSOR_H
/**
* \file
* \internal
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "SubtableProcessor2.h"
#include "NonContextualGlyphSubst.h"
#include "NonContextualGlyphSubstProc2.h"
U_NAMESPACE_BEGIN
class LEGlyphStorage;
class SegmentSingleProcessor2 : public NonContextualGlyphSubstitutionProcessor2
{
public:
virtual void process(LEGlyphStorage &glyphStorage);
SegmentSingleProcessor2(const MorphSubtableHeader2 *morphSubtableHeader);
virtual ~SegmentSingleProcessor2();
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
*
* @stable ICU 2.8
*/
virtual UClassID getDynamicClassID() const;
/**
* ICU "poor man's RTTI", returns a UClassID for this class.
*
* @stable ICU 2.8
*/
static UClassID getStaticClassID();
private:
SegmentSingleProcessor2();
protected:
const SegmentSingleLookupTable *segmentSingleLookupTable;
};
U_NAMESPACE_END
#endif

View File

@ -0,0 +1,51 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "SubtableProcessor2.h"
#include "NonContextualGlyphSubst.h"
#include "NonContextualGlyphSubstProc2.h"
#include "SimpleArrayProcessor2.h"
#include "LEGlyphStorage.h"
#include "LESwaps.h"
U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleArrayProcessor2)
SimpleArrayProcessor2::SimpleArrayProcessor2()
{
}
SimpleArrayProcessor2::SimpleArrayProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
: NonContextualGlyphSubstitutionProcessor2(morphSubtableHeader)
{
const NonContextualGlyphSubstitutionHeader2 *header = (const NonContextualGlyphSubstitutionHeader2 *) morphSubtableHeader;
simpleArrayLookupTable = (const SimpleArrayLookupTable *) &header->table;
}
SimpleArrayProcessor2::~SimpleArrayProcessor2()
{
}
void SimpleArrayProcessor2::process(LEGlyphStorage &glyphStorage)
{
le_int32 glyphCount = glyphStorage.getGlyphCount();
le_int32 glyph;
for (glyph = 0; glyph < glyphCount; glyph += 1) {
LEGlyphID thisGlyph = glyphStorage[glyph];
if (LE_GET_GLYPH(thisGlyph) < 0xFFFF) {
TTGlyphID newGlyph = SWAPW(simpleArrayLookupTable->valueArray[LE_GET_GLYPH(thisGlyph)]);
glyphStorage[glyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
}
}
}
U_NAMESPACE_END

View File

@ -0,0 +1,58 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#ifndef __SIMPLEARRAYPROCESSOR2_H
#define __SIMPLEARRAYPROCESSOR2_H
/**
* \file
* \internal
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "SubtableProcessor2.h"
#include "NonContextualGlyphSubst.h"
#include "NonContextualGlyphSubstProc2.h"
U_NAMESPACE_BEGIN
class LEGlyphStorage;
class SimpleArrayProcessor2 : public NonContextualGlyphSubstitutionProcessor2
{
public:
virtual void process(LEGlyphStorage &glyphStorage);
SimpleArrayProcessor2(const MorphSubtableHeader2 *morphSubtableHeader);
virtual ~SimpleArrayProcessor2();
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
*
* @stable ICU 2.8
*/
virtual UClassID getDynamicClassID() const;
/**
* ICU "poor man's RTTI", returns a UClassID for this class.
*
* @stable ICU 2.8
*/
static UClassID getStaticClassID();
private:
SimpleArrayProcessor2();
protected:
const SimpleArrayLookupTable *simpleArrayLookupTable;
};
U_NAMESPACE_END
#endif

View File

@ -0,0 +1,51 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "SubtableProcessor2.h"
#include "NonContextualGlyphSubst.h"
#include "NonContextualGlyphSubstProc2.h"
#include "SingleTableProcessor2.h"
#include "LEGlyphStorage.h"
#include "LESwaps.h"
U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SingleTableProcessor2)
SingleTableProcessor2::SingleTableProcessor2()
{
}
SingleTableProcessor2::SingleTableProcessor2(const MorphSubtableHeader2 *moprhSubtableHeader)
: NonContextualGlyphSubstitutionProcessor2(moprhSubtableHeader)
{
const NonContextualGlyphSubstitutionHeader2 *header = (const NonContextualGlyphSubstitutionHeader2 *) moprhSubtableHeader;
singleTableLookupTable = (const SingleTableLookupTable *) &header->table;
}
SingleTableProcessor2::~SingleTableProcessor2()
{
}
void SingleTableProcessor2::process(LEGlyphStorage &glyphStorage)
{
const LookupSingle *entries = singleTableLookupTable->entries;
le_int32 glyph;
le_int32 glyphCount = glyphStorage.getGlyphCount();
for (glyph = 0; glyph < glyphCount; glyph += 1) {
const LookupSingle *lookupSingle = singleTableLookupTable->lookupSingle(entries, glyphStorage[glyph]);
if (lookupSingle != NULL) {
glyphStorage[glyph] = SWAPW(lookupSingle->value);
}
}
}
U_NAMESPACE_END

View File

@ -0,0 +1,57 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#ifndef __SINGLETABLEPROCESSOR2_H
#define __SINGLETABLEPROCESSOR2_H
/**
* \file
* \internal
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "SubtableProcessor2.h"
#include "NonContextualGlyphSubst.h"
#include "NonContextualGlyphSubstProc2.h"
U_NAMESPACE_BEGIN
class LEGlyphStorage;
class SingleTableProcessor2 : public NonContextualGlyphSubstitutionProcessor2
{
public:
virtual void process(LEGlyphStorage &glyphStorage);
SingleTableProcessor2(const MorphSubtableHeader2 *morphSubtableHeader);
virtual ~SingleTableProcessor2();
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
*
* @stable ICU 2.8
*/
virtual UClassID getDynamicClassID() const;
/**
* ICU "poor man's RTTI", returns a UClassID for this class.
*
* @stable ICU 2.8
*/
static UClassID getStaticClassID();
private:
SingleTableProcessor2();
protected:
const SingleTableLookupTable *singleTableLookupTable;
};
U_NAMESPACE_END
#endif

View File

@ -0,0 +1,167 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "StateTables.h"
#include "MorphStateTables.h"
#include "SubtableProcessor2.h"
#include "StateTableProcessor2.h"
#include "LEGlyphStorage.h"
#include "LESwaps.h"
#include "LookupTables.h"
#include <stdio.h>
U_NAMESPACE_BEGIN
StateTableProcessor2::StateTableProcessor2()
{
}
StateTableProcessor2::StateTableProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
: SubtableProcessor2(morphSubtableHeader)
{
stateTableHeader = (const MorphStateTableHeader2 *) morphSubtableHeader;
nClasses = SWAPL(stateTableHeader->stHeader.nClasses);
classTableOffset = SWAPL(stateTableHeader->stHeader.classTableOffset);
stateArrayOffset = SWAPL(stateTableHeader->stHeader.stateArrayOffset);
entryTableOffset = SWAPL(stateTableHeader->stHeader.entryTableOffset);
classTable = (LookupTable *) ((char *) &stateTableHeader->stHeader + classTableOffset);
format = SWAPW(classTable->format);
stateArray = (const EntryTableIndex2 *) ((char *) &stateTableHeader->stHeader + stateArrayOffset);
}
StateTableProcessor2::~StateTableProcessor2()
{
}
void StateTableProcessor2::process(LEGlyphStorage &glyphStorage)
{
// Start at state 0
// XXX: How do we know when to start at state 1?
le_uint16 currentState = 0;
le_int32 glyphCount = glyphStorage.getGlyphCount();
le_int32 currGlyph = 0;
if ((coverage & scfReverse2) != 0) { // process glyphs in descending order
currGlyph = glyphCount - 1;
dir = -1;
} else {
dir = 1;
}
beginStateTable();
switch (format) {
case ltfSimpleArray: {
printf("Lookup Table Format0 untested!\n");
SimpleArrayLookupTable *lookupTable0 = (SimpleArrayLookupTable *) classTable;
while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
LookupValue classCode = classCodeOOB;
if (currGlyph == glyphCount || currGlyph == -1) {
// XXX: How do we handle EOT vs. EOL?
classCode = classCodeEOT;
} else {
LEGlyphID gid = glyphStorage[currGlyph];
TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
if (glyphCode == 0xFFFF) {
classCode = classCodeDEL;
} else {
classCode = SWAPW(lookupTable0->valueArray[gid]);
}
}
EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]);
currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); // return a zero-based index instead of a byte offset
}
break;
}
case ltfSegmentSingle: {
SegmentSingleLookupTable *lookupTable2 = (SegmentSingleLookupTable *) classTable;
while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
LookupValue classCode = classCodeOOB;
if (currGlyph == glyphCount || currGlyph == -1) {
// XXX: How do we handle EOT vs. EOL?
classCode = classCodeEOT;
} else {
LEGlyphID gid = glyphStorage[currGlyph];
TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
if (glyphCode == 0xFFFF) {
classCode = classCodeDEL;
} else {
const LookupSegment *segment = lookupTable2->lookupSegment(lookupTable2->segments, gid);
if (segment != NULL) {
classCode = SWAPW(segment->value);
}
}
}
EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]);
currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex);
}
break;
}
case ltfSegmentArray: {
printf("Lookup Table Format4: specific interpretation needed!\n");
break;
}
case ltfSingleTable: {
SingleTableLookupTable *lookupTable6 = (SingleTableLookupTable *) classTable;
while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
LookupValue classCode = classCodeOOB;
if (currGlyph == glyphCount || currGlyph == -1) {
// XXX: How do we handle EOT vs. EOL?
classCode = classCodeEOT;
} else {
LEGlyphID gid = glyphStorage[currGlyph];
TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
if (glyphCode == 0xFFFF) {
classCode = classCodeDEL;
} else {
const LookupSingle *segment = lookupTable6->lookupSingle(lookupTable6->entries, gid);
if (segment != NULL) {
classCode = SWAPW(segment->value);
}
}
}
EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]);
currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex);
}
break;
}
case ltfTrimmedArray: {
TrimmedArrayLookupTable *lookupTable8 = (TrimmedArrayLookupTable *) classTable;
TTGlyphID firstGlyph = SWAPW(lookupTable8->firstGlyph);
TTGlyphID lastGlyph = firstGlyph + SWAPW(lookupTable8->glyphCount);
while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
LookupValue classCode = classCodeOOB;
if (currGlyph == glyphCount || currGlyph == -1) {
// XXX: How do we handle EOT vs. EOL?
classCode = classCodeEOT;
} else {
TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(glyphStorage[currGlyph]);
if (glyphCode == 0xFFFF) {
classCode = classCodeDEL;
} else if ((glyphCode >= firstGlyph) && (glyphCode < lastGlyph)) {
classCode = SWAPW(lookupTable8->valueArray[glyphCode - firstGlyph]);
}
}
EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]);
currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex);
}
break;
}
default:
break;
}
endStateTable();
}
U_NAMESPACE_END

View File

@ -0,0 +1,59 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#ifndef __STATETABLEPROCESSOR2_H
#define __STATETABLEPROCESSOR2_H
/**
* \file
* \internal
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "MorphStateTables.h"
#include "SubtableProcessor2.h"
#include "LookupTables.h"
U_NAMESPACE_BEGIN
class LEGlyphStorage;
class StateTableProcessor2 : public SubtableProcessor2
{
public:
void process(LEGlyphStorage &glyphStorage);
virtual void beginStateTable() = 0;
virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index) = 0;
virtual void endStateTable() = 0;
protected:
StateTableProcessor2(const MorphSubtableHeader2 *morphSubtableHeader);
virtual ~StateTableProcessor2();
StateTableProcessor2();
le_int32 dir;
le_uint16 format;
le_uint32 nClasses;
le_uint32 classTableOffset;
le_uint32 stateArrayOffset;
le_uint32 entryTableOffset;
const LookupTable *classTable;
const EntryTableIndex2 *stateArray;
const MorphStateTableHeader2 *stateTableHeader;
private:
StateTableProcessor2(const StateTableProcessor2 &other); // forbid copying of this class
StateTableProcessor2 &operator=(const StateTableProcessor2 &other); // forbid copying of this class
};
U_NAMESPACE_END
#endif

View File

@ -1,6 +1,6 @@
/*
*
* (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
@ -25,6 +25,14 @@ struct StateTableHeader
ByteOffset entryTableOffset;
};
struct StateTableHeader2
{
le_uint32 nClasses;
le_uint32 classTableOffset;
le_uint32 stateArrayOffset;
le_uint32 entryTableOffset;
};
enum ClassCodes
{
classCodeEOT = 0,
@ -60,6 +68,14 @@ struct StateEntry
le_int16 flags;
};
typedef le_uint16 EntryTableIndex2;
struct StateEntry2 // same struct different interpretation
{
le_uint16 newStateIndex;
le_uint16 flags;
};
U_NAMESPACE_END
#endif

View File

@ -0,0 +1,31 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "SubtableProcessor2.h"
#include "LESwaps.h"
U_NAMESPACE_BEGIN
SubtableProcessor2::SubtableProcessor2()
{
}
SubtableProcessor2::SubtableProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
{
subtableHeader = morphSubtableHeader;
length = SWAPL(subtableHeader->length);
coverage = SWAPL(subtableHeader->coverage);
subtableFeatures = SWAPL(subtableHeader->subtableFeatures);
}
SubtableProcessor2::~SubtableProcessor2()
{
}
U_NAMESPACE_END

View File

@ -0,0 +1,46 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#ifndef __SUBTABLEPROCESSOR2_H
#define __SUBTABLEPROCESSOR2_H
/**
* \file
* \internal
*/
#include "LETypes.h"
#include "MorphTables.h"
U_NAMESPACE_BEGIN
class LEGlyphStorage;
class SubtableProcessor2 : public UMemory {
public:
virtual void process(LEGlyphStorage &glyphStorage) = 0;
virtual ~SubtableProcessor2();
protected:
SubtableProcessor2(const MorphSubtableHeader2 *morphSubtableHeader);
SubtableProcessor2();
le_uint32 length;
SubtableCoverage2 coverage;
FeatureFlags subtableFeatures;
const MorphSubtableHeader2 *subtableHeader;
private:
SubtableProcessor2(const SubtableProcessor2 &other); // forbid copying of this class
SubtableProcessor2 &operator=(const SubtableProcessor2 &other); // forbid copying of this class
};
U_NAMESPACE_END
#endif

View File

@ -0,0 +1,55 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "SubtableProcessor2.h"
#include "NonContextualGlyphSubst.h"
#include "NonContextualGlyphSubstProc2.h"
#include "TrimmedArrayProcessor2.h"
#include "LEGlyphStorage.h"
#include "LESwaps.h"
U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TrimmedArrayProcessor2)
TrimmedArrayProcessor2::TrimmedArrayProcessor2()
{
}
TrimmedArrayProcessor2::TrimmedArrayProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
: NonContextualGlyphSubstitutionProcessor2(morphSubtableHeader)
{
const NonContextualGlyphSubstitutionHeader2 *header = (const NonContextualGlyphSubstitutionHeader2 *) morphSubtableHeader;
trimmedArrayLookupTable = (const TrimmedArrayLookupTable *) &header->table;
firstGlyph = SWAPW(trimmedArrayLookupTable->firstGlyph);
lastGlyph = firstGlyph + SWAPW(trimmedArrayLookupTable->glyphCount);
}
TrimmedArrayProcessor2::~TrimmedArrayProcessor2()
{
}
void TrimmedArrayProcessor2::process(LEGlyphStorage &glyphStorage)
{
le_int32 glyphCount = glyphStorage.getGlyphCount();
le_int32 glyph;
for (glyph = 0; glyph < glyphCount; glyph += 1) {
LEGlyphID thisGlyph = glyphStorage[glyph];
TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(thisGlyph);
if ((ttGlyph > firstGlyph) && (ttGlyph < lastGlyph)) {
TTGlyphID newGlyph = SWAPW(trimmedArrayLookupTable->valueArray[ttGlyph - firstGlyph]);
glyphStorage[glyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
}
}
}
U_NAMESPACE_END

View File

@ -0,0 +1,60 @@
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#ifndef __TRIMMEDARRAYPROCESSOR2_H
#define __TRIMMEDARRAYPROCESSOR2_H
/**
* \file
* \internal
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "SubtableProcessor2.h"
#include "NonContextualGlyphSubst.h"
#include "NonContextualGlyphSubstProc2.h"
U_NAMESPACE_BEGIN
class LEGlyphStorage;
class TrimmedArrayProcessor2 : public NonContextualGlyphSubstitutionProcessor2
{
public:
virtual void process(LEGlyphStorage &glyphStorage);
TrimmedArrayProcessor2(const MorphSubtableHeader2 *morphSubtableHeader);
virtual ~TrimmedArrayProcessor2();
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
*
* @stable ICU 2.8
*/
virtual UClassID getDynamicClassID() const;
/**
* ICU "poor man's RTTI", returns a UClassID for this class.
*
* @stable ICU 2.8
*/
static UClassID getStaticClassID();
private:
TrimmedArrayProcessor2();
protected:
TTGlyphID firstGlyph;
TTGlyphID lastGlyph;
const TrimmedArrayLookupTable *trimmedArrayLookupTable;
};
U_NAMESPACE_END
#endif

View File

@ -1,7 +1,7 @@
/*
*******************************************************************************
*
* Copyright (C) 1999-2008, International Business Machines
* Copyright (C) 1999-2013, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
@ -413,7 +413,7 @@ static void checkFontVersion(PortableFontInstance *fontInstance, const char *tes
const char *getSourceTestData() {
const char *srcDataDir = NULL;
#ifdef U_TOPSRCDIR
srcDataDir = U_TOPSRCDIR U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
srcDataDir = U_TOPSRCDIR U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING;
#else
srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
FILE *f = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"rbbitst.txt", "r");
@ -991,7 +991,7 @@ static const char *ctest_dataOutDir()
*/
#if defined (U_TOPBUILDDIR)
{
dataOutDir = U_TOPBUILDDIR "data"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING;
dataOutDir = U_TOPBUILDDIR "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
}
#else