Home | History | Annotate | Download | only in layout
      1 /*
      2  *
      3  * (C) Copyright IBM Corp. 1998-2008 - All Rights Reserved
      4  *
      5  */
      6 
      7 #include "LETypes.h"
      8 #include "GlyphPositionAdjustments.h"
      9 #include "LEGlyphStorage.h"
     10 #include "LEFontInstance.h"
     11 
     12 U_NAMESPACE_BEGIN
     13 
     14 #define CHECK_ALLOCATE_ARRAY(array, type, size) \
     15     if (array == NULL) { \
     16         array = (type *) new type[size]; \
     17     }
     18 
     19 GlyphPositionAdjustments::GlyphPositionAdjustments(le_int32 glyphCount)
     20     : fGlyphCount(glyphCount), fEntryExitPoints(NULL), fAdjustments(NULL)
     21 {
     22     fAdjustments = (Adjustment *) new Adjustment[glyphCount];
     23 }
     24 
     25 GlyphPositionAdjustments::~GlyphPositionAdjustments()
     26 {
     27     delete[] fEntryExitPoints;
     28     delete[] fAdjustments;
     29 }
     30 
     31 const LEPoint *GlyphPositionAdjustments::getEntryPoint(le_int32 index, LEPoint &entryPoint) const
     32 {
     33     if (fEntryExitPoints == NULL) {
     34         return NULL;
     35     }
     36 
     37     return fEntryExitPoints[index].getEntryPoint(entryPoint);
     38 }
     39 
     40 const LEPoint *GlyphPositionAdjustments::getExitPoint(le_int32 index, LEPoint &exitPoint)const
     41 {
     42     if (fEntryExitPoints == NULL) {
     43         return NULL;
     44     }
     45 
     46     return fEntryExitPoints[index].getExitPoint(exitPoint);
     47 }
     48 
     49 void GlyphPositionAdjustments::clearEntryPoint(le_int32 index)
     50 {
     51     CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);
     52 
     53     fEntryExitPoints[index].clearEntryPoint();
     54 }
     55 
     56 void GlyphPositionAdjustments::clearExitPoint(le_int32 index)
     57 {
     58     CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);
     59 
     60     fEntryExitPoints[index].clearExitPoint();
     61 }
     62 
     63 void GlyphPositionAdjustments::setEntryPoint(le_int32 index, LEPoint &newEntryPoint, le_bool baselineIsLogicalEnd)
     64 {
     65     CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);
     66 
     67     fEntryExitPoints[index].setEntryPoint(newEntryPoint, baselineIsLogicalEnd);
     68 }
     69 
     70 void GlyphPositionAdjustments::setExitPoint(le_int32 index, LEPoint &newExitPoint, le_bool baselineIsLogicalEnd)
     71 {
     72     CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);
     73 
     74     fEntryExitPoints[index].setExitPoint(newExitPoint, baselineIsLogicalEnd);
     75 }
     76 
     77 void GlyphPositionAdjustments::setCursiveGlyph(le_int32 index, le_bool baselineIsLogicalEnd)
     78 {
     79     CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);
     80 
     81     fEntryExitPoints[index].setCursiveGlyph(baselineIsLogicalEnd);
     82 }
     83 
     84 void GlyphPositionAdjustments::applyCursiveAdjustments(LEGlyphStorage &glyphStorage, le_bool rightToLeft, const LEFontInstance *fontInstance)
     85 {
     86     if (! hasCursiveGlyphs()) {
     87         return;
     88     }
     89 
     90     le_int32 start = 0, end = fGlyphCount, dir = 1;
     91     le_int32 firstExitPoint = -1, lastExitPoint = -1;
     92     LEPoint entryAnchor, exitAnchor, pixels;
     93     LEGlyphID lastExitGlyphID = 0;
     94     float baselineAdjustment = 0;
     95 
     96     // This removes a possible warning about
     97     // using exitAnchor before it's been initialized.
     98     exitAnchor.fX = exitAnchor.fY = 0;
     99 
    100     if (rightToLeft) {
    101         start = fGlyphCount - 1;
    102         end = -1;
    103         dir = -1;
    104     }
    105 
    106     for (le_int32 i = start; i != end; i += dir) {
    107         LEGlyphID glyphID = glyphStorage[i];
    108 
    109         if (isCursiveGlyph(i)) {
    110             if (lastExitPoint >= 0 && getEntryPoint(i, entryAnchor) != NULL) {
    111                 float anchorDiffX = exitAnchor.fX - entryAnchor.fX;
    112                 float anchorDiffY = exitAnchor.fY - entryAnchor.fY;
    113 
    114                 baselineAdjustment += anchorDiffY;
    115                 adjustYPlacement(i, baselineAdjustment);
    116 
    117                 if (rightToLeft) {
    118                     LEPoint secondAdvance;
    119 
    120                     fontInstance->getGlyphAdvance(glyphID, pixels);
    121                     fontInstance->pixelsToUnits(pixels, secondAdvance);
    122 
    123                     adjustXAdvance(i, -(anchorDiffX + secondAdvance.fX));
    124                 } else {
    125                     LEPoint firstAdvance;
    126 
    127                     fontInstance->getGlyphAdvance(lastExitGlyphID, pixels);
    128                     fontInstance->pixelsToUnits(pixels, firstAdvance);
    129 
    130                     adjustXAdvance(lastExitPoint, anchorDiffX - firstAdvance.fX);
    131                 }
    132             }
    133 
    134             lastExitPoint = i;
    135 
    136             if (getExitPoint(i, exitAnchor) != NULL) {
    137                 if (firstExitPoint < 0) {
    138                     firstExitPoint = i;
    139                 }
    140 
    141                 lastExitGlyphID = glyphID;
    142             } else {
    143                 if (baselineIsLogicalEnd(i) && firstExitPoint >= 0 && lastExitPoint >= 0) {
    144                     le_int32 limit = lastExitPoint /*+ dir*/;
    145                     LEPoint dummyAnchor;
    146 
    147                     if (getEntryPoint(i, dummyAnchor) != NULL) {
    148                         limit += dir;
    149                     }
    150 
    151                     for (le_int32 j = firstExitPoint; j != limit; j += dir) {
    152                         if (isCursiveGlyph(j)) {
    153                             adjustYPlacement(j, -baselineAdjustment);
    154                         }
    155                     }
    156                 }
    157 
    158                 firstExitPoint = lastExitPoint = -1;
    159                 baselineAdjustment = 0;
    160             }
    161         }
    162     }
    163 }
    164 
    165 LEPoint *GlyphPositionAdjustments::EntryExitPoint::getEntryPoint(LEPoint &entryPoint) const
    166 {
    167     if (fFlags & EEF_HAS_ENTRY_POINT) {
    168         entryPoint = fEntryPoint;
    169         return &entryPoint;
    170     }
    171 
    172     return NULL;
    173 }
    174 
    175 LEPoint *GlyphPositionAdjustments::EntryExitPoint::getExitPoint(LEPoint &exitPoint) const
    176 {
    177     if (fFlags & EEF_HAS_EXIT_POINT) {
    178         exitPoint = fExitPoint;
    179         return &exitPoint;
    180     }
    181 
    182     return NULL;
    183 }
    184 
    185 U_NAMESPACE_END
    186