os/textandloc/fontservices/textshaperplugin/IcuSource/layout/GlyphPositionAdjustments.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/textandloc/fontservices/textshaperplugin/IcuSource/layout/GlyphPositionAdjustments.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,166 @@
1.4 +/*
1.5 + *
1.6 + * (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved
1.7 + *
1.8 + */
1.9 +
1.10 +#include "LETypes.h"
1.11 +#include "GlyphPositionAdjustments.h"
1.12 +#include "LEGlyphStorage.h"
1.13 +#include "LEFontInstance.h"
1.14 +
1.15 +U_NAMESPACE_BEGIN
1.16 +
1.17 +#define CHECK_ALLOCATE_ARRAY(array, type, size) \
1.18 + if (array == NULL) { \
1.19 + array = (type *) new type[size]; \
1.20 + }
1.21 +
1.22 +GlyphPositionAdjustments::GlyphPositionAdjustments(le_int32 glyphCount)
1.23 + : fGlyphCount(glyphCount), fEntryExitPoints(NULL), fAdjustments(NULL)
1.24 +{
1.25 + fAdjustments = (Adjustment *) new Adjustment[glyphCount];
1.26 +}
1.27 +
1.28 +GlyphPositionAdjustments::~GlyphPositionAdjustments()
1.29 +{
1.30 + delete[] fEntryExitPoints;
1.31 + delete[] fAdjustments;
1.32 +}
1.33 +
1.34 +const LEPoint *GlyphPositionAdjustments::getEntryPoint(le_int32 index, LEPoint &entryPoint) const
1.35 +{
1.36 + if (fEntryExitPoints == NULL) {
1.37 + return NULL;
1.38 + }
1.39 +
1.40 + return fEntryExitPoints[index].getEntryPoint(entryPoint);
1.41 +}
1.42 +
1.43 +const LEPoint *GlyphPositionAdjustments::getExitPoint(le_int32 index, LEPoint &exitPoint)const
1.44 +{
1.45 + if (fEntryExitPoints == NULL) {
1.46 + return NULL;
1.47 + }
1.48 +
1.49 + return fEntryExitPoints[index].getExitPoint(exitPoint);
1.50 +}
1.51 +
1.52 +void GlyphPositionAdjustments::setEntryPoint(le_int32 index, LEPoint &newEntryPoint, le_bool baselineIsLogicalEnd)
1.53 +{
1.54 + CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);
1.55 +
1.56 + fEntryExitPoints[index].setEntryPoint(newEntryPoint, baselineIsLogicalEnd);
1.57 +}
1.58 +
1.59 +void GlyphPositionAdjustments::setExitPoint(le_int32 index, LEPoint &newExitPoint, le_bool baselineIsLogicalEnd)
1.60 +{
1.61 + CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);
1.62 +
1.63 + fEntryExitPoints[index].setExitPoint(newExitPoint, baselineIsLogicalEnd);
1.64 +}
1.65 +
1.66 +void GlyphPositionAdjustments::setCursiveGlyph(le_int32 index, le_bool baselineIsLogicalEnd)
1.67 +{
1.68 + CHECK_ALLOCATE_ARRAY(fEntryExitPoints, EntryExitPoint, fGlyphCount);
1.69 +
1.70 + fEntryExitPoints[index].setCursiveGlyph(baselineIsLogicalEnd);
1.71 +}
1.72 +
1.73 +void GlyphPositionAdjustments::applyCursiveAdjustments(LEGlyphStorage &glyphStorage, le_bool rightToLeft, const LEFontInstance *fontInstance)
1.74 +{
1.75 + if (! hasCursiveGlyphs()) {
1.76 + return;
1.77 + }
1.78 +
1.79 + le_int32 start = 0, end = fGlyphCount, dir = 1;
1.80 + le_int32 firstExitPoint = -1, lastExitPoint = -1;
1.81 + LEPoint entryAnchor, exitAnchor, pixels;
1.82 + LEGlyphID lastExitGlyphID = 0;
1.83 + float baselineAdjustment = 0;
1.84 +
1.85 + // This removes a possible warning about
1.86 + // using exitAnchor before it's been initialized.
1.87 + exitAnchor.fX = exitAnchor.fY = 0;
1.88 +
1.89 + if (rightToLeft) {
1.90 + start = fGlyphCount - 1;
1.91 + end = -1;
1.92 + dir = -1;
1.93 + }
1.94 +
1.95 + for (le_int32 i = start; i != end; i += dir) {
1.96 + LEGlyphID glyphID = glyphStorage[i];
1.97 +
1.98 + if (isCursiveGlyph(i)) {
1.99 + if (lastExitPoint >= 0 && getEntryPoint(i, entryAnchor) != NULL) {
1.100 + float anchorDiffX = exitAnchor.fX - entryAnchor.fX;
1.101 + float anchorDiffY = exitAnchor.fY - entryAnchor.fY;
1.102 +
1.103 + baselineAdjustment += anchorDiffY;
1.104 + adjustYPlacement(i, baselineAdjustment);
1.105 +
1.106 + if (rightToLeft) {
1.107 + LEPoint secondAdvance;
1.108 +
1.109 + fontInstance->getGlyphAdvance(glyphID, pixels);
1.110 + fontInstance->pixelsToUnits(pixels, secondAdvance);
1.111 +
1.112 + adjustXAdvance(i, -(anchorDiffX + secondAdvance.fX));
1.113 + } else {
1.114 + LEPoint firstAdvance;
1.115 +
1.116 + fontInstance->getGlyphAdvance(lastExitGlyphID, pixels);
1.117 + fontInstance->pixelsToUnits(pixels, firstAdvance);
1.118 +
1.119 + adjustXAdvance(lastExitPoint, anchorDiffX - firstAdvance.fX);
1.120 + }
1.121 + }
1.122 +
1.123 + lastExitPoint = i;
1.124 +
1.125 + if (getExitPoint(i, exitAnchor) != NULL) {
1.126 + if (firstExitPoint < 0) {
1.127 + firstExitPoint = i;
1.128 + }
1.129 +
1.130 + lastExitGlyphID = glyphID;
1.131 + } else {
1.132 + if (baselineIsLogicalEnd(i) && firstExitPoint >= 0 && lastExitPoint >= 0) {
1.133 + le_int32 limit = lastExitPoint + dir;
1.134 +
1.135 + for (le_int32 j = firstExitPoint; j != limit; j += dir) {
1.136 + if (isCursiveGlyph(j)) {
1.137 + adjustYPlacement(j, -baselineAdjustment);
1.138 + }
1.139 + }
1.140 + }
1.141 +
1.142 + firstExitPoint = lastExitPoint = -1;
1.143 + baselineAdjustment = 0;
1.144 + }
1.145 + }
1.146 + }
1.147 +}
1.148 +
1.149 +LEPoint *GlyphPositionAdjustments::EntryExitPoint::getEntryPoint(LEPoint &entryPoint) const
1.150 +{
1.151 + if (fFlags & EEF_HAS_ENTRY_POINT) {
1.152 + entryPoint = fEntryPoint;
1.153 + return &entryPoint;
1.154 + }
1.155 +
1.156 + return NULL;
1.157 +}
1.158 +
1.159 +LEPoint *GlyphPositionAdjustments::EntryExitPoint::getExitPoint(LEPoint &exitPoint) const
1.160 +{
1.161 + if (fFlags & EEF_HAS_EXIT_POINT) {
1.162 + exitPoint = fExitPoint;
1.163 + return &exitPoint;
1.164 + }
1.165 +
1.166 + return NULL;
1.167 +}
1.168 +
1.169 +U_NAMESPACE_END