ICU-120 Initial checkin of the LayoutEngine!
X-SVN-Rev: 2909
This commit is contained in:
parent
f46dcab450
commit
54c5c881a8
@ -372,6 +372,18 @@ Package=<4>
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "layout"=..\layout\layout.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "makeconv"=..\tools\makeconv\makeconv.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
|
176
icu4c/source/layout/ArabicLayoutEngine.cpp
Normal file
176
icu4c/source/layout/ArabicLayoutEngine.cpp
Normal file
@ -0,0 +1,176 @@
|
||||
|
||||
/*
|
||||
* %W% %E%
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998, 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "LEGlyphFilter.h"
|
||||
#include "LayoutEngine.h"
|
||||
#include "OpenTypeLayoutEngine.h"
|
||||
#include "ArabicLayoutEngine.h"
|
||||
#include "ScriptAndLanguageTags.h"
|
||||
|
||||
#include "GlyphSubstitutionTables.h"
|
||||
#include "GlyphDefinitionTables.h"
|
||||
#include "GlyphPositioningTables.h"
|
||||
|
||||
#include "GDEFMarkFilter.h"
|
||||
|
||||
#include "ArabicShaping.h"
|
||||
#include "HebrewShaping.h"
|
||||
|
||||
class CharSubstitutionFilter : public LEGlyphFilter
|
||||
{
|
||||
private:
|
||||
LEFontInstance *fFontInstance;
|
||||
|
||||
public:
|
||||
CharSubstitutionFilter(LEFontInstance *fontInstance);
|
||||
le_bool accept(LEGlyphID glyph);
|
||||
};
|
||||
|
||||
CharSubstitutionFilter::CharSubstitutionFilter(LEFontInstance *fontInstance)
|
||||
: fFontInstance(fontInstance)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
le_bool CharSubstitutionFilter::accept(LEGlyphID glyph)
|
||||
{
|
||||
return fFontInstance->canDisplay((LEUnicode) glyph);
|
||||
}
|
||||
|
||||
ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
|
||||
GlyphSubstitutionTableHeader *gsubTable)
|
||||
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, gsubTable)
|
||||
{
|
||||
// nothing else to do...
|
||||
}
|
||||
|
||||
ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode)
|
||||
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode)
|
||||
{
|
||||
// nothing else to do...
|
||||
}
|
||||
|
||||
ArabicOpenTypeLayoutEngine::~ArabicOpenTypeLayoutEngine()
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
// Input: characters
|
||||
// Output: characters, char indices, tags
|
||||
// Returns: output character count
|
||||
le_int32 ArabicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
|
||||
LEUnicode *&outChars, le_int32 *&charIndices, const LETag **&featureTags)
|
||||
{
|
||||
featureTags = new const LETag*[count];
|
||||
|
||||
switch (fScriptCode) {
|
||||
case arabScriptCode:
|
||||
{
|
||||
GlyphShaper shaper(featureTags);
|
||||
|
||||
// NOTE: may not need seperate shaper if always use tags...
|
||||
// NOTE: shaper could allocate the feature tags...
|
||||
ArabicShaping::shape(chars, offset, count, max, rightToLeft, shaper);
|
||||
break;
|
||||
}
|
||||
|
||||
case hebrScriptCode:
|
||||
HebrewShaping::shape(chars, offset, count, max, rightToLeft, featureTags);
|
||||
break;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void ArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
|
||||
LEGlyphID glyphs[], le_int32 glyphCount, float positions[])
|
||||
{
|
||||
if (fGPOSTable != NULL) {
|
||||
OpenTypeLayoutEngine::adjustGlyphPositions(chars, offset, count, reverse, glyphs, glyphCount, positions);
|
||||
} else if (fGDEFTable != NULL) {
|
||||
GDEFMarkFilter filter(fGDEFTable);
|
||||
|
||||
adjustMarkGlyphs(glyphs, glyphCount, false, &filter, positions);
|
||||
} else {
|
||||
GlyphDefinitionTableHeader *gdefTable = (GlyphDefinitionTableHeader *) ArabicShaping::glyphDefinitionTable;
|
||||
GDEFMarkFilter filter(gdefTable);
|
||||
|
||||
// this won't work if LEGlyphID and LEUnicode aren't the same size...
|
||||
adjustMarkGlyphs((const LEGlyphID *) &chars[offset], count, reverse, &filter, positions);
|
||||
}
|
||||
}
|
||||
|
||||
UnicodeArabicOpenTypeLayoutEngine::UnicodeArabicOpenTypeLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode)
|
||||
: ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode)
|
||||
{
|
||||
switch (scriptCode) {
|
||||
case arabScriptCode:
|
||||
fGSUBTable = (GlyphSubstitutionTableHeader *) ArabicShaping::glyphSubstitutionTable;
|
||||
fGDEFTable = (GlyphDefinitionTableHeader *) ArabicShaping::glyphDefinitionTable;
|
||||
break;
|
||||
|
||||
case hebrScriptCode:
|
||||
fGSUBTable = (GlyphSubstitutionTableHeader *) HebrewShaping::glyphSubstitutionTable;
|
||||
fGDEFTable = (GlyphDefinitionTableHeader *) HebrewShaping::glyphDefinitionTable;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
fSubstitutionFilter = new CharSubstitutionFilter(fontInstance);
|
||||
}
|
||||
|
||||
UnicodeArabicOpenTypeLayoutEngine::~UnicodeArabicOpenTypeLayoutEngine()
|
||||
{
|
||||
delete fSubstitutionFilter;
|
||||
}
|
||||
|
||||
// "glyphs", "indices" -> glyphs, indices
|
||||
le_int32 UnicodeArabicOpenTypeLayoutEngine::glyphPostProcessing(LEGlyphID tempGlyphs[], le_int32 tempCharIndices[], le_int32 tempGlyphCount,
|
||||
LEGlyphID *&glyphs, le_int32 *&charIndices)
|
||||
{
|
||||
charIndices = tempCharIndices;
|
||||
|
||||
// NOTE: need to copy tempGlyphs to an LEUnicode array if LEGlyphID and LEUnicode aren't the same size...
|
||||
ArabicOpenTypeLayoutEngine::mapCharsToGlyphs((LEUnicode *) tempGlyphs, 0, tempGlyphCount, false, true, glyphs, charIndices);
|
||||
|
||||
return tempGlyphCount;
|
||||
}
|
||||
|
||||
void UnicodeArabicOpenTypeLayoutEngine::mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, le_bool mirror, LEGlyphID *&glyphs, le_int32 *&charIndices)
|
||||
{
|
||||
le_int32 i, dir, out;
|
||||
|
||||
out = 0;
|
||||
dir = 1;
|
||||
|
||||
if (reverse) {
|
||||
out = count - 1;
|
||||
dir = -1;
|
||||
}
|
||||
|
||||
glyphs = new LEGlyphID[count];
|
||||
charIndices = new le_int32[count];
|
||||
|
||||
for (i = 0; i < count; i += 1, out += dir) {
|
||||
glyphs[out] = (LEGlyphID) chars[offset + i];
|
||||
charIndices[out] = i;
|
||||
}
|
||||
}
|
||||
|
||||
void UnicodeArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
|
||||
LEGlyphID glyphs[], le_int32 glyphCount, float positions[])
|
||||
{
|
||||
GDEFMarkFilter filter(fGDEFTable);
|
||||
|
||||
// this won't work if LEGlyphID and LEUnicode aren't the same size...
|
||||
adjustMarkGlyphs((const LEGlyphID *) &chars[offset], count, reverse, &filter, positions);
|
||||
}
|
||||
|
||||
|
||||
|
193
icu4c/source/layout/ArabicLayoutEngine.h
Normal file
193
icu4c/source/layout/ArabicLayoutEngine.h
Normal file
@ -0,0 +1,193 @@
|
||||
|
||||
/*
|
||||
* @(#)ArabicLayoutEngine.h 1.3 00/03/15
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998, 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ARABICLAYOUTENGINE_H
|
||||
#define __ARABICLAYOUTENGINE_H
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "LEFontInstance.h"
|
||||
#include "LEGlyphFilter.h"
|
||||
#include "LayoutEngine.h"
|
||||
#include "OpenTypeLayoutEngine.h"
|
||||
|
||||
#include "GlyphSubstitutionTables.h"
|
||||
#include "GlyphDefinitionTables.h"
|
||||
#include "GlyphPositioningTables.h"
|
||||
|
||||
/**
|
||||
* This class implements OpenType layout for Arabic fonts. It overrides
|
||||
* the characerProcessing method to assign the correct OpenType feature
|
||||
* tags for the Arabic contextual forms. It also overrides the adjustGlyphPositions
|
||||
* method to guarantee that all vowel and accent glyphs have zero advance width.
|
||||
*/
|
||||
class ArabicOpenTypeLayoutEngine : public OpenTypeLayoutEngine
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This is the main constructor. It constructs an instance of ArabicOpenTypeLayoutEngine for
|
||||
* a particular font, script and language. It takes the GSUB table as a parameter since
|
||||
* LayoutEngine::layoutEngineFactory has to read the GSUB table to know that it has an
|
||||
* Indic OpenType font.
|
||||
*
|
||||
* @param fontInstance - the font
|
||||
* @param scriptCode - the script
|
||||
* @param langaugeCode - the language
|
||||
* @param gsubTable - the GSUB table
|
||||
*
|
||||
* @see LayoutEngine::layoutEngineFactory
|
||||
* @see OpenTypeLayoutEngine
|
||||
* @see ScriptAndLangaugeTags.h for script and language codes
|
||||
*/
|
||||
ArabicOpenTypeLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
|
||||
GlyphSubstitutionTableHeader *gsubTable);
|
||||
|
||||
/**
|
||||
* This constructor is used when the font requires a "canned" GSUB table which can't be known
|
||||
* until after this constructor has been invoked.
|
||||
*
|
||||
* @param fontInstance - the font
|
||||
* @param scriptCode - the script
|
||||
* @param langaugeCode - the language
|
||||
*
|
||||
* @see OpenTypeLayoutEngine
|
||||
* @see ScriptAndLangaugeTags.h for script and language codes
|
||||
*/
|
||||
ArabicOpenTypeLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode);
|
||||
|
||||
/**
|
||||
* The destructor, virtual for correct polymorphic invocation.
|
||||
*/
|
||||
virtual ~ArabicOpenTypeLayoutEngine();
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* This method does Arabic OpenType character processing. It assigns the OpenType feature
|
||||
* tags to the characters to generate the correct contextual forms and ligatures.
|
||||
*
|
||||
* 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 - true if the characters are in a right to left directional run
|
||||
*
|
||||
* Output parameters:
|
||||
* @param outChars - the output character arrayt
|
||||
* @param charIndices - the output character index array
|
||||
* @param featureTags - the output feature tag array
|
||||
*
|
||||
* @return the output character count
|
||||
*/
|
||||
virtual le_int32 characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
|
||||
LEUnicode *&outChars, le_int32 *&charIndices, const LETag **&featureTags);
|
||||
|
||||
/**
|
||||
* This method applies the GPOS table if it is present, otherwise it ensures that all vowel
|
||||
* and accent glyphs have a zero advance width by calling the adjustMarkGlyphs method.
|
||||
* If the font contains a GDEF table, that is used to identify voewls and accents. Otherwise
|
||||
* the character codes are used.
|
||||
*
|
||||
* @param chars - the input character context
|
||||
* @param offset - the offset of the first character to process
|
||||
* @param count - the number of characters to process
|
||||
* @param reverse - true if the glyphs in the glyph array have been reordered
|
||||
* @param glyphs - the input glyph array
|
||||
* @param glyphCount - the number of glyphs
|
||||
* @param positions - the position array, will be updated as needed
|
||||
*/
|
||||
virtual void adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, LEGlyphID glyphs[], le_int32 glyphCount, float positions[]);
|
||||
};
|
||||
|
||||
/**
|
||||
* The class implements OpenType layout for Arabic fonts which don't
|
||||
* contain a GSUB table, using a canned GSUB table based on Unicode
|
||||
* Arabic Presentation Forms. It overrides the mapCharsToGlyphs method
|
||||
* to use the Presentation Forms as logical glyph indices. It overrides the
|
||||
* glyphPostProcessing method to convert the Presentation Forms to actual
|
||||
* glyph indices.
|
||||
*
|
||||
* @see ArabicOpenTypeLayoutEngine
|
||||
*/
|
||||
class UnicodeArabicOpenTypeLayoutEngine : public ArabicOpenTypeLayoutEngine
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructs an instance of UnicodeArabicOpenTypeLayoutEngine for a specific font,
|
||||
* script and language.
|
||||
*
|
||||
* @param fontInstance - the font
|
||||
* @param scriptCode - the script
|
||||
* @param languageCode - the language
|
||||
*
|
||||
* @see LEFontInstance
|
||||
* @see ScriptAndLanguageTags.h for script and language codes
|
||||
*/
|
||||
UnicodeArabicOpenTypeLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode);
|
||||
|
||||
/**
|
||||
* The destructor, virtual for correct polymorphic invocation.
|
||||
*/
|
||||
virtual ~UnicodeArabicOpenTypeLayoutEngine();
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* This method converts the Arabic Presentation Forms in the temp glyph array
|
||||
* into actual glyph indices using ArabicOpenTypeLayoutEngine::mapCharsToGlyps.
|
||||
*
|
||||
* Input paramters:
|
||||
* @param tempGlyphs - the input presentation forms
|
||||
* @param tempCharIndices - the input character index array
|
||||
* @param tempGlyphCount - the number of Presentation Froms
|
||||
*
|
||||
* Output parameters:
|
||||
* @param glyphs - the output glyph index array
|
||||
* @param charIndices - the output character index array
|
||||
*
|
||||
* @return the number of glyph indices in the output glyph index array
|
||||
*/
|
||||
virtual le_int32 glyphPostProcessing(LEGlyphID tempGlyphs[], le_int32 tempCharIndices[], le_int32 tempGlyphCount,
|
||||
LEGlyphID *&glyphs, le_int32 *&charIndices);
|
||||
|
||||
/**
|
||||
* This method copies the input characters into the output glyph index array,
|
||||
* for use by the canned GSUB table. It also generates the character index array.
|
||||
*
|
||||
* Input parameters:
|
||||
* @param chars - the input character context
|
||||
* @param offset - the offset of the first character to be mapped
|
||||
* @param count - the number of characters to be mapped
|
||||
* @param reverse - if true, the output will be in reverse order
|
||||
* @param mirror - if true, do character mirroring
|
||||
*
|
||||
* Output parameters:
|
||||
* @param glyphs - the glyph array
|
||||
* @param charIndices - the character index array
|
||||
*/
|
||||
virtual void mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, le_bool mirror,
|
||||
LEGlyphID *&glyphs, le_int32 *&charIndices);
|
||||
|
||||
/**
|
||||
* This method ensures that all vowel and accent glyphs have a zero advance width by calling
|
||||
* the adjustMarkGlyphs method. The character codes are used to identify the vowel and mark
|
||||
* glyphs.
|
||||
*
|
||||
* @param chars - the input character context
|
||||
* @param offset - the offset of the first character to process
|
||||
* @param count - the number of characters to process
|
||||
* @param reverse - true if the glyphs in the glyph array have been reordered
|
||||
* @param glyphs - the input glyph array
|
||||
* @param glyphCount - the number of glyphs
|
||||
* @param positions - the position array, will be updated as needed
|
||||
*/
|
||||
virtual void adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, LEGlyphID glyphs[], le_int32 glyphCount, float positions[]);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
40
icu4c/source/layout/GXLayoutEngine.cpp
Normal file
40
icu4c/source/layout/GXLayoutEngine.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
/*
|
||||
* @(#)GXLayoutEngine.cpp 1.5 00/03/15
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998, 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "LayoutEngine.h"
|
||||
#include "GXLayoutEngine.h"
|
||||
|
||||
#include "MorphTables.h"
|
||||
|
||||
GXLayoutEngine::GXLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, MorphTableHeader *morphTable)
|
||||
: LayoutEngine(fontInstance, scriptCode, languageCode), fMorphTable(morphTable)
|
||||
{
|
||||
// nothing else to do?
|
||||
}
|
||||
|
||||
GXLayoutEngine::~GXLayoutEngine()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
// apply 'mort' table
|
||||
le_int32 GXLayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, LEGlyphID *&glyphs, le_int32 *&charIndices)
|
||||
{
|
||||
mapCharsToGlyphs(chars, offset, count, false, rightToLeft, glyphs, charIndices);
|
||||
fMorphTable->process(glyphs, charIndices, count);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// apply positional tables
|
||||
void GXLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, LEGlyphID glyphs[], le_int32 glyphCount, float positions[])
|
||||
{
|
||||
// FIXME: no positional processing yet...
|
||||
}
|
||||
|
98
icu4c/source/layout/GXLayoutEngine.h
Normal file
98
icu4c/source/layout/GXLayoutEngine.h
Normal file
@ -0,0 +1,98 @@
|
||||
|
||||
/*
|
||||
* @(#)GXLayoutEngine.h 1.4 00/03/15
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998, 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __GXLAYOUTENGINE_H
|
||||
#define __GXLAYOUTENGINE_H
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "LEFontInstance.h"
|
||||
#include "LEGlyphFilter.h"
|
||||
#include "LayoutEngine.h"
|
||||
|
||||
#include "MorphTables.h"
|
||||
|
||||
/**
|
||||
* 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."
|
||||
*/
|
||||
class GXLayoutEngine : 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
|
||||
*
|
||||
* @see LayoutEngine::layoutEngineFactory
|
||||
* @see ScriptAndLangaugeTags.h for script and language codes
|
||||
*/
|
||||
GXLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, MorphTableHeader *morphTable);
|
||||
|
||||
/**
|
||||
* The destructor, virtual for correct polymorphic invocation.
|
||||
*/
|
||||
virtual ~GXLayoutEngine();
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* The address of the 'mort' table
|
||||
*/
|
||||
MorphTableHeader *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 - true if the text is in a right to left directional run
|
||||
*
|
||||
* Output parameters:
|
||||
* @param glyphs - the glyph index array
|
||||
* @param charIndices - the character index array
|
||||
*
|
||||
* @return the number of glyphs in the glyph index array
|
||||
*/
|
||||
virtual le_int32 computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
|
||||
LEGlyphID *&glyphs, le_int32 *&charIndices);
|
||||
|
||||
/**
|
||||
* This method adjusts the glyph positions using the font's
|
||||
* 'kern', 'trak', 'bsln', 'opbd' and 'just' tables.
|
||||
*
|
||||
* Input parameters:
|
||||
* @param glyphs - the input glyph array
|
||||
* @param glyphCount - the number of glyphs in the glyph array
|
||||
* @param x - the starting X position
|
||||
* @param y - the starting Y position
|
||||
*
|
||||
* Output parameters:
|
||||
* @param positions - the output X and Y positions (two entries per glyph)
|
||||
*/
|
||||
virtual void adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, LEGlyphID glyphs[],
|
||||
le_int32 glyphCount, float positions[]);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
112
icu4c/source/layout/IndicLayoutEngine.cpp
Normal file
112
icu4c/source/layout/IndicLayoutEngine.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
|
||||
/*
|
||||
* @(#)IndicLayoutEngine.cpp 1.3 00/03/15
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998, 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "LayoutEngine.h"
|
||||
#include "OpenTypeLayoutEngine.h"
|
||||
#include "IndicLayoutEngine.h"
|
||||
#include "ScriptAndLanguageTags.h"
|
||||
|
||||
#include "GlyphSubstitutionTables.h"
|
||||
#include "GlyphDefinitionTables.h"
|
||||
#include "GlyphPositioningTables.h"
|
||||
|
||||
#include "GDEFMarkFilter.h"
|
||||
|
||||
#include "CDACLayout.h"
|
||||
#include "IndicReordering.h"
|
||||
|
||||
IndicOpenTypeLayoutEngine::IndicOpenTypeLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
|
||||
GlyphSubstitutionTableHeader *gsubTable)
|
||||
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, gsubTable)
|
||||
{
|
||||
// nothing else to do...
|
||||
}
|
||||
|
||||
IndicOpenTypeLayoutEngine::IndicOpenTypeLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode)
|
||||
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode)
|
||||
{
|
||||
// nothing else to do...
|
||||
}
|
||||
|
||||
IndicOpenTypeLayoutEngine::~IndicOpenTypeLayoutEngine()
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
// Input: characters, tags
|
||||
// Output: glyphs, char indices
|
||||
le_int32 IndicOpenTypeLayoutEngine::glyphProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, const LETag **featureTags,
|
||||
LEGlyphID *&glyphs, le_int32 *&charIndices)
|
||||
{
|
||||
le_int32 retCount = OpenTypeLayoutEngine::glyphProcessing(chars, offset, count, max, rightToLeft, featureTags, glyphs, charIndices);
|
||||
|
||||
IndicReordering::adjustMPres(&chars[offset], count, glyphs, charIndices, fScriptCode);
|
||||
|
||||
return retCount;
|
||||
}
|
||||
|
||||
// Input: characters
|
||||
// Output: characters, char indices, tags
|
||||
// Returns: output character count
|
||||
le_int32 IndicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
|
||||
LEUnicode *&outChars, le_int32 *&charIndices, const LETag **&featureTags)
|
||||
{
|
||||
le_int32 worstCase = count * IndicReordering::getWorstCaseExpansion(fScriptCode);
|
||||
|
||||
outChars = new LEUnicode[worstCase];
|
||||
charIndices = new le_int32[worstCase];
|
||||
featureTags = new const LETag*[worstCase];
|
||||
|
||||
// NOTE: assumes this allocates featureTags...
|
||||
// (probably better than doing the worst case stuff here...)
|
||||
return IndicReordering::reorder(&chars[offset], count, fScriptCode, outChars, charIndices, featureTags);
|
||||
}
|
||||
|
||||
CDACOpenTypeLayoutEngine::CDACOpenTypeLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
|
||||
const CDACLayout::ScriptInfo *scriptInfo)
|
||||
: IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode), fScriptInfo(scriptInfo)
|
||||
{
|
||||
fGSUBTable = (GlyphSubstitutionTableHeader *) fScriptInfo->glyphSubstitutionTable;
|
||||
fGDEFTable = (GlyphDefinitionTableHeader *) fScriptInfo->glyphDefinitionTable;
|
||||
}
|
||||
|
||||
CDACOpenTypeLayoutEngine::~CDACOpenTypeLayoutEngine()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
// "glyph" -> char
|
||||
// char -> glyph
|
||||
le_int32 CDACOpenTypeLayoutEngine::glyphPostProcessing(LEGlyphID tempGlyphs[], le_int32 tempCharIndices[], le_int32 tempGlyphCount,
|
||||
LEGlyphID *&glyphs, le_int32 *&charIndices)
|
||||
{
|
||||
LEUnicode *tempChars;
|
||||
le_int32 glyphCount = CDACLayout::countCDACGlyphs(fScriptInfo, tempGlyphs, tempGlyphCount);
|
||||
|
||||
tempChars = new LEUnicode[glyphCount];
|
||||
glyphs = new LEGlyphID[glyphCount];
|
||||
charIndices = new le_int32[glyphCount];
|
||||
|
||||
// NOTE: might want mapCDACGlyphsToChars to count output chars and allocate the array to hold them...
|
||||
// or it could make a guess and grow the array if the guess is too small...
|
||||
CDACLayout::mapCDACGlyphsToChars(fScriptInfo, tempGlyphs, tempCharIndices, tempGlyphCount, tempChars, charIndices);
|
||||
IndicOpenTypeLayoutEngine::mapCharsToGlyphs(tempChars, 0, glyphCount, false, false, glyphs, charIndices);
|
||||
|
||||
delete[] tempChars;
|
||||
|
||||
return glyphCount;
|
||||
}
|
||||
|
||||
void CDACOpenTypeLayoutEngine::mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, le_bool mirror, LEGlyphID *&glyphs, le_int32 *&charIndices)
|
||||
{
|
||||
glyphs = new LEGlyphID[count];
|
||||
|
||||
CDACLayout::initCDACGlyphs(fScriptInfo, chars, offset, count, glyphs);
|
||||
}
|
||||
|
205
icu4c/source/layout/IndicLayoutEngine.h
Normal file
205
icu4c/source/layout/IndicLayoutEngine.h
Normal file
@ -0,0 +1,205 @@
|
||||
|
||||
/*
|
||||
* @(#)IndicLayoutEngine.h 1.4 00/03/15
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998, 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __INDICLAYOUTENGINE_H
|
||||
#define __INDICLAYOUTENGINE_H
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "LEFontInstance.h"
|
||||
#include "LEGlyphFilter.h"
|
||||
#include "LayoutEngine.h"
|
||||
#include "OpenTypeLayoutEngine.h"
|
||||
|
||||
#include "GlyphSubstitutionTables.h"
|
||||
#include "GlyphDefinitionTables.h"
|
||||
#include "GlyphPositioningTables.h"
|
||||
|
||||
#include "CDACLayout.h"
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* This class implements OpenType layout for Indic OpenType fonts, as
|
||||
* specified by Microsoft in "Creating and Supporting OpenType Fonts for
|
||||
* Indic Scripts" (http://www.microsoft.com/typography/otspec/indicot/default.htm)
|
||||
*
|
||||
* This class overrides the characterProcessing method to do Indic character processing
|
||||
* and reordering, and the glyphProcessing method to implement post-GSUB processing for
|
||||
* left matras. (See the MS spec. for more details)
|
||||
*/
|
||||
class IndicOpenTypeLayoutEngine : public OpenTypeLayoutEngine
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This is the main constructor. It constructs an instance of IndicOpenTypeLayoutEngine for
|
||||
* a particular font, script and language. It takes the GSUB table as a parameter since
|
||||
* LayoutEngine::layoutEngineFactory has to read the GSUB table to know that it has an
|
||||
* Indic OpenType font.
|
||||
*
|
||||
* @param fontInstance - the font
|
||||
* @param scriptCode - the script
|
||||
* @param langaugeCode - the language
|
||||
* @param gsubTable - the GSUB table
|
||||
*
|
||||
* @see LayoutEngine::layoutEngineFactory
|
||||
* @see OpenTypeLayoutEngine
|
||||
* @see ScriptAndLangaugeTags.h for script and language codes
|
||||
*/
|
||||
IndicOpenTypeLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
|
||||
GlyphSubstitutionTableHeader *gsubTable);
|
||||
|
||||
/**
|
||||
* This constructor is used when the font requires a "canned" GSUB table which can't be known
|
||||
* until after this constructor has been invoked.
|
||||
*
|
||||
* @param fontInstance - the font
|
||||
* @param scriptCode - the script
|
||||
* @param langaugeCode - the language
|
||||
*
|
||||
* @see OpenTypeLayoutEngine
|
||||
* @see ScriptAndLangaugeTags.h for script and language codes
|
||||
*/
|
||||
IndicOpenTypeLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode);
|
||||
|
||||
/**
|
||||
* The destructor, virtual for correct polymorphic invocation.
|
||||
*/
|
||||
virtual ~IndicOpenTypeLayoutEngine();
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* This method does Indic OpenType character processing. It assigns the OpenType feature
|
||||
* tags to the characters, and may generate output characters which have been reordered. For
|
||||
* some Indic scripts, it may also split some vowels, resulting in more output characters
|
||||
* than input characters.
|
||||
*
|
||||
* 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 - true if the characters are in a right to left directional run
|
||||
*
|
||||
* Output parameters:
|
||||
* @param outChars - the output character arrayt
|
||||
* @param charIndices - the output character index array
|
||||
* @param featureTags - the output feature tag array
|
||||
*
|
||||
* @return the output character count
|
||||
*/
|
||||
virtual le_int32 characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
|
||||
LEUnicode *&outChars, le_int32 *&charIndices, const LETag **&featureTags);
|
||||
|
||||
/**
|
||||
* This method does character to glyph mapping, applies the GSUB table and applies
|
||||
* any post GSUB fixups for left matras. It calls OpenTypeLayoutEngine::glyphProcessing
|
||||
* to do the character to glyph mapping, and apply the GSUB table.
|
||||
*
|
||||
* Note that in the case of "canned" GSUB tables, the output glyph indices may be
|
||||
* "fake" glyph indices that need to be converted to "real" glyph indices by the
|
||||
* glyphPostProcessing method.
|
||||
*
|
||||
* 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 - true if the characters are in a right to left directional run
|
||||
* @param featureTags - the feature tag array
|
||||
*
|
||||
* Output parameters:
|
||||
* @param glyphs - the output glyph index array
|
||||
* @param charIndices - the output character index array
|
||||
*
|
||||
* @return the number of glyphs in the output glyph index array
|
||||
*
|
||||
* Note: if the character index array was already set by the characterProcessing
|
||||
* method, this method won't change it.
|
||||
*/
|
||||
// Input: characters, tags
|
||||
// Output: glyphs, char indices
|
||||
virtual le_int32 glyphProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
|
||||
const LETag **featureTags, LEGlyphID *&glyphs, le_int32 *&charIndices);
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements Indic OpenType layout for CDAC fonts. Since CDAC fonts don't contain
|
||||
* a GSUB table, it uses a canned GSUB table, using logical glyph indices. Each logical glyph
|
||||
* may be rendered with several physical glyphs in the CDAC font. It uses the CDACLayout class
|
||||
* to do the layout.
|
||||
*
|
||||
* @see CDACLayout
|
||||
* @see IndicOpenTypeLayout
|
||||
*/
|
||||
class CDACOpenTypeLayoutEngine : public IndicOpenTypeLayoutEngine
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructs an instance of CDACOpenTypeLayoutEngine for a specific font, script and
|
||||
* language. The scriptInfo parameter contains the information that CDACLayout needs to
|
||||
* layout using the font, including the character to logical glyph mapping information,
|
||||
* the canned GSUB table, and the map from logical to physical glyphs. This will be obtained
|
||||
* by LayoutEngine::layoutEngineFactory to determine if the font is a CDAC font.
|
||||
*
|
||||
* @param fontInstance - the font
|
||||
* @param scriptCode - the script
|
||||
* @param languageCode - the language
|
||||
* @param scriptInfo - the CDAC script information
|
||||
*
|
||||
* @see LEFontInstance
|
||||
* @see CDACLayout
|
||||
* @see ScriptAndLanguageTags.h for script and language codes
|
||||
*/
|
||||
CDACOpenTypeLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
|
||||
const CDACLayout::ScriptInfo *scriptInfo);
|
||||
|
||||
/**
|
||||
* The destructor, virtual for correct polymorphic invocation.
|
||||
*/
|
||||
virtual ~CDACOpenTypeLayoutEngine();
|
||||
|
||||
protected:
|
||||
const CDACLayout::ScriptInfo *fScriptInfo;
|
||||
|
||||
/**
|
||||
* This method converts logical glyph indices to physical glyph indices.
|
||||
*
|
||||
* Input paramters:
|
||||
* @param tempGlyphs - the input "fake" glyph index array
|
||||
* @param tempCharIndices - the input "fake" character index array
|
||||
* @param tempGlyphCount - the number of "fake" glyph indices
|
||||
*
|
||||
* Output parameters:
|
||||
* @param glyphs - the output glyph index array
|
||||
* @param charIndices - the output character index array
|
||||
*
|
||||
* @return the number of glyph indices in the output glyph index array
|
||||
*/
|
||||
virtual le_int32 glyphPostProcessing(LEGlyphID tempGlyphs[], le_int32 tempCharIndices[], le_int32 tempGlyphCount,
|
||||
LEGlyphID *&glyphs, le_int32 *&charIndices);
|
||||
|
||||
/**
|
||||
* This method maps charcters to logical glyph indices.
|
||||
*
|
||||
* Input parameters:
|
||||
* @param chars - the input character context
|
||||
* @param offset - the offset of the first character to be mapped
|
||||
* @param count - the number of characters to be mapped
|
||||
* @param reverse - if true, the output should be in reverse order
|
||||
* @param mirror - if true, map characters like parenthesis to their mirror image
|
||||
*
|
||||
* Output parameters:
|
||||
* @param glyphs - the glyph array
|
||||
* @param charIndices - the character index array
|
||||
*/
|
||||
virtual void mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, le_bool mirror,
|
||||
LEGlyphID *&glyphs, le_int32 *&charIndices);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
263
icu4c/source/layout/LEFontInstance.h
Normal file
263
icu4c/source/layout/LEFontInstance.h
Normal file
@ -0,0 +1,263 @@
|
||||
|
||||
/*
|
||||
* @(#)LEFontInstance.h 1.3 00/03/15
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998, 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LEFONTINSTANCE_H
|
||||
#define __LEFONTINSTANCE_H
|
||||
|
||||
#include "LETypes.h"
|
||||
|
||||
/**
|
||||
* Instances of this class are used by LEFontInstance::mapCharsToGlyphs and
|
||||
* LEFontInstance::mapCharToGlyph to adjust character codes before the character
|
||||
* to glyph mapping process. Examples of this are filtering out control charcters
|
||||
* and character mirroring - replacing a character which has both a left and a right
|
||||
* hand form with the opposite form.
|
||||
*/
|
||||
class LECharMapper
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method does the adjustments.
|
||||
*
|
||||
* @param ch - the input charcter
|
||||
*
|
||||
* @return the adjusted character
|
||||
*/
|
||||
virtual LEUnicode32 mapChar(LEUnicode32 ch) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a pure virtual base class that servers as the interface between a LayoutEngine
|
||||
* and the platform font environment. It allows a LayoutEngine to access font tables, do
|
||||
* character to glyph mapping, and obtain metrics information without knowing any platform
|
||||
* specific details. There are also a few utility methods for converting between points,
|
||||
* pixels and funits. (font design units)
|
||||
*
|
||||
* Each instance of an LEFontInstance represents a renerable instance of a font. (i.e. a
|
||||
* single font at a particular point size, with a particular transform)
|
||||
*/
|
||||
class LEFontInstance
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* This virtual destructor is here so that the subclass
|
||||
* destructors can be invoked through the base class.
|
||||
*/
|
||||
virtual ~LEFontInstance() { };
|
||||
|
||||
//
|
||||
// Font file access
|
||||
//
|
||||
|
||||
/**
|
||||
* This method reads a table from the font.
|
||||
*
|
||||
* @param tableTag - the four byte table tag
|
||||
*
|
||||
* @return the address of the table in memory
|
||||
*/
|
||||
virtual const void *getFontTable(LETag tableTag) = 0;
|
||||
|
||||
/**
|
||||
* This method is used to determine if the font can
|
||||
* render the given character. This can usually be done
|
||||
* by looking the character up in the font's character
|
||||
* to glyph mapping.
|
||||
*
|
||||
* @param ch - the character to be tested
|
||||
*
|
||||
* @return true if the font can render ch.
|
||||
*/
|
||||
virtual le_bool canDisplay(LEUnicode ch) = 0;
|
||||
|
||||
/**
|
||||
* This method returns the number of design units in
|
||||
* the font's EM square.
|
||||
*
|
||||
* @return the number of design units pre EM.
|
||||
*/
|
||||
virtual le_int32 getUnitsPerEM() = 0;
|
||||
|
||||
/**
|
||||
* This method maps an array of charcter codes to an array of glyph
|
||||
* indices, using the font's character to glyph map.
|
||||
*
|
||||
* @param chars - the character array
|
||||
* @param offset - the index of the first charcter
|
||||
* @param count - the number of charcters
|
||||
* @param reverse - if true, store the glyph indices in reverse order.
|
||||
* @param mapper - the character mapper.
|
||||
* @param glyphs - the output glyph array
|
||||
*
|
||||
* @see LECharMapper
|
||||
*/
|
||||
virtual void mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, LECharMapper *mapper, LEGlyphID glyphs[]) = 0;
|
||||
|
||||
/**
|
||||
* This method maps a single character to a glyph index, using the
|
||||
* font's charcter to glyph map.
|
||||
*
|
||||
* @param ch - the character
|
||||
* @param mapper - the character mapper
|
||||
*
|
||||
* @return the glyph index
|
||||
*
|
||||
* @see LECharMapper
|
||||
*/
|
||||
virtual LEGlyphID mapCharToGlyph(LEUnicode32 ch, LECharMapper *mapper) = 0;
|
||||
|
||||
/**
|
||||
* This method gets a name from the font. (e.g. the family name) The encoding
|
||||
* of the name is specified by the platform, the script, and the language.
|
||||
*
|
||||
* @param platformID - the platform id
|
||||
* @param scriptID - the script id
|
||||
* @param langaugeID - the language id
|
||||
* @param name - the destination character array (can be null)
|
||||
*
|
||||
* @return the number of characters in the name
|
||||
*/
|
||||
virtual le_int32 getName(le_uint16 platformID, le_uint16 scriptID, le_uint16 languageID, le_uint16 nameID, LEUnicode *name) = 0;
|
||||
|
||||
//
|
||||
// Metrics
|
||||
//
|
||||
|
||||
/**
|
||||
* This method gets the X and Y advance of a particular glyph, in pixels.
|
||||
*
|
||||
* @param glyph - the glyph index
|
||||
* @param advance - the X and Y pixel values will be stored here
|
||||
*/
|
||||
virtual void getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) = 0;
|
||||
|
||||
/**
|
||||
* This method gets the hinted X and Y pixel coordinates of a particular
|
||||
* point in the outline of the given glyph.
|
||||
*
|
||||
* @param glyph - the glyph index
|
||||
* @param pointNumber - the number of the point
|
||||
* @param point - the point's X and Y pixel values will be stored here
|
||||
*
|
||||
* @return true if the point coordinates could be stored.
|
||||
*/
|
||||
virtual le_bool getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point) = 0;
|
||||
|
||||
/**
|
||||
* This method returns the width of the font's EM square
|
||||
* in pixels.
|
||||
*
|
||||
* @return the pixel width of the EM square
|
||||
*/
|
||||
virtual float getXPixelsPerEm() = 0;
|
||||
|
||||
/**
|
||||
* This method returns the height of the font's EM square
|
||||
* in pixels.
|
||||
*
|
||||
* @return the pixel height of the EM square
|
||||
*/
|
||||
virtual float getYPixelsPerEm() = 0;
|
||||
|
||||
/**
|
||||
* This method converts font design units in the
|
||||
* X direction to points.
|
||||
*
|
||||
* @param xUnits - design units in the X direction
|
||||
*
|
||||
* @return points in the X direction
|
||||
*/
|
||||
virtual float xUnitsToPoints(float xUnits) = 0;
|
||||
|
||||
/**
|
||||
* This method converts font design units in the
|
||||
* Y direction to points.
|
||||
*
|
||||
* @param yUnits - design units in the Y direction
|
||||
*
|
||||
* @return points in the Y direction
|
||||
*/
|
||||
virtual float yUnitsToPoints(float yUunits) = 0;
|
||||
|
||||
/**
|
||||
* This method converts font design units to points.
|
||||
*
|
||||
* @param units - X and Y design units
|
||||
* @param points - set to X and Y points
|
||||
*/
|
||||
virtual void unitsToPoints(LEPoint &units, LEPoint &points) = 0;
|
||||
|
||||
/**
|
||||
* This method converts pixels in the
|
||||
* X direction to font design units.
|
||||
*
|
||||
* @param xPixels - pixels in the X direction
|
||||
*
|
||||
* @return font design units in the X direction
|
||||
*/
|
||||
virtual float xPixelsToUnits(float xPixels) = 0;
|
||||
|
||||
/**
|
||||
* This method converts pixels in the
|
||||
* Y direction to font design units.
|
||||
*
|
||||
* @param yPixels - pixels in the Y direction
|
||||
*
|
||||
* @return font design units in the Y direction
|
||||
*/
|
||||
virtual float yPixelsToUnits(float yPixels) = 0;
|
||||
|
||||
/**
|
||||
* This method converts pixels to font design units.
|
||||
*
|
||||
* @param pixels - X and Y pixel
|
||||
* @param units - set to X and Y font design units
|
||||
*/
|
||||
virtual void pixelsToUnits(LEPoint &pixels, LEPoint &units) = 0;
|
||||
|
||||
/**
|
||||
* This method transforms an X, Y point in font design units to a
|
||||
* pixel coordinate, applying the font's transform.
|
||||
*
|
||||
* @param xFunits - the X coordinate in font design units
|
||||
* @param yFunits - the Y coordinate in font design units
|
||||
* @param pixels - the tranformed co-ordinate in pixels
|
||||
*/
|
||||
virtual void transformFunits(float xFunits, float yFunits, LEPoint &pixels) = 0;
|
||||
|
||||
/**
|
||||
* This is a convenience method used to convert
|
||||
* values in a 16.16 fixed point format to floating point.
|
||||
*
|
||||
* @param fixed - the fixed point value
|
||||
*
|
||||
* @return the floating point value
|
||||
*/
|
||||
static float fixedToFloat(le_int32 fixed)
|
||||
{
|
||||
return (float) (fixed / 65536.0);
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a convenience method used to convert
|
||||
* floating point values to 16.16 fixed point format.
|
||||
*
|
||||
* @param theFloat - the floating point value
|
||||
*
|
||||
* @return the fixed point value
|
||||
*/
|
||||
static le_int32 floatToFixed(float theFloat)
|
||||
{
|
||||
return (le_int32) (theFloat * 65536.0);
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
32
icu4c/source/layout/LEGlyphFilter.h
Normal file
32
icu4c/source/layout/LEGlyphFilter.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* @(#)LEGlyphFilter.h 1.3 00/03/15
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998, 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LEGLYPHFILTER__H
|
||||
#define __LEGLYPHFILTER__H
|
||||
|
||||
#include "LETypes.h"
|
||||
|
||||
/**
|
||||
* This is a helper class that is used to
|
||||
* recognize a set of glyph indices.
|
||||
*/
|
||||
class LEGlyphFilter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method is used to test a particular
|
||||
* glyph index to see if it is in the set
|
||||
* recognized by the filter.
|
||||
*
|
||||
* @param glyph - the glyph index to be tested
|
||||
*
|
||||
* @return true if the glyph index is in the set.
|
||||
*/
|
||||
virtual le_bool accept(LEGlyphID glyph) = 0;
|
||||
};
|
||||
|
||||
#endif
|
44
icu4c/source/layout/LEScripts.h
Normal file
44
icu4c/source/layout/LEScripts.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* %W% %E%
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998, 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LESCRIPTS_H
|
||||
#define __LESCRIPTS_H
|
||||
|
||||
enum ScriptCodes {
|
||||
neutScriptCode = 0,
|
||||
latnScriptCode = 1,
|
||||
grekScriptCode = 2,
|
||||
cyrlScriptCode = 3,
|
||||
armnScriptCode = 4,
|
||||
hebrScriptCode = 5,
|
||||
arabScriptCode = 6,
|
||||
devaScriptCode = 7,
|
||||
bengScriptCode = 8,
|
||||
punjScriptCode = 9,
|
||||
gujrScriptCode = 10,
|
||||
oryaScriptCode = 11,
|
||||
tamlScriptCode = 12,
|
||||
teluScriptCode = 13,
|
||||
kndaScriptCode = 14,
|
||||
mlymScriptCode = 15,
|
||||
thaiScriptCode = 16,
|
||||
laoScriptCode = 17,
|
||||
tibtScriptCode = 18,
|
||||
grgnScriptCode = 19,
|
||||
hangScriptCode = 20,
|
||||
kanaScriptCode = 21,
|
||||
bpmfScriptCode = 22,
|
||||
knbnScriptCode = 23,
|
||||
haniScriptCode = 24,
|
||||
surrScriptCode = 25,
|
||||
puseScriptCode = 26,
|
||||
spclScriptCode = 27,
|
||||
|
||||
scriptCodeCount = 28
|
||||
};
|
||||
|
||||
#endif
|
78
icu4c/source/layout/LESwaps.h
Normal file
78
icu4c/source/layout/LESwaps.h
Normal file
@ -0,0 +1,78 @@
|
||||
|
||||
/*
|
||||
* @(#)LESwaps.h 1.3 00/03/15
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998, 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LESWAPS_H
|
||||
#define __LESWAPS_H
|
||||
|
||||
#include "LETypes.h"
|
||||
|
||||
/**
|
||||
* These are convenience macros which invoke the swap functions
|
||||
* from a concise call.
|
||||
*/
|
||||
#define SWAPW(value) (LESwaps::isBigEndian() ? (value) : LESwaps::swapWord(value))
|
||||
#define SWAPL(value) (LESwaps::isBigEndian() ? (value) : LESwaps::swapLong(value))
|
||||
|
||||
/**
|
||||
* This class is used to access data which stored in big endian order
|
||||
* regardless of the conventions of the platform. It has been designed
|
||||
* to automatically detect the endian-ness of the platform, so that a
|
||||
* compilation flag is not needed.
|
||||
*
|
||||
* All methods are static and inline in an attempt to induce the compiler
|
||||
* to do most of the calculations at compile time.
|
||||
*/
|
||||
class LESwaps
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* This method detects the endian-ness of the platform by
|
||||
* casting a pointer to a word to a pointer to a byte. On
|
||||
* big endian platforms the FF will be in the byte with the
|
||||
* lowest address. On little endian platforms, the FF will
|
||||
* be in the byte with the highest address.
|
||||
*
|
||||
* @return true if the platform is big endian
|
||||
*/
|
||||
static le_bool isBigEndian()
|
||||
{
|
||||
static le_uint16 word = 0xFF00;
|
||||
static le_uint8 *byte = (le_uint8 *) &word;
|
||||
|
||||
return *byte;
|
||||
};
|
||||
|
||||
/**
|
||||
* This method the byte swap required on little endian platforms
|
||||
* to correctly access a word.
|
||||
*
|
||||
* @param value - the word to be byte swapped
|
||||
*
|
||||
* @return the byte swapped word
|
||||
*/
|
||||
static le_uint16 swapWord(le_uint16 value)
|
||||
{
|
||||
return (((le_uint8) (value >> 8)) | (value << 8));
|
||||
};
|
||||
|
||||
/**
|
||||
* This method does the byte swapping required on little endian platforms
|
||||
* to correctly access a long.
|
||||
*
|
||||
* @param value - the long to be byte swapped
|
||||
*
|
||||
* @return the byte swapped long
|
||||
*/
|
||||
static le_uint32 swapLong(le_uint32 value)
|
||||
{
|
||||
return swapWord((le_uint16) (value >> 16)) | (swapWord((le_uint16) value) << 16);
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
49
icu4c/source/layout/LETypes.h
Normal file
49
icu4c/source/layout/LETypes.h
Normal file
@ -0,0 +1,49 @@
|
||||
|
||||
/*
|
||||
* @(#)LETypes.h 1.2 00/03/15
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998, 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LETYPES_H
|
||||
#define __LETYPES_H
|
||||
|
||||
typedef long le_int32;
|
||||
typedef unsigned long le_uint32;
|
||||
typedef short le_int16;
|
||||
typedef unsigned short le_uint16;
|
||||
typedef signed char le_int8;
|
||||
typedef unsigned char le_uint8;
|
||||
|
||||
typedef char le_bool;
|
||||
|
||||
#ifndef true
|
||||
#define true 1
|
||||
#endif
|
||||
|
||||
#ifndef false
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
typedef le_uint32 LETag;
|
||||
|
||||
typedef le_uint16 LEGlyphID;
|
||||
|
||||
typedef le_uint16 LEUnicode16;
|
||||
typedef le_uint32 LEUnicode32;
|
||||
typedef le_uint16 LEUnicode; // FIXME: we should depricate this type in favor of LEUnicode16...
|
||||
|
||||
struct LEPoint
|
||||
{
|
||||
float fX;
|
||||
float fY;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
325
icu4c/source/layout/LayoutEngine.cpp
Normal file
325
icu4c/source/layout/LayoutEngine.cpp
Normal file
@ -0,0 +1,325 @@
|
||||
|
||||
/*
|
||||
* %W% %E%
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998, 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "LayoutEngine.h"
|
||||
#include "ArabicLayoutEngine.h"
|
||||
//#include "HebrewLayoutEngine.h"
|
||||
#include "IndicLayoutEngine.h"
|
||||
#include "ThaiLayoutEngine.h"
|
||||
#include "GXLayoutEngine.h"
|
||||
#include "ScriptAndLanguageTags.h"
|
||||
|
||||
#include "OpenTypeUtilities.h"
|
||||
#include "GlyphSubstitutionTables.h"
|
||||
#include "MorphTables.h"
|
||||
|
||||
#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
|
||||
|
||||
class DefaultCharMapper : public LECharMapper
|
||||
{
|
||||
private:
|
||||
le_bool fFilterControls;
|
||||
le_bool fMirror;
|
||||
|
||||
static LEUnicode32 controlChars[];
|
||||
|
||||
static const le_int32 controlCharsCount;
|
||||
|
||||
static LEUnicode32 mirroredChars[];
|
||||
|
||||
static const le_int32 mirroredCharsCount;
|
||||
|
||||
public:
|
||||
DefaultCharMapper(le_bool filterControls, le_bool mirror)
|
||||
: fFilterControls(filterControls), fMirror(mirror)
|
||||
{
|
||||
// nothing
|
||||
};
|
||||
|
||||
~DefaultCharMapper()
|
||||
{
|
||||
// nada
|
||||
};
|
||||
|
||||
LEUnicode32 mapChar(LEUnicode32 ch);
|
||||
};
|
||||
|
||||
LEUnicode32 DefaultCharMapper::controlChars[] = {
|
||||
0x0009, 0x000A, 0x000D,
|
||||
/*0x200C, 0x200D,*/ 0x200E, 0x200F,
|
||||
0x2028, 0x2029, 0x202A, 0x202B, 0x202C, 0x202D, 0x202E,
|
||||
0x206A, 0x206B, 0x206C, 0x206D, 0x206E, 0x206F
|
||||
};
|
||||
|
||||
const le_int32 DefaultCharMapper::controlCharsCount = ARRAY_SIZE(controlChars);
|
||||
|
||||
LEUnicode32 DefaultCharMapper::mirroredChars[] = {
|
||||
0x0028, 0x0029, // ascii paired punctuation
|
||||
0x003c, 0x003e,
|
||||
0x005b, 0x005d,
|
||||
0x007b, 0x007d,
|
||||
0x2045, 0x2046, // math symbols (not complete)
|
||||
0x207d, 0x207e,
|
||||
0x208d, 0x208e,
|
||||
0x2264, 0x2265,
|
||||
0x3008, 0x3009, // chinese paired punctuation
|
||||
0x300a, 0x300b,
|
||||
0x300c, 0x300d,
|
||||
0x300e, 0x300f,
|
||||
0x3010, 0x3011,
|
||||
0x3014, 0x3015,
|
||||
0x3016, 0x3017,
|
||||
0x3018, 0x3019,
|
||||
0x301a, 0x301b
|
||||
};
|
||||
|
||||
const le_int32 DefaultCharMapper::mirroredCharsCount = ARRAY_SIZE(mirroredChars);
|
||||
|
||||
LEUnicode32 DefaultCharMapper::mapChar(LEUnicode32 ch)
|
||||
{
|
||||
if (fFilterControls) {
|
||||
le_int32 index = OpenTypeUtilities::search(ch, controlChars, controlCharsCount);
|
||||
|
||||
if (controlChars[index] == ch) {
|
||||
return 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
if (fMirror) {
|
||||
le_int32 index = OpenTypeUtilities::search(ch, mirroredChars, mirroredCharsCount);
|
||||
|
||||
if (mirroredChars[index] == ch) {
|
||||
le_int32 mirrorOffset = ((index & 1) == 0) ? 1 : -1;
|
||||
|
||||
return mirroredChars[index + mirrorOffset];
|
||||
}
|
||||
}
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
LayoutEngine::LayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode)
|
||||
: fGlyphCount(0), fGlyphs(NULL), fCharIndices(NULL), fPositions(NULL),
|
||||
fFontInstance(fontInstance), fScriptCode(scriptCode), fLanguageCode(languageCode)
|
||||
{
|
||||
// nothing else to do?
|
||||
}
|
||||
|
||||
void LayoutEngine::getCharIndices(le_int32 charIndices[], le_int32 indexBase)
|
||||
{
|
||||
le_int32 i;
|
||||
|
||||
for (i = 0; i < fGlyphCount; i += 1) {
|
||||
charIndices[i] = fCharIndices[i] + indexBase;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the glyphs into caller's (32-bit) glyph array, OR in extraBits
|
||||
void LayoutEngine::getGlyphs(le_uint32 glyphs[], le_uint32 extraBits)
|
||||
{
|
||||
le_int32 i;
|
||||
|
||||
for (i = 0; i < fGlyphCount; i += 1) {
|
||||
glyphs[i] = fGlyphs[i] | extraBits;
|
||||
}
|
||||
};
|
||||
|
||||
le_int32 LayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
|
||||
LEGlyphID *&glyphs, le_int32 *&charIndices)
|
||||
{
|
||||
mapCharsToGlyphs(chars, offset, count, rightToLeft, rightToLeft, glyphs, charIndices);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// Input: glyphs
|
||||
// Output: positions
|
||||
void LayoutEngine::positionGlyphs(const LEGlyphID glyphs[], le_int32 glyphCount, float x, float y, float *&positions)
|
||||
{
|
||||
if (positions == NULL) {
|
||||
positions = new float[2 * (glyphCount + 1)];
|
||||
}
|
||||
|
||||
le_int32 i;
|
||||
|
||||
for (i = 0; i < glyphCount; i += 1) {
|
||||
LEPoint advance;
|
||||
|
||||
positions[i * 2] = x;
|
||||
positions[i * 2 + 1] = y;
|
||||
|
||||
fFontInstance->getGlyphAdvance(glyphs[i], advance);
|
||||
x += advance.fX;
|
||||
y += advance.fY;
|
||||
}
|
||||
|
||||
positions[glyphCount * 2] = x;
|
||||
positions[glyphCount * 2 + 1] = y;
|
||||
}
|
||||
|
||||
void LayoutEngine::adjustMarkGlyphs(const LEGlyphID glyphs[], le_int32 glyphCount, le_bool reverse, LEGlyphFilter *markFilter,
|
||||
float positions[])
|
||||
{
|
||||
float xAdjust = 0;
|
||||
le_int32 g = 0, direction = 1;
|
||||
le_int32 p;
|
||||
|
||||
if (reverse) {
|
||||
g = glyphCount - 1;
|
||||
direction = -1;
|
||||
}
|
||||
|
||||
for (p = 0; p < glyphCount; p += 1, g += direction) {
|
||||
float xAdvance = positions[(p + 1) * 2] - positions[p * 2];
|
||||
|
||||
positions[p * 2] += xAdjust;
|
||||
|
||||
if (markFilter->accept(glyphs[g])) {
|
||||
xAdjust -= xAdvance;
|
||||
}
|
||||
}
|
||||
|
||||
positions[glyphCount * 2] += xAdjust;
|
||||
}
|
||||
|
||||
void LayoutEngine::mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, le_bool mirror,
|
||||
LEGlyphID *&glyphs, le_int32 *&charIndices)
|
||||
{
|
||||
if (glyphs == NULL) {
|
||||
glyphs = new LEGlyphID[count];
|
||||
}
|
||||
|
||||
if (charIndices == NULL) {
|
||||
le_int32 i, dir = 1, out = 0;
|
||||
|
||||
if (reverse) {
|
||||
out = count - 1;
|
||||
dir = -1;
|
||||
}
|
||||
|
||||
charIndices = new le_int32[count];
|
||||
|
||||
for (i = 0; i < count; i += 1, out += dir) {
|
||||
charIndices[out] = i;
|
||||
}
|
||||
}
|
||||
|
||||
DefaultCharMapper charMapper(true, mirror);
|
||||
|
||||
fFontInstance->mapCharsToGlyphs(chars, offset, count, reverse, &charMapper, glyphs);
|
||||
}
|
||||
|
||||
// Input: characters, font?
|
||||
// Output: glyphs, positions, char indices
|
||||
// Returns: number of glyphs
|
||||
le_int32 LayoutEngine::layoutChars(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
|
||||
float x, float y)
|
||||
{
|
||||
fGlyphCount = computeGlyphs(chars, offset, count, max, rightToLeft, fGlyphs, fCharIndices);
|
||||
positionGlyphs(fGlyphs, fGlyphCount, x, y, fPositions);
|
||||
adjustGlyphPositions(chars, offset, count, rightToLeft, fGlyphs, fGlyphCount, fPositions);
|
||||
|
||||
return fGlyphCount;
|
||||
}
|
||||
|
||||
void LayoutEngine::reset()
|
||||
{
|
||||
fGlyphCount = 0;
|
||||
|
||||
if (fGlyphs != NULL) {
|
||||
delete[] fGlyphs;
|
||||
fGlyphs = NULL;
|
||||
}
|
||||
|
||||
if (fCharIndices != NULL) {
|
||||
delete[] fCharIndices;
|
||||
fCharIndices = NULL;
|
||||
}
|
||||
|
||||
if (fPositions != NULL) {
|
||||
delete[] fPositions;
|
||||
fPositions = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
LayoutEngine *LayoutEngine::layoutEngineFactory(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode)
|
||||
{
|
||||
static le_uint32 gsubTableTag = 0x47535542; // "GSUB"
|
||||
static le_uint32 mortTableTag = 0x6D6F7274; // 'mort'
|
||||
GlyphSubstitutionTableHeader *gsubTable = (GlyphSubstitutionTableHeader *) fontInstance->getFontTable(gsubTableTag);
|
||||
|
||||
if (gsubTable != NULL && gsubTable->coversScript(OpenTypeLayoutEngine::getScriptTag(scriptCode))) {
|
||||
switch (scriptCode) {
|
||||
case bengScriptCode:
|
||||
case devaScriptCode:
|
||||
case gujrScriptCode:
|
||||
case kndaScriptCode:
|
||||
case mlymScriptCode:
|
||||
case oryaScriptCode:
|
||||
case punjScriptCode:
|
||||
case tamlScriptCode:
|
||||
case teluScriptCode:
|
||||
return new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, gsubTable);
|
||||
|
||||
case arabScriptCode:
|
||||
return new ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, gsubTable);
|
||||
|
||||
default:
|
||||
return new OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, gsubTable);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
MorphTableHeader *morphTable = (MorphTableHeader *) fontInstance->getFontTable(mortTableTag);
|
||||
|
||||
if (morphTable != NULL) {
|
||||
return new GXLayoutEngine(fontInstance, scriptCode, languageCode, morphTable);
|
||||
} else {
|
||||
switch (scriptCode) {
|
||||
case bengScriptCode:
|
||||
case devaScriptCode:
|
||||
case gujrScriptCode:
|
||||
case kndaScriptCode:
|
||||
case mlymScriptCode:
|
||||
case oryaScriptCode:
|
||||
case punjScriptCode:
|
||||
case tamlScriptCode:
|
||||
case teluScriptCode:
|
||||
{
|
||||
const CDACLayout::ScriptInfo *scriptInfo = CDACLayout::getCDACScriptInfo(fontInstance, scriptCode);
|
||||
|
||||
if (scriptInfo != NULL) {
|
||||
return new CDACOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, scriptInfo);
|
||||
} else {
|
||||
return new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode);
|
||||
}
|
||||
}
|
||||
|
||||
case arabScriptCode:
|
||||
case hebrScriptCode:
|
||||
return new UnicodeArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode);
|
||||
|
||||
//case hebrScriptCode:
|
||||
// return new HebrewOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode);
|
||||
|
||||
case thaiScriptCode:
|
||||
return new ThaiLayoutEngine(fontInstance, scriptCode, languageCode);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new LayoutEngine(fontInstance, scriptCode, languageCode);
|
||||
}
|
||||
|
||||
LayoutEngine::~LayoutEngine() {
|
||||
reset();
|
||||
}
|
||||
|
371
icu4c/source/layout/LayoutEngine.h
Normal file
371
icu4c/source/layout/LayoutEngine.h
Normal file
@ -0,0 +1,371 @@
|
||||
|
||||
/*
|
||||
* @(#)LayoutEngine.h 1.4 00/03/15
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998, 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LAYOUTENGINE_H
|
||||
#define __LAYOUTENGINE_H
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "LEFontInstance.h"
|
||||
#include "LEGlyphFilter.h"
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define ARRAY_COPY(dst, src, count) memcpy(dst, src, (count) * sizeof (src)[0])
|
||||
|
||||
/**
|
||||
* This is a virtual base class used to do complex text layout. The text must all
|
||||
* be in a single font, script, and language. An instance of a LayoutEngine can be
|
||||
* created by calling the layoutEngineFactory method. Fonts are identified by
|
||||
* instances of the LEFontInstance class. Script and language codes are identified
|
||||
* by integer codes, which are defined in ScriptAndLanuageTags.h.
|
||||
*
|
||||
* The input to the layout process is an array of characters in logical order,
|
||||
* and a starting X, Y position for the text. The output is an array of glyph indices,
|
||||
* an array of character indices for the glyphs, and an array of glyph positions.
|
||||
* These arrays are protected members of LayoutEngine which can be retreived by a
|
||||
* public method. The reset method can be called to free these arrays so that the
|
||||
* LayoutEngine can be reused.
|
||||
*
|
||||
* The layout process is done in three steps. There is a protected virtual method
|
||||
* for each step. These methods have a default implementation which only does
|
||||
* character to glyph mapping and default positioning using the glyph's advance
|
||||
* widths. Subclasses can override these methods for more advanced layout.
|
||||
* There is a public method which invokes the steps in the correct order.
|
||||
*
|
||||
* The steps are:
|
||||
*
|
||||
* 1) Glyph processing - character to glyph mapping and any other glyph processing
|
||||
* such as ligature substitution and contextual forms.
|
||||
*
|
||||
* 2) Glyph positioning - position the glyphs based on their advance widths.
|
||||
*
|
||||
* 3) Glyph position adjustments - adjustment of glyph positions for kerning,
|
||||
* accent placement, etc.
|
||||
*
|
||||
* NOTE: in all methods below, output parameters are references to pointers so
|
||||
* the method can allocate and free the storage as needed. All storage allocated
|
||||
* in this way is owned by the object which created it, and will be freed when it
|
||||
* is no longer needed, or when the object's destructor is invoked.
|
||||
*
|
||||
* @see LEFontInstance
|
||||
* @see ScriptAndLanguageTags.h
|
||||
*/
|
||||
class U_LAYOUT_API LayoutEngine
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* The number of glyphs in the output
|
||||
*/
|
||||
le_int32 fGlyphCount;
|
||||
|
||||
/**
|
||||
* The output glyph array
|
||||
*/
|
||||
LEGlyphID *fGlyphs;
|
||||
|
||||
/**
|
||||
* The character index array. One entry for each output glyph, giving the index
|
||||
* in the input character array of the character which corresponds to this glyph.
|
||||
*/
|
||||
le_int32 *fCharIndices;
|
||||
|
||||
/**
|
||||
* The glyph position array. There are two entries for each glyph giving the
|
||||
* X and Y positions of the glyph. Thus, for glyph i, the X position is at index
|
||||
* 2i, and the Y position is at index 2i + 1.
|
||||
*/
|
||||
float *fPositions;
|
||||
|
||||
/**
|
||||
* The font instance for the text font.
|
||||
*
|
||||
* @see LEFontInstance
|
||||
*/
|
||||
LEFontInstance *fFontInstance;
|
||||
|
||||
/**
|
||||
* The script code for the text
|
||||
*
|
||||
* @see ScriptAndLanguageTags.h for script codes.
|
||||
*/
|
||||
le_int32 fScriptCode;
|
||||
|
||||
/**
|
||||
* The langauge code for the text
|
||||
*
|
||||
* @see ScriptAndLanguageTags.h for language codes.
|
||||
*/
|
||||
le_int32 fLanguageCode;
|
||||
|
||||
/**
|
||||
* This constructs an instance for a given font, script and language. Subclass constructors
|
||||
* must call this constructor.
|
||||
*
|
||||
* @param fontInstance - the font for the text
|
||||
* @param scriptCode - the script for the text
|
||||
* @param langaugeCode - the language for the text
|
||||
*
|
||||
* @see LEFontInstance
|
||||
* @see ScriptAndLanguageTags.h
|
||||
*/
|
||||
LayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode);
|
||||
|
||||
/**
|
||||
* This overrides the default no argument constructor to make it
|
||||
* difficult for clients to call it. Clients are expected to call
|
||||
* layoutEngineFactory.
|
||||
*/
|
||||
LayoutEngine();
|
||||
|
||||
/**
|
||||
* This method does the glyph processing. It converts an array of characters
|
||||
* into an array of glyph indices and character indices. The characters to be
|
||||
* processed are passed in a surrounding context. The context is specified as
|
||||
* a starting address and a maximum character count. An offset and a count are
|
||||
* used to specify the characters to be processed.
|
||||
*
|
||||
* The default implementation of this method only does character to glyph mapping.
|
||||
* Subclasses needing more elaborate glyph processing must override this method.
|
||||
*
|
||||
* Input parameters:
|
||||
* @param chars - the character context
|
||||
* @param offset - the offset of the first character to process
|
||||
* @param count - the number of characters to process
|
||||
* @param max - the number of characters in the context.
|
||||
* @param rightToLeft - true if the text is in a right to left directional run
|
||||
*
|
||||
* Output parameters:
|
||||
* @param glyphs - the glyph index array
|
||||
* @param charIndices - the character index array
|
||||
*
|
||||
* @return the number of glyphs in the glyph index array
|
||||
*/
|
||||
virtual le_int32 computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, LEGlyphID *&glyphs, le_int32 *&charIndices);
|
||||
|
||||
/**
|
||||
* This method does basic glyph positioning. The default implementation positions
|
||||
* the glyphs based on their advance widths. This is sufficient for most uses. It
|
||||
* is not expected that many subclasses will override this method.
|
||||
*
|
||||
* Input parameters:
|
||||
* @param glyphs - the input glyph array
|
||||
* @param glyphCount - the number of glyphs in the glyph array
|
||||
* @param x - the starting X position
|
||||
* @param y - the starting Y position
|
||||
*
|
||||
* Output parameters:
|
||||
* @param positions - the output X and Y positions (two entries per glyph)
|
||||
*/
|
||||
virtual void positionGlyphs(const LEGlyphID glyphs[], le_int32 glyphCount, float x, float y, float *&positions);
|
||||
|
||||
/**
|
||||
* This method does positioning adjustments like accent positioning and
|
||||
* kerning. The default implementation does nothing. Subclasses needing
|
||||
* position adjustments must override this method.
|
||||
*
|
||||
* Note that this method has both characters and glyphs as input so that
|
||||
* it can use the character codes to determine glyph types if that information
|
||||
* isn't directly available. (e.g. Some Arabic OpenType fonts don't have a GDEF
|
||||
* table)
|
||||
*
|
||||
* @param chars - the input character context
|
||||
* @param offset - the offset of the first character to process
|
||||
* @param count - the number of characters to process
|
||||
* @param reverse - true if the glyphs in the glyph array have been reordered
|
||||
* @param glyphs - the input glyph array
|
||||
* @param glyphCount - the number of glyphs
|
||||
* @param positions - the position array, will be updated as needed
|
||||
*
|
||||
* Note: the positions are passed as a plain array because this method should
|
||||
* not need to reallocate them.
|
||||
*/
|
||||
virtual void adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, LEGlyphID glyphs[], le_int32 glyphCount, float positions[])
|
||||
{
|
||||
// default is no adjustments
|
||||
};
|
||||
|
||||
/**
|
||||
* This method gets a table from the font associated with
|
||||
* the text. The default implementation gets the table from
|
||||
* the font instance. Subclasses which need to get the tables
|
||||
* some other way must override this method.
|
||||
*
|
||||
* @param tableTag - the four byte table tag.
|
||||
*
|
||||
* @return the address of the table.
|
||||
*/
|
||||
virtual const void *getFontTable(LETag tableTag)
|
||||
{
|
||||
return fFontInstance->getFontTable(tableTag);
|
||||
};
|
||||
|
||||
/**
|
||||
* This method does character to glyph mapping. The default implementation
|
||||
* uses the font instance to do the mapping. It will allocate the glyph and
|
||||
* character index arrays if they're not already allocated. If it allocates the
|
||||
* character index array, it will fill it it.
|
||||
*
|
||||
* This method supports right to left
|
||||
* text with the ability to store the glyphs in reverse order, and by supporting
|
||||
* character mirroring, which will replace a character which has a left and right
|
||||
* form, such as parens, with the opposite form before mapping it to a glyph index.
|
||||
*
|
||||
* Input parameters:
|
||||
* @param chars - the input character context
|
||||
* @param offset - the offset of the first character to be mapped
|
||||
* @param count - the number of characters to be mapped
|
||||
* @param reverse - if true, the output will be in reverse order
|
||||
* @param mirror - if true, do character mirroring
|
||||
*
|
||||
* Output parameters:
|
||||
* @param glyphs - the glyph array
|
||||
* @param charIndices - the character index array
|
||||
*
|
||||
* @see LEFontInstance
|
||||
*/
|
||||
virtual void mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, le_bool mirror, LEGlyphID *&glyphs, le_int32 *&charIndices);
|
||||
|
||||
/**
|
||||
* This is a convenience method that forces the advance width of mark
|
||||
* glyphs to be zero, which is required for proper selection and highlighting.
|
||||
*
|
||||
* @param glyphs - the glyph array
|
||||
* @param glyphCount - the number of glyphs
|
||||
* @param reverse - true if the glyph array has been reordered
|
||||
* @param markFilter - used to identify mark glyphs
|
||||
* @param positions - the glyph position array - updated as required
|
||||
*
|
||||
* @see LEGlyphFilter
|
||||
*/
|
||||
static void adjustMarkGlyphs(const LEGlyphID glyphs[], le_int32 glyphCount, le_bool reverse, LEGlyphFilter *markFilter, float positions[]);
|
||||
|
||||
public:
|
||||
/**
|
||||
* The destructor. It will free any storage allocated for the
|
||||
* glyph, character index and position arrays by calling the reset
|
||||
* method. It is declared virtual so that it will be invoked by the
|
||||
* subclass destructors.
|
||||
*/
|
||||
virtual ~LayoutEngine();
|
||||
|
||||
/**
|
||||
* This method will invoke the layout steps in their correct order by calling
|
||||
* the computeGlyphs, positionGlyphs and adjustGlyphPosition methods.. It will
|
||||
* compute the glyph, character index and position arrays.
|
||||
*
|
||||
* @param chars - the input character context
|
||||
* @param offset - the offset 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 - true if the characers are in a right to left directional run
|
||||
* @param x - the initial X position
|
||||
* @param y - the initial Y position
|
||||
*
|
||||
* @return the number of glyphs in the glyph array
|
||||
*
|
||||
* Note; the glyph, character index and position array can be accessed
|
||||
* using the getter method below.
|
||||
*/
|
||||
le_int32 layoutChars(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, float x, float y);
|
||||
|
||||
/**
|
||||
* This method copies the glyph array into a caller supplied array.
|
||||
* The caller must ensure that the array is large enough to hold all
|
||||
* the glyphs.
|
||||
*
|
||||
* @param glyphs - the destiniation glyph array
|
||||
*/
|
||||
void getGlyphs(LEGlyphID glyphs[])
|
||||
{
|
||||
ARRAY_COPY(glyphs, fGlyphs, fGlyphCount);
|
||||
};
|
||||
|
||||
/**
|
||||
* This method copies the glyph array into a caller supplied array,
|
||||
* ORing in extra bits. (This functionality is needed by the JDK,
|
||||
* which uses 32 bits pre glyph idex, with the high 16 bits encoding
|
||||
* the composite font slot number)
|
||||
*
|
||||
* @param glyphs - the destination (32 bit) glyph array
|
||||
* @param extraBits - this value will be ORed with each glyph index
|
||||
*/
|
||||
void getGlyphs(le_uint32 glyphs[], le_uint32 extraBits);
|
||||
|
||||
/**
|
||||
* This method copies the character index array into a caller supplied array.
|
||||
* The caller must ensure that the array is large enough to hold all
|
||||
* the character indices.
|
||||
*
|
||||
* @param charIndices - the destiniation character index array
|
||||
*/
|
||||
void getCharIndices(le_int32 charIndices[])
|
||||
{
|
||||
ARRAY_COPY(charIndices, fCharIndices, fGlyphCount);
|
||||
};
|
||||
|
||||
/**
|
||||
* This method copies the character index array into a caller supplied array.
|
||||
* The caller must ensure that the array is large enough to hold all
|
||||
* the character indices.
|
||||
*
|
||||
* @param charIndices - the destiniation character index array
|
||||
* @param indexBase - an offset which will be added to each index
|
||||
*/
|
||||
void getCharIndices(le_int32 charIndices[], le_int32 indexBase);
|
||||
|
||||
/**
|
||||
* This method copies the position array into a caller supplied array.
|
||||
* The caller must ensure that the array is large enough to hold all
|
||||
* the positions.
|
||||
*
|
||||
* @param glyphs - the destiniation position array
|
||||
*/
|
||||
void getGlyphPositions(float positions[])
|
||||
{
|
||||
ARRAY_COPY(positions, fPositions, fGlyphCount * 2 + 2);
|
||||
};
|
||||
|
||||
/**
|
||||
* This method returns the x position of the glyph at the
|
||||
* given index.
|
||||
*
|
||||
* @param glyphIndex - the index of the glyph
|
||||
*
|
||||
* @return the glyph's x position
|
||||
*/
|
||||
float getGlyphXPosition(le_int32 glyphIndex)
|
||||
{
|
||||
return fPositions[glyphIndex * 2];
|
||||
};
|
||||
|
||||
/**
|
||||
* This method frees the glyph, character index and position arrays
|
||||
* so that the LayoutEngine can be reused to layout a different
|
||||
* characer array. (This method is also called by the destructor)
|
||||
*/
|
||||
virtual void reset();
|
||||
|
||||
/**
|
||||
* This method returns a LayoutEngine capable of laying out text
|
||||
* in the given font, script and langauge. Note that the LayoutEngine
|
||||
* returned may be a subclass of LayoutEngine.
|
||||
*
|
||||
* @param fontInstance - the font of the text
|
||||
* @param scriptCode - the script of the text
|
||||
* @param langaugeCode - the language of the text
|
||||
*
|
||||
* @see LEFontInstance
|
||||
*/
|
||||
static LayoutEngine *layoutEngineFactory(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
167
icu4c/source/layout/Makefile.in
Normal file
167
icu4c/source/layout/Makefile.in
Normal file
@ -0,0 +1,167 @@
|
||||
## Makefile.in for ICU - layout
|
||||
|
||||
SO_TARGET_VERSION = @LIB_VERSION@
|
||||
SO_TARGET_VERSION_MAJOR = @LIB_VERSION_MAJOR@
|
||||
|
||||
## Install directory information
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
top_builddir = ..
|
||||
|
||||
include $(top_builddir)/icudefs.mk
|
||||
|
||||
include $(srcdir)/layoutobj.inc
|
||||
|
||||
## Platform-specific setup
|
||||
include @platform_make_fragment@
|
||||
|
||||
## Build directory information
|
||||
subdir = layout
|
||||
|
||||
|
||||
SUBDIRS = aat opentype
|
||||
|
||||
## Extra files to remove for 'make clean'
|
||||
CLEANFILES = *~ $(DEPS)
|
||||
|
||||
## Target information
|
||||
|
||||
ENABLE_STATIC = @ENABLE_STATIC@
|
||||
ENABLE_SHARED = @ENABLE_SHARED@
|
||||
|
||||
TARGET_STUBNAME=layout
|
||||
|
||||
ifneq ($(ENABLE_STATIC),)
|
||||
TARGET = $(LIBICU)$(TARGET_STUBNAME).a
|
||||
RANLIB = @RANLIB@
|
||||
endif
|
||||
|
||||
ifneq ($(ENABLE_SHARED),)
|
||||
SO_TARGET = $(LIBICU)$(TARGET_STUBNAME).$(SO)
|
||||
ALL_SO_TARGETS = $(SO_TARGET) $(MIDDLE_SO_TARGET) $(FINAL_SO_TARGET)
|
||||
endif
|
||||
|
||||
ALL_TARGETS = $(TARGET) $(ALL_SO_TARGETS)
|
||||
|
||||
DYNAMICCPPFLAGS = $(SHAREDLIBCPPFLAGS)
|
||||
DYNAMICCFLAGS = $(SHAREDLIBCFLAGS)
|
||||
DYNAMICCXXFLAGS = $(SHAREDLIBCXXFLAGS)
|
||||
|
||||
DEFS = @DEFS@
|
||||
CPPFLAGS = @CPPFLAGS@ $(LIBCPPFLAGS) -I$(srcdir) -I$(top_builddir)/common -I$(srcdir)/aat -I$(srcdir)/opentype -I$(top_builddir)/common -I$(top_srcdir)/common
|
||||
CFLAGS = @CFLAGS@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
ENABLE_RPATH = @ENABLE_RPATH@
|
||||
ifeq ($(ENABLE_RPATH),YES)
|
||||
RPATHLDFLAGS = $(LD_RPATH)$(LD_RPATH_PRE)$(libdir)
|
||||
endif
|
||||
LDFLAGS = @LDFLAGS@ $(RPATHLDFLAGS)
|
||||
#LIBS = $(LIBICUUC) @LIBS@
|
||||
LIBS= @LIBS@
|
||||
|
||||
|
||||
OBJECTS = $(LAYOUT_OBJS) $(AAT_OBJS:%.o=aat/%.o) $(OPENTYPE_OBJS:%.o=opentype/%.o)
|
||||
|
||||
STATIC_OBJECTS = $(OBJECTS:.o=.$(STATIC_O))
|
||||
|
||||
DEPS = $(LAYOUT_OBJS:.o=.d)
|
||||
|
||||
## Header files to install
|
||||
HEADERS= $(srcdir)/*.h
|
||||
|
||||
## List of phony targets
|
||||
.PHONY : all all-local install install-local clean clean-local \
|
||||
distclean distclean-local install-library install-headers dist \
|
||||
dist-local check check-local
|
||||
|
||||
## Clear suffix list
|
||||
.SUFFIXES :
|
||||
|
||||
## List of standard targets
|
||||
all: all-recursive all-local
|
||||
install: install-local
|
||||
clean: clean-recursive clean-local
|
||||
distclean : distclean-recursive distclean-local
|
||||
dist: dist-recursive dist-local
|
||||
check: all check-local
|
||||
|
||||
## Recursive targets
|
||||
all-recursive install-recursive clean-recursive distclean-recursive dist-recursive check-recursive:
|
||||
@dot_seen=no; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
dot_seen=yes; \
|
||||
local_target="$$target-local"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
(cd $$subdir && $(MAKE) $$local_target) || exit; \
|
||||
done; \
|
||||
if test "$$dot_seen" = "no"; then \
|
||||
$(MAKE) "$$target-local" || exit; \
|
||||
fi
|
||||
|
||||
# end recursion
|
||||
|
||||
all-local: $(ALL_TARGETS)
|
||||
|
||||
install-local: install-headers install-library
|
||||
|
||||
install-library: all-local
|
||||
$(MKINSTALLDIRS) $(DESTDIR)$(libdir)
|
||||
ifneq ($(ENABLE_STATIC),)
|
||||
$(INSTALL-L) $(TARGET) $(DESTDIR)$(libdir)/$(TARGET)
|
||||
endif
|
||||
ifneq ($(ENABLE_SHARED),)
|
||||
$(INSTALL-L) $(FINAL_SO_TARGET) $(DESTDIR)$(libdir)/$(FINAL_SO_TARGET)
|
||||
ifneq ($(FINAL_SO_TARGET),$(SO_TARGET))
|
||||
cd $(DESTDIR)$(libdir) && $(RM) $(MIDDLE_SO_TARGET) && ln -s $(FINAL_SO_TARGET) $(MIDDLE_SO_TARGET)
|
||||
cd $(DESTDIR)$(libdir) && $(RM) $(SO_TARGET) && ln -s $(FINAL_SO_TARGET) $(SO_TARGET)
|
||||
endif
|
||||
endif
|
||||
|
||||
install-headers:
|
||||
$(MKINSTALLDIRS) $(DESTDIR)$(includedir)/layout
|
||||
@for file in $(HEADERS); do \
|
||||
echo " $(INSTALL_DATA) $$file $(DESTDIR)$(includedir)/layout"; \
|
||||
$(INSTALL_DATA) $$file $(DESTDIR)$(includedir)/layout || exit; \
|
||||
done
|
||||
|
||||
dist-local:
|
||||
|
||||
clean-local:
|
||||
test -z "$(CLEANFILES)" || $(RMV) $(CLEANFILES)
|
||||
$(RMV) $(LAYOUT_OBJS) $(ALL_TARGETS)
|
||||
# $(RMV) $(LAYOUT_OBJS) $(STATIC_OBJECTS) $(ALL_TARGETS)
|
||||
|
||||
distclean-local: clean-local
|
||||
$(RMV) Makefile
|
||||
|
||||
check-local:
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
ifneq ($(ENABLE_STATIC),)
|
||||
$(TARGET): $(TARGET)($(STATIC_OBJECTS))
|
||||
$(RANLIB) $@
|
||||
endif
|
||||
|
||||
ifneq ($(ENABLE_SHARED),)
|
||||
$(FINAL_SO_TARGET): $(OBJECTS)
|
||||
$(SHLIB.cc) $(LD_SONAME) -o $@ $^ $(LIBS)
|
||||
endif
|
||||
|
||||
ifeq (,$(MAKECMDGOALS))
|
||||
-include $(DEPS)
|
||||
else
|
||||
ifneq ($(patsubst %clean,,$(MAKECMDGOALS)),)
|
||||
-include $(DEPS)
|
||||
endif
|
||||
endif
|
||||
|
||||
|
200
icu4c/source/layout/OpenTypeLayoutEngine.cpp
Normal file
200
icu4c/source/layout/OpenTypeLayoutEngine.cpp
Normal file
@ -0,0 +1,200 @@
|
||||
|
||||
/*
|
||||
* @(#)OpenTypeLayoutEngine.cpp 1.3 00/03/15
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998, 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "LayoutEngine.h"
|
||||
#include "OpenTypeLayoutEngine.h"
|
||||
#include "ScriptAndLanguageTags.h"
|
||||
|
||||
#include "GlyphSubstitutionTables.h"
|
||||
#include "GlyphDefinitionTables.h"
|
||||
#include "GlyphPositioningTables.h"
|
||||
|
||||
#include "GDEFMarkFilter.h"
|
||||
|
||||
OpenTypeLayoutEngine::OpenTypeLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
|
||||
GlyphSubstitutionTableHeader *gsubTable)
|
||||
: LayoutEngine(fontInstance, scriptCode, languageCode), fFeatureTags(NULL), fGSUBTable(gsubTable), fSubstitutionFilter(NULL)
|
||||
{
|
||||
static le_uint32 gdefTableTag = 0x47444546; // "GDEF"
|
||||
static le_uint32 gposTableTag = 0x47504F53; // "GPOS"
|
||||
|
||||
fGDEFTable = (GlyphDefinitionTableHeader *) getFontTable(gdefTableTag);
|
||||
fGPOSTable = (GlyphPositioningTableHeader *) getFontTable(gposTableTag);
|
||||
|
||||
setScriptAndLanguageTags();
|
||||
}
|
||||
|
||||
void OpenTypeLayoutEngine::reset()
|
||||
{
|
||||
// NOTE: if we're called from
|
||||
// the destructor, LayoutEngine;:reset()
|
||||
// will have been called already by
|
||||
// LayoutEngine::~LayoutEngine()
|
||||
LayoutEngine::reset();
|
||||
|
||||
// The double call could be avoided by
|
||||
// puting the following into a private
|
||||
// method that's called from here and
|
||||
// from our destructor
|
||||
if (fFeatureTags != NULL) {
|
||||
delete[] fFeatureTags;
|
||||
fFeatureTags = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
OpenTypeLayoutEngine::OpenTypeLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode)
|
||||
: LayoutEngine(fontInstance, scriptCode, languageCode), fFeatureTags(NULL), fGSUBTable(NULL), fGDEFTable(NULL), fGPOSTable(NULL),
|
||||
fSubstitutionFilter(NULL)
|
||||
{
|
||||
setScriptAndLanguageTags();
|
||||
}
|
||||
|
||||
OpenTypeLayoutEngine::~OpenTypeLayoutEngine()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
LETag scriptTags[] = {
|
||||
neutScriptTag, // 'NEUT'
|
||||
latnScriptTag, // 'latn'
|
||||
grekScriptTag, // 'grek'
|
||||
cyrlScriptTag, // 'cyrl'
|
||||
armnScriptTag, // 'armn' **** Armenian: no MS definition ****
|
||||
hebrScriptTag, // 'hebr'
|
||||
arabScriptTag, // 'arab'
|
||||
devaScriptTag, // 'deva'
|
||||
bengScriptTag, // 'beng'
|
||||
punjScriptTag, // 'punj' punjabi == gurmukhi
|
||||
gujrScriptTag, // 'gujr'
|
||||
oryaScriptTag, // 'orya'
|
||||
tamlScriptTag, // 'taml'
|
||||
teluScriptTag, // 'telu'
|
||||
kndaScriptTag, // 'knda'
|
||||
mlymScriptTag, // 'mlym'
|
||||
thaiScriptTag, // 'thai'
|
||||
laoScriptTag, // 'lao ' **** Lao: no MS definition ****
|
||||
tibtScriptTag, // 'tibt'
|
||||
grgnScriptTag, // 'grgn' **** Georgian: no MS definition ****
|
||||
hangScriptTag, // 'hang'
|
||||
kanaScriptTag, // 'kana'
|
||||
bpmfScriptTag, // 'bpmf' **** Bopomofo: no MS definition ****
|
||||
knbnScriptTag, // 'knbn' **** Kanbun: no MS definition ****
|
||||
haniScriptTag, // 'hani'
|
||||
surrScriptTag, // 'SURR'
|
||||
puseScriptTag, // 'PUSE'
|
||||
spclScriptTag // 'SPCL'
|
||||
};
|
||||
|
||||
LETag OpenTypeLayoutEngine::getScriptTag(le_int32 scriptCode)
|
||||
{
|
||||
if (scriptCode == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return scriptTags[scriptCode];
|
||||
}
|
||||
|
||||
LETag OpenTypeLayoutEngine::getLangSysTag(le_int32 languageCode)
|
||||
{
|
||||
// FIXME: do this for real some day (soon?)
|
||||
return -1;
|
||||
}
|
||||
|
||||
void OpenTypeLayoutEngine::setScriptAndLanguageTags()
|
||||
{
|
||||
fScriptTag = getScriptTag(fScriptCode);
|
||||
fLangSysTag = getLangSysTag(fLanguageCode);
|
||||
}
|
||||
|
||||
// Input: characters, tags
|
||||
// Output: glyphs, char indices
|
||||
le_int32 OpenTypeLayoutEngine::glyphProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, const LETag **featureTags,
|
||||
LEGlyphID *&glyphs, le_int32 *&charIndices)
|
||||
{
|
||||
mapCharsToGlyphs(chars, offset, count, rightToLeft, rightToLeft, glyphs, charIndices);
|
||||
|
||||
if (fGSUBTable != NULL) {
|
||||
fGSUBTable->process(glyphs, featureTags, count, rightToLeft, fScriptTag, fLangSysTag, fGDEFTable, fSubstitutionFilter);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
le_int32 OpenTypeLayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, LEGlyphID *&glyphs, le_int32 *&charIndices)
|
||||
{
|
||||
LEUnicode *outChars = NULL;
|
||||
LEGlyphID *fakeGlyphs = NULL;
|
||||
le_int32 *tempCharIndices = NULL;
|
||||
le_int32 outCharCount, outGlyphCount, fakeGlyphCount;
|
||||
|
||||
outCharCount = characterProcessing(chars, offset, count, max, rightToLeft, outChars, tempCharIndices, fFeatureTags);
|
||||
|
||||
if (outChars != NULL) {
|
||||
fakeGlyphCount = glyphProcessing(outChars, 0, outCharCount, outCharCount, rightToLeft, fFeatureTags, fakeGlyphs, tempCharIndices);
|
||||
//adjustGlyphs(outChars, 0, outCharCount, rightToLeft, fakeGlyphs, fakeGlyphCount);
|
||||
} else {
|
||||
fakeGlyphCount = glyphProcessing(chars, offset, count, max, rightToLeft, fFeatureTags, fakeGlyphs, tempCharIndices);
|
||||
//adjustGlyphs(chars, offset, count, rightToLeft, fakeGlyphs, fakeGlyphCount);
|
||||
}
|
||||
|
||||
outGlyphCount = glyphPostProcessing(fakeGlyphs, tempCharIndices, fakeGlyphCount, glyphs, charIndices);
|
||||
|
||||
if (outChars != chars) {
|
||||
delete[] outChars;
|
||||
}
|
||||
|
||||
if (fakeGlyphs != glyphs) {
|
||||
delete[] fakeGlyphs;
|
||||
}
|
||||
|
||||
if (tempCharIndices != charIndices) {
|
||||
delete[] tempCharIndices;
|
||||
}
|
||||
|
||||
return outGlyphCount;
|
||||
}
|
||||
|
||||
// apply GPOS table, if any
|
||||
void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
|
||||
LEGlyphID glyphs[], le_int32 glyphCount, float positions[])
|
||||
{
|
||||
if (fGPOSTable != NULL) {
|
||||
GlyphPositionAdjustment *adjustments = new GlyphPositionAdjustment[glyphCount];
|
||||
|
||||
fGPOSTable->process(glyphs, adjustments, fFeatureTags, glyphCount, reverse, fScriptTag, fLangSysTag, fGDEFTable, fFontInstance);
|
||||
|
||||
float xAdjust = 0, yAdjust = 0;
|
||||
le_int32 i;
|
||||
|
||||
for (i = 0; i < glyphCount; i += 1) {
|
||||
float xPlacement = fFontInstance->xUnitsToPoints(adjustments[i].getXPlacement());
|
||||
float xAdvance = fFontInstance->xUnitsToPoints(adjustments[i].getXAdvance());
|
||||
float yPlacement = fFontInstance->yUnitsToPoints(adjustments[i].getYPlacement());
|
||||
float yAdvance = fFontInstance->yUnitsToPoints(adjustments[i].getYAdvance());
|
||||
|
||||
xAdjust += xPlacement;
|
||||
yAdjust += yPlacement;
|
||||
|
||||
positions[i*2] += xAdjust;
|
||||
positions[i*2+1] += yAdjust;
|
||||
|
||||
xAdjust += xAdvance;
|
||||
yAdjust += yAdvance;
|
||||
}
|
||||
|
||||
positions[glyphCount*2] += xAdjust;
|
||||
positions[glyphCount*2+1] += yAdjust;
|
||||
|
||||
delete[] adjustments;
|
||||
}
|
||||
|
||||
delete[] fFeatureTags;
|
||||
fFeatureTags = NULL;
|
||||
}
|
||||
|
280
icu4c/source/layout/OpenTypeLayoutEngine.h
Normal file
280
icu4c/source/layout/OpenTypeLayoutEngine.h
Normal file
@ -0,0 +1,280 @@
|
||||
|
||||
/*
|
||||
* @(#)OpenTypeLayoutEngine.h 1.4 00/03/15
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998, 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __OPENTYPELAYOUTENGINE_H
|
||||
#define __OPENTYPELAYOUTENGINE_H
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "LEGlyphFilter.h"
|
||||
#include "LEFontInstance.h"
|
||||
#include "LayoutEngine.h"
|
||||
|
||||
#include "GlyphSubstitutionTables.h"
|
||||
#include "GlyphDefinitionTables.h"
|
||||
#include "GlyphPositioningTables.h"
|
||||
|
||||
/**
|
||||
* OpenTypeLayoutEngine implements complex text layout for OpenType fonts - that is
|
||||
* fonts which have GSUB and GPOS tables associated with them. In order to do this,
|
||||
* the glyph processsing step described for LayoutEngine is further broken into three
|
||||
* steps:
|
||||
*
|
||||
* 1) Character processing - this step analyses the characters and assigns a list of OpenType
|
||||
* feature tags to each one. It may also change, remove or add characters, and change
|
||||
* their order.
|
||||
*
|
||||
* 2) Glyph processing - This step performs character to glyph mapping,and uses the GSUB
|
||||
* table associated with the font to perform glyph substitutions, such as ligature substitution.
|
||||
*
|
||||
* 3) Glyph post processing - in cases where the font doesn't directly contain a GSUB table,
|
||||
* the previous two steps may have generated "fake" glyph indices to use with a "canned" GSUB
|
||||
* table. This step turns those glyph indices into actual font-specific glyph indices, and may
|
||||
* perform any other adjustments requried by the previous steps.
|
||||
*
|
||||
* OpenTypeLayoutEngine will also use the font's GPOS table to apply position adjustments
|
||||
* such as kerning and accent positioning.
|
||||
*
|
||||
* @see LayoutEngine
|
||||
*/
|
||||
class OpenTypeLayoutEngine : public LayoutEngine
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This is the main constructor. It constructs an instance of OpenTypeLayoutEngine for
|
||||
* a particular font, script and language. It takes the GSUB table as a parameter since
|
||||
* LayoutEngine::layoutEngineFactory has to read the GSUB table to know that it has an
|
||||
* OpenType font.
|
||||
*
|
||||
* @param fontInstance - the font
|
||||
* @param scriptCode - the script
|
||||
* @param langaugeCode - the language
|
||||
* @param gsubTable - the GSUB table
|
||||
*
|
||||
* @see LayoutEngine::layoutEngineFactory
|
||||
* @see ScriptAndLangaugeTags.h for script and language codes
|
||||
*/
|
||||
OpenTypeLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
|
||||
GlyphSubstitutionTableHeader *gsubTable);
|
||||
|
||||
/**
|
||||
* This constructor is used when the font requires a "canned" GSUB table which can't be known
|
||||
* until after this constructor has been invoked.
|
||||
*
|
||||
* @param fontInstance - the font
|
||||
* @param scriptCode - the script
|
||||
* @param langaugeCode - the language
|
||||
*/
|
||||
OpenTypeLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode);
|
||||
|
||||
/**
|
||||
* The destructor, virtual for correct polymorphic invocation.
|
||||
*/
|
||||
virtual ~OpenTypeLayoutEngine();
|
||||
|
||||
/**
|
||||
* A convenience method used to convert the script code into
|
||||
* the four byte script tag required by OpenType.
|
||||
*
|
||||
* @param scriptCode - the script code
|
||||
*
|
||||
* @return the four byte script tag
|
||||
*/
|
||||
static LETag getScriptTag(le_int32 scriptCode);
|
||||
|
||||
/**
|
||||
* A convenience method used to convert the langauge code into
|
||||
* the four byte langauge tag required by OpenType.
|
||||
*
|
||||
* @param languageCode - the language code
|
||||
*
|
||||
* @return the four byte language tag
|
||||
*/
|
||||
static LETag getLangSysTag(le_int32 languageCode);
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* This method is used by the constructors to convert the script
|
||||
* and language codes to four byte tags and save them.
|
||||
*/
|
||||
void setScriptAndLanguageTags();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* An array of pointers to four byte feature tags.
|
||||
* Each pointer points to a list of tags, terminated
|
||||
* by a special empty tag.
|
||||
*/
|
||||
const LETag **fFeatureTags;
|
||||
|
||||
/**
|
||||
* The address of the GSUB table.
|
||||
*/
|
||||
GlyphSubstitutionTableHeader *fGSUBTable;
|
||||
|
||||
/**
|
||||
* The address of the GDEF table.
|
||||
*/
|
||||
GlyphDefinitionTableHeader *fGDEFTable;
|
||||
|
||||
/**
|
||||
* The address of the GPOS table.
|
||||
*/
|
||||
GlyphPositioningTableHeader *fGPOSTable;
|
||||
|
||||
/**
|
||||
* An optional filter used to inhibit substitutions
|
||||
* preformed by the GSUB table. This is used for some
|
||||
* "canned" GSUB tables to restrict substitutions to
|
||||
* glyphs that are in the font.
|
||||
*/
|
||||
LEGlyphFilter *fSubstitutionFilter;
|
||||
|
||||
/**
|
||||
* The four byte script tag.
|
||||
*/
|
||||
LETag fScriptTag;
|
||||
|
||||
/**
|
||||
* The four byte language tag
|
||||
*/
|
||||
LETag fLangSysTag;
|
||||
|
||||
/**
|
||||
* This method does the OpenType character processing. It assigns the OpenType feature
|
||||
* tags to the characters, and may generate output characters that differ from the input
|
||||
* charcters dueto insertions, deletions, or reorderings. In such cases, it will also
|
||||
* generate an output character index array reflecting these changes.
|
||||
*
|
||||
* Subclasses must override this method.
|
||||
*
|
||||
* 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 - true if the characters are in a right to left directional run
|
||||
*
|
||||
* Output parameters:
|
||||
* @param outChars - the output character array, if different from the input
|
||||
* @param charIndices - the output character index array
|
||||
* @param featureTags - the output feature tag array
|
||||
*
|
||||
* @return the output character count (input character count if no change)
|
||||
*/
|
||||
virtual le_int32 characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
|
||||
LEUnicode *&outChars, le_int32 *&charIndices, const LETag **&featureTags) /*= 0;*/
|
||||
{
|
||||
return count;
|
||||
};
|
||||
|
||||
/**
|
||||
* This method does character to glyph mapping, and applies the GSUB table. The
|
||||
* default implementation calls mapCharsToGlyphs and then applies the GSUB table,
|
||||
* if there is one.
|
||||
*
|
||||
* Note that in the case of "canned" GSUB tables, the output glyph indices may be
|
||||
* "fake" glyph indices that need to be converted to "real" glyph indices by the
|
||||
* glyphPostProcessing method.
|
||||
*
|
||||
* 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 - true if the characters are in a right to left directional run
|
||||
* @param featureTags - the feature tag array
|
||||
*
|
||||
* Output parameters:
|
||||
* @param glyphs - the output glyph index array
|
||||
* @param charIndices - the output character index array
|
||||
*
|
||||
* @return the number of glyphs in the output glyph index array
|
||||
*
|
||||
* Note: if the character index array was already set by the characterProcessing
|
||||
* method, this method won't change it.
|
||||
*/
|
||||
virtual le_int32 glyphProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
|
||||
const LETag **featureTags, LEGlyphID *&glyphs, le_int32 *&charIndices);
|
||||
|
||||
/**
|
||||
* This method does any processing necessary to convert "fake"
|
||||
* glyph indices used by the glyphProcessing method into "real" glyph
|
||||
* indices which can be used to render the text. Note that in some
|
||||
* cases, such as CDAC Indic fonts, several "real" glyphs may be needed
|
||||
* to render one "fake" glyph.
|
||||
*
|
||||
* The default implementation of this method just returns the input glyph
|
||||
* index and character index arrays, assuming that no "fake" glyph indices
|
||||
* were needed to do GSUB processing.
|
||||
*
|
||||
* Input paramters:
|
||||
* @param tempGlyphs - the input "fake" glyph index array
|
||||
* @param tempCharIndices - the input "fake" character index array
|
||||
* @param tempGlyphCount - the number of "fake" glyph indices
|
||||
*
|
||||
* Output parameters:
|
||||
* @param glyphs - the output glyph index array
|
||||
* @param charIndices - the output character index array
|
||||
*
|
||||
* @return the number of glyph indices in the output glyph index array
|
||||
*/
|
||||
virtual le_int32 glyphPostProcessing(LEGlyphID tempGlyphs[], le_int32 tempCharIndices[], le_int32 tempGlyphCount,
|
||||
LEGlyphID *&glyphs, le_int32 *&charIndices)
|
||||
{
|
||||
glyphs = tempGlyphs;
|
||||
charIndices = tempCharIndices;
|
||||
|
||||
return tempGlyphCount;
|
||||
};
|
||||
|
||||
/**
|
||||
* This method applies the characterProcessing, glyphProcessing and glyphPostProcessing
|
||||
* methods. Most subclasses will not need to override this method.
|
||||
*
|
||||
* 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 - true if the text is in a right to left directional run
|
||||
*
|
||||
* Output parameters:
|
||||
* @param glyphs - the glyph index array
|
||||
* @param charIndices - the character index array
|
||||
*
|
||||
* @return the number of glyphs in the glyph index array
|
||||
*
|
||||
* @see LayoutEngine::computeGlyphs
|
||||
*/
|
||||
virtual le_int32 computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, LEGlyphID *&glyphs, le_int32 *&charIndices);
|
||||
|
||||
/**
|
||||
* This method uses the GPOS table, if there is one, to adjust the glyph positions.
|
||||
*
|
||||
* Input parameters:
|
||||
* @param glyphs - the input glyph array
|
||||
* @param glyphCount - the number of glyphs in the glyph array
|
||||
* @param x - the starting X position
|
||||
* @param y - the starting Y position
|
||||
*
|
||||
* Output parameters:
|
||||
* @param positions - the output X and Y positions (two entries per glyph)
|
||||
*/
|
||||
virtual void adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, LEGlyphID glyphs[], le_int32 glyphCount, float positions[]);
|
||||
|
||||
/**
|
||||
* This method frees the feature tag array so that the
|
||||
* OpenTypeLayoutEngine can be reused for different text.
|
||||
* It is also called from our destructor.
|
||||
*/
|
||||
virtual void reset();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
67
icu4c/source/layout/ThaiLayoutEngine.cpp
Normal file
67
icu4c/source/layout/ThaiLayoutEngine.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
|
||||
/*
|
||||
* @(#)ThaiLayoutEngine.cpp 1.2 00/03/15
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998, 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "LayoutEngine.h"
|
||||
#include "ThaiLayoutEngine.h"
|
||||
#include "ScriptAndLanguageTags.h"
|
||||
|
||||
#include "ThaiShaping.h"
|
||||
|
||||
ThaiLayoutEngine::ThaiLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode)
|
||||
: LayoutEngine(fontInstance, scriptCode, languageCode)
|
||||
{
|
||||
fErrorChar = 0x25CC;
|
||||
|
||||
// Figure out which presentation forms the font uses
|
||||
if (fontInstance->canDisplay(0x0E64)) {
|
||||
// WorldType uses reserved space in Thai block
|
||||
fGlyphSet = 0;
|
||||
} else if (fontInstance->canDisplay(0xF701)) {
|
||||
// Microsoft corporate zone
|
||||
fGlyphSet = 1;
|
||||
|
||||
if (!fontInstance->canDisplay(fErrorChar)) {
|
||||
fErrorChar = 0xF71B;
|
||||
}
|
||||
} else if (fontInstance->canDisplay(0xF885)) {
|
||||
// Apple corporate zone
|
||||
fGlyphSet = 2;
|
||||
} else {
|
||||
// no presentation forms in the font
|
||||
fGlyphSet = 3;
|
||||
}
|
||||
}
|
||||
|
||||
ThaiLayoutEngine::~ThaiLayoutEngine()
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
// Input: characters (0..max provided for context)
|
||||
// Output: glyphs, char indices
|
||||
// Returns: the glyph count
|
||||
// NOTE: this assumes that ThaiShaping::compose will allocate the outChars array...
|
||||
le_int32 ThaiLayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, LEGlyphID *&glyphs, le_int32 *&charIndices)
|
||||
{
|
||||
LEUnicode *outChars;
|
||||
le_int32 glyphCount;
|
||||
|
||||
// This is enough room for the worst-case expansion
|
||||
// (it says here...)
|
||||
outChars = new LEUnicode[count * 2];
|
||||
charIndices = new le_int32[count * 2];
|
||||
|
||||
glyphCount = ThaiShaping::compose(chars, offset, count, fGlyphSet, fErrorChar, outChars, charIndices);
|
||||
mapCharsToGlyphs(outChars, 0, glyphCount, false, false, glyphs, charIndices);
|
||||
|
||||
delete[] outChars;
|
||||
|
||||
return glyphCount;
|
||||
}
|
||||
|
90
icu4c/source/layout/ThaiLayoutEngine.h
Normal file
90
icu4c/source/layout/ThaiLayoutEngine.h
Normal file
@ -0,0 +1,90 @@
|
||||
|
||||
/*
|
||||
* @(#)ThaiLayoutEngine.h 1.3 00/03/15
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998, 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __THAILAYOUTENGINE_H
|
||||
#define __THAILAYOUTENGINE_H
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "LEFontInstance.h"
|
||||
#include "LayoutEngine.h"
|
||||
|
||||
#include "ThaiShaping.h"
|
||||
|
||||
/**
|
||||
* This class implements layout for the Thai script, using the ThaiShapingClass.
|
||||
* All existing Thai fonts use an encoding which assigns character codes to all
|
||||
* the variant forms needed to display accents and tone marks correctly in context.
|
||||
* This class can deal with fonts using the Microsoft, Macintosh, and WorldType encodings.
|
||||
*/
|
||||
class ThaiLayoutEngine : public LayoutEngine
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructs an instance of ThaiLayoutEngine for the given font, script and
|
||||
* language. It examines the font, using LEFontInstance::canDisplay, to set fGlyphSet
|
||||
* and fErrorChar. (see below)
|
||||
*
|
||||
* @param fontInstance - the font
|
||||
* @param scriptCode - the script
|
||||
* @param languageCode - the language
|
||||
*
|
||||
* @see LEFontInstance
|
||||
* @see ScriptAndLanguageTags.h for script and language codes
|
||||
*/
|
||||
ThaiLayoutEngine(LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode);
|
||||
|
||||
/**
|
||||
* The destructor, virtual for correct polymorphic invocation.
|
||||
*/
|
||||
virtual ~ThaiLayoutEngine();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* A small integer indicating which Thai encoding
|
||||
* the font uses.
|
||||
*
|
||||
* @see ThaiShaping
|
||||
*/
|
||||
le_uint8 fGlyphSet;
|
||||
|
||||
/**
|
||||
* The character used as a base for vowels and
|
||||
* tone marks that are out of sequence. Usually
|
||||
* this will be Unicode 0x25CC, if the font can
|
||||
* display it.
|
||||
*
|
||||
* @see ThaiShaping
|
||||
*/
|
||||
LEUnicode fErrorChar;
|
||||
|
||||
/**
|
||||
* This method performs Thai layout. It calls ThaiShaping::compose to
|
||||
* generate the correct contextual character codes, and then calls
|
||||
* mapCharsToGlyphs to generate the glyph indices.
|
||||
*
|
||||
* 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 - true if the text is in a right to left directional run
|
||||
*
|
||||
* Output parameters:
|
||||
* @param glyphs - the glyph index array
|
||||
* @param charIndices - the character index array
|
||||
*
|
||||
* @return the number of glyphs in the glyph index array
|
||||
*
|
||||
* @see ThaiShaping
|
||||
*/
|
||||
virtual le_int32 computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
|
||||
LEGlyphID *&glyphs, le_int32 *&charIndices);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
354
icu4c/source/layout/ThaiShaping.cpp
Normal file
354
icu4c/source/layout/ThaiShaping.cpp
Normal file
@ -0,0 +1,354 @@
|
||||
/*
|
||||
* @(#)ThaiShaping.cpp 1.13 00/03/15
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998, 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "LEGlyphFilter.h"
|
||||
#include "OpenTypeTables.h"
|
||||
#include "ThaiShaping.h"
|
||||
|
||||
enum {
|
||||
CH_SPACE = 0x0020,
|
||||
CH_YAMAKKAN = 0x0E4E,
|
||||
CH_MAI_HANAKAT = 0x0E31,
|
||||
CH_SARA_AA = 0x0E32,
|
||||
CH_SARA_AM = 0x0E33,
|
||||
CH_SARA_UEE = 0x0E37,
|
||||
CH_MAITAIKHU = 0x0E47,
|
||||
CH_NIKHAHIT = 0x0E4D,
|
||||
CH_SARA_U = 0x0E38,
|
||||
CH_PHINTHU = 0x0E3A,
|
||||
CH_YO_YING = 0x0E0D,
|
||||
CH_THO_THAN = 0x0E10,
|
||||
CH_DOTTED_CIRCLE = 0x25CC
|
||||
};
|
||||
|
||||
le_uint8 ThaiShaping::getCharClass(LEUnicode ch)
|
||||
{
|
||||
le_uint8 charClass = NON;
|
||||
|
||||
if (ch >= 0x0E00 && ch <= 0x0E5B) {
|
||||
charClass = classTable[ch - 0x0E00];
|
||||
}
|
||||
|
||||
return charClass;
|
||||
}
|
||||
|
||||
|
||||
LEUnicode ThaiShaping::leftAboveVowel(LEUnicode vowel, le_uint8 glyphSet)
|
||||
{
|
||||
static LEUnicode leftAboveVowels[][7] = {
|
||||
{0x0E61, 0x0E32, 0x0E33, 0x0E64, 0x0E65, 0x0E66, 0x0E67},
|
||||
{0xF710, 0x0E32, 0x0E33, 0xF701, 0xF702, 0xF703, 0xF704},
|
||||
{0xF884, 0x0E32, 0x0E33, 0xF885, 0xF886, 0xF887, 0xF788},
|
||||
{0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37}
|
||||
};
|
||||
|
||||
if (vowel >= CH_MAI_HANAKAT && vowel <= CH_SARA_UEE) {
|
||||
return leftAboveVowels[glyphSet][vowel - CH_MAI_HANAKAT];
|
||||
}
|
||||
|
||||
if (vowel == CH_YAMAKKAN && glyphSet == 0) {
|
||||
return 0x0E7E;
|
||||
}
|
||||
|
||||
return vowel;
|
||||
}
|
||||
|
||||
LEUnicode ThaiShaping::lowerRightTone(LEUnicode tone, le_uint8 glyphSet)
|
||||
{
|
||||
static LEUnicode lowerRightTones[][7] = {
|
||||
{0x0E68, 0x0E69, 0x0E6A, 0x0E6B, 0x0E6C, 0x0E6D, 0x0E6E},
|
||||
{0x0E47, 0xF70A, 0xF70B, 0xF70C, 0xF70D, 0xF70E, 0x0E4D},
|
||||
{0x0E47, 0xF88B, 0xF88E, 0xF891, 0xF894, 0xF897, 0x0E4D},
|
||||
{0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D}
|
||||
};
|
||||
|
||||
if (tone >= CH_MAITAIKHU && tone <= CH_NIKHAHIT) {
|
||||
return lowerRightTones[glyphSet][tone - CH_MAITAIKHU];
|
||||
}
|
||||
|
||||
return tone;
|
||||
}
|
||||
|
||||
LEUnicode ThaiShaping::lowerLeftTone(LEUnicode tone, le_uint8 glyphSet)
|
||||
{
|
||||
static LEUnicode lowerLeftTones[][7] = {
|
||||
{0x0E76, 0x0E77, 0x0E78, 0x0E79, 0x0E7A, 0x0E7B, 0x0E7C},
|
||||
{0xF712, 0xF705, 0xF706, 0xF707, 0xF708, 0xF709, 0xF711},
|
||||
{0xF889, 0xF88C, 0xF88F, 0xF892, 0xF895, 0xF898, 0xF899},
|
||||
{0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D}
|
||||
};
|
||||
|
||||
if (tone >= CH_MAITAIKHU && tone <= CH_NIKHAHIT) {
|
||||
return lowerLeftTones[glyphSet][tone - CH_MAITAIKHU];
|
||||
}
|
||||
|
||||
return tone;
|
||||
}
|
||||
|
||||
LEUnicode ThaiShaping::upperLeftTone(LEUnicode tone, le_uint8 glyphSet)
|
||||
{
|
||||
static LEUnicode upperLeftTones[][7] = {
|
||||
{0x0E6F, 0x0E70, 0x0E71, 0x0E72, 0x0E73, 0x0E74, 0x0E75},
|
||||
{0xF712, 0xF713, 0xF714, 0xF715, 0xF716, 0xF717, 0xF711},
|
||||
{0xF889, 0xF88A, 0xF88D, 0xF890, 0xF893, 0xF896, 0xF899},
|
||||
{0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D}
|
||||
};
|
||||
|
||||
if (tone >= CH_MAITAIKHU && tone <= CH_NIKHAHIT) {
|
||||
return upperLeftTones[glyphSet][tone - CH_MAITAIKHU];
|
||||
}
|
||||
|
||||
return tone;
|
||||
}
|
||||
|
||||
LEUnicode ThaiShaping::lowerBelowVowel(LEUnicode vowel, le_uint8 glyphSet)
|
||||
{
|
||||
static LEUnicode lowerBelowVowels[][3] = {
|
||||
{0x0E3C, 0x0E3D, 0x0E3E},
|
||||
{0xF718, 0xF719, 0xF71A},
|
||||
{0x0E38, 0x0E39, 0x0E3A},
|
||||
{0x0E38, 0x0E39, 0x0E3A}
|
||||
|
||||
};
|
||||
|
||||
if (vowel >= CH_SARA_U && vowel <= CH_PHINTHU) {
|
||||
return lowerBelowVowels[glyphSet][vowel - CH_SARA_U];
|
||||
}
|
||||
|
||||
return vowel;
|
||||
}
|
||||
|
||||
LEUnicode ThaiShaping::noDescenderCOD(LEUnicode cod, le_uint8 glyphSet)
|
||||
{
|
||||
static LEUnicode noDescenderCODs[][4] = {
|
||||
{0x0E60, 0x0E0E, 0x0E0F, 0x0E63},
|
||||
{0xF70F, 0x0E0E, 0x0E0F, 0xF700},
|
||||
{0x0E0D, 0x0E0E, 0x0E0F, 0x0E10},
|
||||
{0x0E0D, 0x0E0E, 0x0E0F, 0x0E10}
|
||||
|
||||
};
|
||||
|
||||
if (cod >= CH_YO_YING && cod <= CH_THO_THAN) {
|
||||
return noDescenderCODs[glyphSet][cod - CH_YO_YING];
|
||||
}
|
||||
|
||||
return cod;
|
||||
}
|
||||
|
||||
le_uint8 ThaiShaping::doTransition (StateTransition transition, LEUnicode currChar, le_int32 inputIndex, le_uint8 glyphSet,
|
||||
LEUnicode errorChar, LEUnicode *outputBuffer, le_int32 *charIndicies, le_int32 &outputIndex)
|
||||
{
|
||||
switch (transition.action) {
|
||||
case _A:
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = currChar;
|
||||
break;
|
||||
|
||||
case _C:
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = currChar;
|
||||
break;
|
||||
|
||||
case _D:
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = leftAboveVowel(currChar, glyphSet);
|
||||
break;
|
||||
|
||||
case _E:
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = lowerRightTone(currChar, glyphSet);
|
||||
break;
|
||||
|
||||
case _F:
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = lowerLeftTone(currChar, glyphSet);
|
||||
break;
|
||||
|
||||
case _G:
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = upperLeftTone(currChar, glyphSet);
|
||||
break;
|
||||
|
||||
case _H:
|
||||
{
|
||||
LEUnicode cod = outputBuffer[outputIndex - 1];
|
||||
LEUnicode coa = noDescenderCOD(cod, glyphSet);
|
||||
|
||||
if (cod != coa) {
|
||||
outputBuffer[outputIndex - 1] = coa;
|
||||
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = currChar;
|
||||
break;
|
||||
}
|
||||
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = lowerBelowVowel(currChar, glyphSet);
|
||||
break;
|
||||
}
|
||||
|
||||
case _R:
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = errorChar;
|
||||
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = currChar;
|
||||
break;
|
||||
|
||||
case _S:
|
||||
if (currChar == CH_SARA_AM) {
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = errorChar;
|
||||
}
|
||||
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = currChar;
|
||||
break;
|
||||
|
||||
default:
|
||||
// FIXME: if we get here, there's an error
|
||||
// in the state table!
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = currChar;
|
||||
break;
|
||||
}
|
||||
|
||||
return transition.nextState;
|
||||
}
|
||||
|
||||
le_uint8 ThaiShaping::getNextState(LEUnicode ch, le_uint8 prevState, le_int32 inputIndex, le_uint8 glyphSet, LEUnicode errorChar,
|
||||
le_uint8 &charClass, LEUnicode *output, le_int32 *charIndicies, le_int32 &outputIndex)
|
||||
{
|
||||
StateTransition transition;
|
||||
|
||||
charClass = getCharClass(ch);
|
||||
transition = getTransition(prevState, charClass);
|
||||
|
||||
return doTransition(transition, ch, inputIndex, glyphSet, errorChar, output, charIndicies, outputIndex);
|
||||
}
|
||||
|
||||
le_bool ThaiShaping::isLegalHere(LEUnicode ch, le_uint8 prevState)
|
||||
{
|
||||
le_uint8 charClass = getCharClass(ch);
|
||||
StateTransition transition = getTransition(prevState, charClass);
|
||||
|
||||
switch (transition.action) {
|
||||
case _A:
|
||||
case _C:
|
||||
case _D:
|
||||
case _E:
|
||||
case _F:
|
||||
case _G:
|
||||
case _H:
|
||||
return true;
|
||||
|
||||
case _R:
|
||||
case _S:
|
||||
return false;
|
||||
|
||||
default:
|
||||
// FIXME: if we get here, there's an error
|
||||
// in the state table!
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
le_int32 ThaiShaping::compose(const LEUnicode *input, le_int32 offset, le_int32 charCount, le_uint8 glyphSet,
|
||||
LEUnicode errorChar, LEUnicode *output, le_int32 *charIndicies)
|
||||
{
|
||||
le_uint8 state = 0;
|
||||
le_int32 inputIndex;
|
||||
le_int32 outputIndex = 0;
|
||||
le_uint8 conState = -1;
|
||||
le_int32 conInput = -1;
|
||||
le_int32 conOutput = -1;
|
||||
|
||||
for (inputIndex = 0; inputIndex < charCount; inputIndex += 1) {
|
||||
LEUnicode ch = input[inputIndex + offset];
|
||||
le_uint8 charClass;
|
||||
|
||||
// Decompose SARA AM into NIKHAHIT + SARA AA
|
||||
if (ch == CH_SARA_AM && isLegalHere(ch, state)) {
|
||||
outputIndex = conOutput;
|
||||
state = getNextState(CH_NIKHAHIT, conState, inputIndex, glyphSet, errorChar, charClass,
|
||||
output, charIndicies, outputIndex);
|
||||
|
||||
for (int j = conInput + 1; j < inputIndex; j += 1) {
|
||||
ch = input[j + offset];
|
||||
state = getNextState(ch, state, j, glyphSet, errorChar, charClass,
|
||||
output, charIndicies, outputIndex);
|
||||
}
|
||||
|
||||
ch = CH_SARA_AA;
|
||||
}
|
||||
|
||||
state = getNextState(ch, state, inputIndex, glyphSet, errorChar, charClass,
|
||||
output, charIndicies, outputIndex);
|
||||
|
||||
if (charClass >= CON && charClass <= COD) {
|
||||
conState = state;
|
||||
conInput = inputIndex;
|
||||
conOutput = outputIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return outputIndex;
|
||||
}
|
||||
|
||||
ThaiMarkFilter::ThaiMarkFilter(le_uint8 glyphSet)
|
||||
: rangeList(NULL)
|
||||
{
|
||||
static MarkRange glyphSet0MarkRanges[] =
|
||||
{
|
||||
{0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E}, {0x0E61, 0x0E61}, {0x0E64, 0x0E7C}, {0xFFFF, 0xFFFF}
|
||||
};
|
||||
|
||||
static MarkRange glyphSet1MarkRanges[] =
|
||||
{
|
||||
{0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E}, {0xF701, 0xF70E}, {0xF710, 0xF71A}, {0xFFFF, 0xFFFF}
|
||||
};
|
||||
|
||||
static MarkRange glyphSet2MarkRanges[] =
|
||||
{
|
||||
{0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E}, {0xF884, 0xF899}, {0xFFFF, 0xFFFF}
|
||||
};
|
||||
|
||||
static MarkRange glyphSet3MarkRanges[] =
|
||||
{
|
||||
{0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E}, {0xFFFF, 0xFFFF}
|
||||
};
|
||||
|
||||
static MarkRange *rangeTable[] =
|
||||
{glyphSet0MarkRanges, glyphSet1MarkRanges, glyphSet2MarkRanges, glyphSet3MarkRanges};
|
||||
|
||||
if (glyphSet <= 3) {
|
||||
rangeList = rangeTable[glyphSet];
|
||||
}
|
||||
}
|
||||
|
||||
ThaiMarkFilter::~ThaiMarkFilter()
|
||||
{
|
||||
// nothing to do here...
|
||||
}
|
||||
|
||||
le_bool ThaiMarkFilter::filter(LEGlyphID glyph)
|
||||
{
|
||||
le_int32 i;
|
||||
|
||||
if (rangeList != NULL) {
|
||||
for (i = 0; rangeList[i].first <= glyph; i += 1) {
|
||||
if (rangeList[i].last >= glyph) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
114
icu4c/source/layout/ThaiShaping.h
Normal file
114
icu4c/source/layout/ThaiShaping.h
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* @(#)ThaiShaping.h 1.9 00/03/15
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998, 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __THAISHAPING_H
|
||||
#define __THAISHAPING_H
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "LEGlyphFilter.h"
|
||||
#include "OpenTypeTables.h"
|
||||
|
||||
class ThaiMarkFilter : public LEGlyphFilter
|
||||
{
|
||||
private:
|
||||
struct MarkRange
|
||||
{
|
||||
LEUnicode first;
|
||||
LEUnicode last;
|
||||
};
|
||||
|
||||
MarkRange *rangeList;
|
||||
|
||||
public:
|
||||
ThaiMarkFilter(le_uint8 glyphSet);
|
||||
~ThaiMarkFilter();
|
||||
|
||||
virtual le_bool filter(LEGlyphID glyph);
|
||||
};
|
||||
|
||||
class ThaiShaping
|
||||
{
|
||||
public:
|
||||
|
||||
enum {
|
||||
// Character classes
|
||||
NON = 0,
|
||||
CON = 1,
|
||||
COA = 2,
|
||||
COD = 3,
|
||||
LVO = 4,
|
||||
FV1 = 5,
|
||||
FV2 = 6,
|
||||
FV3 = 7,
|
||||
BV1 = 8,
|
||||
BV2 = 9,
|
||||
BDI = 10,
|
||||
TON = 11,
|
||||
AD1 = 12,
|
||||
AD2 = 13,
|
||||
AD3 = 14,
|
||||
NIK = 15,
|
||||
AV1 = 16,
|
||||
AV2 = 17,
|
||||
AV3 = 18,
|
||||
classCount = 19,
|
||||
|
||||
// State Transition actions
|
||||
_A = 0,
|
||||
_C = 1,
|
||||
_D = 2,
|
||||
_E = 3,
|
||||
_F = 4,
|
||||
_G = 5,
|
||||
_H = 6,
|
||||
_R = 7,
|
||||
_S = 8
|
||||
};
|
||||
|
||||
struct StateTransition
|
||||
{
|
||||
le_uint8 nextState;
|
||||
le_uint8 action;
|
||||
|
||||
le_uint8 getNextState() { return nextState; };
|
||||
le_uint8 getAction() { return action; };
|
||||
};
|
||||
|
||||
static le_int32 compose(const LEUnicode *input, le_int32 offset, le_int32 charCount, le_uint8 glyphSet,
|
||||
LEUnicode errorChar, LEUnicode *output, le_int32 *charIndicies);
|
||||
|
||||
private:
|
||||
|
||||
static le_uint8 classTable[];
|
||||
static StateTransition thaiStateTable[][classCount];
|
||||
static StateTransition getTransition(le_uint8 state, le_uint8 currClass);
|
||||
static le_uint8 doTransition(StateTransition transition, LEUnicode currChar, le_int32 inputIndex, le_uint8 glyphSet,
|
||||
LEUnicode errorChar, LEUnicode *outputBuffer, le_int32 *charIndicies, le_int32 &outputIndex);
|
||||
|
||||
static le_uint8 getNextState(LEUnicode ch, le_uint8 state, le_int32 inputIndex, le_uint8 glyphSet, LEUnicode errorChar,
|
||||
le_uint8 &charClass, LEUnicode *output, le_int32 *charIndicies, le_int32 &outputIndex);
|
||||
|
||||
static le_bool isLegalHere(LEUnicode ch, le_uint8 prevState);
|
||||
static le_uint8 getCharClass(LEUnicode ch);
|
||||
|
||||
static LEUnicode noDescenderCOD(LEUnicode cod, le_uint8 glyphSet);
|
||||
static LEUnicode leftAboveVowel(LEUnicode vowel, le_uint8 glyphSet);
|
||||
static LEUnicode lowerBelowVowel(LEUnicode vowel, le_uint8 glyphSet);
|
||||
static LEUnicode lowerRightTone(LEUnicode tone, le_uint8 glyphSet);
|
||||
static LEUnicode lowerLeftTone(LEUnicode tone, le_uint8 glyphSet);
|
||||
static LEUnicode upperLeftTone(LEUnicode tone, le_uint8 glyphSet);
|
||||
|
||||
};
|
||||
|
||||
inline ThaiShaping::StateTransition ThaiShaping::getTransition(le_uint8 state, le_uint8 currClass)
|
||||
{
|
||||
return thaiStateTable[state][currClass];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
84
icu4c/source/layout/ThaiStateTables.cpp
Normal file
84
icu4c/source/layout/ThaiStateTables.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* @(#)ThaiStateTables.cpp 1.8 00/03/15
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1999, 2000 - All Rights Reserved
|
||||
*
|
||||
* WARNING: THIS FILE IS MACHINE GENERATED. DO NOT HAND EDIT IT UNLESS
|
||||
* YOU REALLY KNOW WHAT YOU'RE DOING.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "ThaiShaping.h"
|
||||
|
||||
le_uint8 ThaiShaping::classTable[] = {
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
// -------------------------------------------------------------------------------
|
||||
/*0E00*/ NON, CON, CON, CON, CON, CON, CON, CON, CON, CON, CON, CON, CON, COD, COD, COD,
|
||||
/*0E10*/ COD, CON, CON, CON, CON, CON, CON, CON, CON, CON, CON, COA, CON, COA, CON, COA,
|
||||
/*0E20*/ CON, CON, CON, CON, FV3, CON, FV3, CON, CON, CON, CON, CON, CON, CON, CON, NON,
|
||||
/*0E30*/ FV1, AV2, FV1, FV1, AV1, AV3, AV2, AV3, BV1, BV2, BDI, NON, NON, NON, NON, NON,
|
||||
/*0E40*/ LVO, LVO, LVO, LVO, LVO, FV2, NON, AD2, TON, TON, TON, TON, AD1, NIK, AD3, NON,
|
||||
/*0E50*/ NON, NON, NON, NON, NON, NON, NON, NON, NON, NON, NON, NON
|
||||
};
|
||||
|
||||
ThaiShaping::StateTransition ThaiShaping::thaiStateTable[][ThaiShaping::classCount] = {
|
||||
//+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
//| N C C C L F F F B B B T A A A N A A A |
|
||||
//| O O O O V V V V V V D O D D D I V V V |
|
||||
//| N N A D O 1 2 3 1 2 I N 1 2 3 K 1 2 3 |
|
||||
//+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
/*00*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*01*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 2, _C}, { 6, _C}, { 0, _C}, { 8, _E}, { 0, _E}, { 0, _E}, { 0, _C}, { 9, _E}, {11, _C}, {14, _C}, {16, _C}},
|
||||
/*02*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 3, _E}, { 0, _E}, { 0, _R}, { 0, _R}, { 4, _E}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*03*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*04*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 5, _C}, { 0, _C}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*05*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*06*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 7, _E}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*07*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*08*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _A}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*09*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, {10, _C}, { 0, _C}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*10*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*11*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, {12, _C}, { 0, _C}, { 0, _R}, { 0, _R}, {13, _C}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*12*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*13*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*14*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, {15, _C}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*15*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*16*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, {17, _C}, { 0, _R}, { 0, _C}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*17*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*18*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _A}, { 0, _S}, { 0, _A}, {19, _C}, {23, _C}, { 0, _C}, {25, _F}, { 0, _F}, { 0, _F}, { 0, _D}, {26, _F}, {28, _D}, {31, _D}, {33, _D}},
|
||||
/*19*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, {20, _F}, { 0, _F}, { 0, _R}, { 0, _R}, {21, _F}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*20*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*21*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, {22, _C}, { 0, _C}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*22*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*23*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, {24, _F}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*24*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*25*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _A}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*26*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, {27, _G}, { 0, _G}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*27*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*28*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, {29, _G}, { 0, _G}, { 0, _R}, { 0, _R}, {30, _G}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*29*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*30*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*31*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, {32, _G}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*32*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*33*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, {34, _G}, { 0, _R}, { 0, _G}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*34*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*35*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _A}, { 0, _S}, { 0, _A}, {36, _H}, {40, _H}, { 0, _H}, {42, _E}, { 0, _E}, { 0, _E}, { 0, _C}, {43, _E}, {45, _C}, {48, _C}, {50, _C}},
|
||||
/*36*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, {37, _E}, { 0, _E}, { 0, _R}, { 0, _R}, {38, _E}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*37*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*38*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, {39, _C}, { 0, _C}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*39*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*40*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, {41, _E}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*41*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*42*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _A}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*43*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, {44, _C}, { 0, _C}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*44*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*45*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, {46, _C}, { 0, _C}, { 0, _R}, { 0, _R}, {47, _C}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*46*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*47*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*48*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, {49, _C}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*49*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*50*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _S}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, {51, _C}, { 0, _R}, { 0, _C}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}},
|
||||
/*51*/ {{ 0, _A}, { 1, _A}, {18, _A}, {35, _A}, { 0, _A}, { 0, _S}, { 0, _A}, { 0, _A}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}, { 0, _R}}
|
||||
};
|
||||
|
1279
icu4c/source/layout/layout.dsp
Normal file
1279
icu4c/source/layout/layout.dsp
Normal file
File diff suppressed because it is too large
Load Diff
29
icu4c/source/layout/layout.dsw
Normal file
29
icu4c/source/layout/layout.dsw
Normal file
@ -0,0 +1,29 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "layout"=.\layout.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
Loading…
Reference in New Issue
Block a user