Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/ikvm-fork.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsmallsql <smallsql>2012-11-18 22:25:46 +0400
committersmallsql <smallsql>2012-11-18 22:25:46 +0400
commit794b852895dded82e1eac2c44ad47b1ce3333e62 (patch)
tree8ee2aa314fbb0c78dbddad7b101da48c52a1c595 /openjdk/sun
parent779894ee33312beeaa6ef6bfa237d215e22cb895 (diff)
Implements performDefaultLayout(), setGlyphPosition(int,Point2D)
reorder the methods like the Oracle implementation for simpler merging, add some range checks from the Oracle implementation
Diffstat (limited to 'openjdk/sun')
-rw-r--r--openjdk/sun/font/StandardGlyphVector.java445
1 files changed, 241 insertions, 204 deletions
diff --git a/openjdk/sun/font/StandardGlyphVector.java b/openjdk/sun/font/StandardGlyphVector.java
index c2f30848..72fd3cc8 100644
--- a/openjdk/sun/font/StandardGlyphVector.java
+++ b/openjdk/sun/font/StandardGlyphVector.java
@@ -27,10 +27,9 @@ import ikvm.awt.IkvmToolkit;
import java.awt.Font;
import java.awt.Shape;
-import java.awt.Toolkit;
import java.awt.font.FontRenderContext;
-import java.awt.font.GlyphJustificationInfo;
import java.awt.font.GlyphMetrics;
+import java.awt.font.GlyphJustificationInfo;
import java.awt.font.GlyphVector;
import java.awt.font.LineMetrics;
import java.awt.geom.AffineTransform;
@@ -45,20 +44,22 @@ import ikvm.internal.NotYetImplementedError;
*
*/
public class StandardGlyphVector extends GlyphVector{
-
+ private Font font;
+ private FontRenderContext frc;
+ private final String glyphs; // always
private float[] positions; // only if not default advances
- private final Font font;
-
- private final FontRenderContext frc;
- private final String glyphs;
private Font2D font2D;
private FontStrike strike;
- public StandardGlyphVector(Font font, String str, FontRenderContext frc){
+ /////////////////////////////
+ // Constructors and Factory methods
+ /////////////////////////////
+
+ public StandardGlyphVector(Font font, String str, FontRenderContext frc) {
if(str == null){
throw new NullPointerException("Glyphs are null");
}
@@ -72,289 +73,333 @@ public class StandardGlyphVector extends GlyphVector{
this.strike = font2D.getStrike(font, frc);
}
-
- public StandardGlyphVector(Font font, CharacterIterator ci, FontRenderContext frc){
- this(font, getString(ci), frc);
+ public StandardGlyphVector(Font font, char[] text, FontRenderContext frc) {
+ this(font, text, 0, text.length, frc);
}
-
- public StandardGlyphVector(Font font, int[] glyphCodes, FontRenderContext frc){
- throw new NotYetImplementedError();
+ public StandardGlyphVector(Font font, char[] text, int start, int count,
+ FontRenderContext frc) {
+ this(font, new String(text, start, count), frc);
}
-
- public StandardGlyphVector(Font font, char[] chars, FontRenderContext frc){
- this(font, chars, 0, chars.length, frc);
+ private float getTracking(Font font) {
+ if (font.hasLayoutAttributes()) {
+ AttributeValues values = ((AttributeMap)font.getAttributes()).getValues();
+ return values.getTracking();
+ }
+ return 0;
}
+ public StandardGlyphVector(Font font, CharacterIterator iter, FontRenderContext frc) {
+ this(font, getString(iter), frc);
+ }
- public StandardGlyphVector(Font font, char[] chars, int beginIndex, int length, FontRenderContext frc){
- this(font, new String(chars, beginIndex, length), frc);
+ public StandardGlyphVector(Font font, int[] glyphs, FontRenderContext frc) {
+ throw new NotYetImplementedError();
}
+ /////////////////////////////
+ // GlyphVector API
+ /////////////////////////////
- /**
- * As a concrete subclass of GlyphVector, this must implement clone.
- */
@Override
- public Object clone(){
- try{
- StandardGlyphVector result = (StandardGlyphVector)super.clone();
-
- return result;
- }catch(CloneNotSupportedException e){
- e.printStackTrace();
- }
-
- return this;
+ public Font getFont() {
+ return this.font;
}
-
- // ////////////////////
- // StandardGlyphVector new public methods
- // ///////////////////
-
- /**
- * Set all the glyph positions, including the 'after last glyph' position. The srcPositions array must be of length
- * (numGlyphs + 1) * 2.
- */
- public void setGlyphPositions(float[] srcPositions){
- positions = srcPositions.clone();
+ @Override
+ public FontRenderContext getFontRenderContext() {
+ return this.frc;
}
-
- /**
- * This is a convenience overload that gets all the glyph positions, which is what you usually want to do if you're
- * getting more than one. !!! should I bother taking result parameter?
- */
- public float[] getGlyphPositions(float[] result){
- initPositions();
- return positions;
+ @Override
+ public void performDefaultLayout() {
+ positions = null;
}
-
- /**
- * For each glyph return posx, posy, advx, advy, visx, visy, visw, vish.
- */
- public float[] getGlyphInfo(){
- initPositions();
- float[] result = new float[glyphs.length() * 8];
- for (int i = 0, n = 0; i < glyphs.length(); ++i, n += 8) {
- float x = positions[i*2];
- float y = positions[i*2+1];
- result[n] = x;
- result[n+1] = y;
-
- int glyphID = glyphs.charAt(i);
- Point2D.Float adv = strike.getGlyphMetrics(glyphID);
- result[n+2] = adv.x;
- result[n+3] = adv.y;
-
- Rectangle2D vb = getGlyphVisualBounds(i).getBounds2D();
- result[n+4] = (float)(vb.getMinX());
- result[n+5] = (float)(vb.getMinY());
- result[n+6] = (float)(vb.getWidth());
- result[n+7] = (float)(vb.getHeight());
- }
- return result;
+ @Override
+ public int getNumGlyphs() {
+ return glyphs.length();
}
+ @Override
+ public int getGlyphCode(int glyphIndex) {
+ return glyphs.charAt(glyphIndex);
+ }
@Override
- public boolean equals(GlyphVector gv){
- if(!(gv instanceof StandardGlyphVector)){
- return false;
+ public int[] getGlyphCodes(int start, int count, int[] result) {
+ if (count < 0) {
+ throw new IllegalArgumentException("count = " + count);
}
- StandardGlyphVector sgv = (StandardGlyphVector)gv;
- if(!glyphs.equals(sgv.glyphs)){
- return false;
+ if (start < 0) {
+ throw new IndexOutOfBoundsException("start = " + start);
+ }
+ if (start > glyphs.length() - count) { // watch out for overflow if index + count overlarge
+ throw new IndexOutOfBoundsException("start + count = " + (start + count));
}
- if(equals(font, sgv.font)){
- return false;
+
+ if (result == null) {
+ result = new int[count];
}
- if(equals(frc, sgv.frc)){
- return false;
+ for (int i = 0; i < count; ++i) {
+ result[i] = glyphs.charAt(i + start);
}
- return true;
- }
-
- /**
- * Compare 2 objects via equals where both can be null
- */
- private static boolean equals(Object obj1, Object obj2){
- if(obj1 != null){
- if(!obj1.equals(obj2)){
- return false;
- }
- }else{
- if(obj2 != null){
- return false;
- }
- }
- return true;
+ return result;
}
-
+ // !!! not cached, assume TextLayout will cache if necessary
+ // !!! reexamine for per-glyph-transforms
+ // !!! revisit for text-on-a-path, vertical
@Override
- public Font getFont(){
- return font;
- }
+ public Rectangle2D getLogicalBounds() {
+ initPositions();
+ LineMetrics lm = font.getLineMetrics("", frc);
- @Override
- public FontRenderContext getFontRenderContext(){
- return frc;
- }
+ float minX, minY, maxX, maxY;
+ // horiz only for now...
+ minX = 0;
+ minY = -lm.getAscent();
+ maxX = 0;
+ maxY = lm.getDescent() + lm.getLeading();
+ if (glyphs.length() > 0) {
+ maxX = positions[positions.length - 2];
+ }
+ return new Rectangle2D.Float(minX, minY, maxX - minX, maxY - minY);
+ }
+ // !!! not cached, assume TextLayout will cache if necessary
@Override
- public int getGlyphCode(int glyphIndex){
- return glyphs.charAt(glyphIndex);
+ public Rectangle2D getVisualBounds() {
+ return getOutline().getBounds2D();
}
-
@Override
- public int[] getGlyphCodes(int beginGlyphIndex, int numEntries, int[] codeReturn){
- if(codeReturn == null || codeReturn.length < numEntries){
- codeReturn = new int[numEntries];
- }
- for(int i=0; i<numEntries; i++){
- codeReturn[i] = glyphs.charAt(i + beginGlyphIndex);
- }
- return codeReturn;
+ public Shape getOutline() {
+ return getOutline( 0, 0 );
}
+ @Override
+ public Shape getOutline(float x, float y) {
+ return IkvmToolkit.DefaultToolkit.get().outline( font, frc, glyphs, x, y );
+ }
@Override
- public GlyphJustificationInfo getGlyphJustificationInfo(int glyphIndex){
+ public Shape getGlyphOutline(int ix) {
throw new NotYetImplementedError();
}
-
@Override
- public GlyphMetrics getGlyphMetrics( int glyphIndex ) {
- if( (glyphIndex < 0) || (glyphIndex >= glyphs.length()) ) {
- throw new IndexOutOfBoundsException( "ix = " + glyphIndex );
- }
- Rectangle2D bounds = getGlyphVisualBounds( glyphIndex ).getBounds2D();
- Point2D pos = getGlyphPosition( glyphIndex );
- bounds.setRect( bounds.getX() - pos.getX(), bounds.getY()- pos.getY(), bounds.getWidth(), bounds.getHeight() );
-
- Point2D.Float advance = strike.getGlyphMetrics( glyphs.charAt( glyphIndex ) );
+ public Point2D getGlyphPosition(int ix) {
+ initPositions();
- return new GlyphMetrics( true, advance.x, advance.y, bounds, (byte)0 );
+ ix *= 2;
+ return new Point2D.Float(positions[ix], positions[ix + 1]);
}
@Override
- public Shape getGlyphOutline(int glyphIndex){
- throw new NotYetImplementedError();
- }
+ public void setGlyphPosition(int ix, Point2D pos) {
+ initPositions();
+ int ix2 = ix << 1;
+ positions[ix2] = (float)pos.getX();
+ positions[ix2 + 1] = (float)pos.getY();
+ }
@Override
- public Point2D getGlyphPosition( int glyphIndex ) {
- initPositions();
- return new Point2D.Float( positions[glyphIndex * 2], positions[glyphIndex * 2 + 1] );
+ public AffineTransform getGlyphTransform(int ix) {
+ throw new NotYetImplementedError();
}
@Override
- public float[] getGlyphPositions( int beginGlyphIndex, int numEntries, float[] positionReturn ) {
- if( numEntries < 0 ) {
- throw new IllegalArgumentException( "count = " + numEntries );
+ public float[] getGlyphPositions(int start, int count, float[] result) {
+ if (count < 0) {
+ throw new IllegalArgumentException("count = " + count);
}
- if( beginGlyphIndex < 0 ) {
- throw new IndexOutOfBoundsException( "start = " + beginGlyphIndex );
+ if (start < 0) {
+ throw new IndexOutOfBoundsException("start = " + start);
}
- if( beginGlyphIndex > this.glyphs.length() + 1 - numEntries ) {
- throw new IndexOutOfBoundsException( "start + count = " + (beginGlyphIndex + numEntries) );
+ if (start > this.glyphs.length() + 1 - count) {
+ throw new IndexOutOfBoundsException("start + count = " + (start + count));
}
- int count = numEntries * 2;
- if( positionReturn == null ) {
- positionReturn = new float[count];
+ int count2 = count * 2;
+ if( result == null ) {
+ result = new float[count2];
}
initPositions();
- System.arraycopy( positions, beginGlyphIndex * 2, positionReturn, 0, count );
- return positionReturn;
+ System.arraycopy( positions, start * 2, result, 0, count2 );
+ return result;
}
@Override
- public AffineTransform getGlyphTransform(int glyphIndex){
- throw new NotYetImplementedError();
- }
-
+ public Shape getGlyphLogicalBounds(int ix) {
+ if (ix < 0 || ix >= glyphs.length()) {
+ throw new IndexOutOfBoundsException("ix = " + ix);
+ }
- @Override
- public Shape getGlyphLogicalBounds( int glyphIndex ) {
- //return getMetrics().getStringBounds( glyphs.substring( glyphIndex, glyphIndex + 1 ), getGraphics() );
initPositions();
StrikeMetrics metrics = strike.getFontMetrics();
- float x = positions[glyphIndex * 2];
- return new Rectangle2D.Float( x, -metrics.getAscent(), positions[(glyphIndex + 1) * 2] - x, metrics.getAscent()
+ float x = positions[ix * 2];
+ return new Rectangle2D.Float( x, -metrics.getAscent(), positions[(ix + 1) * 2] - x, metrics.getAscent()
+ metrics.getDescent() + metrics.getLeading() );
}
-
@Override
- public Shape getGlyphVisualBounds( int glyphIndex ) {
+ public Shape getGlyphVisualBounds(int ix) {
+ if (ix < 0 || ix >= glyphs.length()) {
+ throw new IndexOutOfBoundsException("ix = " + ix);
+ }
+
initPositions();
- return IkvmToolkit.DefaultToolkit.get().outline( font, frc, glyphs.substring( glyphIndex, glyphIndex + 1 ), positions[glyphIndex * 2], 0 );
+ return IkvmToolkit.DefaultToolkit.get().outline( font, frc, glyphs.substring( ix, ix + 1 ), positions[ix * 2], 0 );
}
@Override
- public Rectangle2D getLogicalBounds(){
- initPositions();
+ public GlyphMetrics getGlyphMetrics(int ix) {
+ if (ix < 0 || ix >= glyphs.length()) {
+ throw new IndexOutOfBoundsException("ix = " + ix);
+ }
- LineMetrics lm = font.getLineMetrics("", frc);
+ Rectangle2D vb = getGlyphVisualBounds(ix).getBounds2D();
+ Point2D pt = getGlyphPosition(ix);
+ vb.setRect(vb.getMinX() - pt.getX(),
+ vb.getMinY() - pt.getY(),
+ vb.getWidth(),
+ vb.getHeight());
+ Point2D.Float adv =
+ strike.getGlyphMetrics( glyphs.charAt( ix ) );
+ GlyphMetrics gm = new GlyphMetrics(true, adv.x, adv.y,
+ vb,
+ (byte)0);
+ return gm;
+ }
- float minX, minY, maxX, maxY;
- // horiz only for now...
- minX = 0;
- minY = -lm.getAscent();
- maxX = 0;
- maxY = lm.getDescent() + lm.getLeading();
- if (glyphs.length() > 0) {
- maxX = positions[positions.length - 2];
+ @Override
+ public GlyphJustificationInfo getGlyphJustificationInfo(int ix) {
+ if (ix < 0 || ix >= glyphs.length()) {
+ throw new IndexOutOfBoundsException("ix = " + ix);
}
- return new Rectangle2D.Float(minX, minY, maxX - minX, maxY - minY);
- }
+ // currently we don't have enough information to do this right. should
+ // get info from the font and use real OT/GX justification. Right now
+ // sun/font/ExtendedTextSourceLabel assigns one of three infos
+ // based on whether the char is kanji, space, or other.
+ return null;
+ }
@Override
- public Rectangle2D getVisualBounds(){
- return getOutline().getBounds2D();
+ public boolean equals(GlyphVector rhs) {
+ if(!(rhs instanceof StandardGlyphVector)){
+ return false;
+ }
+ StandardGlyphVector sgv = (StandardGlyphVector)rhs;
+ if(!glyphs.equals(sgv.glyphs)){
+ return false;
+ }
+ if(equals(font, sgv.font)){
+ return false;
+ }
+ if(equals(frc, sgv.frc)){
+ return false;
+ }
+ return true;
}
+ /**
+ * Compare 2 objects via equals where both can be null
+ */
+ private static boolean equals(Object obj1, Object obj2){
+ if(obj1 != null){
+ if(!obj1.equals(obj2)){
+ return false;
+ }
+ }else{
+ if(obj2 != null){
+ return false;
+ }
+ }
+ return true;
+ }
+ /**
+ * As a concrete subclass of GlyphVector, this must implement clone.
+ */
@Override
- public int getNumGlyphs(){
- return glyphs.length();
- }
+ public Object clone() {
+ // positions, gti are mutable so we have to clone them
+ // font2d can be shared
+ // fsref is a cache and can be shared
+ try {
+ StandardGlyphVector result = (StandardGlyphVector)super.clone();
+ if (positions != null) {
+ result.positions = (float[])positions.clone();
+ }
- @Override
- public Shape getOutline(){
- return getOutline( 0, 0 );
+ return result;
+ }
+ catch (CloneNotSupportedException e) {
+ }
+
+ return this;
}
+ //////////////////////
+ // StandardGlyphVector new public methods
+ /////////////////////
- @Override
- public Shape getOutline(float x, float y){
- return IkvmToolkit.DefaultToolkit.get().outline( font, frc, glyphs, x, y );
- }
+ /**
+ * Set all the glyph positions, including the 'after last glyph' position.
+ * The srcPositions array must be of length (numGlyphs + 1) * 2.
+ */
+ public void setGlyphPositions(float[] srcPositions) {
+ int requiredLength = glyphs.length() * 2 + 2;
+ if (srcPositions.length != requiredLength) {
+ throw new IllegalArgumentException("srcPositions.length != " + requiredLength);
+ }
+ positions = (float[])srcPositions.clone();
- @Override
- public void performDefaultLayout(){
- throw new NotYetImplementedError();
}
-
- @Override
- public void setGlyphPosition(int glyphIndex, Point2D newPos){
- throw new NotYetImplementedError();
+ /**
+ * This is a convenience overload that gets all the glyph positions, which
+ * is what you usually want to do if you're getting more than one.
+ * !!! should I bother taking result parameter?
+ */
+ public float[] getGlyphPositions(float[] result) {
+ initPositions();
+ return positions;
}
+ /**
+ * For each glyph return posx, posy, advx, advy, visx, visy, visw, vish.
+ */
+ public float[] getGlyphInfo() {
+ initPositions();
+ float[] result = new float[glyphs.length() * 8];
+ for (int i = 0, n = 0; i < glyphs.length(); ++i, n += 8) {
+ float x = positions[i*2];
+ float y = positions[i*2+1];
+ result[n] = x;
+ result[n+1] = y;
+
+ int glyphID = glyphs.charAt(i);
+ Point2D.Float adv = strike.getGlyphMetrics(glyphID);
+ result[n+2] = adv.x;
+ result[n+3] = adv.y;
+
+ Rectangle2D vb = getGlyphVisualBounds(i).getBounds2D();
+ result[n+4] = (float)(vb.getMinX());
+ result[n+5] = (float)(vb.getMinY());
+ result[n+6] = (float)(vb.getWidth());
+ result[n+7] = (float)(vb.getHeight());
+ }
+ return result;
+ }
@Override
public void setGlyphTransform(int glyphIndex, AffineTransform newTX){
@@ -383,14 +428,6 @@ public class StandardGlyphVector extends GlyphVector{
return sb.toString();
}
- private float getTracking(Font font) {
- if (font.hasLayoutAttributes()) {
- AttributeValues values = ((AttributeMap)font.getAttributes()).getValues();
- return values.getTracking();
- }
- return 0;
- }
-
/**
* Ensure that the positions array exists and holds position data.
* If the array is null, this allocates it and sets default positions.