Home | History | Annotate | Download | only in layout
      1 /*
      2  **********************************************************************
      3  *   Copyright (C) 1998-2009, International Business Machines
      4  *   Corporation and others.  All Rights Reserved.
      5  **********************************************************************
      6  */
      7 
      8 #include "LETypes.h"
      9 #include "LEInsertionList.h"
     10 #include "LEGlyphStorage.h"
     11 
     12 U_NAMESPACE_BEGIN
     13 
     14 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LEGlyphStorage)
     15 
     16 LEInsertionCallback::~LEInsertionCallback()
     17 {
     18 	// nothing to do...
     19 }
     20 
     21 LEGlyphStorage::LEGlyphStorage()
     22     : fGlyphCount(0), fGlyphs(NULL), fCharIndices(NULL), fPositions(NULL),
     23       fAuxData(NULL), fInsertionList(NULL), fSrcIndex(0), fDestIndex(0)
     24 {
     25     // nothing else to do!
     26 }
     27 
     28 LEGlyphStorage::~LEGlyphStorage()
     29 {
     30     reset();
     31 }
     32 
     33 void LEGlyphStorage::reset()
     34 {
     35     fGlyphCount = 0;
     36 
     37     if (fPositions != NULL) {
     38         LE_DELETE_ARRAY(fPositions);
     39         fPositions = NULL;
     40     }
     41 
     42     if (fAuxData != NULL) {
     43         LE_DELETE_ARRAY(fAuxData);
     44         fAuxData = NULL;
     45     }
     46 
     47     if (fInsertionList != NULL) {
     48         delete fInsertionList;
     49         fInsertionList = NULL;
     50     }
     51 
     52     if (fCharIndices != NULL) {
     53         LE_DELETE_ARRAY(fCharIndices);
     54         fCharIndices = NULL;
     55     }
     56 
     57     if (fGlyphs != NULL) {
     58         LE_DELETE_ARRAY(fGlyphs);
     59         fGlyphs = NULL;
     60     }
     61 }
     62 
     63 // FIXME: This might get called more than once, for various reasons. Is
     64 // testing for pre-existing glyph and charIndices arrays good enough?
     65 void LEGlyphStorage::allocateGlyphArray(le_int32 initialGlyphCount, le_bool rightToLeft, LEErrorCode &success)
     66 {
     67     if (LE_FAILURE(success)) {
     68         return;
     69     }
     70 
     71     if (initialGlyphCount <= 0) {
     72         success = LE_ILLEGAL_ARGUMENT_ERROR;
     73         return;
     74     }
     75 
     76     if (fGlyphs == NULL) {
     77         fGlyphCount = initialGlyphCount;
     78         fGlyphs = LE_NEW_ARRAY(LEGlyphID, fGlyphCount);
     79 
     80         if (fGlyphs == NULL) {
     81             success = LE_MEMORY_ALLOCATION_ERROR;
     82             return;
     83         }
     84     }
     85 
     86     if (fCharIndices == NULL) {
     87         fCharIndices = LE_NEW_ARRAY(le_int32, fGlyphCount);
     88 
     89         if (fCharIndices == NULL) {
     90             LE_DELETE_ARRAY(fGlyphs);
     91             fGlyphs = NULL;
     92             success = LE_MEMORY_ALLOCATION_ERROR;
     93             return;
     94         }
     95 
     96         // Initialize the charIndices array
     97         le_int32 i, count = fGlyphCount, dir = 1, out = 0;
     98 
     99         if (rightToLeft) {
    100             out = fGlyphCount - 1;
    101             dir = -1;
    102         }
    103 
    104         for (i = 0; i < count; i += 1, out += dir) {
    105             fCharIndices[out] = i;
    106         }
    107     }
    108 
    109     if (fInsertionList == NULL) {
    110         // FIXME: check this for failure?
    111         fInsertionList = new LEInsertionList(rightToLeft);
    112         if (fInsertionList == NULL) {
    113             LE_DELETE_ARRAY(fCharIndices);
    114             fCharIndices = NULL;
    115 
    116             LE_DELETE_ARRAY(fGlyphs);
    117             fGlyphs = NULL;
    118 
    119             success = LE_MEMORY_ALLOCATION_ERROR;
    120             return;
    121         }
    122     }
    123 }
    124 
    125 // FIXME: do we want to initialize the positions to [0, 0]?
    126 le_int32 LEGlyphStorage::allocatePositions(LEErrorCode &success)
    127 {
    128     if (LE_FAILURE(success)) {
    129         return -1;
    130     }
    131 
    132     if (fPositions != NULL) {
    133         success = LE_INTERNAL_ERROR;
    134         return -1;
    135     }
    136 
    137     fPositions = LE_NEW_ARRAY(float, 2 * (fGlyphCount + 1));
    138 
    139     if (fPositions == NULL) {
    140         success = LE_MEMORY_ALLOCATION_ERROR;
    141         return -1;
    142     }
    143 
    144     return fGlyphCount;
    145 }
    146 
    147 // FIXME: do we want to initialize the aux data to NULL?
    148 le_int32 LEGlyphStorage::allocateAuxData(LEErrorCode &success)
    149 {
    150     if (LE_FAILURE(success)) {
    151         return -1;
    152     }
    153 
    154     if (fAuxData != NULL) {
    155         success = LE_INTERNAL_ERROR;
    156         return -1;
    157     }
    158 
    159     fAuxData = LE_NEW_ARRAY(le_uint32, fGlyphCount);
    160 
    161     if (fAuxData == NULL) {
    162         success = LE_MEMORY_ALLOCATION_ERROR;
    163         return -1;
    164     }
    165 
    166     return fGlyphCount;
    167 }
    168 
    169 void LEGlyphStorage::getCharIndices(le_int32 charIndices[], le_int32 indexBase, LEErrorCode &success) const
    170 {
    171     le_int32 i;
    172 
    173     if (LE_FAILURE(success)) {
    174         return;
    175     }
    176 
    177     if (charIndices == NULL) {
    178         success = LE_ILLEGAL_ARGUMENT_ERROR;
    179         return;
    180     }
    181 
    182     if (fCharIndices == NULL) {
    183         success = LE_NO_LAYOUT_ERROR;
    184         return;
    185     }
    186 
    187     for (i = 0; i < fGlyphCount; i += 1) {
    188         charIndices[i] = fCharIndices[i] + indexBase;
    189     }
    190 }
    191 
    192 void LEGlyphStorage::getCharIndices(le_int32 charIndices[], LEErrorCode &success) const
    193 {
    194     if (LE_FAILURE(success)) {
    195       return;
    196     }
    197 
    198     if (charIndices == NULL) {
    199       success = LE_ILLEGAL_ARGUMENT_ERROR;
    200       return;
    201     }
    202 
    203     if (fCharIndices == NULL) {
    204       success = LE_NO_LAYOUT_ERROR;
    205       return;
    206     }
    207 
    208     LE_ARRAY_COPY(charIndices, fCharIndices, fGlyphCount);
    209 }
    210 
    211 // Copy the glyphs into caller's (32-bit) glyph array, OR in extraBits
    212 void LEGlyphStorage::getGlyphs(le_uint32 glyphs[], le_uint32 extraBits, LEErrorCode &success) const
    213 {
    214     le_int32 i;
    215 
    216     if (LE_FAILURE(success)) {
    217         return;
    218     }
    219 
    220     if (glyphs == NULL) {
    221         success = LE_ILLEGAL_ARGUMENT_ERROR;
    222         return;
    223     }
    224 
    225     if (fGlyphs == NULL) {
    226         success = LE_NO_LAYOUT_ERROR;
    227         return;
    228     }
    229 
    230     for (i = 0; i < fGlyphCount; i += 1) {
    231         glyphs[i] = fGlyphs[i] | extraBits;
    232     }
    233 }
    234 
    235 void LEGlyphStorage::getGlyphs(LEGlyphID glyphs[], LEErrorCode &success) const
    236 {
    237     if (LE_FAILURE(success)) {
    238       return;
    239     }
    240 
    241     if (glyphs == NULL) {
    242       success = LE_ILLEGAL_ARGUMENT_ERROR;
    243       return;
    244     }
    245 
    246     if (fGlyphs == NULL) {
    247       success = LE_NO_LAYOUT_ERROR;
    248       return;
    249     }
    250 
    251     LE_ARRAY_COPY(glyphs, fGlyphs, fGlyphCount);
    252 }
    253 
    254 LEGlyphID LEGlyphStorage::getGlyphID(le_int32 glyphIndex, LEErrorCode &success) const
    255 {
    256     if (LE_FAILURE(success)) {
    257         return 0xFFFF;
    258     }
    259 
    260     if (fGlyphs == NULL) {
    261         success = LE_NO_LAYOUT_ERROR;
    262         return 0xFFFF;
    263     }
    264 
    265     if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
    266         success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
    267         return 0xFFFF;
    268     }
    269 
    270     return fGlyphs[glyphIndex];
    271 }
    272 
    273 void LEGlyphStorage::setGlyphID(le_int32 glyphIndex, LEGlyphID glyphID, LEErrorCode &success)
    274 {
    275     if (LE_FAILURE(success)) {
    276         return;
    277     }
    278 
    279     if (fGlyphs == NULL) {
    280         success = LE_NO_LAYOUT_ERROR;
    281         return;
    282     }
    283 
    284     if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
    285         success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
    286         return;
    287     }
    288 
    289     fGlyphs[glyphIndex] = glyphID;
    290 }
    291 
    292 le_int32 LEGlyphStorage::getCharIndex(le_int32 glyphIndex, LEErrorCode &success) const
    293 {
    294     if (LE_FAILURE(success)) {
    295         return -1;
    296     }
    297 
    298     if (fCharIndices == NULL) {
    299         success = LE_NO_LAYOUT_ERROR;
    300         return -1;
    301     }
    302 
    303     if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
    304         success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
    305         return -1;
    306     }
    307 
    308     return fCharIndices[glyphIndex];
    309 }
    310 
    311 void LEGlyphStorage::setCharIndex(le_int32 glyphIndex, le_int32 charIndex, LEErrorCode &success)
    312 {
    313     if (LE_FAILURE(success)) {
    314         return;
    315     }
    316 
    317     if (fCharIndices == NULL) {
    318         success = LE_NO_LAYOUT_ERROR;
    319         return;
    320     }
    321 
    322     if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
    323         success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
    324         return;
    325     }
    326 
    327     fCharIndices[glyphIndex] = charIndex;
    328 }
    329 
    330 void LEGlyphStorage::getAuxData(le_uint32 auxData[], LEErrorCode &success) const
    331 {
    332     if (LE_FAILURE(success)) {
    333       return;
    334     }
    335 
    336     if (auxData == NULL) {
    337       success = LE_ILLEGAL_ARGUMENT_ERROR;
    338       return;
    339     }
    340 
    341     if (fAuxData == NULL) {
    342       success = LE_NO_LAYOUT_ERROR;
    343       return;
    344     }
    345 
    346     LE_ARRAY_COPY(auxData, fAuxData, fGlyphCount);
    347 }
    348 
    349 le_uint32 LEGlyphStorage::getAuxData(le_int32 glyphIndex, LEErrorCode &success) const
    350 {
    351     if (LE_FAILURE(success)) {
    352         return 0;
    353     }
    354 
    355     if (fAuxData == NULL) {
    356         success = LE_NO_LAYOUT_ERROR;
    357         return 0;
    358     }
    359 
    360     if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
    361         success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
    362         return 0;
    363     }
    364 
    365     return fAuxData[glyphIndex];
    366 }
    367 
    368 void LEGlyphStorage::setAuxData(le_int32 glyphIndex, le_uint32 auxData, LEErrorCode &success)
    369 {
    370     if (LE_FAILURE(success)) {
    371         return;
    372     }
    373 
    374     if (fAuxData == NULL) {
    375         success = LE_NO_LAYOUT_ERROR;
    376         return;
    377     }
    378 
    379     if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
    380         success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
    381         return;
    382     }
    383 
    384     fAuxData[glyphIndex] = auxData;
    385 }
    386 
    387 void LEGlyphStorage::getGlyphPositions(float positions[], LEErrorCode &success) const
    388 {
    389     if (LE_FAILURE(success)) {
    390       return;
    391     }
    392 
    393     if (positions == NULL) {
    394       success = LE_ILLEGAL_ARGUMENT_ERROR;
    395       return;
    396     }
    397 
    398     if (fPositions == NULL) {
    399       success = LE_NO_LAYOUT_ERROR;
    400       return;
    401     }
    402 
    403     LE_ARRAY_COPY(positions, fPositions, fGlyphCount * 2 + 2);
    404 }
    405 
    406 void LEGlyphStorage::getGlyphPosition(le_int32 glyphIndex, float &x, float &y, LEErrorCode &success) const
    407 {
    408     if (LE_FAILURE(success)) {
    409       return;
    410     }
    411 
    412     if (glyphIndex < 0 || glyphIndex > fGlyphCount) {
    413       success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
    414       return;
    415     }
    416 
    417     if (fPositions == NULL) {
    418       success = LE_NO_LAYOUT_ERROR;
    419       return;
    420     }
    421 
    422     x = fPositions[glyphIndex * 2];
    423     y = fPositions[glyphIndex * 2 + 1];
    424 }
    425 
    426 void LEGlyphStorage::setPosition(le_int32 glyphIndex, float x, float y, LEErrorCode &success)
    427 {
    428     if (LE_FAILURE(success)) {
    429         return;
    430     }
    431 
    432     if (glyphIndex < 0 || glyphIndex > fGlyphCount) {
    433       success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
    434       return;
    435     }
    436 
    437     fPositions[glyphIndex * 2]     = x;
    438     fPositions[glyphIndex * 2 + 1] = y;
    439 }
    440 
    441 void LEGlyphStorage::adjustPosition(le_int32 glyphIndex, float xAdjust, float yAdjust, LEErrorCode &success)
    442 {
    443     if (LE_FAILURE(success)) {
    444         return;
    445     }
    446 
    447     if (glyphIndex < 0 || glyphIndex > fGlyphCount) {
    448       success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
    449       return;
    450     }
    451 
    452     fPositions[glyphIndex * 2]     += xAdjust;
    453     fPositions[glyphIndex * 2 + 1] += yAdjust;
    454 }
    455 
    456 void LEGlyphStorage::adoptGlyphArray(LEGlyphStorage &from)
    457 {
    458     if (fGlyphs != NULL) {
    459         LE_DELETE_ARRAY(fGlyphs);
    460     }
    461 
    462     fGlyphs = from.fGlyphs;
    463     from.fGlyphs = NULL;
    464 
    465     if (fInsertionList != NULL) {
    466         delete fInsertionList;
    467     }
    468 
    469     fInsertionList = from.fInsertionList;
    470     from.fInsertionList = NULL;
    471 }
    472 
    473 void LEGlyphStorage::adoptCharIndicesArray(LEGlyphStorage &from)
    474 {
    475     if (fCharIndices != NULL) {
    476         LE_DELETE_ARRAY(fCharIndices);
    477     }
    478 
    479     fCharIndices = from.fCharIndices;
    480     from.fCharIndices = NULL;
    481 }
    482 
    483 void LEGlyphStorage::adoptPositionArray(LEGlyphStorage &from)
    484 {
    485     if (fPositions != NULL) {
    486         LE_DELETE_ARRAY(fPositions);
    487     }
    488 
    489     fPositions = from.fPositions;
    490     from.fPositions = NULL;
    491 }
    492 
    493 void LEGlyphStorage::adoptAuxDataArray(LEGlyphStorage &from)
    494 {
    495     if (fAuxData != NULL) {
    496         LE_DELETE_ARRAY(fAuxData);
    497     }
    498 
    499     fAuxData = from.fAuxData;
    500     from.fAuxData = NULL;
    501 }
    502 
    503 void LEGlyphStorage::adoptGlyphCount(LEGlyphStorage &from)
    504 {
    505     fGlyphCount = from.fGlyphCount;
    506 }
    507 
    508 void LEGlyphStorage::adoptGlyphCount(le_int32 newGlyphCount)
    509 {
    510     fGlyphCount = newGlyphCount;
    511 }
    512 
    513 // Move a glyph to a different position in the LEGlyphStorage ( used for Indic v2 processing )
    514 
    515 void LEGlyphStorage::moveGlyph(le_int32 fromPosition, le_int32 toPosition, le_uint32 marker )
    516 {
    517 
    518     LEErrorCode success = LE_NO_ERROR;
    519 
    520     LEGlyphID holdGlyph = getGlyphID(fromPosition,success);
    521     le_int32 holdCharIndex = getCharIndex(fromPosition,success);
    522     le_uint32 holdAuxData = getAuxData(fromPosition,success);
    523 
    524     if ( fromPosition < toPosition ) {
    525         for ( le_int32 i = fromPosition ; i < toPosition ; i++ ) {
    526             setGlyphID(i,getGlyphID(i+1,success),success);
    527             setCharIndex(i,getCharIndex(i+1,success),success);
    528             setAuxData(i,getAuxData(i+1,success),success);
    529         }
    530     } else {
    531         for ( le_int32 i = toPosition ; i > fromPosition ; i-- ) {
    532             setGlyphID(i,getGlyphID(i-1,success),success);
    533             setCharIndex(i,getCharIndex(i-1,success),success);
    534             setAuxData(i,getAuxData(i-1,success),success);
    535 
    536         }
    537     }
    538 
    539     setGlyphID(toPosition,holdGlyph,success);
    540     setCharIndex(toPosition,holdCharIndex,success);
    541     setAuxData(toPosition,holdAuxData | marker,success);
    542 
    543 }
    544 
    545 // Glue code for existing stable API
    546 LEGlyphID *LEGlyphStorage::insertGlyphs(le_int32  atIndex, le_int32 insertCount)
    547 {
    548     LEErrorCode ignored = LE_NO_LAYOUT_ERROR;
    549     return insertGlyphs(atIndex, insertCount, ignored);
    550 }
    551 
    552 // FIXME: add error checking?
    553 LEGlyphID *LEGlyphStorage::insertGlyphs(le_int32  atIndex, le_int32 insertCount, LEErrorCode& success)
    554 {
    555     return fInsertionList->insert(atIndex, insertCount, success);
    556 }
    557 
    558 le_int32 LEGlyphStorage::applyInsertions()
    559 {
    560     le_int32 growAmount = fInsertionList->getGrowAmount();
    561 
    562     if (growAmount == 0) {
    563         return fGlyphCount;
    564     }
    565 
    566     le_int32 newGlyphCount = fGlyphCount + growAmount;
    567 
    568     LEGlyphID *newGlyphs = (LEGlyphID *) LE_GROW_ARRAY(fGlyphs, newGlyphCount);
    569     if (newGlyphs == NULL) {
    570         // Could not grow the glyph array
    571         return fGlyphCount;
    572     }
    573     fGlyphs = newGlyphs;
    574 
    575     le_int32 *newCharIndices = (le_int32 *) LE_GROW_ARRAY(fCharIndices, newGlyphCount);
    576     if (newCharIndices == NULL) {
    577         // Could not grow the glyph array
    578         return fGlyphCount;
    579     }
    580     fCharIndices = newCharIndices;
    581 
    582     if (fAuxData != NULL) {
    583         le_uint32 *newAuxData = (le_uint32 *) LE_GROW_ARRAY(fAuxData, newGlyphCount);
    584         if (newAuxData == NULL) {
    585             // could not grow the aux data array
    586             return fGlyphCount;
    587         }
    588         fAuxData = (le_uint32 *)newAuxData;
    589     }
    590 
    591     fSrcIndex  = fGlyphCount - 1;
    592     fDestIndex = newGlyphCount - 1;
    593 
    594 #if 0
    595     // If the current position is at the end of the array
    596     // update it to point to the end of the new array. The
    597     // insertion callback will handle all other cases.
    598     // FIXME: this is left over from GlyphIterator, but there's no easy
    599     // way to implement this here... it seems that GlyphIterator doesn't
    600     // really need it 'cause the insertions don't get  applied until after a
    601     // complete pass over the glyphs, after which the iterator gets reset anyhow...
    602     // probably better to just document that for LEGlyphStorage and GlyphIterator...
    603     if (position == glyphCount) {
    604         position = newGlyphCount;
    605     }
    606 #endif
    607 
    608     fInsertionList->applyInsertions(this);
    609 
    610     fInsertionList->reset();
    611 
    612     return fGlyphCount = newGlyphCount;
    613 }
    614 
    615 le_bool LEGlyphStorage::applyInsertion(le_int32 atPosition, le_int32 count, LEGlyphID newGlyphs[])
    616 {
    617 #if 0
    618     // if the current position is within the block we're shifting
    619     // it needs to be updated to the current glyph's
    620     // new location.
    621     // FIXME: this is left over from GlyphIterator, but there's no easy
    622     // way to implement this here... it seems that GlyphIterator doesn't
    623     // really need it 'cause the insertions don't get  applied until after a
    624     // complete pass over the glyphs, after which the iterator gets reset anyhow...
    625     // probably better to just document that for LEGlyphStorage and GlyphIterator...
    626     if (position >= atPosition && position <= fSrcIndex) {
    627         position += fDestIndex - fSrcIndex;
    628     }
    629 #endif
    630 
    631     if (fAuxData != NULL) {
    632         le_int32 src = fSrcIndex, dest = fDestIndex;
    633 
    634         while (src > atPosition) {
    635             fAuxData[dest--] = fAuxData[src--];
    636         }
    637 
    638         for (le_int32 i = count - 1; i >= 0; i -= 1) {
    639             fAuxData[dest--] = fAuxData[atPosition];
    640         }
    641     }
    642 
    643     while (fSrcIndex > atPosition) {
    644         fGlyphs[fDestIndex]      = fGlyphs[fSrcIndex];
    645         fCharIndices[fDestIndex] = fCharIndices[fSrcIndex];
    646 
    647         fDestIndex -= 1;
    648         fSrcIndex  -= 1;
    649     }
    650 
    651     for (le_int32 i = count - 1; i >= 0; i -= 1) {
    652         fGlyphs[fDestIndex]      = newGlyphs[i];
    653         fCharIndices[fDestIndex] = fCharIndices[atPosition];
    654 
    655         fDestIndex -= 1;
    656     }
    657 
    658     // the source glyph we're pointing at
    659     // just got replaced by the insertion
    660     fSrcIndex -= 1;
    661 
    662     return FALSE;
    663 }
    664 
    665 U_NAMESPACE_END
    666 
    667