diff options
Diffstat (limited to 'awt/org/apache/harmony/awt/gl/font/TextRunSegmentImpl.java')
-rw-r--r-- | awt/org/apache/harmony/awt/gl/font/TextRunSegmentImpl.java | 979 |
1 files changed, 0 insertions, 979 deletions
diff --git a/awt/org/apache/harmony/awt/gl/font/TextRunSegmentImpl.java b/awt/org/apache/harmony/awt/gl/font/TextRunSegmentImpl.java deleted file mode 100644 index 0ec2d05..0000000 --- a/awt/org/apache/harmony/awt/gl/font/TextRunSegmentImpl.java +++ /dev/null @@ -1,979 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * @author Oleg V. Khaschansky - * @version $Revision$ - * - */ - -package org.apache.harmony.awt.gl.font; - -import java.awt.*; -import java.awt.font.*; -import java.awt.geom.Rectangle2D; -import java.awt.geom.GeneralPath; -import java.awt.geom.AffineTransform; -import java.awt.geom.Point2D; -// XXX - TODO - bidi not implemented yet -//import java.text.Bidi; -import java.util.Arrays; - -import org.apache.harmony.awt.internal.nls.Messages; - -/** - * Date: Apr 25, 2005 - * Time: 4:33:18 PM - * - * This class contains the implementation of the behavior of the - * text run segment with constant text attributes and direction. - */ -public class TextRunSegmentImpl { - - /** - * This class contains basic information required for creation - * of the glyph-based text run segment. - */ - public static class TextSegmentInfo { - // XXX - TODO - bidi not implemented yet - //Bidi bidi; - - Font font; - FontRenderContext frc; - - char text[]; - - int start; - int end; - int length; - - int flags = 0; - - byte level = 0; - - TextSegmentInfo( - byte level, - Font font, FontRenderContext frc, - char text[], int start, int end - ) { - this.font = font; - this.frc = frc; - this.text = text; - this.start = start; - this.end = end; - this.level = level; - length = end - start; - } - } - - /** - * This class represents a simple text segment backed by the glyph vector - */ - public static class TextRunSegmentCommon extends TextRunSegment { - TextSegmentInfo info; - private GlyphVector gv; - private float advanceIncrements[]; - private int char2glyph[]; - private GlyphJustificationInfo gjis[]; // Glyph justification info - - TextRunSegmentCommon(TextSegmentInfo i, TextDecorator.Decoration d) { - // XXX - todo - check support bidi - i.flags &= ~0x09; // Clear bidi flags - - if ((i.level & 0x1) != 0) { - i.flags |= Font.LAYOUT_RIGHT_TO_LEFT; - } - - info = i; - this.decoration = d; - - LineMetrics lm = i.font.getLineMetrics(i.text, i.start, i.end, i.frc); - this.metrics = new BasicMetrics(lm, i.font); - - if (lm.getNumChars() != i.length) { // XXX todo - This should be handled - // awt.41=Font returned unsupported type of line metrics. This case is known, but not supported yet. - throw new UnsupportedOperationException( - Messages.getString("awt.41")); //$NON-NLS-1$ - } - } - - @Override - public Object clone() { - return new TextRunSegmentCommon(info, decoration); - } - - /** - * Creates glyph vector from the managed text if needed - * @return glyph vector - */ - private GlyphVector getGlyphVector() { - if (gv==null) { - gv = info.font.layoutGlyphVector( - info.frc, - info.text, - info.start, - info.end - info.start, // NOTE: This parameter violates - // spec, it is count, - // not limit as spec states - info.flags - ); - } - - return gv; - } - - /** - * Renders this text run segment - * @param g2d - graphics to render to - * @param xOffset - X offset from the graphics origin to the - * origin of the text layout - * @param yOffset - Y offset from the graphics origin to the - * origin of the text layout - */ - @Override - void draw(Graphics2D g2d, float xOffset, float yOffset) { - if (decoration == null) { - g2d.drawGlyphVector(getGlyphVector(), xOffset + x, yOffset + y); - } else { - TextDecorator.prepareGraphics(this, g2d, xOffset, yOffset); - g2d.drawGlyphVector(getGlyphVector(), xOffset + x, yOffset + y); - TextDecorator.drawTextDecorations(this, g2d, xOffset, yOffset); - TextDecorator.restoreGraphics(decoration, g2d); - } - } - - /** - * Returns visual bounds of this segment - * @return visual bounds - */ - @Override - Rectangle2D getVisualBounds() { - if (visualBounds == null) { - visualBounds = - TextDecorator.extendVisualBounds( - this, - getGlyphVector().getVisualBounds(), - decoration - ); - - visualBounds.setRect( - x + visualBounds.getX(), - y + visualBounds.getY(), - visualBounds.getWidth(), - visualBounds.getHeight() - ); - } - - return (Rectangle2D) visualBounds.clone(); - } - - /** - * Returns logical bounds of this segment - * @return logical bounds - */ - @Override - Rectangle2D getLogicalBounds() { - if (logicalBounds == null) { - logicalBounds = getGlyphVector().getLogicalBounds(); - - logicalBounds.setRect( - x + logicalBounds.getX(), - y + logicalBounds.getY(), - logicalBounds.getWidth(), - logicalBounds.getHeight() - ); - } - - return (Rectangle2D) logicalBounds.clone(); - } - - @Override - float getAdvance() { - return (float) getLogicalBounds().getWidth(); - } - - /** - * Attemts to map each character to the corresponding advance increment - */ - void initAdvanceMapping() { - GlyphVector gv = getGlyphVector(); - int charIndicies[] = gv.getGlyphCharIndices(0, gv.getNumGlyphs(), null); - advanceIncrements = new float[info.length]; - - for (int i=0; i<charIndicies.length; i++) { - advanceIncrements[charIndicies[i]] = gv.getGlyphMetrics(i).getAdvance(); - } - } - - /** - * Calculates advance delta between two characters - * @param start - 1st position - * @param end - 2nd position - * @return advance increment between specified positions - */ - @Override - float getAdvanceDelta(int start, int end) { - // Get coordinates in the segment context - start -= info.start; - end -= info.start; - - if (advanceIncrements == null) { - initAdvanceMapping(); - } - - if (start < 0) { - start = 0; - } - if (end > info.length) { - end = info.length; - } - - float sum = 0; - for (int i=start; i<end; i++) { - sum += advanceIncrements[i]; - } - - return sum; - } - - /** - * Calculates index of the character which advance is equal to - * the given. If the given advance is greater then the segment - * advance it returns the position after the last character. - * @param advance - given advance - * @param start - character, from which to start measuring advance - * @return character index - */ - @Override - int getCharIndexFromAdvance(float advance, int start) { - // XXX - todo - probably, possible to optimize - // Add check if the given advance is greater then - // the segment advance in the beginning. In this case - // we don't need to run through all increments - if (advanceIncrements == null) { - initAdvanceMapping(); - } - - start -= info.start; - - if (start < 0) { - start = 0; - } - - int i = start; - for (; i<info.length; i++) { - advance -= advanceIncrements[i]; - if (advance < 0) { - break; - } - } - - return i + info.start; - } - - @Override - int getStart() { - return info.start; - } - - @Override - int getEnd() { - return info.end; - } - - @Override - int getLength() { - return info.length; - } - - /** - * Attemts to create mapping of the characters to glyphs in the glyph vector. - * @return array where for each character index stored corresponding glyph index - */ - private int[] getChar2Glyph() { - if (char2glyph == null) { - GlyphVector gv = getGlyphVector(); - char2glyph = new int[info.length]; - Arrays.fill(char2glyph, -1); - - // Fill glyph indicies for first characters corresponding to each glyph - int charIndicies[] = gv.getGlyphCharIndices(0, gv.getNumGlyphs(), null); - for (int i=0; i<charIndicies.length; i++) { - char2glyph[charIndicies[i]] = i; - } - - // If several characters corresponds to one glyph, create mapping for them - // Suppose that these characters are going all together - int currIndex = 0; - for (int i=0; i<char2glyph.length; i++) { - if (char2glyph[i] < 0) { - char2glyph[i] = currIndex; - } else { - currIndex = char2glyph[i]; - } - } - } - - return char2glyph; - } - - /** - * Creates black box bounds shape for the specified range - * @param start - range sart - * @param limit - range end - * @return black box bounds shape - */ - @Override - Shape getCharsBlackBoxBounds(int start, int limit) { - start -= info.start; - limit -= info.start; - - if (limit > info.length) { - limit = info.length; - } - - GeneralPath result = new GeneralPath(); - - int glyphIndex = 0; - - for (int i=start; i<limit; i++) { - glyphIndex = getChar2Glyph()[i]; - result.append(getGlyphVector().getGlyphVisualBounds(glyphIndex), false); - } - - // Shift to the segment's coordinates - result.transform(AffineTransform.getTranslateInstance(x, y)); - - return result; - } - - /** - * Calculates position of the character on the screen - * @param index - character index - * @return X coordinate of the character position - */ - @Override - float getCharPosition(int index) { - index -= info.start; - - if (index > info.length) { - index = info.length; - } - - float result = 0; - - int glyphIndex = getChar2Glyph()[index]; - result = (float) getGlyphVector().getGlyphPosition(glyphIndex).getX(); - - // Shift to the segment's coordinates - result += x; - - return result; - } - - /** - * Returns the advance of the individual character - * @param index - character index - * @return character advance - */ - @Override - float getCharAdvance(int index) { - if (advanceIncrements == null) { - initAdvanceMapping(); - } - - return advanceIncrements[index - this.getStart()]; - } - - /** - * Returns the outline shape - * @return outline - */ - @Override - Shape getOutline() { - AffineTransform t = AffineTransform.getTranslateInstance(x, y); - return t.createTransformedShape( - TextDecorator.extendOutline( - this, - getGlyphVector().getOutline(), - decoration - ) - ); - } - - /** - * Checks if the character doesn't contribute to the text advance - * @param index - character index - * @return true if the character has zero advance - */ - @Override - boolean charHasZeroAdvance(int index) { - if (advanceIncrements == null) { - initAdvanceMapping(); - } - - return advanceIncrements[index - this.getStart()] == 0; - } - - /** - * Creates text hit info from the hit position - * @param hitX - X coordinate relative to the origin of the layout - * @param hitY - Y coordinate relative to the origin of the layout - * @return hit info - */ - @Override - TextHitInfo hitTest(float hitX, float hitY) { - hitX -= x; - - float glyphPositions[] = - getGlyphVector().getGlyphPositions(0, info.length+1, null); - - int glyphIdx; - boolean leading = false; - for (glyphIdx = 1; glyphIdx <= info.length; glyphIdx++) { - if (glyphPositions[(glyphIdx)*2] >= hitX) { - float advance = - glyphPositions[(glyphIdx)*2] - glyphPositions[(glyphIdx-1)*2]; - leading = glyphPositions[(glyphIdx-1)*2] + advance/2 > hitX ? true : false; - glyphIdx--; - break; - } - } - - if (glyphIdx == info.length) { - glyphIdx--; - } - - int charIdx = getGlyphVector().getGlyphCharIndex(glyphIdx); - - return (leading) ^ ((info.level & 0x1) == 0x1)? - TextHitInfo.leading(charIdx + info.start) : - TextHitInfo.trailing(charIdx + info.start); - } - - /** - * Collects GlyphJustificationInfo objects from the glyph vector - * @return array of all GlyphJustificationInfo objects - */ - private GlyphJustificationInfo[] getGlyphJustificationInfos() { - if (gjis == null) { - GlyphVector gv = getGlyphVector(); - int nGlyphs = gv.getNumGlyphs(); - int charIndicies[] = gv.getGlyphCharIndices(0, nGlyphs, null); - gjis = new GlyphJustificationInfo[nGlyphs]; - - // Patch: temporary patch, getGlyphJustificationInfo is not implemented - float fontSize = info.font.getSize2D(); - GlyphJustificationInfo defaultInfo = - new GlyphJustificationInfo( - 0, // weight - false, GlyphJustificationInfo.PRIORITY_NONE, 0, 0, // grow - false, GlyphJustificationInfo.PRIORITY_NONE, 0, 0); // shrink - GlyphJustificationInfo spaceInfo = new GlyphJustificationInfo( - fontSize, // weight - true, GlyphJustificationInfo.PRIORITY_WHITESPACE, 0, fontSize, // grow - true, GlyphJustificationInfo.PRIORITY_WHITESPACE, 0, fontSize); // shrink - - //////// - // Temporary patch, getGlyphJustificationInfo is not implemented - for (int i = 0; i < nGlyphs; i++) { - //gjis[i] = getGlyphVector().getGlyphJustificationInfo(i); - - char c = info.text[charIndicies[i] + info.start]; - if (Character.isWhitespace(c)) { - gjis[i] = spaceInfo; - } else { - gjis[i] = defaultInfo; - } - // End patch - } - } - - return gjis; - } - - /** - * Collects justification information into JustificationInfo object - * @param jInfo - JustificationInfo object - */ - @Override - void updateJustificationInfo(TextRunBreaker.JustificationInfo jInfo) { - int lastChar = Math.min(jInfo.lastIdx, info.end) - info.start; - boolean haveFirst = info.start <= jInfo.firstIdx; - boolean haveLast = info.end >= (jInfo.lastIdx + 1); - - int prevGlyphIdx = -1; - int currGlyphIdx; - - if (jInfo.grow) { // Check how much we can grow/shrink on current priority level - for (int i=0; i<lastChar; i++) { - currGlyphIdx = getChar2Glyph()[i]; - - if (currGlyphIdx == prevGlyphIdx) { - // Several chars could be represented by one glyph, - // suppose they are contiguous - continue; - } - prevGlyphIdx = currGlyphIdx; - - GlyphJustificationInfo gji = getGlyphJustificationInfos()[currGlyphIdx]; - if (gji.growPriority == jInfo.priority) { - jInfo.weight += gji.weight * 2; - jInfo.growLimit += gji.growLeftLimit; - jInfo.growLimit += gji.growRightLimit; - if (gji.growAbsorb) { - jInfo.absorbedWeight += gji.weight * 2; - } - } - } - } else { - for (int i=0; i<lastChar; i++) { - currGlyphIdx = getChar2Glyph()[i]; - if (currGlyphIdx == prevGlyphIdx) { - continue; - } - prevGlyphIdx = currGlyphIdx; - - GlyphJustificationInfo gji = getGlyphJustificationInfos()[currGlyphIdx]; - if (gji.shrinkPriority == jInfo.priority) { - jInfo.weight += gji.weight * 2; - jInfo.growLimit -= gji.shrinkLeftLimit; - jInfo.growLimit -= gji.shrinkRightLimit; - if (gji.shrinkAbsorb) { - jInfo.absorbedWeight += gji.weight * 2; - } - } - } - } - - if (haveFirst) { // Don't add padding before first char - GlyphJustificationInfo gji = getGlyphJustificationInfos()[getChar2Glyph()[0]]; - jInfo.weight -= gji.weight; - if (jInfo.grow) { - jInfo.growLimit -= gji.growLeftLimit; - if (gji.growAbsorb) { - jInfo.absorbedWeight -= gji.weight; - } - } else { - jInfo.growLimit += gji.shrinkLeftLimit; - if (gji.shrinkAbsorb) { - jInfo.absorbedWeight -= gji.weight; - } - } - } - - if (haveLast) { // Don't add padding after last char - GlyphJustificationInfo gji = - getGlyphJustificationInfos()[getChar2Glyph()[lastChar]]; - jInfo.weight -= gji.weight; - if (jInfo.grow) { - jInfo.growLimit -= gji.growRightLimit; - if (gji.growAbsorb) { - jInfo.absorbedWeight -= gji.weight; - } - } else { - jInfo.growLimit += gji.shrinkRightLimit; - if (gji.shrinkAbsorb) { - jInfo.absorbedWeight -= gji.weight; - } - } - } - } - - /** - * Performs justification of the segment. - * Updates positions of individual characters. - * @param jInfos - justification information, gathered by the previous passes - * @return amount of growth or shrink of the segment - */ - @Override - float doJustification(TextRunBreaker.JustificationInfo jInfos[]) { - int lastPriority = - jInfos[jInfos.length-1] == null ? - -1 : jInfos[jInfos.length-1].priority; - - // Get the highest priority - int highestPriority = 0; - for (; highestPriority<jInfos.length; highestPriority++) { - if (jInfos[highestPriority] != null) { - break; - } - } - - if (highestPriority == jInfos.length) { - return 0; - } - - TextRunBreaker.JustificationInfo firstInfo = jInfos[highestPriority]; - TextRunBreaker.JustificationInfo lastInfo = - lastPriority > 0 ? jInfos[lastPriority] : null; - - boolean haveFirst = info.start <= firstInfo.firstIdx; - boolean haveLast = info.end >= (firstInfo.lastIdx + 1); - - // Here we suppose that GLYPHS are ordered LEFT TO RIGHT - int firstGlyph = haveFirst ? - getChar2Glyph()[firstInfo.firstIdx - info.start] : - getChar2Glyph()[0]; - - int lastGlyph = haveLast ? - getChar2Glyph()[firstInfo.lastIdx - info.start] : - getChar2Glyph()[info.length - 1]; - if (haveLast) { - lastGlyph--; - } - - TextRunBreaker.JustificationInfo currInfo; - float glyphOffset = 0; - float positionIncrement = 0; - float sideIncrement = 0; - - if (haveFirst) { // Don't add padding before first char - GlyphJustificationInfo gji = getGlyphJustificationInfos()[firstGlyph]; - currInfo = jInfos[gji.growPriority]; - if (currInfo != null) { - if (currInfo.useLimits) { - if (currInfo.absorb) { - glyphOffset += gji.weight * currInfo.absorbedGapPerUnit; - } else if ( - lastInfo != null && - lastInfo.priority == currInfo.priority - ) { - glyphOffset += gji.weight * lastInfo.absorbedGapPerUnit; - } - glyphOffset += - firstInfo.grow ? - gji.growRightLimit : - -gji.shrinkRightLimit; - } else { - glyphOffset += gji.weight * currInfo.gapPerUnit; - } - } - - firstGlyph++; - } - - if (firstInfo.grow) { - for (int i=firstGlyph; i<=lastGlyph; i++) { - GlyphJustificationInfo gji = getGlyphJustificationInfos()[i]; - currInfo = jInfos[gji.growPriority]; - if (currInfo == null) { - // We still have to increment glyph position - Point2D glyphPos = getGlyphVector().getGlyphPosition(i); - glyphPos.setLocation(glyphPos.getX() + glyphOffset, glyphPos.getY()); - getGlyphVector().setGlyphPosition(i, glyphPos); - - continue; - } - - if (currInfo.useLimits) { - glyphOffset += gji.growLeftLimit; - if (currInfo.absorb) { - sideIncrement = gji.weight * currInfo.absorbedGapPerUnit; - glyphOffset += sideIncrement; - positionIncrement = glyphOffset; - glyphOffset += sideIncrement; - } else if (lastInfo != null && lastInfo.priority == currInfo.priority) { - sideIncrement = gji.weight * lastInfo.absorbedGapPerUnit; - glyphOffset += sideIncrement; - positionIncrement = glyphOffset; - glyphOffset += sideIncrement; - } else { - positionIncrement = glyphOffset; - } - glyphOffset += gji.growRightLimit; - } else { - sideIncrement = gji.weight * currInfo.gapPerUnit; - glyphOffset += sideIncrement; - positionIncrement = glyphOffset; - glyphOffset += sideIncrement; - } - - Point2D glyphPos = getGlyphVector().getGlyphPosition(i); - glyphPos.setLocation(glyphPos.getX() + positionIncrement, glyphPos.getY()); - getGlyphVector().setGlyphPosition(i, glyphPos); - } - } else { - for (int i=firstGlyph; i<=lastGlyph; i++) { - GlyphJustificationInfo gji = getGlyphJustificationInfos()[i]; - currInfo = jInfos[gji.shrinkPriority]; - if (currInfo == null) { - // We still have to increment glyph position - Point2D glyphPos = getGlyphVector().getGlyphPosition(i); - glyphPos.setLocation(glyphPos.getX() + glyphOffset, glyphPos.getY()); - getGlyphVector().setGlyphPosition(i, glyphPos); - - continue; - } - - if (currInfo.useLimits) { - glyphOffset -= gji.shrinkLeftLimit; - if (currInfo.absorb) { - sideIncrement = gji.weight * currInfo.absorbedGapPerUnit; - glyphOffset += sideIncrement; - positionIncrement = glyphOffset; - glyphOffset += sideIncrement; - } else if (lastInfo != null && lastInfo.priority == currInfo.priority) { - sideIncrement = gji.weight * lastInfo.absorbedGapPerUnit; - glyphOffset += sideIncrement; - positionIncrement = glyphOffset; - glyphOffset += sideIncrement; - } else { - positionIncrement = glyphOffset; - } - glyphOffset -= gji.shrinkRightLimit; - } else { - sideIncrement = gji.weight * currInfo.gapPerUnit; - glyphOffset += sideIncrement; - positionIncrement = glyphOffset; - glyphOffset += sideIncrement; - } - - Point2D glyphPos = getGlyphVector().getGlyphPosition(i); - glyphPos.setLocation(glyphPos.getX() + positionIncrement, glyphPos.getY()); - getGlyphVector().setGlyphPosition(i, glyphPos); - } - } - - - if (haveLast) { // Don't add padding after last char - lastGlyph++; - - GlyphJustificationInfo gji = getGlyphJustificationInfos()[lastGlyph]; - currInfo = jInfos[gji.growPriority]; - - if (currInfo != null) { - if (currInfo.useLimits) { - glyphOffset += firstInfo.grow ? gji.growLeftLimit : -gji.shrinkLeftLimit; - if (currInfo.absorb) { - glyphOffset += gji.weight * currInfo.absorbedGapPerUnit; - } else if (lastInfo != null && lastInfo.priority == currInfo.priority) { - glyphOffset += gji.weight * lastInfo.absorbedGapPerUnit; - } - } else { - glyphOffset += gji.weight * currInfo.gapPerUnit; - } - } - - // Ajust positions of all glyphs after last glyph - for (int i=lastGlyph; i<getGlyphVector().getNumGlyphs()+1; i++) { - Point2D glyphPos = getGlyphVector().getGlyphPosition(i); - glyphPos.setLocation(glyphPos.getX() + glyphOffset, glyphPos.getY()); - getGlyphVector().setGlyphPosition(i, glyphPos); - } - } else { // Update position after last glyph in glyph vector - - // to get correct advance for it - Point2D glyphPos = getGlyphVector().getGlyphPosition(lastGlyph+1); - glyphPos.setLocation(glyphPos.getX() + glyphOffset, glyphPos.getY()); - getGlyphVector().setGlyphPosition(lastGlyph+1, glyphPos); - } - - gjis = null; // We don't need justification infos any more - // Also we have to reset cached bounds and metrics - this.visualBounds = null; - this.logicalBounds = null; - - return glyphOffset; // How much our segment grown or shrunk - } - } - - public static class TextRunSegmentGraphic extends TextRunSegment { - GraphicAttribute ga; - int start; - int length; - float fullAdvance; - - TextRunSegmentGraphic(GraphicAttribute attr, int len, int start) { - this.start = start; - length = len; - ga = attr; - metrics = new BasicMetrics(ga); - fullAdvance = ga.getAdvance() * length; - } - - @Override - public Object clone() { - return new TextRunSegmentGraphic(ga, length, start); - } - - // Renders this text run segment - @Override - void draw(Graphics2D g2d, float xOffset, float yOffset) { - if (decoration != null) { - TextDecorator.prepareGraphics(this, g2d, xOffset, yOffset); - } - - float xPos = x + xOffset; - float yPos = y + yOffset; - - for (int i=0; i < length; i++) { - ga.draw(g2d, xPos, yPos); - xPos += ga.getAdvance(); - } - - if (decoration != null) { - TextDecorator.drawTextDecorations(this, g2d, xOffset, yOffset); - TextDecorator.restoreGraphics(decoration, g2d); - } - } - - // Returns visual bounds of this segment - @Override - Rectangle2D getVisualBounds() { - if (visualBounds == null) { - Rectangle2D bounds = ga.getBounds(); - - // First and last chars can be out of logical bounds, so we calculate - // (bounds.getWidth() - ga.getAdvance()) which is exactly the difference - bounds.setRect( - bounds.getMinX() + x, - bounds.getMinY() + y, - bounds.getWidth() - ga.getAdvance() + getAdvance(), - bounds.getHeight() - ); - visualBounds = TextDecorator.extendVisualBounds(this, bounds, decoration); - } - - return (Rectangle2D) visualBounds.clone(); - } - - @Override - Rectangle2D getLogicalBounds() { - if (logicalBounds == null) { - logicalBounds = - new Rectangle2D.Float( - x, y - metrics.ascent, - getAdvance(), metrics.ascent + metrics.descent - ); - } - - return (Rectangle2D) logicalBounds.clone(); - } - - @Override - float getAdvance() { - return fullAdvance; - } - - @Override - float getAdvanceDelta(int start, int end) { - return ga.getAdvance() * (end - start); - } - - @Override - int getCharIndexFromAdvance(float advance, int start) { - start -= this.start; - - if (start < 0) { - start = 0; - } - - int charOffset = (int) (advance/ga.getAdvance()); - - if (charOffset + start > length) { - return length + this.start; - } - return charOffset + start + this.start; - } - - @Override - int getStart() { - return start; - } - - @Override - int getEnd() { - return start + length; - } - - @Override - int getLength() { - return length; - } - - @Override - Shape getCharsBlackBoxBounds(int start, int limit) { - start -= this.start; - limit -= this.start; - - if (limit > length) { - limit = length; - } - - Rectangle2D charBounds = ga.getBounds(); - charBounds.setRect( - charBounds.getX() + ga.getAdvance() * start + x, - charBounds.getY() + y, - charBounds.getWidth() + ga.getAdvance() * (limit - start), - charBounds.getHeight() - ); - - return charBounds; - } - - @Override - float getCharPosition(int index) { - index -= start; - if (index > length) { - index = length; - } - - return ga.getAdvance() * index + x; - } - - @Override - float getCharAdvance(int index) { - return ga.getAdvance(); - } - - @Override - Shape getOutline() { - AffineTransform t = AffineTransform.getTranslateInstance(x, y); - return t.createTransformedShape( - TextDecorator.extendOutline(this, getVisualBounds(), decoration) - ); - } - - @Override - boolean charHasZeroAdvance(int index) { - return false; - } - - @Override - TextHitInfo hitTest(float hitX, float hitY) { - hitX -= x; - - float tmp = hitX / ga.getAdvance(); - int hitIndex = Math.round(tmp); - - if (tmp > hitIndex) { - return TextHitInfo.leading(hitIndex + this.start); - } - return TextHitInfo.trailing(hitIndex + this.start); - } - - @Override - void updateJustificationInfo(TextRunBreaker.JustificationInfo jInfo) { - // Do nothing - } - - @Override - float doJustification(TextRunBreaker.JustificationInfo jInfos[]) { - // Do nothing - return 0; - } - } -} |