os/textandloc/fontservices/textshaperplugin/IcuSource/layout/GlyphPositionAdjustments.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2  *
     3  * (C) Copyright IBM Corp. 1998-2005 - 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::setEntryPoint(le_int32 index, LEPoint &newEntryPoint, le_bool baselineIsLogicalEnd)
    50 {
    51     CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);
    52 
    53     fEntryExitPoints[index].setEntryPoint(newEntryPoint, baselineIsLogicalEnd);
    54 }
    55 
    56 void GlyphPositionAdjustments::setExitPoint(le_int32 index, LEPoint &newExitPoint, le_bool baselineIsLogicalEnd)
    57 {
    58     CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);
    59 
    60     fEntryExitPoints[index].setExitPoint(newExitPoint, baselineIsLogicalEnd);
    61 }
    62 
    63 void GlyphPositionAdjustments::setCursiveGlyph(le_int32 index, le_bool baselineIsLogicalEnd)
    64 {
    65     CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);
    66 
    67     fEntryExitPoints[index].setCursiveGlyph(baselineIsLogicalEnd);
    68 }
    69 
    70 void GlyphPositionAdjustments::applyCursiveAdjustments(LEGlyphStorage &glyphStorage, le_bool rightToLeft, const LEFontInstance *fontInstance)
    71 {
    72     if (! hasCursiveGlyphs()) {
    73         return;
    74     }
    75 
    76     le_int32 start = 0, end = fGlyphCount, dir = 1;
    77     le_int32 firstExitPoint = -1, lastExitPoint = -1;
    78     LEPoint entryAnchor, exitAnchor, pixels;
    79     LEGlyphID lastExitGlyphID = 0;
    80     float baselineAdjustment = 0;
    81 
    82     // This removes a possible warning about
    83     // using exitAnchor before it's been initialized.
    84     exitAnchor.fX = exitAnchor.fY = 0;
    85 
    86     if (rightToLeft) {
    87         start = fGlyphCount - 1;
    88         end = -1;
    89         dir = -1;
    90     }
    91 
    92     for (le_int32 i = start; i != end; i += dir) {
    93         LEGlyphID glyphID = glyphStorage[i];
    94 
    95         if (isCursiveGlyph(i)) {
    96             if (lastExitPoint >= 0 && getEntryPoint(i, entryAnchor) != NULL) {
    97                 float anchorDiffX = exitAnchor.fX - entryAnchor.fX;
    98                 float anchorDiffY = exitAnchor.fY - entryAnchor.fY;
    99 
   100                 baselineAdjustment += anchorDiffY;
   101                 adjustYPlacement(i, baselineAdjustment);
   102 
   103                 if (rightToLeft) {
   104                     LEPoint secondAdvance;
   105 
   106                     fontInstance->getGlyphAdvance(glyphID, pixels);
   107                     fontInstance->pixelsToUnits(pixels, secondAdvance);
   108 
   109                     adjustXAdvance(i, -(anchorDiffX + secondAdvance.fX));
   110                 } else {
   111                     LEPoint firstAdvance;
   112 
   113                     fontInstance->getGlyphAdvance(lastExitGlyphID, pixels);
   114                     fontInstance->pixelsToUnits(pixels, firstAdvance);
   115 
   116                     adjustXAdvance(lastExitPoint, anchorDiffX - firstAdvance.fX);
   117                 }
   118             }
   119 
   120             lastExitPoint = i;
   121 
   122             if (getExitPoint(i, exitAnchor) != NULL) {
   123                 if (firstExitPoint < 0) {
   124                     firstExitPoint = i;
   125                 }
   126 
   127                 lastExitGlyphID = glyphID;
   128             } else {
   129                 if (baselineIsLogicalEnd(i) && firstExitPoint >= 0 && lastExitPoint >= 0) {
   130                     le_int32 limit = lastExitPoint + dir;
   131 
   132                     for (le_int32 j = firstExitPoint; j != limit; j += dir) {
   133                         if (isCursiveGlyph(j)) {
   134                             adjustYPlacement(j, -baselineAdjustment);
   135                         }
   136                     }
   137                 }
   138 
   139                 firstExitPoint = lastExitPoint = -1;
   140                 baselineAdjustment = 0;
   141             }
   142         }
   143     }
   144 }
   145 
   146 LEPoint *GlyphPositionAdjustments::EntryExitPoint::getEntryPoint(LEPoint &entryPoint) const
   147 {
   148     if (fFlags & EEF_HAS_ENTRY_POINT) {
   149         entryPoint = fEntryPoint;
   150         return &entryPoint;
   151     }
   152 
   153     return NULL;
   154 }
   155 
   156 LEPoint *GlyphPositionAdjustments::EntryExitPoint::getExitPoint(LEPoint &exitPoint) const
   157 {
   158     if (fFlags & EEF_HAS_EXIT_POINT) {
   159         exitPoint = fExitPoint;
   160         return &exitPoint;
   161     }
   162 
   163     return NULL;
   164 }
   165 
   166 U_NAMESPACE_END