]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/layout/ArabicLayoutEngine.cpp
ICU-491.11.1.tar.gz
[apple/icu.git] / icuSources / layout / ArabicLayoutEngine.cpp
index 7f65b98852f4cf1da42407da8da3edaca8266537..c0f780e4480b4f980970f210c505b46b4077c7bc 100644 (file)
@@ -1,18 +1,19 @@
 
 /*
- * %W% %E%
  *
- * (C) Copyright IBM Corp. 1998-2003 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2008 - All Rights Reserved
  *
  */
 
 #include "LETypes.h"
 #include "LEScripts.h"
 #include "LEGlyphFilter.h"
+#include "LEGlyphStorage.h"
 #include "LayoutEngine.h"
 #include "OpenTypeLayoutEngine.h"
 #include "ArabicLayoutEngine.h"
 #include "ScriptAndLanguageTags.h"
+#include "CharSubstitutionFilter.h"
 
 #include "GlyphSubstitutionTables.h"
 #include "GlyphDefinitionTables.h"
 #include "GDEFMarkFilter.h"
 
 #include "ArabicShaping.h"
-#include "HebrewShaping.h"
+#include "CanonShaping.h"
 
 U_NAMESPACE_BEGIN
 
-class CharSubstitutionFilter : public UMemory, public LEGlyphFilter
-{
-private:
-    const LEFontInstance *fFontInstance;
-
-    CharSubstitutionFilter(const CharSubstitutionFilter &other); // forbid copying of this class
-    CharSubstitutionFilter &operator=(const CharSubstitutionFilter &other); // forbid copying of this class
-
-public:
-    CharSubstitutionFilter(const LEFontInstance *fontInstance);
-    le_bool accept(LEGlyphID glyph) const;
-};
-
-CharSubstitutionFilter::CharSubstitutionFilter(const LEFontInstance *fontInstance)
-  : fFontInstance(fontInstance)
-{
-    // nothing to do
-}
-
 le_bool CharSubstitutionFilter::accept(LEGlyphID glyph) const
 {
     return fFontInstance->canDisplay((LEUnicode) glyph);
 }
 
-const char ArabicOpenTypeLayoutEngine::fgClassID=0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ArabicOpenTypeLayoutEngine)
 
 ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
-                        const GlyphSubstitutionTableHeader *gsubTable)
-    : OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, gsubTable)
+                        le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success)
+    : OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success)
 {
-    // fFeatureOrder = ArabicShaping::getFeatureOrder();
+    fFeatureMap = ArabicShaping::getFeatureMap(fFeatureMapCount);
+    fFeatureOrder = TRUE;
 }
 
-ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode)
-    : OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode)
+ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
+                                                      le_int32 typoFlags, LEErrorCode &success)
+    : OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success)
 {
-    // fFeatureOrder = ArabicShaping::getFeatureOrder();
+    fFeatureMap = ArabicShaping::getFeatureMap(fFeatureMapCount);
+
+    // NOTE: We don't need to set fFeatureOrder to TRUE here
+    // because this constructor is only called by the constructor
+    // for UnicodeArabicOpenTypeLayoutEngine, which uses a pre-built
+    // GSUB table that has the features in the correct order.
+
+    //fFeatureOrder = TRUE;
 }
 
 ArabicOpenTypeLayoutEngine::~ArabicOpenTypeLayoutEngine()
@@ -73,7 +64,7 @@ ArabicOpenTypeLayoutEngine::~ArabicOpenTypeLayoutEngine()
 // 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, LEErrorCode &success)
+        LEUnicode *&outChars, LEGlyphStorage &glyphStorage, LEErrorCode &success)
 {
     if (LE_FAILURE(success)) {
         return 0;
@@ -84,90 +75,62 @@ le_int32 ArabicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[]
         return 0;
     }
 
-    featureTags = LE_NEW_ARRAY(const LETag *, count);
+    outChars = LE_NEW_ARRAY(LEUnicode, count);
 
-    if (featureTags == NULL) {
+    if (outChars == NULL) {
         success = LE_MEMORY_ALLOCATION_ERROR;
         return 0;
     }
 
-    switch (fScriptCode) {
-    case arabScriptCode:
-    {
-        GlyphShaper shaper(featureTags);
+    glyphStorage.allocateGlyphArray(count, rightToLeft, success);
+    glyphStorage.allocateAuxData(success);
 
-        // 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;
+    if (LE_FAILURE(success)) {
+        LE_DELETE_ARRAY(outChars);
+        return 0;
     }
 
-    case hebrScriptCode:
-        HebrewShaping::shape(chars, offset, count, max, rightToLeft, featureTags);
-        break;
-    }
+    CanonShaping::reorderMarks(&chars[offset], count, rightToLeft, outChars, glyphStorage);
+
+    // Note: This processes the *original* character array so we can get context
+    // for the first and last characters. This is OK because only the marks
+    // will have been reordered, and they don't contribute to shaping.
+    ArabicShaping::shape(chars, offset, count, max, rightToLeft, glyphStorage);
 
     return count;
 }
 
 void ArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
-                                                      LEGlyphID glyphs[], le_int32 glyphCount, float positions[], LEErrorCode &success)
+                                                      LEGlyphStorage &glyphStorage, LEErrorCode &success)
 {
     if (LE_FAILURE(success)) {
         return;
     }
 
-    if (chars == NULL || glyphs == NULL || positions == NULL || offset < 0 || count < 0) {
+    if (chars == NULL || offset < 0 || count < 0) {
         success = LE_ILLEGAL_ARGUMENT_ERROR;
         return;
     }
 
     if (fGPOSTable != NULL) {
-        OpenTypeLayoutEngine::adjustGlyphPositions(chars, offset, count, reverse, glyphs, glyphCount, positions, success);
+        OpenTypeLayoutEngine::adjustGlyphPositions(chars, offset, count, reverse, glyphStorage, success);
     } else if (fGDEFTable != NULL) {
         GDEFMarkFilter filter(fGDEFTable);
 
-        adjustMarkGlyphs(glyphs, glyphCount, false, &filter, positions, success);
+        adjustMarkGlyphs(glyphStorage, &filter, success);
     } else {
-        GlyphDefinitionTableHeader *gdefTable = (GlyphDefinitionTableHeader *) ArabicShaping::glyphDefinitionTable;
+        GlyphDefinitionTableHeader *gdefTable = (GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
         GDEFMarkFilter filter(gdefTable);
-        LEGlyphID *tempGlyphs;
-
-        // FIXME: we could avoid the memory allocation and copying here by
-        // making a clone of the adjustMarkGlyphs method which took characters
-        // directly...
-        tempGlyphs = LE_NEW_ARRAY(LEGlyphID, count);
-
-        if (tempGlyphs == NULL) {
-            success = LE_MEMORY_ALLOCATION_ERROR;
-            return;
-        }
 
-        for (le_int32 i = 0; i < count; i += 1) {
-            tempGlyphs[i] = (LEGlyphID) chars[offset + i];
-        }
-
-        adjustMarkGlyphs(tempGlyphs, count, reverse, &filter, positions, success);
-
-        LE_DELETE_ARRAY(tempGlyphs);
+        adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
     }
 }
 
-UnicodeArabicOpenTypeLayoutEngine::UnicodeArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode)
-    : ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode)
+UnicodeArabicOpenTypeLayoutEngine::UnicodeArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success)
+    : ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success)
 {
-    switch (scriptCode) {
-    case arabScriptCode:
-        fGSUBTable = (const GlyphSubstitutionTableHeader *) ArabicShaping::glyphSubstitutionTable;
-        fGDEFTable = (const GlyphDefinitionTableHeader *) ArabicShaping::glyphDefinitionTable;
-        break;
-
-    case hebrScriptCode:
-        fGSUBTable = (const GlyphSubstitutionTableHeader *) HebrewShaping::glyphSubstitutionTable;
-        fGDEFTable = (const GlyphDefinitionTableHeader *) HebrewShaping::glyphDefinitionTable;
-        break;
-    }
-
+    fGSUBTable = (const GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable;
+    fGDEFTable = (const GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
 
     fSubstitutionFilter = new CharSubstitutionFilter(fontInstance);
 }
@@ -178,21 +141,16 @@ UnicodeArabicOpenTypeLayoutEngine::~UnicodeArabicOpenTypeLayoutEngine()
 }
 
 // "glyphs", "indices" -> glyphs, indices
-le_int32 UnicodeArabicOpenTypeLayoutEngine::glyphPostProcessing(LEGlyphID tempGlyphs[], le_int32 tempCharIndices[], le_int32 tempGlyphCount,
-                LEGlyphID *&glyphs, le_int32 *&charIndices, LEErrorCode &success)
+le_int32 UnicodeArabicOpenTypeLayoutEngine::glyphPostProcessing(LEGlyphStorage &tempGlyphStorage, LEGlyphStorage &glyphStorage, LEErrorCode &success)
 {
     if (LE_FAILURE(success)) {
         return 0;
     }
 
-    if (tempGlyphs == NULL || tempCharIndices == NULL ||tempGlyphCount < 0) {
-        success = LE_ILLEGAL_ARGUMENT_ERROR;
-        return 0;
-    }
-
     // FIXME: we could avoid the memory allocation and copy if we
     // made a clone of mapCharsToGlyphs which took the fake glyphs
     // directly.
+    le_int32 tempGlyphCount = tempGlyphStorage.getGlyphCount();
     LEUnicode *tempChars = LE_NEW_ARRAY(LEUnicode, tempGlyphCount);
 
     if (tempChars == NULL) {
@@ -201,19 +159,19 @@ le_int32 UnicodeArabicOpenTypeLayoutEngine::glyphPostProcessing(LEGlyphID tempGl
     }
 
     for (le_int32 i = 0; i < tempGlyphCount; i += 1) {
-        tempChars[i] = (LEUnicode) LE_GET_GLYPH(tempGlyphs[i]);
+        tempChars[i] = (LEUnicode) LE_GET_GLYPH(tempGlyphStorage[i]);
     }
 
-    charIndices = tempCharIndices;
+    glyphStorage.adoptCharIndicesArray(tempGlyphStorage);
 
-    ArabicOpenTypeLayoutEngine::mapCharsToGlyphs(tempChars, 0, tempGlyphCount, false, true, glyphs, charIndices, success);
+    ArabicOpenTypeLayoutEngine::mapCharsToGlyphs(tempChars, 0, tempGlyphCount, FALSE, TRUE, glyphStorage, success);
 
     LE_DELETE_ARRAY(tempChars);
 
     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, LEErrorCode &success)
+void UnicodeArabicOpenTypeLayoutEngine::mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, le_bool /*mirror*/, LEGlyphStorage &glyphStorage, LEErrorCode &success)
 {
     if (LE_FAILURE(success)) {
         return;
@@ -224,68 +182,35 @@ void UnicodeArabicOpenTypeLayoutEngine::mapCharsToGlyphs(const LEUnicode chars[]
         return;
     }
 
-    le_int32 i, dir, out;
-
-    out = 0;
-    dir = 1;
+    le_int32 i, dir = 1, out = 0;
 
     if (reverse) {
         out = count - 1;
         dir = -1;
     }
 
-    glyphs = LE_NEW_ARRAY(LEGlyphID, count);
-
-    if (glyphs == NULL) {
-        success = LE_MEMORY_ALLOCATION_ERROR;
-        return;
-    }
-
-    charIndices = LE_NEW_ARRAY(le_int32, count);
-
-    if (charIndices == NULL) {
-        LE_DELETE_ARRAY(glyphs);
-        success = LE_MEMORY_ALLOCATION_ERROR;
-        return;
-    }
+    glyphStorage.allocateGlyphArray(count, reverse, success);
 
     for (i = 0; i < count; i += 1, out += dir) {
-        glyphs[out] = (LEGlyphID) chars[offset + i];
-        charIndices[out] = i;
+        glyphStorage[out] = (LEGlyphID) chars[offset + i];
     }
 }
 
 void UnicodeArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
-                                                      LEGlyphID glyphs[], le_int32 glyphCount, float positions[], LEErrorCode &success)
+                                                      LEGlyphStorage &glyphStorage, LEErrorCode &success)
 {
     if (LE_FAILURE(success)) {
         return;
     }
 
-    if (chars == NULL || glyphs == NULL || positions == NULL || offset < 0 || count < 0 || glyphCount < 0) {
+    if (chars == NULL || offset < 0 || count < 0) {
         success = LE_ILLEGAL_ARGUMENT_ERROR;
         return;
     }
 
     GDEFMarkFilter filter(fGDEFTable);
 
-    // FIXME: we could avoid the memory allocation and copying here by
-    // making a clone of the adjustMarkGlyphs method which took characters
-    // directly...
-    LEGlyphID *tempGlyphs = LE_NEW_ARRAY(LEGlyphID, count);
-
-    if (tempGlyphs == NULL) {
-        success = LE_MEMORY_ALLOCATION_ERROR;
-        return;
-    }
-
-    for (le_int32 i = 0; i < count; i += 1) {
-        tempGlyphs[i] = (LEGlyphID) chars[offset + i];
-    }
-
-    adjustMarkGlyphs(tempGlyphs, count, reverse, &filter, positions, success);
-
-    LE_DELETE_ARRAY(tempGlyphs);
+    adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
 }
 
 U_NAMESPACE_END