From 54c5c881a8b06976efd3b6bb7c887b5bd41ddf1c Mon Sep 17 00:00:00 2001 From: Eric Mader Date: Tue, 14 Nov 2000 21:22:14 +0000 Subject: [PATCH] ICU-120 Initial checkin of the LayoutEngine! X-SVN-Rev: 2909 --- icu4c/source/allinone/allinone.dsw | 12 + icu4c/source/layout/ArabicLayoutEngine.cpp | 176 +++ icu4c/source/layout/ArabicLayoutEngine.h | 193 +++ icu4c/source/layout/GXLayoutEngine.cpp | 40 + icu4c/source/layout/GXLayoutEngine.h | 98 ++ icu4c/source/layout/IndicLayoutEngine.cpp | 112 ++ icu4c/source/layout/IndicLayoutEngine.h | 205 +++ icu4c/source/layout/LEFontInstance.h | 263 ++++ icu4c/source/layout/LEGlyphFilter.h | 32 + icu4c/source/layout/LEScripts.h | 44 + icu4c/source/layout/LESwaps.h | 78 ++ icu4c/source/layout/LETypes.h | 49 + icu4c/source/layout/LayoutEngine.cpp | 325 +++++ icu4c/source/layout/LayoutEngine.h | 371 +++++ icu4c/source/layout/Makefile.in | 167 +++ icu4c/source/layout/OpenTypeLayoutEngine.cpp | 200 +++ icu4c/source/layout/OpenTypeLayoutEngine.h | 280 ++++ icu4c/source/layout/ThaiLayoutEngine.cpp | 67 + icu4c/source/layout/ThaiLayoutEngine.h | 90 ++ icu4c/source/layout/ThaiShaping.cpp | 354 +++++ icu4c/source/layout/ThaiShaping.h | 114 ++ icu4c/source/layout/ThaiStateTables.cpp | 84 ++ icu4c/source/layout/layout.dsp | 1279 ++++++++++++++++++ icu4c/source/layout/layout.dsw | 29 + 24 files changed, 4662 insertions(+) create mode 100644 icu4c/source/layout/ArabicLayoutEngine.cpp create mode 100644 icu4c/source/layout/ArabicLayoutEngine.h create mode 100644 icu4c/source/layout/GXLayoutEngine.cpp create mode 100644 icu4c/source/layout/GXLayoutEngine.h create mode 100644 icu4c/source/layout/IndicLayoutEngine.cpp create mode 100644 icu4c/source/layout/IndicLayoutEngine.h create mode 100644 icu4c/source/layout/LEFontInstance.h create mode 100644 icu4c/source/layout/LEGlyphFilter.h create mode 100644 icu4c/source/layout/LEScripts.h create mode 100644 icu4c/source/layout/LESwaps.h create mode 100644 icu4c/source/layout/LETypes.h create mode 100644 icu4c/source/layout/LayoutEngine.cpp create mode 100644 icu4c/source/layout/LayoutEngine.h create mode 100644 icu4c/source/layout/Makefile.in create mode 100644 icu4c/source/layout/OpenTypeLayoutEngine.cpp create mode 100644 icu4c/source/layout/OpenTypeLayoutEngine.h create mode 100644 icu4c/source/layout/ThaiLayoutEngine.cpp create mode 100644 icu4c/source/layout/ThaiLayoutEngine.h create mode 100644 icu4c/source/layout/ThaiShaping.cpp create mode 100644 icu4c/source/layout/ThaiShaping.h create mode 100644 icu4c/source/layout/ThaiStateTables.cpp create mode 100644 icu4c/source/layout/layout.dsp create mode 100644 icu4c/source/layout/layout.dsw diff --git a/icu4c/source/allinone/allinone.dsw b/icu4c/source/allinone/allinone.dsw index df560dedd4..23c185696e 100644 --- a/icu4c/source/allinone/allinone.dsw +++ b/icu4c/source/allinone/allinone.dsw @@ -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> diff --git a/icu4c/source/layout/ArabicLayoutEngine.cpp b/icu4c/source/layout/ArabicLayoutEngine.cpp new file mode 100644 index 0000000000..7ef867d0b3 --- /dev/null +++ b/icu4c/source/layout/ArabicLayoutEngine.cpp @@ -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); +} + + + diff --git a/icu4c/source/layout/ArabicLayoutEngine.h b/icu4c/source/layout/ArabicLayoutEngine.h new file mode 100644 index 0000000000..636cf34d43 --- /dev/null +++ b/icu4c/source/layout/ArabicLayoutEngine.h @@ -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 + diff --git a/icu4c/source/layout/GXLayoutEngine.cpp b/icu4c/source/layout/GXLayoutEngine.cpp new file mode 100644 index 0000000000..f5a24d58b9 --- /dev/null +++ b/icu4c/source/layout/GXLayoutEngine.cpp @@ -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... +} + diff --git a/icu4c/source/layout/GXLayoutEngine.h b/icu4c/source/layout/GXLayoutEngine.h new file mode 100644 index 0000000000..a0f2d99b88 --- /dev/null +++ b/icu4c/source/layout/GXLayoutEngine.h @@ -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 + diff --git a/icu4c/source/layout/IndicLayoutEngine.cpp b/icu4c/source/layout/IndicLayoutEngine.cpp new file mode 100644 index 0000000000..2923f991f1 --- /dev/null +++ b/icu4c/source/layout/IndicLayoutEngine.cpp @@ -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); +} + diff --git a/icu4c/source/layout/IndicLayoutEngine.h b/icu4c/source/layout/IndicLayoutEngine.h new file mode 100644 index 0000000000..8efa8e3825 --- /dev/null +++ b/icu4c/source/layout/IndicLayoutEngine.h @@ -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 + +/** + * 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 + diff --git a/icu4c/source/layout/LEFontInstance.h b/icu4c/source/layout/LEFontInstance.h new file mode 100644 index 0000000000..acb3b9ceb7 --- /dev/null +++ b/icu4c/source/layout/LEFontInstance.h @@ -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 + + diff --git a/icu4c/source/layout/LEGlyphFilter.h b/icu4c/source/layout/LEGlyphFilter.h new file mode 100644 index 0000000000..8688c12f07 --- /dev/null +++ b/icu4c/source/layout/LEGlyphFilter.h @@ -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 diff --git a/icu4c/source/layout/LEScripts.h b/icu4c/source/layout/LEScripts.h new file mode 100644 index 0000000000..3d669d9571 --- /dev/null +++ b/icu4c/source/layout/LEScripts.h @@ -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 diff --git a/icu4c/source/layout/LESwaps.h b/icu4c/source/layout/LESwaps.h new file mode 100644 index 0000000000..907382ba77 --- /dev/null +++ b/icu4c/source/layout/LESwaps.h @@ -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 diff --git a/icu4c/source/layout/LETypes.h b/icu4c/source/layout/LETypes.h new file mode 100644 index 0000000000..c17ca05a1b --- /dev/null +++ b/icu4c/source/layout/LETypes.h @@ -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 + + diff --git a/icu4c/source/layout/LayoutEngine.cpp b/icu4c/source/layout/LayoutEngine.cpp new file mode 100644 index 0000000000..3182e221da --- /dev/null +++ b/icu4c/source/layout/LayoutEngine.cpp @@ -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(); +} + diff --git a/icu4c/source/layout/LayoutEngine.h b/icu4c/source/layout/LayoutEngine.h new file mode 100644 index 0000000000..24a85065df --- /dev/null +++ b/icu4c/source/layout/LayoutEngine.h @@ -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 + +#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 + diff --git a/icu4c/source/layout/Makefile.in b/icu4c/source/layout/Makefile.in new file mode 100644 index 0000000000..a5c076cf87 --- /dev/null +++ b/icu4c/source/layout/Makefile.in @@ -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 + + diff --git a/icu4c/source/layout/OpenTypeLayoutEngine.cpp b/icu4c/source/layout/OpenTypeLayoutEngine.cpp new file mode 100644 index 0000000000..13be2c2373 --- /dev/null +++ b/icu4c/source/layout/OpenTypeLayoutEngine.cpp @@ -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; +} + diff --git a/icu4c/source/layout/OpenTypeLayoutEngine.h b/icu4c/source/layout/OpenTypeLayoutEngine.h new file mode 100644 index 0000000000..bdeb2cf335 --- /dev/null +++ b/icu4c/source/layout/OpenTypeLayoutEngine.h @@ -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 + diff --git a/icu4c/source/layout/ThaiLayoutEngine.cpp b/icu4c/source/layout/ThaiLayoutEngine.cpp new file mode 100644 index 0000000000..e6402bd147 --- /dev/null +++ b/icu4c/source/layout/ThaiLayoutEngine.cpp @@ -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; +} + diff --git a/icu4c/source/layout/ThaiLayoutEngine.h b/icu4c/source/layout/ThaiLayoutEngine.h new file mode 100644 index 0000000000..0e8f308278 --- /dev/null +++ b/icu4c/source/layout/ThaiLayoutEngine.h @@ -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 + diff --git a/icu4c/source/layout/ThaiShaping.cpp b/icu4c/source/layout/ThaiShaping.cpp new file mode 100644 index 0000000000..97a05db746 --- /dev/null +++ b/icu4c/source/layout/ThaiShaping.cpp @@ -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; +} + + diff --git a/icu4c/source/layout/ThaiShaping.h b/icu4c/source/layout/ThaiShaping.h new file mode 100644 index 0000000000..ad9bd4ea94 --- /dev/null +++ b/icu4c/source/layout/ThaiShaping.h @@ -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 + + diff --git a/icu4c/source/layout/ThaiStateTables.cpp b/icu4c/source/layout/ThaiStateTables.cpp new file mode 100644 index 0000000000..d1107c26ae --- /dev/null +++ b/icu4c/source/layout/ThaiStateTables.cpp @@ -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}} + }; + diff --git a/icu4c/source/layout/layout.dsp b/icu4c/source/layout/layout.dsp new file mode 100644 index 0000000000..192323e53f --- /dev/null +++ b/icu4c/source/layout/layout.dsp @@ -0,0 +1,1279 @@ +# Microsoft Developer Studio Project File - Name="layout" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=layout - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "layout.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "layout.mak" CFG="layout - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "layout - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "layout - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "layout - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\lib\" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LAYOUT_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\common.\opentype .\aat" /I "..\common" /I "opentype" /I "aat" /I "..\layout" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LAYOUT_EXPORTS" /D "U_LAYOUT_IMPLEMENTATION" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 /nologo /dll /machine:I386 /out:"..\..\bin\icule17.dll" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "layout___Win32_Debug" +# PROP BASE Intermediate_Dir "layout___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\lib\" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LAYOUT_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\common" /I "..\layout" /I "opentype" /I "aat" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LAYOUT_EXPORTS" /D "U_LAYOUT_IMPLEMENTATION" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 /nologo /dll /debug /machine:I386 /out:"..\..\bin\icule17d.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "layout - Win32 Release" +# Name "layout - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\opentype\AlternateSubstitutionSubtables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\AnchorTables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\ArabicLayoutEngine.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\ArabicLigatureData.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\ArabicShaping.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\CDACLayout.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\CDACLigatureData.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\ClassDefinitionTables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\aat\ContextualGlyphSubstitutionProcessor.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\ContextualSubstitutionSubtables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\CoverageTables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\DeviceTables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\Features.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\GDEFMarkFilter.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\GlyphDefinitionTables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\GlyphIterator.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\GlyphPositioningLookupProcessor.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\GlyphPositioningTables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\GlyphSubstitutionLookupProcessor.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\GlyphSubstitutionTables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\GXLayoutEngine.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\HebrewLigatureData.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\HebrewShaping.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\IndicClassTables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\IndicLayoutEngine.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\aat\IndicRearrangementProcessor.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\IndicReordering.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\LayoutEngine.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\aat\LigatureSubstitutionProcessor.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\LigatureSubstitutionSubtables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\LookupProcessor.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\Lookups.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\aat\LookupTables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\MarkArrays.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\MarkToBasePositioningSubtables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\MarkToLigaturePositioningSubtables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\MarkToMarkPositioningSubtables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\aat\MorphTables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\MultipleSubstitutionSubtables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\aat\NonContextualGlyphSubstitutionProcessor.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\OpenTypeLayoutEngine.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\OpenTypeUtilities.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\PairPositioningSubtables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\ScriptAndLanguage.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\aat\SegmentArrayProcessor.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\aat\SegmentSingleProcessor.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\aat\SimpleArrayProcessor.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\SinglePositioningSubtables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\SingleSubstitutionSubtables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\aat\SingleTableProcessor.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\aat\StateTableProcessor.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\SubstitutionLookups.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\aat\SubtableProcessor.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\ThaiLayoutEngine.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\ThaiShaping.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\ThaiStateTables.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\aat\TrimmedArrayProcessor.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\opentype\ValueRecords.cpp + +!IF "$(CFG)" == "layout - Win32 Release" + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# PROP Intermediate_Dir "debug" + +!ENDIF + +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\opentype\AlternateSubstitutionSubtables.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\AnchorTables.h +# End Source File +# Begin Source File + +SOURCE=.\ArabicLayoutEngine.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\ArabicShaping.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\AttachmentPositioningSubtables.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\CDACLayout.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\ClassDefinitionTables.h +# End Source File +# Begin Source File + +SOURCE=.\aat\ContextualGlyphInsertion.h +# End Source File +# Begin Source File + +SOURCE=.\aat\ContextualGlyphSubstitution.h +# End Source File +# Begin Source File + +SOURCE=.\aat\ContextualGlyphSubstitutionProcessor.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\ContextualSubstitutionSubtables.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\CoverageTables.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\DeviceTables.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\Features.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\GDEFMarkFilter.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\GlyphDefinitionTables.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\GlyphIterator.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\GlyphPositionAdjustments.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\GlyphPositioningLookupProcessor.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\GlyphPositioningTables.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\GlyphSubstitutionLookupProcessor.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\GlyphSubstitutionTables.h +# End Source File +# Begin Source File + +SOURCE=.\GXLayoutEngine.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\HebrewShaping.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\HindiFeatureTags.h +# End Source File +# Begin Source File + +SOURCE=.\IndicLayoutEngine.h +# End Source File +# Begin Source File + +SOURCE=.\aat\IndicRearrangement.h +# End Source File +# Begin Source File + +SOURCE=.\aat\IndicRearrangementProcessor.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\IndicReordering.h +# End Source File +# Begin Source File + +SOURCE=.\LayoutEngine.h + +!IF "$(CFG)" == "layout - Win32 Release" + +# Begin Custom Build +InputPath=.\LayoutEngine.h + +"..\..\include\layout\LayoutEngine.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + copy LayoutEngine.h ..\..\include\layout + +# End Custom Build + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# Begin Custom Build +InputPath=.\LayoutEngine.h + +"..\..\include\layout\LayoutEngine.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + copy LayoutEngine.h ..\..\include\layout + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\aat\LayoutTables.h +# End Source File +# Begin Source File + +SOURCE=.\LEFontInstance.h + +!IF "$(CFG)" == "layout - Win32 Release" + +# Begin Custom Build +InputPath=.\LEFontInstance.h + +"..\..\include\layout\LEFontInstance.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + copy LEFontInstance.h ..\..\include\layout + +# End Custom Build + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# Begin Custom Build +InputPath=.\LEFontInstance.h + +"..\..\include\layout\LEFontInstance.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + copy LEFontInstance.h ..\..\include\layout + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\LEGlyphFilter.h + +!IF "$(CFG)" == "layout - Win32 Release" + +# Begin Custom Build +InputPath=.\LEGlyphFilter.h + +"..\..\include\layout\LEGlyphFilter.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + copy LEGlyphFilter.h ..\..\include\layout + +# End Custom Build + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# Begin Custom Build +InputPath=.\LEGlyphFilter.h + +"..\..\include\layout\LEGlyphFilter.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + copy LEGlyphFilter.h ..\..\include\layout + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\LEScripts.h + +!IF "$(CFG)" == "layout - Win32 Release" + +# Begin Custom Build +InputPath=.\LEScripts.h + +"..\..\include\layout\LEScripts.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + copy LEScripts.h ..\..\include\layout + +# End Custom Build + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# Begin Custom Build +InputPath=.\LEScripts.h + +"..\..\include\layout\LEScripts.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + copy LEScripts.h ..\..\include\layout + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\LESwaps.h + +!IF "$(CFG)" == "layout - Win32 Release" + +# Begin Custom Build +InputPath=.\LESwaps.h + +"..\..\include\layout\LESwaps.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + copy LESwaps.h ..\..\include\layout + +# End Custom Build + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# Begin Custom Build +InputPath=.\LESwaps.h + +"..\..\include\layout\LESwaps.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + copy LESwaps.h ..\..\include\layout + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\LETypes.h + +!IF "$(CFG)" == "layout - Win32 Release" + +# Begin Custom Build +InputPath=.\LETypes.h + +"..\..\include\layout\LETypes.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + copy LETypes.h ..\..\include\layout + +# End Custom Build + +!ELSEIF "$(CFG)" == "layout - Win32 Debug" + +# Begin Custom Build +InputPath=.\LETypes.h + +"..\..\include\layout\LETypes.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + copy LETypes.h ..\..\include\layout + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\aat\LigatureSubstitution.h +# End Source File +# Begin Source File + +SOURCE=.\aat\LigatureSubstitutionProcessor.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\LigatureSubstitutionSubtables.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\LookupProcessor.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\Lookups.h +# End Source File +# Begin Source File + +SOURCE=.\aat\LookupTables.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\MarkArrays.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\MarkToBasePositioningSubtables.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\MarkToLigaturePositioningSubtables.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\MarkToMarkPositioningSubtables.h +# End Source File +# Begin Source File + +SOURCE=.\aat\MorphStateTables.h +# End Source File +# Begin Source File + +SOURCE=.\aat\MorphTables.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\MultipleSubstitutionSubtables.h +# End Source File +# Begin Source File + +SOURCE=.\aat\NonContextualGlyphSubstitution.h +# End Source File +# Begin Source File + +SOURCE=.\aat\NonContextualGlyphSubstitutionProcessor.h +# End Source File +# Begin Source File + +SOURCE=.\OpenTypeLayoutEngine.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\OpenTypeTables.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\OpenTypeUtilities.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\PairPositioningSubtables.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\ScriptAndLanguage.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\ScriptAndLanguageTags.h +# End Source File +# Begin Source File + +SOURCE=.\aat\SegmentArrayProcessor.h +# End Source File +# Begin Source File + +SOURCE=.\aat\SegmentSingleProcessor.h +# End Source File +# Begin Source File + +SOURCE=.\aat\SimpleArrayProcessor.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\SinglePositioningSubtables.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\SingleSubstitutionSubtables.h +# End Source File +# Begin Source File + +SOURCE=.\aat\SingleTableProcessor.h +# End Source File +# Begin Source File + +SOURCE=.\aat\StateTableProcessor.h +# End Source File +# Begin Source File + +SOURCE=.\aat\StateTables.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\SubstitutionLookups.h +# End Source File +# Begin Source File + +SOURCE=.\aat\SubtableProcessor.h +# End Source File +# Begin Source File + +SOURCE=.\ThaiLayoutEngine.h +# End Source File +# Begin Source File + +SOURCE=.\ThaiShaping.h +# End Source File +# Begin Source File + +SOURCE=.\aat\TrimmedArrayProcessor.h +# End Source File +# Begin Source File + +SOURCE=.\opentype\ValueRecords.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/icu4c/source/layout/layout.dsw b/icu4c/source/layout/layout.dsw new file mode 100644 index 0000000000..611d964b01 --- /dev/null +++ b/icu4c/source/layout/layout.dsw @@ -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> +{{{ +}}} + +############################################################################### +