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