Imported GNU Classpath 0.92
2006-08-14 Mark Wielaard <mark@klomp.org> Imported GNU Classpath 0.92 * HACKING: Add more importing hints. Update automake version requirement. * configure.ac (gconf-peer): New enable AC argument. Add --disable-gconf-peer and --enable-default-preferences-peer to classpath configure when gconf is disabled. * scripts/makemake.tcl: Set gnu/java/util/prefs/gconf and gnu/java/awt/dnd/peer/gtk to bc. Classify gnu/java/security/Configuration.java as generated source file. * gnu/java/lang/management/VMGarbageCollectorMXBeanImpl.java, gnu/java/lang/management/VMMemoryPoolMXBeanImpl.java, gnu/java/lang/management/VMClassLoadingMXBeanImpl.java, gnu/java/lang/management/VMRuntimeMXBeanImpl.java, gnu/java/lang/management/VMMemoryManagerMXBeanImpl.java, gnu/java/lang/management/VMThreadMXBeanImpl.java, gnu/java/lang/management/VMMemoryMXBeanImpl.java, gnu/java/lang/management/VMCompilationMXBeanImpl.java: New VM stub classes. * java/lang/management/VMManagementFactory.java: Likewise. * java/net/VMURLConnection.java: Likewise. * gnu/java/nio/VMChannel.java: Likewise. * java/lang/Thread.java (getState): Add stub implementation. * java/lang/Class.java (isEnum): Likewise. * java/lang/Class.h (isEnum): Likewise. * gnu/awt/xlib/XToolkit.java (getClasspathTextLayoutPeer): Removed. * javax/naming/spi/NamingManager.java: New override for StackWalker functionality. * configure, sources.am, Makefile.in, gcj/Makefile.in, include/Makefile.in, testsuite/Makefile.in: Regenerated. From-SVN: r116139
This commit is contained in:
@@ -83,7 +83,15 @@ public class FontRenderContext
|
||||
|
||||
public boolean equals (FontRenderContext rhs)
|
||||
{
|
||||
return (affineTransform.equals (rhs.getTransform ())
|
||||
if (rhs == null)
|
||||
return false;
|
||||
|
||||
if (affineTransform == null && rhs.affineTransform != null
|
||||
|| affineTransform != null && rhs.affineTransform == null)
|
||||
return false;
|
||||
|
||||
return ((affineTransform == rhs.affineTransform
|
||||
|| affineTransform.equals (rhs.getTransform ()))
|
||||
&& isAntiAliased == rhs.isAntiAliased ()
|
||||
&& usesFractionalMetrics == rhs.usesFractionalMetrics ());
|
||||
}
|
||||
|
||||
@@ -41,57 +41,41 @@ package java.awt.font;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.text.AttributedString;
|
||||
import java.text.BreakIterator;
|
||||
import java.awt.font.TextLayout;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.Shape;
|
||||
|
||||
public final class LineBreakMeasurer
|
||||
{
|
||||
private AttributedCharacterIterator text;
|
||||
private int position;
|
||||
private FontRenderContext frc;
|
||||
private TextLayout totalLayout;
|
||||
private TextMeasurer tm;
|
||||
private int numChars;
|
||||
|
||||
public LineBreakMeasurer(AttributedCharacterIterator text,
|
||||
BreakIterator breakIter, FontRenderContext frc)
|
||||
{
|
||||
this.text = text;
|
||||
this.frc = frc;
|
||||
position = 0;
|
||||
totalLayout = new TextLayout(text, frc);
|
||||
numChars = totalLayout.getCharacterCount();
|
||||
this( text, frc );
|
||||
}
|
||||
|
||||
public LineBreakMeasurer(AttributedCharacterIterator text,
|
||||
FontRenderContext frc)
|
||||
{
|
||||
this.text = text;
|
||||
this.frc = frc;
|
||||
position = 0;
|
||||
totalLayout = new TextLayout(text, frc);
|
||||
numChars = totalLayout.getCharacterCount();
|
||||
numChars = text.getEndIndex();
|
||||
tm = new TextMeasurer( text, frc );
|
||||
}
|
||||
|
||||
public void deleteChar(AttributedCharacterIterator newParagraph,
|
||||
int deletePos)
|
||||
{
|
||||
totalLayout = new TextLayout(newParagraph, frc);
|
||||
if( deletePos < 0 || deletePos > totalLayout.getCharacterCount() )
|
||||
throw new NullPointerException("Invalid deletePos:"+deletePos);
|
||||
numChars = totalLayout.getCharacterCount();
|
||||
text = newParagraph;
|
||||
tm.deleteChar( newParagraph, deletePos );
|
||||
position = 0;
|
||||
}
|
||||
|
||||
public void insertChar(AttributedCharacterIterator newParagraph,
|
||||
int insertPos)
|
||||
{
|
||||
totalLayout = new TextLayout(newParagraph, frc);
|
||||
if( insertPos < 0 || insertPos > totalLayout.getCharacterCount() )
|
||||
throw new NullPointerException("Invalid insertPos:"+insertPos);
|
||||
numChars = totalLayout.getCharacterCount();
|
||||
text = newParagraph;
|
||||
tm.insertChar( newParagraph, insertPos );
|
||||
position = 0;
|
||||
}
|
||||
|
||||
@@ -104,11 +88,9 @@ public final class LineBreakMeasurer
|
||||
boolean requireNextWord)
|
||||
{
|
||||
int next = nextOffset( wrappingWidth, offsetLimit, requireNextWord );
|
||||
AttributedCharacterIterator aci = (new AttributedString( text,
|
||||
position, next )
|
||||
).getIterator();
|
||||
TextLayout tl = tm.getLayout( position, next );
|
||||
position = next;
|
||||
return new TextLayout( aci, frc );
|
||||
return tl;
|
||||
}
|
||||
|
||||
public int nextOffset(float wrappingWidth)
|
||||
@@ -119,69 +101,40 @@ public final class LineBreakMeasurer
|
||||
public int nextOffset(float wrappingWidth, int offsetLimit,
|
||||
boolean requireNextWord)
|
||||
{
|
||||
Shape s = totalLayout.getBlackBoxBounds( position, offsetLimit );
|
||||
double remainingLength = s.getBounds2D().getWidth();
|
||||
int guessOffset = tm.getLineBreakIndex(position, wrappingWidth);
|
||||
if( offsetLimit > numChars )
|
||||
offsetLimit = numChars;
|
||||
|
||||
int guessOffset = (int)( ( (double)wrappingWidth / (double)remainingLength)
|
||||
* ( (double)numChars - (double)position ) );
|
||||
guessOffset += position;
|
||||
if( guessOffset > offsetLimit )
|
||||
guessOffset = offsetLimit;
|
||||
|
||||
s = totalLayout.getBlackBoxBounds( position, guessOffset );
|
||||
double guessLength = s.getBounds2D().getWidth();
|
||||
|
||||
boolean makeSmaller = ( guessLength > wrappingWidth );
|
||||
int inc = makeSmaller ? -1 : 1;
|
||||
boolean keepGoing = true;
|
||||
|
||||
do
|
||||
{
|
||||
guessOffset = guessOffset + inc;
|
||||
if( guessOffset <= position || guessOffset > offsetLimit )
|
||||
{
|
||||
keepGoing = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
s = totalLayout.getBlackBoxBounds( position, guessOffset );
|
||||
guessLength = s.getBounds2D().getWidth();
|
||||
if( makeSmaller && ( guessLength <= wrappingWidth) )
|
||||
keepGoing = false;
|
||||
if( !makeSmaller && ( guessLength >= wrappingWidth) )
|
||||
keepGoing = false;
|
||||
}
|
||||
text.setIndex( offsetLimit );
|
||||
return offsetLimit;
|
||||
}
|
||||
while( keepGoing );
|
||||
|
||||
if( !makeSmaller )
|
||||
guessOffset--;
|
||||
|
||||
if( guessOffset >= offsetLimit )
|
||||
return offsetLimit;
|
||||
|
||||
text.setIndex( guessOffset );
|
||||
|
||||
// If we're on a breaking character, return directly
|
||||
if( Character.isWhitespace( text.current() ) )
|
||||
return guessOffset;
|
||||
|
||||
// Otherwise jump forward or backward to the last such char.
|
||||
if( !requireNextWord )
|
||||
{
|
||||
char c = text.previous();
|
||||
while( !Character.isWhitespace( c ) && c != '-' &&
|
||||
guessOffset > position )
|
||||
{
|
||||
guessOffset--;
|
||||
c = text.previous();
|
||||
}
|
||||
}
|
||||
while( !Character.isWhitespace( text.previous() ) &&
|
||||
guessOffset > position )
|
||||
guessOffset--;
|
||||
else
|
||||
while( !Character.isWhitespace( text.next() ) &&
|
||||
guessOffset < offsetLimit )
|
||||
guessOffset++;
|
||||
|
||||
if( guessOffset > offsetLimit )
|
||||
{
|
||||
char c = text.next();
|
||||
while( !Character.isWhitespace( c ) && c != '-' &&
|
||||
guessOffset < offsetLimit )
|
||||
{
|
||||
guessOffset++;
|
||||
c = text.next();
|
||||
}
|
||||
text.setIndex( offsetLimit );
|
||||
return offsetLimit;
|
||||
}
|
||||
|
||||
text.setIndex( guessOffset );
|
||||
|
||||
return guessOffset;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,13 +43,12 @@ import gnu.classpath.NotImplementedException;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Shape;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.text.CharacterIterator;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.text.AttributedString;
|
||||
import java.text.Bidi;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -72,6 +71,12 @@ public final class TextLayout implements Cloneable
|
||||
*/
|
||||
private int[][] runIndices;
|
||||
|
||||
/**
|
||||
* Character indices.
|
||||
* Fixt index is the glyphvector, second index is the (first) glyph.
|
||||
*/
|
||||
private int[][] charIndices;
|
||||
|
||||
/**
|
||||
* Base directionality, determined from the first char.
|
||||
*/
|
||||
@@ -85,7 +90,7 @@ public final class TextLayout implements Cloneable
|
||||
/**
|
||||
* The default caret policy.
|
||||
*/
|
||||
static TextLayout.CaretPolicy DEFAULT_CARET_POLICY = new CaretPolicy();
|
||||
public static final TextLayout.CaretPolicy DEFAULT_CARET_POLICY = new CaretPolicy();
|
||||
|
||||
/**
|
||||
* Constructs a TextLayout.
|
||||
@@ -139,6 +144,7 @@ public final class TextLayout implements Cloneable
|
||||
Font.LAYOUT_LEFT_TO_RIGHT :
|
||||
Font.LAYOUT_RIGHT_TO_LEFT );
|
||||
}
|
||||
setCharIndices();
|
||||
}
|
||||
|
||||
public TextLayout (String string, Map attributes, FontRenderContext frc)
|
||||
@@ -147,9 +153,97 @@ public final class TextLayout implements Cloneable
|
||||
}
|
||||
|
||||
public TextLayout (AttributedCharacterIterator text, FontRenderContext frc)
|
||||
throws NotImplementedException
|
||||
{
|
||||
throw new Error ("not implemented");
|
||||
// FIXME: Very rudimentary.
|
||||
this(getText(text), getFont(text), frc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Package-private constructor to make a textlayout from an existing one.
|
||||
* This is used by TextMeasurer for returning sub-layouts, and it
|
||||
* saves a lot of time in not having to relayout the text.
|
||||
*/
|
||||
TextLayout(TextLayout t, int startIndex, int endIndex)
|
||||
{
|
||||
font = t.font;
|
||||
frc = t.frc;
|
||||
boundsCache = null;
|
||||
lm = t.lm;
|
||||
leftToRight = t.leftToRight;
|
||||
|
||||
if( endIndex > t.getCharacterCount() )
|
||||
endIndex = t.getCharacterCount();
|
||||
string = t.string.substring( startIndex, endIndex );
|
||||
|
||||
int startingRun = t.charIndices[startIndex][0];
|
||||
int nRuns = 1 + t.charIndices[endIndex - 1][0] - startingRun;
|
||||
runIndices = new int[ nRuns ][2];
|
||||
|
||||
runs = new GlyphVector[ nRuns ];
|
||||
for( int i = 0; i < nRuns; i++ )
|
||||
{
|
||||
GlyphVector run = t.runs[ i + startingRun ];
|
||||
// Copy only the relevant parts of the first and last runs.
|
||||
int beginGlyphIndex = (i > 0) ? 0 : t.charIndices[startIndex][1];
|
||||
int numEntries = ( i < nRuns - 1) ? run.getNumGlyphs() :
|
||||
1 + t.charIndices[endIndex - 1][1] - beginGlyphIndex;
|
||||
|
||||
int[] codes = run.getGlyphCodes(beginGlyphIndex, numEntries, null);
|
||||
runs[ i ] = font.createGlyphVector( frc, codes );
|
||||
runIndices[ i ][0] = t.runIndices[i + startingRun][0] - startIndex;
|
||||
runIndices[ i ][1] = t.runIndices[i + startingRun][1] - startIndex;
|
||||
}
|
||||
runIndices[ nRuns - 1 ][1] = endIndex - 1;
|
||||
|
||||
setCharIndices();
|
||||
determineWhiteSpace();
|
||||
}
|
||||
|
||||
private void setCharIndices()
|
||||
{
|
||||
charIndices = new int[ getCharacterCount() ][2];
|
||||
int i = 0;
|
||||
int currentChar = 0;
|
||||
for(int run = 0; run < runs.length; run++)
|
||||
{
|
||||
currentChar = -1;
|
||||
for( int gi = 0; gi < runs[ run ].getNumGlyphs(); gi++)
|
||||
{
|
||||
if( runs[ run ].getGlyphCharIndex( gi ) != currentChar )
|
||||
{
|
||||
charIndices[ i ][0] = run;
|
||||
charIndices[ i ][1] = gi;
|
||||
currentChar = runs[ run ].getGlyphCharIndex( gi );
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getText(AttributedCharacterIterator iter)
|
||||
{
|
||||
StringBuffer sb = new StringBuffer();
|
||||
int idx = iter.getIndex();
|
||||
for(char c = iter.first(); c != CharacterIterator.DONE; c = iter.next())
|
||||
sb.append(c);
|
||||
iter.setIndex( idx );
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static Font getFont(AttributedCharacterIterator iter)
|
||||
{
|
||||
Font f = (Font)iter.getAttribute(TextAttribute.FONT);
|
||||
if( f == null )
|
||||
{
|
||||
int size;
|
||||
Float i = (Float)iter.getAttribute(TextAttribute.SIZE);
|
||||
if( i != null )
|
||||
size = (int)i.floatValue();
|
||||
else
|
||||
size = 14;
|
||||
f = new Font("Dialog", Font.PLAIN, size );
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,10 +273,14 @@ public final class TextLayout implements Cloneable
|
||||
gotDirection = true;
|
||||
break;
|
||||
}
|
||||
determineWhiteSpace();
|
||||
}
|
||||
|
||||
private void determineWhiteSpace()
|
||||
{
|
||||
// Determine if there's whitespace in the thing.
|
||||
// Ignore trailing chars.
|
||||
i = string.length() - 1;
|
||||
int i = string.length() - 1;
|
||||
hasWhitespace = false;
|
||||
while( i >= 0 && Character.isWhitespace( string.charAt(i) ) )
|
||||
i--;
|
||||
@@ -251,56 +349,42 @@ public final class TextLayout implements Cloneable
|
||||
|
||||
public Shape getBlackBoxBounds (int firstEndpoint, int secondEndpoint)
|
||||
{
|
||||
if( firstEndpoint < 0 || secondEndpoint > getCharacterCount() )
|
||||
if( secondEndpoint - firstEndpoint <= 0 )
|
||||
return new Rectangle2D.Float(); // Hmm?
|
||||
|
||||
if( firstEndpoint < 0 || secondEndpoint > getCharacterCount())
|
||||
return new Rectangle2D.Float();
|
||||
|
||||
GeneralPath gp = new GeneralPath();
|
||||
int i = 0; // run index
|
||||
|
||||
int ri = charIndices[ firstEndpoint ][0];
|
||||
int gi = charIndices[ firstEndpoint ][1];
|
||||
|
||||
double advance = 0;
|
||||
|
||||
// go to first run
|
||||
while( runIndices[i + 1][1] < firstEndpoint )
|
||||
|
||||
for( int i = 0; i < ri; i++ )
|
||||
advance += runs[i].getLogicalBounds().getWidth();
|
||||
|
||||
for( int i = ri; i <= charIndices[ secondEndpoint - 1 ][0]; i++ )
|
||||
{
|
||||
advance += runs[i].getLogicalBounds().getWidth();
|
||||
i++;
|
||||
}
|
||||
int dg;
|
||||
if( i == charIndices[ secondEndpoint - 1 ][0] )
|
||||
dg = charIndices[ secondEndpoint - 1][1];
|
||||
else
|
||||
dg = runs[i].getNumGlyphs() - 1;
|
||||
|
||||
int j = 0; // index into the run.
|
||||
if( runIndices[i][1] - runIndices[i][0] > 1 )
|
||||
{
|
||||
while( runs[i].getGlyphCharIndex( j + 1 ) <
|
||||
(firstEndpoint - runIndices[i][0] ) )j++;
|
||||
}
|
||||
|
||||
gp.append(runs[i].getGlyphVisualBounds( j ), false);
|
||||
boolean keepGoing = true;;
|
||||
|
||||
do
|
||||
{
|
||||
while( j < runs[i].getNumGlyphs() &&
|
||||
runs[i].getGlyphCharIndex( j ) + runIndices[i][0] <
|
||||
secondEndpoint )
|
||||
for( int j = 0; j <= dg; j++ )
|
||||
{
|
||||
Rectangle2D r2 = (runs[i].getGlyphVisualBounds( j )).
|
||||
getBounds2D();
|
||||
Point2D p = runs[i].getGlyphPosition( j );
|
||||
r2.setRect( advance + p.getX(), r2.getY(),
|
||||
r2.setRect( advance + r2.getX(), r2.getY(),
|
||||
r2.getWidth(), r2.getHeight() );
|
||||
gp.append(r2, false);
|
||||
j++;
|
||||
}
|
||||
|
||||
if( j >= runs[i].getNumGlyphs() )
|
||||
{
|
||||
advance += runs[i].getLogicalBounds().getWidth();
|
||||
i++;
|
||||
j = 0;
|
||||
}
|
||||
else
|
||||
keepGoing = false;
|
||||
advance += runs[i].getLogicalBounds().getWidth();
|
||||
}
|
||||
while( keepGoing );
|
||||
|
||||
return gp;
|
||||
}
|
||||
|
||||
@@ -384,55 +468,42 @@ public final class TextLayout implements Cloneable
|
||||
public Shape getLogicalHighlightShape (int firstEndpoint, int secondEndpoint,
|
||||
Rectangle2D bounds)
|
||||
{
|
||||
if( firstEndpoint < 0 || secondEndpoint > getCharacterCount() )
|
||||
if( secondEndpoint - firstEndpoint <= 0 )
|
||||
return new Rectangle2D.Float(); // Hmm?
|
||||
|
||||
if( firstEndpoint < 0 || secondEndpoint > getCharacterCount())
|
||||
return new Rectangle2D.Float();
|
||||
|
||||
int i = 0; // run index
|
||||
Rectangle2D r = null;
|
||||
int ri = charIndices[ firstEndpoint ][0];
|
||||
int gi = charIndices[ firstEndpoint ][1];
|
||||
|
||||
double advance = 0;
|
||||
|
||||
for( int i = 0; i < ri; i++ )
|
||||
advance += runs[i].getLogicalBounds().getWidth();
|
||||
|
||||
// go to first run
|
||||
if( i > 0 )
|
||||
while( runIndices[i + 1][1] < firstEndpoint )
|
||||
{
|
||||
advance += runs[i].getLogicalBounds().getWidth();
|
||||
i++;
|
||||
}
|
||||
|
||||
int j = 0; // index into the run.
|
||||
if( runIndices[i][1] - runIndices[i][0] > 1 )
|
||||
for( int i = ri; i <= charIndices[ secondEndpoint - 1 ][0]; i++ )
|
||||
{
|
||||
while( runs[i].getGlyphCharIndex( j + 1 ) <
|
||||
(firstEndpoint - runIndices[i][0] ) )j++;
|
||||
}
|
||||
|
||||
Rectangle2D r = (runs[i].getGlyphLogicalBounds( j )).getBounds2D();
|
||||
boolean keepGoing = true;;
|
||||
|
||||
do
|
||||
{
|
||||
while( j < runs[i].getNumGlyphs() &&
|
||||
runs[i].getGlyphCharIndex( j ) + runIndices[i][0] <
|
||||
secondEndpoint )
|
||||
{
|
||||
Rectangle2D r2 = (runs[i].getGlyphLogicalBounds( j )).
|
||||
getBounds2D();
|
||||
Point2D p = runs[i].getGlyphPosition( j );
|
||||
r2.setRect( advance + p.getX(), r2.getY(),
|
||||
r2.getWidth(), r2.getHeight() );
|
||||
r = r.createUnion( r2 );
|
||||
j++;
|
||||
}
|
||||
|
||||
if( j >= runs[i].getNumGlyphs() )
|
||||
{
|
||||
advance += runs[i].getLogicalBounds().getWidth();
|
||||
i++;
|
||||
j = 0;
|
||||
}
|
||||
int dg; // last index in this run to use.
|
||||
if( i == charIndices[ secondEndpoint - 1 ][0] )
|
||||
dg = charIndices[ secondEndpoint - 1][1];
|
||||
else
|
||||
keepGoing = false;
|
||||
dg = runs[i].getNumGlyphs() - 1;
|
||||
|
||||
for(; gi <= dg; gi++ )
|
||||
{
|
||||
Rectangle2D r2 = (runs[i].getGlyphLogicalBounds( gi )).
|
||||
getBounds2D();
|
||||
if( r == null )
|
||||
r = r2;
|
||||
else
|
||||
r = r.createUnion(r2);
|
||||
}
|
||||
gi = 0; // reset glyph index into run for next run.
|
||||
|
||||
advance += runs[i].getLogicalBounds().getWidth();
|
||||
}
|
||||
while( keepGoing );
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -593,8 +664,9 @@ public final class TextLayout implements Cloneable
|
||||
}
|
||||
|
||||
public TextHitInfo hitTestChar (float x, float y, Rectangle2D bounds)
|
||||
throws NotImplementedException
|
||||
{
|
||||
return hitTestChar( x, y, getBounds() );
|
||||
throw new Error ("not implemented");
|
||||
}
|
||||
|
||||
public boolean isLeftToRight ()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* TextMeasurer.java
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
@@ -38,67 +38,154 @@ exception statement from your version. */
|
||||
|
||||
package java.awt.font;
|
||||
|
||||
import gnu.classpath.NotImplementedException;
|
||||
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.text.AttributedString;
|
||||
import java.awt.Shape;
|
||||
|
||||
/**
|
||||
* @author Michael Koch
|
||||
* TextMeasurer is a small utility class for measuring the length of laid-out
|
||||
* text objects.
|
||||
*
|
||||
* @author Sven de Marothy
|
||||
* @since 1.3
|
||||
*/
|
||||
public final class TextMeasurer implements Cloneable
|
||||
{
|
||||
private AttributedCharacterIterator ci;
|
||||
private AttributedCharacterIterator text;
|
||||
private FontRenderContext frc;
|
||||
|
||||
private TextLayout totalLayout;
|
||||
private int numChars;
|
||||
|
||||
/**
|
||||
* Creates a TextMeasurer from a given text in the form of an
|
||||
* <code>AttributedCharacterIterator</code> and a
|
||||
* <code>FontRenderContext</code>.
|
||||
*/
|
||||
public TextMeasurer (AttributedCharacterIterator text, FontRenderContext frc)
|
||||
{
|
||||
this.ci = text;
|
||||
this.text = text;
|
||||
this.frc = frc;
|
||||
totalLayout = new TextLayout( text, frc );
|
||||
numChars = totalLayout.getCharacterCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones the TextMeasurer object
|
||||
*/
|
||||
protected Object clone ()
|
||||
{
|
||||
try
|
||||
{
|
||||
return super.clone ();
|
||||
}
|
||||
catch (CloneNotSupportedException e)
|
||||
{
|
||||
// This may never occur
|
||||
throw new InternalError ();
|
||||
}
|
||||
return new TextMeasurer( text, frc );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the text if a character is deleted at the position deletePos
|
||||
* @param newParagraph - the updated paragraph.
|
||||
* @param deletePos - the deletion position
|
||||
*/
|
||||
public void deleteChar (AttributedCharacterIterator newParagraph,
|
||||
int deletePos)
|
||||
throws NotImplementedException
|
||||
{
|
||||
throw new Error ("not implemented");
|
||||
}
|
||||
|
||||
public float getAdvanceBetween (int start, int limit)
|
||||
throws NotImplementedException
|
||||
{
|
||||
throw new Error ("not implemented");
|
||||
}
|
||||
|
||||
public TextLayout getLayout (int start, int limit)
|
||||
throws NotImplementedException
|
||||
{
|
||||
throw new Error ("not implemented");
|
||||
}
|
||||
|
||||
public int getLineBreakIndex (int start, float maxAdvance)
|
||||
throws NotImplementedException
|
||||
{
|
||||
throw new Error ("not implemented");
|
||||
totalLayout = new TextLayout(newParagraph, frc);
|
||||
if( deletePos < 0 || deletePos > totalLayout.getCharacterCount() )
|
||||
throw new NullPointerException("Invalid deletePos:"+deletePos);
|
||||
numChars = totalLayout.getCharacterCount();
|
||||
text = newParagraph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the text if a character is inserted at the position insertPos
|
||||
* @param newParagraph - the updated paragraph.
|
||||
* @param insertPos - the insertion position
|
||||
*/
|
||||
public void insertChar (AttributedCharacterIterator newParagraph,
|
||||
int insertPos)
|
||||
throws NotImplementedException
|
||||
{
|
||||
throw new Error ("not implemented");
|
||||
totalLayout = new TextLayout(newParagraph, frc);
|
||||
if( insertPos < 0 || insertPos > totalLayout.getCharacterCount() )
|
||||
throw new NullPointerException("Invalid insertPos:"+insertPos);
|
||||
numChars = totalLayout.getCharacterCount();
|
||||
text = newParagraph;
|
||||
}
|
||||
|
||||
/***
|
||||
* Returns the total advance between two positions in the paragraph.
|
||||
* Characters from start to limit-1 (inclusive) are included in this count.
|
||||
*
|
||||
* @param start - the starting character index.
|
||||
* @param limit - the limiting index.
|
||||
*/
|
||||
public float getAdvanceBetween (int start, int limit)
|
||||
{
|
||||
Shape s = totalLayout.getLogicalHighlightShape( start, limit );
|
||||
return (float)s.getBounds2D().getWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>TextLayout</code> object corresponding to the characters
|
||||
* from text to limit.
|
||||
* @param start - the starting character index.
|
||||
* @param limit - the limiting index.
|
||||
*/
|
||||
public TextLayout getLayout (int start, int limit)
|
||||
{
|
||||
if( start >= limit )
|
||||
throw new IllegalArgumentException("Start position must be < limit.");
|
||||
return new TextLayout( totalLayout, start, limit );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the line-break index from a given starting index and a maximum
|
||||
* advance. The index returned is the first character outside the given
|
||||
* advance (or the limit of the string, if all remaining characters fit.)
|
||||
*
|
||||
* @param start - the starting index.
|
||||
* @param maxAdvance - the maximum advance allowed.
|
||||
* @return the index of the first character beyond maxAdvance, or the
|
||||
* index of the last character + 1.
|
||||
*/
|
||||
public int getLineBreakIndex (int start, float maxAdvance)
|
||||
{
|
||||
if( start < 0 )
|
||||
throw new IllegalArgumentException("Start parameter must be > 0.");
|
||||
|
||||
double remainingLength = getAdvanceBetween( start, numChars );
|
||||
|
||||
int guessOffset = (int)( ( (double)maxAdvance / (double)remainingLength)
|
||||
* ( (double)numChars - (double)start ) );
|
||||
guessOffset += start;
|
||||
if( guessOffset > numChars )
|
||||
guessOffset = numChars;
|
||||
|
||||
double guessLength = getAdvanceBetween( start, guessOffset );
|
||||
boolean makeSmaller = ( guessLength > maxAdvance );
|
||||
int inc = makeSmaller ? -1 : 1;
|
||||
boolean keepGoing = true;
|
||||
|
||||
do
|
||||
{
|
||||
guessOffset = guessOffset + inc;
|
||||
if( guessOffset <= start || guessOffset > numChars )
|
||||
{
|
||||
keepGoing = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
guessLength = getAdvanceBetween( start, guessOffset );
|
||||
if( makeSmaller && ( guessLength <= maxAdvance) )
|
||||
keepGoing = false;
|
||||
if( !makeSmaller && ( guessLength >= maxAdvance) )
|
||||
keepGoing = false;
|
||||
}
|
||||
}
|
||||
while( keepGoing );
|
||||
|
||||
// Return first index that doesn't fit.
|
||||
if( !makeSmaller )
|
||||
guessOffset--;
|
||||
|
||||
if( guessOffset > numChars )
|
||||
return numChars;
|
||||
|
||||
return guessOffset;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user