Home | History | Annotate | Download | only in layout
      1 
      2 /*
      3  *
      4  * (C) Copyright IBM Corp. 1998-2008 - All Rights Reserved
      5  *
      6  */
      7 
      8 #include "LETypes.h"
      9 #include "LEScripts.h"
     10 #include "LEGlyphFilter.h"
     11 #include "LEGlyphStorage.h"
     12 #include "LayoutEngine.h"
     13 #include "OpenTypeLayoutEngine.h"
     14 #include "ArabicLayoutEngine.h"
     15 #include "ScriptAndLanguageTags.h"
     16 #include "CharSubstitutionFilter.h"
     17 
     18 #include "GlyphSubstitutionTables.h"
     19 #include "GlyphDefinitionTables.h"
     20 #include "GlyphPositioningTables.h"
     21 
     22 #include "GDEFMarkFilter.h"
     23 
     24 #include "ArabicShaping.h"
     25 #include "CanonShaping.h"
     26 
     27 U_NAMESPACE_BEGIN
     28 
     29 le_bool CharSubstitutionFilter::accept(LEGlyphID glyph) const
     30 {
     31     return fFontInstance->canDisplay((LEUnicode) glyph);
     32 }
     33 
     34 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ArabicOpenTypeLayoutEngine)
     35 
     36 ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
     37                         le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success)
     38     : OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success)
     39 {
     40     fFeatureMap = ArabicShaping::getFeatureMap(fFeatureMapCount);
     41     fFeatureOrder = TRUE;
     42 }
     43 
     44 ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
     45 						       le_int32 typoFlags, LEErrorCode &success)
     46     : OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success)
     47 {
     48     fFeatureMap = ArabicShaping::getFeatureMap(fFeatureMapCount);
     49 
     50     // NOTE: We don't need to set fFeatureOrder to TRUE here
     51     // because this constructor is only called by the constructor
     52     // for UnicodeArabicOpenTypeLayoutEngine, which uses a pre-built
     53     // GSUB table that has the features in the correct order.
     54 
     55     //fFeatureOrder = TRUE;
     56 }
     57 
     58 ArabicOpenTypeLayoutEngine::~ArabicOpenTypeLayoutEngine()
     59 {
     60     // nothing to do
     61 }
     62 
     63 // Input: characters
     64 // Output: characters, char indices, tags
     65 // Returns: output character count
     66 le_int32 ArabicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
     67         LEUnicode *&outChars, LEGlyphStorage &glyphStorage, LEErrorCode &success)
     68 {
     69     if (LE_FAILURE(success)) {
     70         return 0;
     71     }
     72 
     73     if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
     74         success = LE_ILLEGAL_ARGUMENT_ERROR;
     75         return 0;
     76     }
     77 
     78     outChars = LE_NEW_ARRAY(LEUnicode, count);
     79 
     80     if (outChars == NULL) {
     81         success = LE_MEMORY_ALLOCATION_ERROR;
     82         return 0;
     83     }
     84 
     85     glyphStorage.allocateGlyphArray(count, rightToLeft, success);
     86     glyphStorage.allocateAuxData(success);
     87 
     88     if (LE_FAILURE(success)) {
     89         LE_DELETE_ARRAY(outChars);
     90         return 0;
     91     }
     92 
     93     CanonShaping::reorderMarks(&chars[offset], count, rightToLeft, outChars, glyphStorage);
     94 
     95     // Note: This processes the *original* character array so we can get context
     96     // for the first and last characters. This is OK because only the marks
     97     // will have been reordered, and they don't contribute to shaping.
     98     ArabicShaping::shape(chars, offset, count, max, rightToLeft, glyphStorage);
     99 
    100     return count;
    101 }
    102 
    103 void ArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
    104                                                       LEGlyphStorage &glyphStorage, LEErrorCode &success)
    105 {
    106     if (LE_FAILURE(success)) {
    107         return;
    108     }
    109 
    110     if (chars == NULL || offset < 0 || count < 0) {
    111         success = LE_ILLEGAL_ARGUMENT_ERROR;
    112         return;
    113     }
    114 
    115     if (fGPOSTable != NULL) {
    116         OpenTypeLayoutEngine::adjustGlyphPositions(chars, offset, count, reverse, glyphStorage, success);
    117     } else if (fGDEFTable != NULL) {
    118         GDEFMarkFilter filter(fGDEFTable);
    119 
    120         adjustMarkGlyphs(glyphStorage, &filter, success);
    121     } else {
    122         GlyphDefinitionTableHeader *gdefTable = (GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
    123         GDEFMarkFilter filter(gdefTable);
    124 
    125         adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
    126     }
    127 }
    128 
    129 UnicodeArabicOpenTypeLayoutEngine::UnicodeArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success)
    130     : ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success)
    131 {
    132     fGSUBTable = (const GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable;
    133     fGDEFTable = (const GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
    134 
    135     fSubstitutionFilter = new CharSubstitutionFilter(fontInstance);
    136 }
    137 
    138 UnicodeArabicOpenTypeLayoutEngine::~UnicodeArabicOpenTypeLayoutEngine()
    139 {
    140     delete fSubstitutionFilter;
    141 }
    142 
    143 // "glyphs", "indices" -> glyphs, indices
    144 le_int32 UnicodeArabicOpenTypeLayoutEngine::glyphPostProcessing(LEGlyphStorage &tempGlyphStorage, LEGlyphStorage &glyphStorage, LEErrorCode &success)
    145 {
    146     if (LE_FAILURE(success)) {
    147         return 0;
    148     }
    149 
    150     // FIXME: we could avoid the memory allocation and copy if we
    151     // made a clone of mapCharsToGlyphs which took the fake glyphs
    152     // directly.
    153     le_int32 tempGlyphCount = tempGlyphStorage.getGlyphCount();
    154     LEUnicode *tempChars = LE_NEW_ARRAY(LEUnicode, tempGlyphCount);
    155 
    156     if (tempChars == NULL) {
    157         success = LE_MEMORY_ALLOCATION_ERROR;
    158         return 0;
    159     }
    160 
    161     for (le_int32 i = 0; i < tempGlyphCount; i += 1) {
    162         tempChars[i] = (LEUnicode) LE_GET_GLYPH(tempGlyphStorage[i]);
    163     }
    164 
    165     glyphStorage.adoptCharIndicesArray(tempGlyphStorage);
    166 
    167     ArabicOpenTypeLayoutEngine::mapCharsToGlyphs(tempChars, 0, tempGlyphCount, FALSE, TRUE, glyphStorage, success);
    168 
    169     LE_DELETE_ARRAY(tempChars);
    170 
    171     return tempGlyphCount;
    172 }
    173 
    174 void UnicodeArabicOpenTypeLayoutEngine::mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, le_bool /*mirror*/, LEGlyphStorage &glyphStorage, LEErrorCode &success)
    175 {
    176     if (LE_FAILURE(success)) {
    177         return;
    178     }
    179 
    180     if (chars == NULL || offset < 0 || count < 0) {
    181         success = LE_ILLEGAL_ARGUMENT_ERROR;
    182         return;
    183     }
    184 
    185     le_int32 i, dir = 1, out = 0;
    186 
    187     if (reverse) {
    188         out = count - 1;
    189         dir = -1;
    190     }
    191 
    192     glyphStorage.allocateGlyphArray(count, reverse, success);
    193 
    194     for (i = 0; i < count; i += 1, out += dir) {
    195         glyphStorage[out] = (LEGlyphID) chars[offset + i];
    196     }
    197 }
    198 
    199 void UnicodeArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
    200                                                       LEGlyphStorage &glyphStorage, LEErrorCode &success)
    201 {
    202     if (LE_FAILURE(success)) {
    203         return;
    204     }
    205 
    206     if (chars == NULL || offset < 0 || count < 0) {
    207         success = LE_ILLEGAL_ARGUMENT_ERROR;
    208         return;
    209     }
    210 
    211     GDEFMarkFilter filter(fGDEFTable);
    212 
    213     adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
    214 }
    215 
    216 U_NAMESPACE_END
    217 
    218