dy = (Float) aci.getAttribute(DY);
rotation = (Float) aci.getAttribute(ROTATION);
baseline = aci.getAttribute(BASELINE_SHIFT);
}
GVTGlyphMetrics gm = gv.getGlyphMetrics(i);
if (i==0) {
if (isVertical()) {
if (glyphOrientationAuto) {
if (isLatinChar(ch)) {
// it will be rotated 90
verticalFirstOffset = 0f;
} else {
// it won't be rotated
float advY = gm.getVerticalAdvance();
float asc = metrics.getAscent();
float dsc = metrics.getDescent();
verticalFirstOffset = asc+(advY-(asc+dsc))/2;
}
} else {
if (glyphOrientationAngle == 0) {
float advY = gm.getVerticalAdvance();
float asc = metrics.getAscent();
float dsc = metrics.getDescent();
verticalFirstOffset = asc+(advY-(asc+dsc))/2;
} else {
// 90, 180, 270
verticalFirstOffset = 0f;
}
}
} else { // not vertical
if ((glyphOrientationAngle == 270)) {
horizontalFirstOffset =
(float)gm.getBounds2D().getHeight();
} else {
// 0, 90, 180
horizontalFirstOffset = 0;
}
}
} else { // not the first char
if (glyphOrientationAuto &&
(verticalFirstOffset == 0f) && !isLatinChar(ch)) {
float advY = gm.getVerticalAdvance();
float asc = metrics.getAscent();
float dsc = metrics.getDescent();
verticalFirstOffset = asc + (advY - (asc+dsc))/2;
}
}
// ox and oy are origin adjustments for each glyph,
// computed on the basis of baseline-shifts, etc.
float ox = 0f;
float oy = 0f;
float glyphOrientationRotation = 0f;
float glyphRotation = 0f;
if (ch != CharacterIterator.DONE) {
if (vertical) {
if (glyphOrientationAuto) {
if (isLatinChar(ch)) {
// If character is Latin, then rotate by
// 90 degrees
glyphOrientationRotation = (float) (Math.PI / 2f);
} else {
glyphOrientationRotation = 0f;
}
} else {
glyphOrientationRotation = (float)Math.toRadians(glyphOrientationAngle);
}
if (textPath != null) {
// if vertical and on a path, any x's are ignored
x = null;
}
} else {
glyphOrientationRotation = (float)Math.toRadians(glyphOrientationAngle);
if (textPath != null) {
// if horizontal and on a path, any y's are ignored
y = null;
}
}
// calculate the total rotation for this glyph
if (rotation == null || rotation.isNaN()) {
glyphRotation = glyphOrientationRotation;
} else {
glyphRotation = (rotation.floatValue() +
glyphOrientationRotation);
}
if ((x != null) && !x.isNaN()) {
if (i == 0)
shift_x_pos = (float)(x.floatValue()-offset.getX());
curr_x_pos = x.floatValue()-shift_x_pos;
}
if (dx != null && !dx.isNaN()) {
curr_x_pos += dx.floatValue();
}
if ((y != null) && !y.isNaN()) {
if (i == 0)
shift_y_pos = (float)(y.floatValue()-offset.getY());
curr_y_pos = y.floatValue()-shift_y_pos;
}
if (dy != null && !dy.isNaN()) {
curr_y_pos += dy.floatValue();
} else if (i > 0) {
curr_y_pos += gp[i*2 + 1]-gp[i*2 - 1];
}
float baselineAdjust = 0f;
if (baseline != null) {
if (baseline instanceof Integer) {
if (baseline==TextAttribute.SUPERSCRIPT_SUPER) {
baselineAdjust = baselineAscent*0.5f;
} else if (baseline==TextAttribute.SUPERSCRIPT_SUB) {
baselineAdjust = -baselineAscent*0.5f;
}
} else if (baseline instanceof Float) {
baselineAdjust = ((Float) baseline).floatValue();
}
if (vertical) {
ox = baselineAdjust;
} else {
oy = -baselineAdjust;
}
}
if (vertical) {
// offset due to rotation of first character
oy += verticalFirstOffset;
if (glyphOrientationAuto) {
if (isLatinChar(ch)) {
ox += metrics.getStrikethroughOffset();
} else {
Rectangle2D glyphBounds
= gv.getGlyphVisualBounds(i).getBounds2D();
ox -= (float)((glyphBounds.getMaxX() - gp[2*i]) -
glyphBounds.getWidth()/2);
}
} else {
// center the character if it's not auto orient
Rectangle2D glyphBounds
= gv.getGlyphVisualBounds(i).getBounds2D();
if (glyphOrientationAngle == 0) {
ox -= (float)((glyphBounds.getMaxX() - gp[2*i]) -
glyphBounds.getWidth()/2);
} else if (glyphOrientationAngle == 180) {
ox += (float)((glyphBounds.getMaxX() - gp[2*i]) -
glyphBounds.getWidth()/2);
} else if (glyphOrientationAngle == 90) {
ox += metrics.getStrikethroughOffset();
} else { // 270
ox -= metrics.getStrikethroughOffset();
}
}
} else {
ox += horizontalFirstOffset;
if (glyphOrientationAngle == 90) {
oy -= gm.getHorizontalAdvance();
} else if (glyphOrientationAngle == 180) {
oy -= metrics.getAscent();
}
}
}
// set the new glyph position
pos.x = curr_x_pos+ox;
pos.y = curr_y_pos+oy;
gv.setGlyphPosition(i, pos);
// calculate the position of the next glyph
if (ArabicTextHandler.arabicCharTransparent(ch)) {
hasArabicTransparent = true;
} else {
// Apply the advance if the current char is not transparent
if (vertical) {
float advanceY = 0;
if (glyphOrientationAuto) {
if (isLatinChar(ch)) {
advanceY = gm.getHorizontalAdvance();
} else {
advanceY = gm.getVerticalAdvance();
}
} else {
if ((glyphOrientationAngle == 0) ||
(glyphOrientationAngle == 180)) {
advanceY = gm.getVerticalAdvance();
} else if (glyphOrientationAngle == 90) {
advanceY = gm.getHorizontalAdvance();
} else { // 270
advanceY = gm.getHorizontalAdvance();
// need to translate so that the spacing
// between chars is correct
gv.setGlyphTransform
(i, AffineTransform.getTranslateInstance
(0, advanceY));
}
}
curr_y_pos += advanceY;
} else {
float advanceX = 0;
if (glyphOrientationAngle == 0) {
advanceX = gm.getHorizontalAdvance();
} else if (glyphOrientationAngle == 180) {
advanceX = gm.getHorizontalAdvance();
// need to translate so that the spacing
// between chars is correct
gv.setGlyphTransform
(i, AffineTransform.getTranslateInstance
(advanceX, 0));
} else {
// 90, 270
advanceX = gm.getVerticalAdvance();
}
curr_x_pos += advanceX;
}
}
// rotate the glyph
if (!epsEQ(glyphRotation,0)) {
AffineTransform glyphTransform = gv.getGlyphTransform(i);
if (glyphTransform == null) {
glyphTransform = new AffineTransform();
}
AffineTransform rotAt;
// Make the 90Deg rotations slightly 'snap to'.
// Also use explicit matrix to avoid round-off.
if (epsEQ(glyphRotation, Math.PI/2)) {
rotAt = new AffineTransform(0, 1, -1, 0, 0, 0);
} else if (epsEQ(glyphRotation, Math.PI)) {
rotAt = new AffineTransform(-1, 0, 0, -1, 0, 0);
} else if (epsEQ(glyphRotation, 3*Math.PI/2)) {
rotAt = new AffineTransform(0, -1, 1, 0, 0, 0);
} else {
rotAt = AffineTransform.getRotateInstance(glyphRotation);
}
glyphTransform.concatenate(rotAt);
gv.setGlyphTransform(i, glyphTransform);
}
aciIndex += gv.getCharacterCount(i,i);
if (aciIndex >= charMap.length)
aciIndex = charMap.length-1;
ch = aci.setIndex(aciIndex+aciStart);
i++;
}
// Update last glyph pos
pos.x = curr_x_pos;
pos.y = curr_y_pos;
gv.setGlyphPosition(i, pos);
advance = new Point2D.Float((float)(curr_x_pos - offset.getX()),
(float)(curr_y_pos - offset.getY()));
// Do a last pass positioning the transparent/mark glyphs on the
// base glyphs.
if (hasArabicTransparent) {
ch = aci.first();
aciIndex = 0;
i=0;
int transparentStart = -1;
while (i < numGlyphs) {
if (ArabicTextHandler.arabicCharTransparent(ch)) {
if (transparentStart == -1) transparentStart = i;
} else {
if (transparentStart != -1) {
Point2D loc = gv.getGlyphPosition(i);
GVTGlyphMetrics gm = gv.getGlyphMetrics(i);
int tyS=0, txS=0; // these never changed ?? todo
float advX=0, advY=0;
if (vertical) {
if (glyphOrientationAuto ||
(glyphOrientationAngle == 90))
advY = gm.getHorizontalAdvance();
else if (glyphOrientationAngle == 270)
advY = 0;
else if (glyphOrientationAngle == 0)
advX = gm.getHorizontalAdvance();
else // 180
advX = -gm.getHorizontalAdvance();
} else {
if (glyphOrientationAngle == 0)
advX = gm.getHorizontalAdvance();
else if (glyphOrientationAngle == 90)
advY = gm.getHorizontalAdvance();
else if (glyphOrientationAngle == 180)
advX = 0;
else // 270
advY = -gm.getHorizontalAdvance();
}
float baseX = (float)(loc.getX()+advX);
float baseY = (float)(loc.getY()+advY);
for (int j=transparentStart; j<i; j++) {
Point2D locT = gv.getGlyphPosition(j);
GVTGlyphMetrics gmT = gv.getGlyphMetrics(j);
float locX = (float)locT.getX();
float locY = (float)locT.getY();
float tx=0, ty=0;
float advT = gmT.getHorizontalAdvance();
if (vertical) {
if (glyphOrientationAuto ||
(glyphOrientationAngle == 90))
locY = baseY-advT;
else if (glyphOrientationAngle == 270)