OSDN Git Service

2006-06-09 Andreas Krebbel <krebbel1@de.ibm.com>
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / java / awt / peer / gtk / GdkGlyphVector.java
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 }