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