Source for gnu.java.awt.peer.gtk.GdkGlyphVector

   1: /* GdkGlyphVector.java -- Glyph vector object
   2:    Copyright (C) 2003, 2004, 2005  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package gnu.java.awt.peer.gtk;
  40: 
  41: import java.awt.Font;
  42: import java.awt.Rectangle;
  43: import java.awt.Shape;
  44: import java.awt.font.FontRenderContext;
  45: import java.awt.font.GlyphJustificationInfo;
  46: import java.awt.font.GlyphMetrics;
  47: import java.awt.font.GlyphVector;
  48: import java.awt.geom.AffineTransform;
  49: import java.awt.geom.Point2D;
  50: import java.awt.geom.Rectangle2D;
  51: 
  52: public class GdkGlyphVector extends GlyphVector
  53: {
  54: 
  55:   /* We use a simple representation for glyph vectors here. Glyph i
  56:    * consumes 8 doubles:
  57:    *
  58:    *      logical x: extents[ 10*i     ]
  59:    *      logical y: extents[ 10*i + 1 ]
  60:    *  logical width: extents[ 10*i + 2 ]
  61:    * logical height: extents[ 10*i + 3 ]
  62:    *
  63:    *       visual x: extents[ 10*i + 4 ]
  64:    *       visual y: extents[ 10*i + 5 ]
  65:    *   visual width: extents[ 10*i + 6 ]
  66:    *  visual height: extents[ 10*i + 7 ]
  67:    *
  68:    *   origin pos x: extents[ 10*i + 8 ]
  69:    *   origin pos y: extents[ 10*i + 9 ]
  70:    * 
  71:    * as well as one int, code[i], representing the glyph code in the font.
  72:    */
  73: 
  74:   double [] extents;
  75:   int [] codes;
  76: 
  77:   Font font;
  78:   FontRenderContext fontRenderContext;
  79: 
  80:   Rectangle2D allLogical;
  81:   Rectangle2D allVisual;
  82: 
  83:   public GdkGlyphVector(double[] extents, int[] codes, Font font, FontRenderContext frc)
  84:   {
  85:     this.extents = extents;
  86:     this.codes = codes;
  87:     this.font = font;
  88:     this.fontRenderContext = frc;
  89: 
  90:     allLogical = new Rectangle2D.Double();
  91:     allVisual = new Rectangle2D.Double();
  92:     
  93:     for (int i = 0; i < codes.length; ++i)
  94:       {
  95:         allLogical.add (new Rectangle2D.Double(extents[10*i    ] + extents[10*i + 8],
  96:                                                extents[10*i + 1] + extents[10*i + 9],
  97:                                                extents[10*i + 2],
  98:                                                extents[10*i + 3]));
  99: 
 100:         allVisual.add (new Rectangle2D.Double(extents[10*i + 4] + extents[10*i + 8],
 101:                                               extents[10*i + 5] + extents[10*i + 9],
 102:                                               extents[10*i + 6],
 103:                                               extents[10*i + 7]));
 104:       }
 105:   }
 106: 
 107:   /* 
 108:      geometric notes:
 109: 
 110:      the FRC contains a mapping from points -> pixels.
 111: 
 112:      typographics points are typically 1/72 of an inch.
 113: 
 114:      pixel displays are often around 72 dpi.
 115: 
 116:      so the FRC can get away with using an identity transform on a screen,
 117:      often. behavior is documented by sun to fall back to an identity
 118:      transform if the internal transformation is null.
 119: 
 120:      coordinates coming up from pango are expressed as floats -- in device
 121:      space, so basically pixels-with-fractional-bits -- derived from their
 122:      storage format in pango (1024ths of pixels). 
 123: 
 124:      it is not clear from the javadocs whether the results of methods like
 125:      getGlyphPositions ought to return coordinates in device space, or
 126:      "point" space, or what. for now I'm returning them in device space.
 127:      
 128:    */
 129: 
 130:   public double[] getExtents() 
 131:   {
 132:     return extents;
 133:   }
 134: 
 135:   public int[] getCodes()
 136:   {
 137:     return codes;
 138:   }
 139: 
 140:   public Font getFont () 
 141:   { 
 142:     return font; 
 143:   }
 144: 
 145:   public FontRenderContext getFontRenderContext () 
 146:   { 
 147:     return fontRenderContext; 
 148:   }
 149: 
 150:   public int getGlyphCharIndex (int glyphIndex) 
 151:   { 
 152:     // FIXME: currently pango does not provide glyph-by-glyph
 153:     // reverse mapping information, so we assume a broken 1:1
 154:     // glyph model here. This is plainly wrong.
 155:     return glyphIndex;
 156:   }
 157: 
 158:   public int[] getGlyphCharIndices (int beginGlyphIndex, 
 159:                                     int numEntries,
 160:                                     int[] codeReturn)
 161:   {
 162:     int ix[] = codeReturn;
 163:     if (ix == null)
 164:       ix = new int[numEntries];
 165: 
 166:     for (int i = 0; i < numEntries; i++)
 167:       ix[i] = getGlyphCharIndex (beginGlyphIndex + i);
 168:     return ix;
 169:   }
 170: 
 171:   public int getGlyphCode (int glyphIndex) 
 172:   { 
 173:     return codes[glyphIndex];
 174:   }
 175: 
 176:   public int[] getGlyphCodes (int beginGlyphIndex, int numEntries,
 177:                               int[] codeReturn)
 178:   {
 179:     if (codeReturn == null)
 180:       codeReturn = new int[numEntries];
 181: 
 182:     System.arraycopy(codes, beginGlyphIndex, codeReturn, 0, numEntries);
 183:     return codeReturn;
 184:   }
 185: 
 186:   public Shape getGlyphLogicalBounds (int i)
 187:   {
 188:     return new Rectangle2D.Double (extents[8*i], extents[8*i + 1],
 189:                                    extents[8*i + 2], extents[8*i + 3]);
 190:   }
 191:     
 192:   public GlyphMetrics getGlyphMetrics (int i)
 193:   {
 194:     // FIXME: pango does not yield vertical layout information at the
 195:     // moment.
 196: 
 197:     boolean is_horizontal = true;
 198:     double advanceX = extents[8*i + 2]; // "logical width" == advanceX 
 199:     double advanceY = 0; 
 200:    
 201:     return new GlyphMetrics (is_horizontal, 
 202:                              (float) advanceX, (float) advanceY, 
 203:                              (Rectangle2D) getGlyphVisualBounds(i), 
 204:                              GlyphMetrics.STANDARD);
 205:   }
 206: 
 207:   public Shape getGlyphOutline (int glyphIndex)
 208:   {
 209:     throw new UnsupportedOperationException ();      
 210:   }
 211: 
 212:   public Shape getGlyphOutline (int glyphIndex, float x, float y)
 213:   {
 214:     throw new UnsupportedOperationException ();
 215:   }
 216: 
 217:   public Rectangle getGlyphPixelBounds (int i, 
 218:                                         FontRenderContext renderFRC,
 219:                                         float x, float y)
 220:   {
 221:     return new Rectangle((int) x, (int) y,
 222:                          (int) extents[8*i + 6], (int) extents[8*i + 7]);
 223:   }
 224:     
 225:   public Point2D getGlyphPosition (int i)
 226:   {
 227:     return new Point2D.Double (extents[10*i + 8], 
 228:                                extents[10*i + 9]);
 229:   }
 230: 
 231:   public float[] getGlyphPositions (int beginGlyphIndex,
 232:                                     int numEntries,
 233:                                     float[] positionReturn)
 234:   {
 235:     float fx[] = positionReturn;
 236:     if (fx == null)
 237:       fx = new float[numEntries * 2];
 238: 
 239:     for (int i = 0; i < numEntries; ++i)
 240:       {
 241:         fx[2*i    ] = (float) extents[10*i + 8];
 242:         fx[2*i + 1] = (float) extents[10*i + 9];
 243:       }
 244:     return fx;
 245:   }
 246: 
 247:   public AffineTransform getGlyphTransform (int glyphIndex)
 248:   {
 249:     // Glyphs don't have independent transforms in these simple glyph
 250:     // vectors; docs specify null is an ok return here.
 251:     return null;  
 252:   }
 253:     
 254:   public Shape getGlyphVisualBounds (int i)
 255:   {
 256:     return new Rectangle2D.Double(extents[8*i + 4], extents[8*i + 5],
 257:                                   extents[8*i + 6], extents[8*i + 7]);
 258:   }
 259:     
 260:   public int getLayoutFlags ()
 261:   {
 262:     return 0;
 263:   }
 264: 
 265:   public Rectangle2D getLogicalBounds ()
 266:   {
 267:     return allLogical;
 268:   }
 269: 
 270:   public int getNumGlyphs ()
 271:   {
 272:     return codes.length;
 273:   }
 274: 
 275:   public Shape getOutline ()
 276:   {
 277:     throw new UnsupportedOperationException ();      
 278:   }
 279: 
 280:   public Rectangle getPixelBounds (FontRenderContext renderFRC,
 281:                                    float x, float y)
 282:   {
 283:     return new Rectangle((int)x, 
 284:                          (int)y, 
 285:                          (int) allVisual.getWidth(),
 286:                          (int) allVisual.getHeight());
 287:   }
 288:     
 289:   public Rectangle2D getVisualBounds ()
 290:   {
 291:     return allVisual;
 292:   }
 293: 
 294:   public void performDefaultLayout ()
 295:   {
 296:   }
 297:     
 298:   public void setGlyphPosition (int i, Point2D newPos)
 299:   {
 300:     extents[8*i    ] = newPos.getX();
 301:     extents[8*i + 1] = newPos.getY();
 302: 
 303:     extents[8*i + 4] = newPos.getX();
 304:     extents[8*i + 5] = newPos.getY();
 305:   }
 306: 
 307:   public void setGlyphTransform (int glyphIndex,
 308:                                  AffineTransform newTX)
 309:   {
 310:     // not yet.. maybe not ever?
 311:     throw new UnsupportedOperationException ();      
 312:   }
 313: 
 314:   public boolean equals(GlyphVector gv)
 315:   {
 316:     if (gv == null)
 317:       return false;
 318: 
 319:     if (! (gv instanceof GdkGlyphVector))
 320:       return false;
 321: 
 322:     GdkGlyphVector ggv = (GdkGlyphVector) gv;
 323: 
 324:     if ((ggv.codes.length != this.codes.length)
 325:         || (ggv.extents.length != this.extents.length))
 326:       return false;
 327:     
 328:     if ((ggv.font == null && this.font != null)
 329:         || (ggv.font != null && this.font == null)
 330:         || (!ggv.font.equals(this.font)))
 331:       return false;
 332: 
 333:     if ((ggv.fontRenderContext == null && this.fontRenderContext != null)
 334:         || (ggv.fontRenderContext != null && this.fontRenderContext == null)
 335:         || (!ggv.fontRenderContext.equals(this.fontRenderContext)))
 336:       return false;
 337: 
 338:     for (int i = 0; i < ggv.codes.length; ++i)
 339:       if (ggv.codes[i] != this.codes[i])
 340:         return false;
 341: 
 342:     for (int i = 0; i < ggv.extents.length; ++i)
 343:       if (ggv.extents[i] != this.extents[i])
 344:         return false;
 345: 
 346:     return true;
 347:   }
 348: 
 349:   public GlyphJustificationInfo getGlyphJustificationInfo(int idx)
 350:   {
 351:     throw new UnsupportedOperationException ();      
 352:   }
 353: 
 354:   public Shape getOutline(float x, float y)    
 355:   {
 356:     throw new UnsupportedOperationException ();      
 357:   }
 358: 
 359: }