Imported GNU Classpath 0.90
Imported GNU Classpath 0.90 * scripts/makemake.tcl: LocaleData.java moved to gnu/java/locale. * sources.am: Regenerated. * gcj/javaprims.h: Regenerated. * Makefile.in: Regenerated. * gcj/Makefile.in: Regenerated. * include/Makefile.in: Regenerated. * testsuite/Makefile.in: Regenerated. * gnu/java/lang/VMInstrumentationImpl.java: New override. * gnu/java/net/local/LocalSocketImpl.java: Likewise. * gnu/classpath/jdwp/VMMethod.java: Likewise. * gnu/classpath/jdwp/VMVirtualMachine.java: Update to latest interface. * java/lang/Thread.java: Add UncaughtExceptionHandler. * java/lang/reflect/Method.java: Implements GenericDeclaration and isSynthetic(), * java/lang/reflect/Field.java: Likewise. * java/lang/reflect/Constructor.java * java/lang/Class.java: Implements Type, GenericDeclaration, getSimpleName() and getEnclosing*() methods. * java/lang/Class.h: Add new public methods. * java/lang/Math.java: Add signum(), ulp() and log10(). * java/lang/natMath.cc (log10): New function. * java/security/VMSecureRandom.java: New override. * java/util/logging/Logger.java: Updated to latest classpath version. * java/util/logging/LogManager.java: New override. From-SVN: r113887
This commit is contained in:
parent
eaec4980e1
commit
4f9533c772
1640 changed files with 126485 additions and 104808 deletions
313
libjava/classpath/gnu/java/awt/font/FontDelegate.java
Normal file
313
libjava/classpath/gnu/java/awt/font/FontDelegate.java
Normal file
|
@ -0,0 +1,313 @@
|
|||
/* FontDelegate.java -- Interface implemented by all font delegates.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.font;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.text.CharacterIterator;
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
/**
|
||||
* The interface that all font delegate objects implement,
|
||||
* irrespective of where they get their information from.
|
||||
*
|
||||
* <p><b>Thread Safety:</b> All classes that implement the
|
||||
* <code>FontDelegate</code> interface must allow calling these
|
||||
* methods from multiple concurrent threads. The delegates are
|
||||
* responsible for performing the necessary synchronization.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
public interface FontDelegate
|
||||
{
|
||||
/**
|
||||
* Returns the full name of this font face in the specified
|
||||
* locale, for example <i>“Univers Light”</i>.
|
||||
*
|
||||
* @param locale the locale for which to localize the name.
|
||||
*
|
||||
* @return the face name.
|
||||
*/
|
||||
public String getFullName(Locale locale);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the family to which this font face belongs,
|
||||
* for example <i>“Univers”</i>.
|
||||
*
|
||||
* @param locale the locale for which to localize the name.
|
||||
*
|
||||
* @return the family name.
|
||||
*/
|
||||
public String getFamilyName(Locale locale);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of this font face inside the family, for example
|
||||
* <i>“Light”</i>.
|
||||
*
|
||||
* @param locale the locale for which to localize the name.
|
||||
*
|
||||
* @return the name of the face inside its family.
|
||||
*/
|
||||
public String getSubFamilyName(Locale locale);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the PostScript name of this font face, for example
|
||||
* <i>“Helvetica-Bold”</i>.
|
||||
*
|
||||
* @return the PostScript name, or <code>null</code> if the font
|
||||
* does not provide a PostScript name.
|
||||
*/
|
||||
public String getPostScriptName();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of glyphs in this font face.
|
||||
*/
|
||||
public int getNumGlyphs();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the index of the glyph which gets displayed if the font
|
||||
* cannot map a Unicode code point to a glyph. Many fonts show this
|
||||
* glyph as an empty box.
|
||||
*/
|
||||
public int getMissingGlyphCode();
|
||||
|
||||
|
||||
/**
|
||||
* Creates a GlyphVector by mapping each character in a
|
||||
* CharacterIterator to the corresponding glyph.
|
||||
*
|
||||
* <p>The mapping takes only the font’s <code>cmap</code>
|
||||
* tables into consideration. No other operations (such as glyph
|
||||
* re-ordering, composition, or ligature substitution) are
|
||||
* performed. This means that the resulting GlyphVector will not be
|
||||
* correct for text in languages that have complex
|
||||
* character-to-glyph mappings, such as Arabic, Hebrew, Hindi, or
|
||||
* Thai.
|
||||
*
|
||||
* @param font the font object that the created GlyphVector
|
||||
* will return when it gets asked for its font. This argument is
|
||||
* needed because the public API works with java.awt.Font,
|
||||
* not with some private delegate like OpenTypeFont.
|
||||
*
|
||||
* @param frc the font rendering parameters that are used for
|
||||
* measuring glyphs. The exact placement of text slightly depends on
|
||||
* device-specific characteristics, for instance the device
|
||||
* resolution or anti-aliasing. For this reason, any measurements
|
||||
* will only be accurate if the passed
|
||||
* <code>FontRenderContext</code> correctly reflects the relevant
|
||||
* parameters. Hence, <code>frc</code> should be obtained from the
|
||||
* same <code>Graphics2D</code> that will be used for drawing, and
|
||||
* any rendering hints should be set to the desired values before
|
||||
* obtaining <code>frc</code>.
|
||||
*
|
||||
* @param ci a CharacterIterator for iterating over the
|
||||
* characters to be displayed.
|
||||
*/
|
||||
public GlyphVector createGlyphVector(Font font,
|
||||
FontRenderContext frc,
|
||||
CharacterIterator ci);
|
||||
|
||||
|
||||
/**
|
||||
* Determines the advance width and height for a glyph.
|
||||
*
|
||||
* @param glyphIndex the glyph whose advance width is to be
|
||||
* determined.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialias <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @param advance a point whose <code>x</code> and <code>y</code>
|
||||
* fields will hold the advance in each direction. It is well
|
||||
* possible that both values are non-zero, for example for rotated
|
||||
* text or for Urdu fonts.
|
||||
*/
|
||||
public void getAdvance(int glyphIndex,
|
||||
float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal,
|
||||
Point2D advance);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the shape of a glyph.
|
||||
*
|
||||
* @param glyphIndex the glyph whose advance width is to be
|
||||
* determined.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialias <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts, this
|
||||
* parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional
|
||||
* metrics, <code>false</code> for rounding the result to a pixel
|
||||
* boundary.
|
||||
*
|
||||
* @return the scaled and grid-fitted outline of the specified
|
||||
* glyph, or <code>null</code> for bitmap fonts.
|
||||
*/
|
||||
public GeneralPath getGlyphOutline(int glyphIndex,
|
||||
float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics);
|
||||
|
||||
|
||||
/**
|
||||
* Returns a name for the specified glyph. This is useful for
|
||||
* generating PostScript or PDF files that embed some glyphs of a
|
||||
* font.
|
||||
*
|
||||
* <p><b>Names are not unique:</b> Under some rare circumstances,
|
||||
* the same name can be returned for different glyphs. It is
|
||||
* therefore recommended that printer drivers check whether the same
|
||||
* name has already been returned for antoher glyph, and make the
|
||||
* name unique by adding the string ".alt" followed by the glyph
|
||||
* index.</p>
|
||||
*
|
||||
* <p>This situation would occur for an OpenType or TrueType font
|
||||
* that has a <code>post</code> table of format 3 and provides a
|
||||
* mapping from glyph IDs to Unicode sequences through a
|
||||
* <code>Zapf</code> table. If the same sequence of Unicode
|
||||
* codepoints leads to different glyphs (depending on contextual
|
||||
* position, for example, or on typographic sophistication level),
|
||||
* the same name would get synthesized for those glyphs.
|
||||
*
|
||||
* @param glyphIndex the glyph whose name the caller wants to
|
||||
* retrieve.
|
||||
*/
|
||||
public String getGlyphName(int glyphIndex);
|
||||
|
||||
|
||||
/**
|
||||
* Determines the distance between the base line and the highest
|
||||
* ascender.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialiased <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the ascent, which usually is a positive number.
|
||||
*/
|
||||
public float getAscent(float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialiased,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal);
|
||||
|
||||
|
||||
/**
|
||||
* Determines the distance between the base line and the lowest
|
||||
* descender.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialiased <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the descent, which usually is a nagative number.
|
||||
*/
|
||||
public float getDescent(float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialiased,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal);
|
||||
}
|
90
libjava/classpath/gnu/java/awt/font/FontFactory.java
Normal file
90
libjava/classpath/gnu/java/awt/font/FontFactory.java
Normal file
|
@ -0,0 +1,90 @@
|
|||
/* FontFactory.java -- Factory for font delegates.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.font;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import java.awt.FontFormatException;
|
||||
import gnu.java.awt.font.opentype.OpenTypeFontFactory;
|
||||
|
||||
|
||||
/**
|
||||
* A factory for creating font delegate objects.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
public final class FontFactory
|
||||
{
|
||||
/**
|
||||
* The constructor is private so nobody can construct an instance
|
||||
*/
|
||||
private FontFactory()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates FontDelegate objects for the fonts in the specified buffer.
|
||||
* The following font formats are currently recognized:
|
||||
* recognized font formats are:
|
||||
*
|
||||
* <p><ul>
|
||||
* <li>OpenType (*.otf);</li>
|
||||
* <li>TrueType (*.ttf);</li>
|
||||
* <li>TrueType Collections (*.ttc);</li>
|
||||
* <li>Apple MacOS X data-fork font (*.dfont).</li></ul>
|
||||
*
|
||||
* <p>Some formats may contain more than a single font, for example
|
||||
* *.ttc and *.dfont files. This is the reason why this function
|
||||
* returns an array.
|
||||
*
|
||||
* <p>The implementation reads data from the buffer only when
|
||||
* needed. Therefore, it greatly increases efficiency if
|
||||
* <code>buf</code> has been obtained through mapping a file into
|
||||
* the virtual address space.
|
||||
*
|
||||
* @throws FontFormatException if the font data is not in one of the
|
||||
* known formats.
|
||||
*/
|
||||
public static FontDelegate[] createFonts(ByteBuffer buf)
|
||||
throws FontFormatException
|
||||
{
|
||||
return OpenTypeFontFactory.createFonts(buf);
|
||||
}
|
||||
}
|
596
libjava/classpath/gnu/java/awt/font/GNUGlyphVector.java
Normal file
596
libjava/classpath/gnu/java/awt/font/GNUGlyphVector.java
Normal file
|
@ -0,0 +1,596 @@
|
|||
/* GNUGlyphVector.java -- The GNU implementation of GlyphVector.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.java.awt.font;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphMetrics;
|
||||
import java.awt.font.GlyphJustificationInfo;
|
||||
import java.awt.font.GlyphVector;
|
||||
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
|
||||
/**
|
||||
* The GNU implementation of the abstract GlyphVector class, which
|
||||
* uses the services provided by a FontDelegate for its functionality.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
public class GNUGlyphVector
|
||||
extends GlyphVector
|
||||
{
|
||||
private FontDelegate fontDelegate;
|
||||
private Font font;
|
||||
private FontRenderContext renderContext;
|
||||
private int[] glyphs;
|
||||
private float fontSize;
|
||||
private AffineTransform transform;
|
||||
private boolean valid;
|
||||
|
||||
|
||||
/**
|
||||
* The position of each glyph. The horizontal position of the
|
||||
* <code>i</code>-th glyph is at <code>pos[i * 2]</code>, its
|
||||
* vertical position at <code>pos[i * 2 + 1]</code>. The total
|
||||
* advance width of the entire vector is stored at
|
||||
* <code>pos[numGlyphs]</code>, the total advance height at
|
||||
* <code>pos[numGlyphs + 1]</code>.
|
||||
*/
|
||||
private float[] pos;
|
||||
|
||||
|
||||
private AffineTransform[] transforms;
|
||||
private int layoutFlags;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new GNUGlyphVector.
|
||||
*
|
||||
* @param fontDelegate the FontDelegate that creates this vector.
|
||||
*
|
||||
* @param font the Font that this GlyphVector will return for {@link
|
||||
* #getFont()}. That object is also used to determine the point
|
||||
* size, which affects the affine transformation used by the font
|
||||
* scaler.
|
||||
*
|
||||
* @param renderContext an object with parameters for font
|
||||
* rendering, such as whether anti-aliasing is enabled.
|
||||
*
|
||||
* @param glyphs the glyphs in this vector.
|
||||
*/
|
||||
public GNUGlyphVector(FontDelegate fontDelegate,
|
||||
Font font,
|
||||
FontRenderContext renderContext,
|
||||
int[] glyphs)
|
||||
{
|
||||
this.fontDelegate = fontDelegate;
|
||||
this.font = font;
|
||||
this.renderContext = renderContext;
|
||||
this.glyphs = glyphs;
|
||||
|
||||
fontSize = font.getSize2D();
|
||||
transform = font.getTransform(); // returns a modifiable copy
|
||||
transform.concatenate(renderContext.getTransform());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the font of the glyphs in this GlyphVector.
|
||||
*/
|
||||
public Font getFont()
|
||||
{
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the FontRenderContext that is used to calculate the
|
||||
* extent and position of the glyphs.
|
||||
*/
|
||||
public FontRenderContext getFontRenderContext()
|
||||
{
|
||||
return renderContext;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves each glyph in the vector to its default position.
|
||||
*/
|
||||
public void performDefaultLayout()
|
||||
{
|
||||
float x, y, advanceWidth, advanceHeight;
|
||||
int i, p;
|
||||
AffineTransform tx;
|
||||
Point2D.Float advance = new Point2D.Float();
|
||||
|
||||
pos = new float[(glyphs.length + 1) * 2];
|
||||
x = y = 0.0f;
|
||||
p = 0;
|
||||
for (i = p = 0; i < glyphs.length; i++)
|
||||
{
|
||||
p += 2;
|
||||
|
||||
if ((transforms == null) || (tx = transforms[i]) == null)
|
||||
tx = this.transform;
|
||||
else
|
||||
{
|
||||
tx = new AffineTransform(tx);
|
||||
tx.concatenate(this.transform);
|
||||
}
|
||||
|
||||
fontDelegate.getAdvance(glyphs[i], fontSize, tx,
|
||||
renderContext.isAntiAliased(),
|
||||
renderContext.usesFractionalMetrics(),
|
||||
/* horizontal */ true,
|
||||
advance);
|
||||
pos[p] = x += advance.x;
|
||||
pos[p + 1] = y += advance.y;
|
||||
}
|
||||
valid = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the number of glyphs in this GlyphVector.
|
||||
*/
|
||||
public int getNumGlyphs()
|
||||
{
|
||||
return glyphs.length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the glyph number by index in this vector.
|
||||
* Glyph numbers are specific to each font, so two fonts
|
||||
* will likely assign different numbers to the same glyph.
|
||||
*
|
||||
* @param glyphIndex the index of the glyph whose glyph number is to
|
||||
* be retrieved.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if <code>glyphIndex</code>
|
||||
* is not in the range <code[0 .. getNumGlyphs() - 1]</code>.
|
||||
*/
|
||||
public int getGlyphCode(int glyphIndex)
|
||||
{
|
||||
/* The exception is thrown automatically if the index is out
|
||||
* of the valid bounds.
|
||||
*/
|
||||
return glyphs[glyphIndex];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a slice of this GlyphVector.
|
||||
*
|
||||
* @param firstGlyphIndex the index of the first glyph in the
|
||||
* returned slice.
|
||||
*
|
||||
* @param numEntries the size of the returned slice.
|
||||
*
|
||||
* @param outCodes a pre-allocated array for storing the slice,
|
||||
* or <code>null</code> to cause allocation of a new array.
|
||||
*
|
||||
* @return a slice of this GlyphVector. If <code>outCodes</code>
|
||||
* is <code>null</code>, the slice will be stored into a freshly
|
||||
* allocated array; otherwise, the result will be stored into
|
||||
* <code>outCodes</code>.
|
||||
*/
|
||||
public int[] getGlyphCodes(int firstGlyphIndex,
|
||||
int numEntries,
|
||||
int[] outCodes)
|
||||
{
|
||||
if (numEntries < 0)
|
||||
throw new IllegalArgumentException();
|
||||
if (outCodes == null)
|
||||
outCodes = new int[numEntries];
|
||||
System.arraycopy(glyphs, firstGlyphIndex, outCodes, 0, numEntries);
|
||||
return outCodes;
|
||||
}
|
||||
|
||||
|
||||
public Rectangle2D getLogicalBounds()
|
||||
{
|
||||
float ascent, descent;
|
||||
|
||||
validate();
|
||||
|
||||
return new Rectangle2D.Float(0, 0,
|
||||
pos[pos.length - 2],
|
||||
getAscent() - getDescent());
|
||||
}
|
||||
|
||||
|
||||
public Rectangle2D getVisualBounds()
|
||||
{
|
||||
validate();
|
||||
|
||||
// FIXME: Not yet implemented.
|
||||
return getLogicalBounds();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the shape of this GlyphVector.
|
||||
*/
|
||||
public Shape getOutline()
|
||||
{
|
||||
validate();
|
||||
return getOutline(0.0f, 0.0f);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the shape of this GlyphVector, translated to the
|
||||
* specified position.
|
||||
*
|
||||
* @param x the horizontal position for rendering this vector.
|
||||
* @param y the vertical position for rendering this vector.
|
||||
*/
|
||||
public Shape getOutline(float x, float y)
|
||||
{
|
||||
validate();
|
||||
|
||||
GeneralPath outline = new GeneralPath();
|
||||
int len = glyphs.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
GeneralPath p = new GeneralPath(getGlyphOutline(i));
|
||||
outline.append(p, false);
|
||||
}
|
||||
AffineTransform t = new AffineTransform();
|
||||
t.translate(x, y);
|
||||
outline.transform(t);
|
||||
return outline;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the shape of the specified glyph.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if <code>glyphIndex</code> is
|
||||
* not in the range <code[0 .. getNumGlyphs()]</code>.
|
||||
*/
|
||||
public Shape getGlyphOutline(int glyphIndex)
|
||||
{
|
||||
AffineTransform tx, glyphTx;
|
||||
GeneralPath path;
|
||||
|
||||
validate();
|
||||
|
||||
if ((transforms != null)
|
||||
&& ((glyphTx = transforms[glyphIndex]) != null))
|
||||
{
|
||||
tx = new AffineTransform(transform);
|
||||
tx.concatenate(glyphTx);
|
||||
}
|
||||
else
|
||||
tx = transform;
|
||||
|
||||
path = fontDelegate.getGlyphOutline(glyphs[glyphIndex], fontSize, tx,
|
||||
renderContext.isAntiAliased(),
|
||||
renderContext.usesFractionalMetrics());
|
||||
|
||||
tx = new AffineTransform();
|
||||
tx.translate(pos[glyphIndex * 2], pos[glyphIndex * 2 + 1]);
|
||||
path.transform(tx);
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the position of the specified glyph, or the
|
||||
* total advance width and height of the vector.
|
||||
*
|
||||
* @param glyphIndex the index of the glyph in question.
|
||||
* If this value equals <code>getNumGlyphs()</code>, the
|
||||
* position <i>after</i> the last glyph will be returned,
|
||||
* which is the total advance width and height of the vector.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if <code>glyphIndex</code> is
|
||||
* not in the range <code[0 .. getNumGlyphs()]</code>.
|
||||
*/
|
||||
public Point2D getGlyphPosition(int glyphIndex)
|
||||
{
|
||||
validate();
|
||||
return new Point2D.Float(pos[glyphIndex * 2],
|
||||
pos[glyphIndex * 2 + 1]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves the specified glyph to a new position, or changes the
|
||||
* advance width and height of the entire glyph vector.
|
||||
*
|
||||
* <p>Note that the position of an individual glyph may also
|
||||
* affected by its affine transformation.
|
||||
*
|
||||
* @param glyphIndex the index of the moved glyph. If
|
||||
* <code>glyphIndex</code> equals the total number of glyphs in this
|
||||
* vector, the advance width and height of the vector is changed.
|
||||
*
|
||||
* @param position the new position of the glyph.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if <code>glyphIndex</code> is
|
||||
* not in the range <code[0 .. getNumGlyphs()]</code>.
|
||||
*/
|
||||
public void setGlyphPosition(int glyphIndex, Point2D position)
|
||||
{
|
||||
validate();
|
||||
pos[glyphIndex * 2] = (float) position.getX();
|
||||
pos[glyphIndex * 2 + 1] = (float) position.getY();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the affine transformation that is applied to the
|
||||
* glyph at the specified index.
|
||||
*
|
||||
* @param glyphIndex the index of the glyph whose transformation
|
||||
* is to be retrieved.
|
||||
*
|
||||
* @return an affine transformation, or <code>null</code>
|
||||
* for the identity transformation.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if <code>glyphIndex</code> is
|
||||
* not in the range <code[0 .. getNumGlyphs() - 1]</code>.
|
||||
*/
|
||||
public AffineTransform getGlyphTransform(int glyphIndex)
|
||||
{
|
||||
if (transforms == null)
|
||||
return null;
|
||||
else
|
||||
return transforms[glyphIndex];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Applies an affine transformation to the glyph at the specified
|
||||
* index.
|
||||
*
|
||||
* @param glyphIndex the index of the glyph to which the
|
||||
* transformation is applied.
|
||||
*
|
||||
* @param transform the affine transformation for the glyph, or
|
||||
* <code>null</code> for an identity transformation.
|
||||
*/
|
||||
public void setGlyphTransform(int glyphIndex,
|
||||
AffineTransform transform)
|
||||
{
|
||||
if (transforms == null)
|
||||
transforms = new AffineTransform[glyphs.length];
|
||||
transforms[glyphIndex] = transform;
|
||||
|
||||
/* If the GlyphVector has only a transform for a single glyph, and
|
||||
* the caller clears its transform, the FLAG_HAS_TRANSFORMS bit
|
||||
* should be cleared in layoutFlags. However, this would require
|
||||
* that we keep track of the number of transformed glyphs, or that
|
||||
* we count them when a transform is cleared. This would
|
||||
* complicate the code quite a bit. Note that the only drawback of
|
||||
* wrongly setting FLAG_HAS_TRANSFORMS is that a slower code path
|
||||
* might be taken for rendering the vector. Right now, we never
|
||||
* really look at the flag, so it does not make any difference.
|
||||
*/
|
||||
if (transform != null)
|
||||
layoutFlags |= FLAG_HAS_TRANSFORMS;
|
||||
valid = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns flags that can be used for optimizing the rendering
|
||||
* of this GlyphVector.
|
||||
*
|
||||
* @return a bit mask with the applicable flags set.
|
||||
*
|
||||
* @since 1.4
|
||||
*
|
||||
* @see GlyphVector#FLAG_HAS_POSITION_ADJUSTMENTS
|
||||
* @see GlyphVector#FLAG_HAS_TRANSFORMS
|
||||
* @see GlyphVector#FLAG_RUN_RTL
|
||||
* @see GlyphVector#FLAG_COMPLEX_GLYPHS
|
||||
* @see GlyphVector#FLAG_MASK
|
||||
*/
|
||||
public int getLayoutFlags()
|
||||
{
|
||||
return layoutFlags;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the positions of a range of glyphs in this vector.
|
||||
*
|
||||
* @param firstGlyphIndex the index of the first glyph whose
|
||||
* position is retrieved.
|
||||
*
|
||||
* @param numGlyphs the number of glyphs whose positions
|
||||
* are retrieved.
|
||||
*
|
||||
* @param outPositions an array for storing the results
|
||||
* (the length must be at least twice <code>numGlyphs</code>),
|
||||
* or <code>null</code> for freshly allocating an array.
|
||||
*
|
||||
* @return an array with the glyph positions. The horizontal
|
||||
* position of the <code>i</code>-th glyph is at index <code>2 *
|
||||
* i</code>, the vertical position at index <code>2 * i + 1</code>.
|
||||
*
|
||||
* @throws IllegalArgumentException if <code>numGlyphs</code>
|
||||
* is less than zero.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if either
|
||||
* <code>firstGlyphIndex</code> or <code>(firstGlyphIndex +
|
||||
* numGlyphs)</code> is not in the range <code>[0 .. getNumGlyphs() -
|
||||
* 1]</code>.
|
||||
*/
|
||||
public float[] getGlyphPositions(int firstGlyphIndex,
|
||||
int numGlyphs,
|
||||
float[] outPositions)
|
||||
{
|
||||
if (numGlyphs < 0)
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
validate();
|
||||
if (outPositions == null)
|
||||
outPositions = new float[numGlyphs * 2];
|
||||
|
||||
System.arraycopy(/*src */ pos, /* srcStart */ firstGlyphIndex * 2,
|
||||
/* dest */ outPositions, /* destStart */ 0,
|
||||
/* length */ numGlyphs * 2);
|
||||
return outPositions;
|
||||
}
|
||||
|
||||
|
||||
private float getAscent()
|
||||
{
|
||||
return fontDelegate.getAscent(fontSize, transform,
|
||||
renderContext.isAntiAliased(),
|
||||
renderContext.usesFractionalMetrics(),
|
||||
/* horizontal */ true);
|
||||
}
|
||||
|
||||
|
||||
private float getDescent()
|
||||
{
|
||||
return fontDelegate.getDescent(fontSize, transform,
|
||||
renderContext.isAntiAliased(),
|
||||
renderContext.usesFractionalMetrics(),
|
||||
/* horizontal */ true);
|
||||
}
|
||||
|
||||
|
||||
public Shape getGlyphLogicalBounds(int glyphIndex)
|
||||
{
|
||||
float x, y, ascent;
|
||||
|
||||
validate();
|
||||
ascent = getAscent();
|
||||
x = pos[glyphIndex * 2];
|
||||
y = pos[glyphIndex * 2 + 1];
|
||||
|
||||
return new Rectangle2D.Float(x, y - ascent,
|
||||
pos[(glyphIndex + 1) * 2] - x,
|
||||
ascent - getDescent());
|
||||
}
|
||||
|
||||
|
||||
public Shape getGlyphVisualBounds(int glyphIndex)
|
||||
{
|
||||
return getGlyphOutline(glyphIndex).getBounds2D();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the metrics of the glyph at the specified index.
|
||||
*
|
||||
* @param glyphIndex the index of the glyph whose metrics is to be
|
||||
* retrieved.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if <code>glyphIndex</code> is
|
||||
* not in the range <code[0 .. getNumGlyphs() - 1]</code>.
|
||||
*/
|
||||
public GlyphMetrics getGlyphMetrics(int glyphIndex)
|
||||
{
|
||||
// FIXME: Not yet implemented.
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the justification information for the glyph at the
|
||||
* specified index.
|
||||
*
|
||||
* @param glyphIndex the index of the glyph whose justification
|
||||
* information is to be retrieved.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if <code>glyphIndex</code> is
|
||||
* not in the range <code[0 .. getNumGlyphs() - 1]</code>.
|
||||
*/
|
||||
public GlyphJustificationInfo getGlyphJustificationInfo(int glyphIndex)
|
||||
{
|
||||
// FIXME: Not yet implemented.
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines whether another GlyphVector is for the same font and
|
||||
* rendering context, uses the same glyphs and positions them to the
|
||||
* same location.
|
||||
*
|
||||
* @param other the GlyphVector to compare with.
|
||||
*
|
||||
* @return <code>true</code> if the two vectors are equal,
|
||||
* <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean equals(GlyphVector other)
|
||||
{
|
||||
GNUGlyphVector o;
|
||||
if (!(other instanceof GNUGlyphVector))
|
||||
return false;
|
||||
|
||||
o = (GNUGlyphVector) other;
|
||||
if ((this.font != o.font)
|
||||
|| (this.fontDelegate != o.fontDelegate)
|
||||
|| (this.renderContext != o.renderContext)
|
||||
|| (this.glyphs.length != o.glyphs.length))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < glyphs.length; i++)
|
||||
if (this.glyphs[i] != o.glyphs[i])
|
||||
return false;
|
||||
|
||||
validate();
|
||||
o.validate();
|
||||
for (int i = 0; i < pos.length; i++)
|
||||
if (this.pos[i] != o.pos[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void validate()
|
||||
{
|
||||
if (!valid)
|
||||
performDefaultLayout();
|
||||
}
|
||||
}
|
1027
libjava/classpath/gnu/java/awt/font/opentype/CharGlyphMap.java
Normal file
1027
libjava/classpath/gnu/java/awt/font/opentype/CharGlyphMap.java
Normal file
File diff suppressed because it is too large
Load diff
1133
libjava/classpath/gnu/java/awt/font/opentype/GlyphNamer.java
Normal file
1133
libjava/classpath/gnu/java/awt/font/opentype/GlyphNamer.java
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,235 @@
|
|||
/* MacResourceFork.java -- Parses MacOS resource forks.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.font.opentype;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
|
||||
/**
|
||||
* A class for accessing data that is stored in the resource fork of
|
||||
* Macintosh files. Writing resource forks is currently not supported.
|
||||
*
|
||||
* <p>The gnu.java.awt.font package uses this class for accessing
|
||||
* fonts in the MacOS X ".dfont" format, which is is a file in the
|
||||
* format of a Macintosh resource fork, but stored in the normal data
|
||||
* fork of the file.
|
||||
*
|
||||
* <p>The implementation has been designed to work efficiently with
|
||||
* the virtual memory subsystem. It is recommended to pass an
|
||||
* instance of {@link java.nio.MappedByteBuffer} to the constructor.
|
||||
*
|
||||
* <p>Thread Safety: All access is synchronized on the ByteBuffer
|
||||
* that is passed to the constructor.
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html"
|
||||
* >Apple’ developer documentation about the Resource File
|
||||
* Format</a>
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
final class MacResourceFork
|
||||
{
|
||||
int[] types;
|
||||
Resource[][] resources;
|
||||
ByteBuffer buf;
|
||||
|
||||
public MacResourceFork(ByteBuffer buf)
|
||||
{
|
||||
int typeListOffset;
|
||||
int refListOffset;
|
||||
int nameListOffset;
|
||||
int mapOffset, mapLen;
|
||||
int dataOffset, dataLen;
|
||||
int numTypes;
|
||||
|
||||
synchronized (buf)
|
||||
{
|
||||
buf = buf.duplicate();
|
||||
this.buf = buf;
|
||||
buf.position(0);
|
||||
dataOffset = buf.getInt();
|
||||
mapOffset = buf.getInt();
|
||||
dataLen = buf.getInt();
|
||||
mapLen = buf.getInt();
|
||||
buf.position(mapOffset + 24);
|
||||
refListOffset = mapOffset + buf.getChar();
|
||||
nameListOffset = mapOffset + buf.getChar();
|
||||
numTypes = buf.getChar() + 1;
|
||||
types = new int[numTypes];
|
||||
resources = new Resource[numTypes][];
|
||||
|
||||
/* Parse resource type list. */
|
||||
typeListOffset = buf.position();
|
||||
for (int i = 0; i < numTypes; i++)
|
||||
{
|
||||
buf.position(typeListOffset + 8 * i);
|
||||
int resType = buf.getInt();
|
||||
int numRes = buf.getChar() + 1;
|
||||
|
||||
types[i] = resType;
|
||||
resources[i] = new Resource[numRes];
|
||||
|
||||
buf.position(refListOffset + buf.getChar());
|
||||
for (int j = 0; j < numRes; j++)
|
||||
{
|
||||
short resID = buf.getShort();
|
||||
int resNameOffset = nameListOffset + buf.getChar();
|
||||
int resDataOffset = buf.getInt();
|
||||
byte resAttr = (byte) (resDataOffset >> 24);
|
||||
resDataOffset = dataOffset + (resDataOffset & 0x00ffffff);
|
||||
buf.getInt(); /* skip four reserved bytes */
|
||||
|
||||
Resource rsrc = new Resource(buf, resType, resID, resDataOffset,
|
||||
resNameOffset);
|
||||
resources[i][j] = rsrc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Resource[] getResources(int type)
|
||||
{
|
||||
synchronized (buf)
|
||||
{
|
||||
for (int i = 0; i < types.length; i++)
|
||||
{
|
||||
if (types[i] == type)
|
||||
return resources[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public Resource getResource(int type, short id)
|
||||
{
|
||||
Resource[] res;
|
||||
|
||||
synchronized (buf)
|
||||
{
|
||||
for (int i = 0; i < types.length; i++)
|
||||
{
|
||||
if (types[i] != type)
|
||||
continue;
|
||||
|
||||
res = resources[i];
|
||||
for (int j = 0; j < res.length; j++)
|
||||
if (res[j].getID() == id)
|
||||
return res[j];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A single resource that is contained in a resource fork.
|
||||
*/
|
||||
public static final class Resource
|
||||
{
|
||||
int type;
|
||||
short id;
|
||||
byte attribute;
|
||||
int nameOffset;
|
||||
int dataOffset;
|
||||
ByteBuffer buf;
|
||||
|
||||
private Resource(ByteBuffer buf,
|
||||
int type, short id, int dataOffset, int nameOffset)
|
||||
{
|
||||
this.buf = buf;
|
||||
this.type = type;
|
||||
this.id = id;
|
||||
this.dataOffset = dataOffset;
|
||||
this.nameOffset = nameOffset;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the type of this resource.
|
||||
*
|
||||
* @return an <code>int</code> encoding a four-byte type tag,
|
||||
* such as <code>0x464f4e54</code> for <code>'FONT'</code>.
|
||||
*/
|
||||
public int getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the ID of this resource.
|
||||
*/
|
||||
public short getID()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the content of the resource. Only one page of memory
|
||||
* is touched, irrespective of the actual size of the resource.
|
||||
*/
|
||||
public ByteBuffer getContent()
|
||||
{
|
||||
synchronized (buf)
|
||||
{
|
||||
buf.limit(buf.capacity());
|
||||
int len = buf.getInt(dataOffset);
|
||||
buf.position(dataOffset + 4).limit(dataOffset + 4 + len);
|
||||
return buf.slice();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the length of the resource in bytes.
|
||||
*/
|
||||
public int getLength()
|
||||
{
|
||||
synchronized (buf)
|
||||
{
|
||||
return buf.getInt(dataOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
686
libjava/classpath/gnu/java/awt/font/opentype/NameDecoder.java
Normal file
686
libjava/classpath/gnu/java/awt/font/opentype/NameDecoder.java
Normal file
|
@ -0,0 +1,686 @@
|
|||
/* NameDecoder.java -- Decodes names of OpenType and TrueType fonts.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.java.awt.font.opentype;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
/**
|
||||
* A utility class that helps with decoding the names of OpenType
|
||||
* and TrueType fonts.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
class NameDecoder
|
||||
{
|
||||
public static final int NAME_COPYRIGHT = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Specifies the name of the family to which a font belongs, for
|
||||
* example “Univers”.
|
||||
*/
|
||||
public static final int NAME_FAMILY = 1;
|
||||
|
||||
|
||||
/**
|
||||
* Specified the name of the font inside its family, for
|
||||
* example “Light”.
|
||||
*/
|
||||
public static final int NAME_SUBFAMILY = 2;
|
||||
|
||||
|
||||
public static final int NAME_UNIQUE = 3;
|
||||
|
||||
|
||||
/**
|
||||
* Specifies the full human-readable name of a font, for example
|
||||
* “Univers Light”
|
||||
*/
|
||||
public static final int NAME_FULL = 4;
|
||||
|
||||
|
||||
public static final int NAME_VERSION = 5;
|
||||
|
||||
|
||||
/**
|
||||
* Specifies the PostScript name of a font, for example
|
||||
* “Univers-Light”.
|
||||
*/
|
||||
public static final int NAME_POSTSCRIPT = 6;
|
||||
|
||||
|
||||
public static final int NAME_TRADEMARK = 7;
|
||||
public static final int NAME_MANUFACTURER = 8;
|
||||
public static final int NAME_DESIGNER = 9;
|
||||
public static final int NAME_DESCRIPTION = 10;
|
||||
public static final int NAME_VENDOR_URL = 11;
|
||||
public static final int NAME_DESIGNER_URL = 12;
|
||||
public static final int NAME_LICENSE = 13;
|
||||
public static final int NAME_LICENSE_URL = 14;
|
||||
public static final int NAME_PREFERRED_FAMILY = 16;
|
||||
public static final int NAME_PREFERRED_SUBFAMILY = 17;
|
||||
public static final int NAME_FULL_MACCOMPATIBLE = 18;
|
||||
public static final int NAME_SAMPLE_TEXT = 19;
|
||||
public static final int NAME_POSTSCRIPT_CID = 20;
|
||||
|
||||
|
||||
private static final int PLATFORM_MACINTOSH = 1;
|
||||
private static final int PLATFORM_MICROSOFT = 3;
|
||||
|
||||
|
||||
public static String getName(ByteBuffer nameTable,
|
||||
int name, Locale locale)
|
||||
{
|
||||
int numRecords;
|
||||
int macLanguage, msLanguage;
|
||||
int offset;
|
||||
int namePlatform, nameEncoding, nameLanguage, nameID, nameLen;
|
||||
int nameStart;
|
||||
String result;
|
||||
boolean match;
|
||||
|
||||
if (nameTable == null)
|
||||
return null;
|
||||
|
||||
nameTable.position(0);
|
||||
/* We understand only format 0 of the name table. */
|
||||
if (nameTable.getChar() != 0)
|
||||
return null;
|
||||
|
||||
macLanguage = getMacLanguageCode(locale);
|
||||
msLanguage = getMicrosoftLanguageCode(locale);
|
||||
numRecords = nameTable.getChar();
|
||||
offset = nameTable.getChar();
|
||||
|
||||
for (int i = 0; i < numRecords; i++)
|
||||
{
|
||||
namePlatform = nameTable.getChar();
|
||||
nameEncoding = nameTable.getChar();
|
||||
nameLanguage = nameTable.getChar();
|
||||
nameID = nameTable.getChar();
|
||||
nameLen = nameTable.getChar();
|
||||
nameStart = offset + nameTable.getChar();
|
||||
|
||||
|
||||
if (nameID != name)
|
||||
continue;
|
||||
|
||||
match = false;
|
||||
switch (namePlatform)
|
||||
{
|
||||
case PLATFORM_MACINTOSH:
|
||||
if ((nameLanguage == macLanguage) || (locale == null))
|
||||
match = true;
|
||||
else
|
||||
{
|
||||
switch (macLanguage)
|
||||
{
|
||||
case 49: /* Azerbaijani/Cyrillic */
|
||||
match = (nameLanguage == /* Azerbaijani/Arabic */ 50)
|
||||
|| (nameLanguage == /* Azerbaijani/Roman */ 150);
|
||||
break;
|
||||
|
||||
case 57: /* Mongolian/Mongolian */
|
||||
match = (nameLanguage == /* Mongolian/Cyrillic */ 58);
|
||||
break;
|
||||
|
||||
case 83: /* Malay/Roman */
|
||||
match = (nameLanguage == /* Malay/Arabic */ 84);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PLATFORM_MICROSOFT:
|
||||
if (((nameLanguage & 0xff) == msLanguage) || (locale == null))
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (match)
|
||||
{
|
||||
result = decodeName(namePlatform, nameEncoding, nameLanguage,
|
||||
nameTable, nameStart, nameLen);
|
||||
if (result != null)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The language codes used by the Macintosh operating system. MacOS
|
||||
* defines numeric language identifiers in the range [0 .. 95] and
|
||||
* [128 .. 150]. To map this numeric identifier into an ISO 639
|
||||
* language code, multiply it by two and take the substring at that
|
||||
* position.
|
||||
*
|
||||
* <p>ISO 639 has revised the code for some languages, namely
|
||||
* <code>he</code> for Hebrew (formerly <code>iw</code>),
|
||||
* <code>yi</code> (formerly <code>ji</code>), and <code>id</code>
|
||||
* for Indonesian (formerly <code>in</code>). In those cases, this
|
||||
* table intentionally contains the older, obsolete code. The
|
||||
* reason is that this is the code which
|
||||
* java.util.Locale.getLanguage() is specified to return. The
|
||||
* implementation of {@link #getMacLanguageCode} depends on this.
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://www.unicode.org/unicode/onlinedat/languages.html"
|
||||
* >Language Codes: ISO 639, Microsoft and Macintosh</a>
|
||||
*/
|
||||
private static final String macLanguageCodes
|
||||
// 0 1 2
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
|
||||
= "enfrdeitnlsvesdaptnoiwjaarfielismttrhrzhurhithkoltplhuetlv "
|
||||
|
||||
// 3 4 5
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
|
||||
+ "fofaruzhnlgdsqrocssksljisrmkbgukbeuzkkazazhykamokytgtkmnmnps"
|
||||
|
||||
// 6 7 8
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
|
||||
+ "kukssdbonesamrbnasgupaormlkntatesimykmloviintlmsmsamti sosw"
|
||||
|
||||
// 9 10 11
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
|
||||
+ "rwrn mgeo "
|
||||
|
||||
// 12 13 14
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
|
||||
+ " cyeucalaqugnayttugtsjwsuglafbriugdgvgatoelkl"
|
||||
|
||||
// 15
|
||||
// 0
|
||||
+ "az";
|
||||
|
||||
|
||||
/**
|
||||
* The primary language IDs used by the Microsoft operating systems.
|
||||
*
|
||||
* <p>ISO 639 has revised the code for some languages, namely
|
||||
* <code>he</code> for Hebrew (formerly <code>iw</code>),
|
||||
* <code>yi</code> (formerly <code>ji</code>), and <code>id</code>
|
||||
* for Indonesian (formerly <code>in</code>). In those cases, this
|
||||
* table intentionally contains the older, obsolete code. The
|
||||
* reason is that this is the code which
|
||||
* java.util.Locale.getLanguage() is specified to return. The
|
||||
* implementation of {@link #getMicrosoftLanguageCode} depends on
|
||||
* this.
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://www.unicode.org/unicode/onlinedat/languages.html"
|
||||
* >Language Codes: ISO 639, Microsoft and Macintosh</a>
|
||||
*/
|
||||
private static final String microsoftLanguageCodes
|
||||
// 0 1 2
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
|
||||
= " arbgcazhcsdadeelenesfifriwhuisitjakonlnoplptrmrorushsksqsv"
|
||||
|
||||
// 3 4 5
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
|
||||
+ "thtrurinukbesletlvlttgfavihyazeu mk ts xhzuafkafohimt "
|
||||
|
||||
// 6 7 8
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
|
||||
+ "gajimskkkyswtkuzttbnpaguortateknmlasmrsamnbocykmlomygl sd"
|
||||
|
||||
// 9 10 11
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
|
||||
+ " si iuam ksnefypstl ha yo omtign laso";
|
||||
|
||||
|
||||
/**
|
||||
* Maps a Java Locale into a MacOS language code.
|
||||
*
|
||||
* <p>For languages that are written in several script systems,
|
||||
* MacOS defines multiple language codes. Java Locales have a
|
||||
* variant which could be used for that purpose, but a small
|
||||
* test program revealed that with Sun's JDK 1.4.1_01, only two
|
||||
* of 134 available Locales have a variant tag (namely no_NO_NY
|
||||
* and th_TH_TH).</p>
|
||||
*
|
||||
* <p>The following cases are problematic:
|
||||
*
|
||||
* <ul> <li>Azerbaijani (az): The MacOS language code is 49 if
|
||||
* Azerbaijani is written in the Cyrillic script; 50 if written in
|
||||
* the Arabic script; 150 if written in the Roman script. This
|
||||
* method will always return 49 for the Azerbaijani locale.</li>
|
||||
*
|
||||
* <li>Mongolian (mn): The MacOS language code is 57 if Mongolian is
|
||||
* written in the Mongolian script; 58 if written in the Cyrillic
|
||||
* script. This method will always return 57 for the Mongolian
|
||||
* locale.</li>
|
||||
*
|
||||
* <li>Malay (ms): The MacOS language code is 83 if Malay is written
|
||||
* in the Roman script; 84 if written in the Arabic script. This
|
||||
* method will always return 83 for the Malay locale.</li> </ul>
|
||||
*
|
||||
* @return a MacOS language code, or -1 if there is no such code for
|
||||
* <code>loc</code>’s language.
|
||||
*/
|
||||
private static int getMacLanguageCode(Locale loc)
|
||||
{
|
||||
int code;
|
||||
|
||||
if (loc == null)
|
||||
return -1;
|
||||
|
||||
code = findLanguageCode(loc.getLanguage(), macLanguageCodes);
|
||||
switch (code)
|
||||
{
|
||||
case 19:
|
||||
/* Traditional Chinese (MacOS language #19) and and Simplified
|
||||
* Chinese (MacOS language #33) both have "zh" as their ISO 639
|
||||
* code.
|
||||
*/
|
||||
if (loc.equals(Locale.SIMPLIFIED_CHINESE))
|
||||
code = 33;
|
||||
break;
|
||||
|
||||
// Other special cases would be 49, 57 and 83, but we do not
|
||||
// know what do do about them. See the method documentation for
|
||||
// details.
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Maps a Java Locale into a Microsoft language code.
|
||||
*/
|
||||
private static int getMicrosoftLanguageCode(Locale locale)
|
||||
{
|
||||
String isoCode;
|
||||
int code;
|
||||
|
||||
if (locale == null)
|
||||
return -1;
|
||||
|
||||
isoCode = locale.getLanguage();
|
||||
code = findLanguageCode(isoCode, microsoftLanguageCodes);
|
||||
if (code == -1)
|
||||
{
|
||||
if (isoCode.equals("hr") || isoCode.equals("sr"))
|
||||
{
|
||||
/* Microsoft uses code 26 for "sh" (Serbo-Croatian),
|
||||
* "hr" (Croatian) and "sr" (Serbian). Our table contains
|
||||
* "sh".
|
||||
*/
|
||||
code = 26;
|
||||
}
|
||||
else if (isoCode.equals("gd"))
|
||||
{
|
||||
/* Microsoft uses code 60 for "gd" (Scottish Gaelic) and
|
||||
* "ga" (Irish Gaelic). Out table contains "ga".
|
||||
*/
|
||||
code = 60;
|
||||
}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
private static int findLanguageCode(String lang, String langCodes)
|
||||
{
|
||||
int index;
|
||||
if (lang == null)
|
||||
return -1;
|
||||
|
||||
if (lang.length() != 2)
|
||||
return -1;
|
||||
|
||||
index = 0;
|
||||
do
|
||||
{
|
||||
index = langCodes.indexOf(lang, index);
|
||||
|
||||
/* The index must be even to be considered a match. Otherwise, we
|
||||
* could match with the second letter of one language and the
|
||||
* first of antoher one.
|
||||
*/
|
||||
}
|
||||
while (!((index < 0) || ((index & 1) == 0)));
|
||||
if (index < 0)
|
||||
return -1;
|
||||
|
||||
index = index / 2;
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
private static String decodeName(int platform, int encoding, int language,
|
||||
ByteBuffer buffer, int offset, int len)
|
||||
{
|
||||
byte[] byteBuf;
|
||||
String charsetName;
|
||||
int oldPosition;
|
||||
|
||||
charsetName = getCharsetName(platform, language, encoding);
|
||||
if (charsetName == null)
|
||||
return null;
|
||||
|
||||
byteBuf = new byte[len];
|
||||
oldPosition = buffer.position();
|
||||
try
|
||||
{
|
||||
buffer.position(offset);
|
||||
buffer.get(byteBuf);
|
||||
try
|
||||
{
|
||||
return new String(byteBuf, charsetName);
|
||||
}
|
||||
catch (UnsupportedEncodingException uex)
|
||||
{
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
buffer.position(oldPosition);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Maps a MacOS language code into a Java Locale.
|
||||
*
|
||||
* @param macLanguageCode the MacOS language code for
|
||||
* the language whose Java locale is to be retrieved.
|
||||
*
|
||||
* @return an suitable Locale, or <code>null</code> if
|
||||
* the mapping cannot be performed.
|
||||
*/
|
||||
private static Locale getMacLocale(int macLanguageCode)
|
||||
{
|
||||
String isoCode;
|
||||
|
||||
switch (macLanguageCode)
|
||||
{
|
||||
case 0: return Locale.ENGLISH;
|
||||
case 1: return Locale.FRENCH;
|
||||
case 2: return Locale.GERMAN;
|
||||
case 3: return Locale.ITALIAN;
|
||||
case 11: return Locale.JAPANESE;
|
||||
case 23: return Locale.KOREAN;
|
||||
case 19: return Locale.TRADITIONAL_CHINESE;
|
||||
case 33: return Locale.SIMPLIFIED_CHINESE;
|
||||
}
|
||||
|
||||
if ((macLanguageCode < 0) || (macLanguageCode > 150))
|
||||
return null;
|
||||
|
||||
isoCode = macLanguageCodes.substring(macLanguageCode << 1,
|
||||
(macLanguageCode + 1) << 1);
|
||||
if (isoCode.charAt(0) == ' ')
|
||||
return null;
|
||||
|
||||
return new Locale(isoCode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Maps a Windows LCID into a Java Locale.
|
||||
*
|
||||
* @param lcid the Windows language ID whose Java locale
|
||||
* is to be retrieved.
|
||||
*
|
||||
* @return an suitable Locale, or <code>null</code> if
|
||||
* the mapping cannot be performed.
|
||||
*/
|
||||
private static Locale getWindowsLocale(int lcid)
|
||||
{
|
||||
/* FIXME: This is grossly incomplete. */
|
||||
switch (lcid)
|
||||
{
|
||||
case 0x0407: return Locale.GERMAN;
|
||||
case 0x0408: return new Locale("el", "GR");
|
||||
case 0x0409: return Locale.ENGLISH;
|
||||
case 0x040b: return new Locale("fi");
|
||||
case 0x040c: return Locale.FRENCH;
|
||||
case 0x0416: return new Locale("pt");
|
||||
case 0x0807: return new Locale("de", "CH");
|
||||
case 0x0809: return new Locale("en", "UK");
|
||||
case 0x080c: return new Locale("fr", "BE");
|
||||
case 0x0816: return new Locale("pt", "BR");
|
||||
case 0x0c07: return new Locale("de", "AT");
|
||||
case 0x0c09: return new Locale("en", "AU");
|
||||
case 0x0c0c: return new Locale("fr", "CA");
|
||||
case 0x1007: return new Locale("de", "LU");
|
||||
case 0x1009: return new Locale("en", "CA");
|
||||
case 0x100c: return new Locale("fr", "CH");
|
||||
case 0x1407: return new Locale("de", "LI");
|
||||
case 0x1409: return new Locale("en", "NZ");
|
||||
case 0x140c: return new Locale("fr", "LU");
|
||||
case 0x1809: return new Locale("en", "IE");
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Maps a Macintosh Script Manager code to the name of the
|
||||
* corresponding Java Charset.
|
||||
*
|
||||
* @param macScript a MacOS ScriptCode, for example
|
||||
* 6 for <code>smGreek</code>.
|
||||
*
|
||||
* @return a String that can be used to retrieve a Java
|
||||
* CharsetDecorder, for example <code>MacGreek</code>, or
|
||||
* <code>null</code> if <code>macScript</code> has an
|
||||
* unsupported value.
|
||||
*/
|
||||
private static String getMacCharsetName(int macScript)
|
||||
{
|
||||
switch (macScript)
|
||||
{
|
||||
case 0: return "MacRoman";
|
||||
case 1: return "MacJapanese";
|
||||
case 2: return "MacKorean";
|
||||
case 3: return "MacTradChinese";
|
||||
case 4: return "MacArabic";
|
||||
case 5: return "MacHebrew";
|
||||
case 6: return "MacGreek";
|
||||
case 7: return "MacCyrillic";
|
||||
case 8: return "MacRSymbol";
|
||||
case 9: return "MacDevanagari";
|
||||
case 10: return "MacGurmukhi";
|
||||
case 11: return "MacGujarati";
|
||||
case 12: return "MacOriya";
|
||||
case 13: return "MacBengali";
|
||||
case 14: return "MacTamil";
|
||||
case 15: return "MacTelugu";
|
||||
case 16: return "MacKannada";
|
||||
case 17: return "MacMalayalam";
|
||||
case 18: return "MacSinhalese";
|
||||
case 19: return "MacBurmese";
|
||||
case 20: return "MacKhmer";
|
||||
case 21: return "MacThai";
|
||||
case 22: return "MacLao";
|
||||
case 23: return "MacGeorgian";
|
||||
case 24: return "MacArmenian";
|
||||
case 25: return "MacSimpChinese";
|
||||
case 26: return "MacTibetan";
|
||||
case 27: return "MacMongolian";
|
||||
case 28: return "MacEthiopic";
|
||||
case 29: return "MacCentralEurope";
|
||||
case 30: return "MacVietnamese";
|
||||
case 31: return "MacExtArabic";
|
||||
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Maps a Microsoft locale ID (LCID) to the name of the
|
||||
* corresponding Java Charset.
|
||||
*
|
||||
* @param lcid the Microsoft locale ID.
|
||||
*
|
||||
* @return a String that can be used to retrieve a Java
|
||||
* CharsetDecorder, for example <code>windows-1252</code>, or
|
||||
* <code>null</code> if <code>lcid</code> has an unsupported value.
|
||||
*/
|
||||
private static String getMicrosoftCharsetName(int lcid)
|
||||
{
|
||||
int lang;
|
||||
char codePage = '?';
|
||||
|
||||
/* Extract the language code from the LCID. */
|
||||
lang = lcid & 0x3ff;
|
||||
|
||||
/* In the majority of cases, the language alone determines the
|
||||
* codepage.
|
||||
*/
|
||||
if (lang < 100)
|
||||
codePage = (" 612D022322225022EC2202201?002A462110777 68 ?2 1 "
|
||||
+ " 2 2 2112 ?1 1 2 2 ")
|
||||
.charAt(lang);
|
||||
|
||||
/* There are a few exceptions, however, where multiple code pages
|
||||
* are used for the same language. */
|
||||
if (codePage == '?')
|
||||
{
|
||||
switch (lcid)
|
||||
{
|
||||
case 0x041a: // Croatian --> Windows-1250 (Central Europe)
|
||||
case 0x081a: // Serbian (Latin) --> Windows-1250 (Central Europe)
|
||||
codePage = '0';
|
||||
break;
|
||||
|
||||
case 0x42c: // Azeri (Latin) --> Windows-1254 (Turkish)
|
||||
case 0x443: // Uzbek (Latin) --> Windows-1254 (Turkish)
|
||||
codePage = '4';
|
||||
break;
|
||||
|
||||
case 0x82c: // Azeri (Cyrillic) --> Windows-1251 (Cyrillic)
|
||||
case 0x843: // Uzbek (Cyrillic) --> Windows-1251 (Cyrillic)
|
||||
case 0xc1a: // Serbian (Cyrillic) --> Windows-1251 (Cyrillic)
|
||||
codePage = '1';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (codePage)
|
||||
{
|
||||
case '0': return "windows-1250"; // Central Europe
|
||||
case '1': return "windows-1251"; // Cyrillic
|
||||
case '2': return "windows-1252"; // Latin 1
|
||||
case '3': return "windows-1253"; // Greek
|
||||
case '4': return "windows-1254"; // Turkish
|
||||
case '5': return "windows-1255"; // Hebrew
|
||||
case '6': return "windows-1256"; // Arabic
|
||||
case '7': return "windows-1257"; // Baltic
|
||||
case '8': return "windows-1258"; // Vietnam
|
||||
case 'A': return "windows-874"; // Thai
|
||||
case 'B': return "windows-936"; // Simplified Chinese, GBK
|
||||
case 'C': return "windows-949"; // Korean
|
||||
case 'D': return "windows-950"; // Traditional Chinese, Big5
|
||||
case 'E': return "windows-932"; // Japanese Shift-JIS
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the Locale of an OpenType name.
|
||||
*
|
||||
* @param platform the OpenType platform ID.
|
||||
*
|
||||
* @param language the language tag of the OpenType name. If
|
||||
* <code>platform</code> is 1, this is the MacOS language code.
|
||||
*
|
||||
* @param encoding the encoding tag of the OpenType name. If
|
||||
* <code>platform</code> is 1, this is the MacOS script code.
|
||||
*/
|
||||
public static Locale getLocale(int platform, int language, int encoding)
|
||||
{
|
||||
switch (platform)
|
||||
{
|
||||
case 1: /* Apple Macintosh */
|
||||
return getMacLocale(language);
|
||||
|
||||
case 3: /* Microsoft Windows */
|
||||
return getWindowsLocale(language);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the name of the charset for an OpenType font name.
|
||||
*
|
||||
* @param platform the OpenType platform ID.
|
||||
*
|
||||
* @param language the language tag of the OpenType name. If
|
||||
* <code>platform</code> is 1, this is the MacOS language code.
|
||||
*
|
||||
* @param encoding the encoding tag of the OpenType name. If
|
||||
* <code>platform</code> is 1, this is the MacOS script code.
|
||||
*
|
||||
* @return a charset name such as <code>"MacRoman"</code>,
|
||||
* or <code>null</code> if the combination is not known.
|
||||
*/
|
||||
public static String getCharsetName(int platform, int language, int encoding)
|
||||
{
|
||||
switch (platform)
|
||||
{
|
||||
case 1: /* Apple Macintosh */
|
||||
return getMacCharsetName(encoding);
|
||||
|
||||
case 3: /* Microsoft Windows */
|
||||
return getMicrosoftCharsetName(language);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
825
libjava/classpath/gnu/java/awt/font/opentype/OpenTypeFont.java
Normal file
825
libjava/classpath/gnu/java/awt/font/opentype/OpenTypeFont.java
Normal file
|
@ -0,0 +1,825 @@
|
|||
/* OpenTypeFont.java -- Manages OpenType and TrueType fonts.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.java.awt.font.opentype;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.FontFormatException;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.font.OpenType;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.text.CharacterIterator;
|
||||
import java.util.Locale;
|
||||
|
||||
import gnu.java.awt.font.FontDelegate;
|
||||
import gnu.java.awt.font.GNUGlyphVector;
|
||||
import gnu.java.awt.font.opentype.truetype.TrueTypeScaler;
|
||||
|
||||
|
||||
/**
|
||||
* A font that takes its data from OpenType or TrueType font tables.
|
||||
*
|
||||
* <p>OpenType is an extension of the TrueType font format. In addition
|
||||
* to tables for names, kerning or layout, it also stores the shapes
|
||||
* of individual glyphs. Three formats are recognized for glyphs:
|
||||
* Quadratic splines (classic TrueType), cubic splines (PostScript),
|
||||
* and bitmaps.
|
||||
*
|
||||
* @see <a
|
||||
* href="http://partners.adobe.com/asn/tech/type/opentype/">Adobe’s
|
||||
* OpenType specification</a>
|
||||
*
|
||||
* @see <a
|
||||
* href="http://developer.apple.com/fonts/TTRefMan/">Apple’s</code>
|
||||
* TrueType specification</a>
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
public final class OpenTypeFont
|
||||
implements FontDelegate
|
||||
{
|
||||
static final int TAG_OTTO = 0x4f54544f; // 'OTTO'
|
||||
static final int TAG_SFNT = 0x73666e74; // 'sfnt'
|
||||
static final int TAG_TRUE = 0x74727565; // 'true'
|
||||
static final int TAG_TTCF = 0x74746366; // 'ttcf'
|
||||
static final int TAG_ZAPF = 0x5a617066; // 'Zapf'
|
||||
|
||||
|
||||
/**
|
||||
* A buffer containing the font data. Note that this may well be an
|
||||
* instance of the subclass MappedByteBuffer, in which case the
|
||||
* virtual memory subsystem can more efficiently handle requests for
|
||||
* font data. This is especially recommended for large font files
|
||||
* that contain many glyphs that are rarely accessed.
|
||||
*/
|
||||
ByteBuffer buf;
|
||||
|
||||
|
||||
/**
|
||||
* The number of glyphs in this font.
|
||||
*/
|
||||
final int numGlyphs;
|
||||
|
||||
int[] tableTag, tableStart, tableLength;
|
||||
|
||||
|
||||
/**
|
||||
* The version of the font in 16.16 fixed-point encoding, for
|
||||
* example 0x00010000 for version 1.0. There are also two special
|
||||
* version IDs used by fonts for Apple Macintosh, namely 'true'
|
||||
* (0x74727565) and 'typ1'. OpenType fonts sometimes have 'OTTO' as
|
||||
* their version.
|
||||
*/
|
||||
private int version;
|
||||
|
||||
|
||||
/**
|
||||
* The number of font units per em. For fonts with TrueType
|
||||
* outlines, this is usually a power of two (such as 2048). For
|
||||
* OpenType fonts with PostScript outlines, other values are
|
||||
* acceptable (such as 1000).
|
||||
*/
|
||||
private int unitsPerEm;
|
||||
|
||||
|
||||
/**
|
||||
* A factor to convert font units into ems. This value is <code>1 /
|
||||
* unitsPerEm</code>.
|
||||
*/
|
||||
private float emsPerUnit;
|
||||
|
||||
|
||||
/**
|
||||
* The scaler to which the actual scaling work is delegated.
|
||||
*/
|
||||
private Scaler scaler;
|
||||
|
||||
|
||||
/**
|
||||
* A delegate object for mapping Unicode UCS-4 codepoints to glyph
|
||||
* IDs.
|
||||
*/
|
||||
private CharGlyphMap cmap;
|
||||
|
||||
|
||||
/**
|
||||
* A delegate object for providing a name for each glyph.
|
||||
*/
|
||||
private GlyphNamer glyphNamer;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an OpenType or TrueType font.
|
||||
*
|
||||
* @param buf a buffer with the contents of the font file. It is
|
||||
* recommended to use a <code>MappedByteBuffer</code> for very
|
||||
* large font files.
|
||||
*
|
||||
* @param offsetTablePosition the position of the OpenType offset
|
||||
* table in the font file. The offset table of most OpenType and
|
||||
* TrueType fonts starts at position 0. However, so-called TrueType
|
||||
* Collections support multiple OpenType fonts in a single file,
|
||||
* which allows sharing some glyphs between fonts. If many glyphs
|
||||
* are shared (for example all the Kanji glyphs between multiple
|
||||
* Japanese fonts), the space savings can be considerable. In that
|
||||
* case, the offset table of each individual font would start at its
|
||||
* own position.
|
||||
*
|
||||
* @throws java.awt.FontFormatException if the font data is
|
||||
* not in OpenType or TrueType format.
|
||||
*/
|
||||
OpenTypeFont(ByteBuffer buf, int offsetTablePosition)
|
||||
throws FontFormatException
|
||||
{
|
||||
int numTables, searchRange, entrySelector, rangeShift;
|
||||
|
||||
//buf = buf.duplicate();
|
||||
this.buf = buf;
|
||||
buf.limit(buf.capacity());
|
||||
buf.position(offsetTablePosition);
|
||||
|
||||
/* Check that the font data is in a supported format. */
|
||||
version = buf.getInt();
|
||||
switch (version)
|
||||
{
|
||||
case 0x00010000: // Microsoft TrueType
|
||||
case OpenType.TAG_TYP1: // Adobe PostScript embeded in Apple SFNT ('typ1')
|
||||
case TAG_SFNT: // Apple TrueType
|
||||
case TAG_TRUE: // Apple TrueType
|
||||
case TAG_OTTO: // OpenType
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new FontFormatException("not in OpenType or TrueType format");
|
||||
}
|
||||
|
||||
numTables = buf.getShort();
|
||||
searchRange = buf.getShort();
|
||||
entrySelector = buf.getShort();
|
||||
rangeShift = buf.getShort();
|
||||
|
||||
tableTag = new int[numTables];
|
||||
tableStart = new int[numTables];
|
||||
tableLength = new int[numTables];
|
||||
int lastTag = 0;
|
||||
for (int i = 0; i < numTables; i++)
|
||||
{
|
||||
tableTag[i] = buf.getInt();
|
||||
if (lastTag >= tableTag[i])
|
||||
throw new FontFormatException("unordered OpenType table");
|
||||
|
||||
buf.getInt(); // ignore checksum
|
||||
tableStart[i] = buf.getInt();
|
||||
tableLength[i] = buf.getInt();
|
||||
|
||||
//System.out.println(tagToString(tableTag[i]) + ", " + tableLength[i]);
|
||||
}
|
||||
|
||||
ByteBuffer head = getFontTable(OpenType.TAG_HEAD);
|
||||
if ((head.getInt(0) != 0x00010000)
|
||||
|| (head.getInt(12) != 0x5f0f3cf5))
|
||||
throw new FontFormatException("unsupported head version");
|
||||
|
||||
unitsPerEm = head.getChar(18);
|
||||
emsPerUnit = 1.0f / (float) unitsPerEm;
|
||||
|
||||
|
||||
ByteBuffer maxp = getFontTable(OpenType.TAG_MAXP);
|
||||
int maxpVersion = maxp.getInt(0);
|
||||
switch (maxpVersion)
|
||||
{
|
||||
case 0x00005000: /* version 0.5, with wrong fractional part */
|
||||
numGlyphs = maxp.getChar(4);
|
||||
break;
|
||||
|
||||
case 0x00010000: /* version 1.0 */
|
||||
numGlyphs = maxp.getChar(4);
|
||||
scaler = new TrueTypeScaler(unitsPerEm,
|
||||
getFontTable(OpenType.TAG_HHEA),
|
||||
getFontTable(OpenType.TAG_HMTX),
|
||||
getFontTable(OpenType.TAG_VHEA),
|
||||
getFontTable(OpenType.TAG_VMTX),
|
||||
maxp,
|
||||
getFontTable(OpenType.TAG_CVT),
|
||||
getFontTable(OpenType.TAG_FPGM),
|
||||
/* loca format */ head.getShort(50),
|
||||
getFontTable(OpenType.TAG_LOCA),
|
||||
getFontTable(OpenType.TAG_GLYF),
|
||||
getFontTable(OpenType.TAG_PREP));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new FontFormatException("unsupported maxp version");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the index of a table into the offset table. The
|
||||
* result can be used to find the offset and length of a table, as
|
||||
* in <code>tableStart[getTableIndex(TAG_NAME)]</code>.
|
||||
*
|
||||
* @param tag the table identifier, for instance
|
||||
* <code>OpenType.TAG_NAME</code>.
|
||||
*
|
||||
* @return the index of that table into the offset table, or
|
||||
* -1 if the font does not contain the table specified by
|
||||
* <code>tag</code>.
|
||||
*/
|
||||
private int getTableIndex(int tag)
|
||||
{
|
||||
/* FIXME: Since the font specification requires tableTag[] to be
|
||||
* ordered, one should do binary search here.
|
||||
*/
|
||||
for (int i = 0; i < tableTag.length; i++)
|
||||
if (tableTag[i] == tag)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the family to which this font face belongs,
|
||||
* for example <i>“Univers”</i>.
|
||||
*
|
||||
* @param locale the locale for which to localize the name.
|
||||
*
|
||||
* @return the family name.
|
||||
*/
|
||||
public synchronized String getFamilyName(Locale locale)
|
||||
{
|
||||
String name;
|
||||
|
||||
if (locale == null)
|
||||
locale = Locale.getDefault();
|
||||
|
||||
name = getName(NameDecoder.NAME_FAMILY, locale);
|
||||
if (name == null)
|
||||
name = getName(NameDecoder.NAME_FAMILY, Locale.ENGLISH);
|
||||
if (name == null)
|
||||
name = getName(NameDecoder.NAME_FAMILY, /* any language */ null);
|
||||
if (name == null)
|
||||
name = getName(NameDecoder.NAME_FULL, locale);
|
||||
if (name == null)
|
||||
name = getName(NameDecoder.NAME_FULL, /* any language */ null);
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of this font face inside the family, for example
|
||||
* <i>“Light”</i>.
|
||||
*
|
||||
* @param locale the locale for which to localize the name.
|
||||
*
|
||||
* @return the name of the face inside its family.
|
||||
*/
|
||||
public synchronized String getSubFamilyName(Locale locale)
|
||||
{
|
||||
String name;
|
||||
|
||||
if (locale == null)
|
||||
locale = Locale.getDefault();
|
||||
|
||||
name = getName(NameDecoder.NAME_SUBFAMILY, locale);
|
||||
if (name == null)
|
||||
{
|
||||
name = getName(NameDecoder.NAME_SUBFAMILY, Locale.ENGLISH);
|
||||
if ("Regular".equals(name))
|
||||
name = null;
|
||||
}
|
||||
|
||||
if (name == null)
|
||||
{
|
||||
String lang = locale.getLanguage();
|
||||
if ("de".equals(lang))
|
||||
name = "Standard";
|
||||
else if ("fr".equals(lang))
|
||||
name = "Standard";
|
||||
else if ("it".equals(lang))
|
||||
name = "Normale";
|
||||
else if ("nl".equals(lang))
|
||||
name = "Normaal";
|
||||
else if ("fi".equals(lang))
|
||||
name = "Normaali";
|
||||
else if ("sv".equals(lang))
|
||||
name = "Normal";
|
||||
else
|
||||
name = "Regular";
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the full name of this font face, for example
|
||||
* <i>“Univers Light”</i>.
|
||||
*
|
||||
* @param locale the locale for which to localize the name.
|
||||
*
|
||||
* @return the face name.
|
||||
*/
|
||||
public synchronized String getFullName(Locale locale)
|
||||
{
|
||||
String name;
|
||||
|
||||
if (locale == null)
|
||||
locale = Locale.getDefault();
|
||||
|
||||
name = getName(NameDecoder.NAME_FULL, locale);
|
||||
if (name == null)
|
||||
name = getName(NameDecoder.NAME_FULL, Locale.ENGLISH);
|
||||
if (name == null)
|
||||
name = getName(NameDecoder.NAME_FULL, /* any language */ null);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the PostScript name of this font face, for example
|
||||
* <i>“Univers-Light”</i>.
|
||||
*
|
||||
* @return the PostScript name, or <code>null</code> if the font
|
||||
* does not provide a PostScript name.
|
||||
*/
|
||||
public synchronized String getPostScriptName()
|
||||
{
|
||||
return getName(NameDecoder.NAME_POSTSCRIPT, /* any language */ null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of glyphs in this font face.
|
||||
*/
|
||||
public int getNumGlyphs()
|
||||
{
|
||||
/* No synchronization is needed because the number of glyphs is
|
||||
* set in the constructor, and it cannot change during the
|
||||
* lifetime of the object.
|
||||
*/
|
||||
return numGlyphs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the index of the glyph which gets displayed if the font
|
||||
* cannot map a Unicode code point to a glyph. Many fonts show this
|
||||
* glyph as an empty box.
|
||||
*/
|
||||
public int getMissingGlyphCode()
|
||||
{
|
||||
/* No synchronization is needed because the result is constant. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The font’s name table, or <code>null</code> if this
|
||||
* table has not yet been accessed.
|
||||
*/
|
||||
private ByteBuffer nameTable;
|
||||
|
||||
|
||||
/**
|
||||
* Extracts a String from the font’s name table.
|
||||
*
|
||||
* @param name the numeric TrueType or OpenType name ID.
|
||||
*
|
||||
* @param locale the locale for which names shall be localized, or
|
||||
* <code>null</code> if the locale does mot matter because the name
|
||||
* is known to be language-independent (for example, because it is
|
||||
* the PostScript name).
|
||||
*/
|
||||
private String getName(int name, Locale locale)
|
||||
{
|
||||
if (nameTable == null)
|
||||
nameTable = getFontTable(OpenType.TAG_NAME);
|
||||
return NameDecoder.getName(nameTable, name, locale);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the version of the font.
|
||||
*
|
||||
* @see java.awt.font.OpenType#getVersion
|
||||
*
|
||||
* @return the version in 16.16 fixed-point encoding, for example
|
||||
* 0x00010000 for version 1.0.
|
||||
*/
|
||||
public int getVersion()
|
||||
{
|
||||
/* No synchronization is needed because the version is set in the
|
||||
* constructor, and it cannot change during the lifetime of the
|
||||
* object.
|
||||
*/
|
||||
return version;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a view buffer for an OpenType table. The caller can
|
||||
* access the returned buffer without needing to synchronize access
|
||||
* from multiple threads.
|
||||
*
|
||||
* @param tag the table identifier, for example
|
||||
* <code>OpenType.GLYF</code>.
|
||||
*
|
||||
* @return a slice of the underlying buffer containing the table, or
|
||||
* <code>null</code> if the font does not contain the requested
|
||||
* table.
|
||||
*/
|
||||
public synchronized ByteBuffer getFontTable(int tag)
|
||||
{
|
||||
int index, start, len;
|
||||
ByteBuffer result;
|
||||
|
||||
index = getTableIndex(tag);
|
||||
if (index < 0)
|
||||
return null;
|
||||
|
||||
start = tableStart[index];
|
||||
len = tableLength[index];
|
||||
buf.limit(start + len).position(start);
|
||||
result = buf.slice();
|
||||
result.limit(len);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the size of one of the tables in the font,
|
||||
* or -1 if the table does not exist.
|
||||
*/
|
||||
public int getFontTableSize(int tag)
|
||||
{
|
||||
int index = getTableIndex(tag);
|
||||
if (index == -1)
|
||||
return index;
|
||||
return tableLength[index];
|
||||
}
|
||||
|
||||
|
||||
private CharGlyphMap getCharGlyphMap()
|
||||
{
|
||||
if (cmap != null)
|
||||
return cmap;
|
||||
|
||||
synchronized (this)
|
||||
{
|
||||
if (cmap == null)
|
||||
{
|
||||
int index = getTableIndex(OpenType.TAG_CMAP);
|
||||
int start = tableStart[index];
|
||||
buf.limit(start + tableLength[index]).position(start);
|
||||
cmap = CharGlyphMap.forTable(buf);
|
||||
}
|
||||
return cmap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Looks up a glyph in the font’s <code>cmap</code> tables,
|
||||
* without performing any glyph substitution or reordering. Because
|
||||
* of this limitation, this method cannot be used for script systems
|
||||
* that need advanced glyph mapping, such as Arabic, Korean, or even
|
||||
* Latin with exotic accents.
|
||||
*
|
||||
* <p>It is safe to call this method from any thread.
|
||||
*
|
||||
* @param ucs4 the Unicode codepoint in the 32-bit Unicode character
|
||||
* set UCS-4. Because UTF-16 surrogates do not correspond to a single
|
||||
* glyph, it does not make sense to pass them here.
|
||||
*
|
||||
* @return the glyph index, or zero if the font does not contain
|
||||
* a glyph for the specified codepoint.
|
||||
*/
|
||||
public int getGlyph(int ucs4)
|
||||
{
|
||||
return getCharGlyphMap().getGlyph(ucs4);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a GlyphVector by mapping each character in a
|
||||
* CharacterIterator to the corresponding glyph.
|
||||
*
|
||||
* <p>The mapping takes only the font’s <code>cmap</code>
|
||||
* tables into consideration. No other operations (such as glyph
|
||||
* re-ordering, composition, or ligature substitution) are
|
||||
* performed. This means that the resulting GlyphVector will not be
|
||||
* correct for text in languages that have complex
|
||||
* character-to-glyph mappings, such as Arabic, Hebrew, Hindi, or
|
||||
* Thai.
|
||||
*
|
||||
* @param font the font object that the created GlyphVector
|
||||
* will return when it gets asked for its font. This argument is
|
||||
* needed because the public API works with java.awt.Font,
|
||||
* not with some private delegate like OpenTypeFont.
|
||||
*
|
||||
* @param frc the font rendering parameters that are used for
|
||||
* measuring glyphs. The exact placement of text slightly depends on
|
||||
* device-specific characteristics, for instance the device
|
||||
* resolution or anti-aliasing. For this reason, any measurements
|
||||
* will only be accurate if the passed
|
||||
* <code>FontRenderContext</code> correctly reflects the relevant
|
||||
* parameters. Hence, <code>frc</code> should be obtained from the
|
||||
* same <code>Graphics2D</code> that will be used for drawing, and
|
||||
* any rendering hints should be set to the desired values before
|
||||
* obtaining <code>frc</code>.
|
||||
*
|
||||
* @param ci a CharacterIterator for iterating over the
|
||||
* characters to be displayed.
|
||||
*/
|
||||
public synchronized GlyphVector createGlyphVector(Font font,
|
||||
FontRenderContext frc,
|
||||
CharacterIterator ci)
|
||||
{
|
||||
CharGlyphMap cmap;
|
||||
int numGlyphs;
|
||||
int[] glyphs;
|
||||
int glyph;
|
||||
int c;
|
||||
|
||||
cmap = getCharGlyphMap();
|
||||
numGlyphs = ci.getEndIndex() - ci.getBeginIndex();
|
||||
glyphs = new int[numGlyphs];
|
||||
glyph = 0;
|
||||
for (c = ci.first(); c != CharacterIterator.DONE; c = ci.next())
|
||||
{
|
||||
/* handle surrogate pairs */
|
||||
if (c >> 10 == 0x36) // U+D800 .. U+DBFF: High surrogate
|
||||
c = (((c & 0x3ff) << 10) | (ci.next() & 0x3ff)) + 0x10000;
|
||||
glyphs[glyph] = cmap.getGlyph(c);
|
||||
glyph += 1;
|
||||
}
|
||||
|
||||
/* If we had surrogates, the allocated array is too large.
|
||||
* Because this will occur very rarely, it seems acceptable to
|
||||
* re-allocate a shorter array and copy the contents around.
|
||||
*/
|
||||
if (glyph != numGlyphs)
|
||||
{
|
||||
int[] newGlyphs = new int[glyph];
|
||||
System.arraycopy(glyphs, 0, newGlyphs, 0, glyph);
|
||||
glyphs = newGlyphs;
|
||||
}
|
||||
|
||||
return new GNUGlyphVector(this, font, frc, glyphs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Determines the advance width for a glyph.
|
||||
*
|
||||
* @param glyphIndex the glyph whose advance width is to be
|
||||
* determined.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialias <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @param advance a point whose <code>x</code> and <code>y</code>
|
||||
* fields will hold the advance in each direction. It is possible
|
||||
* that both values are non-zero, for example if
|
||||
* <code>transform</code> is a rotation, or in the case of Urdu
|
||||
* fonts.
|
||||
*/
|
||||
public synchronized void getAdvance(int glyphIndex,
|
||||
float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal,
|
||||
Point2D advance)
|
||||
{
|
||||
/* Delegate the measurement to the scaler. The synchronization is
|
||||
* needed because the scaler is not synchronized.
|
||||
*/
|
||||
scaler.getAdvance(glyphIndex, pointSize, transform,
|
||||
antialias, fractionalMetrics, horizontal,
|
||||
advance);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the shape of a glyph.
|
||||
*
|
||||
* @param glyph the glyph whose advance width is to be determined
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialias <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts, this
|
||||
* parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional
|
||||
* metrics, <code>false</code> for rounding the result to a pixel
|
||||
* boundary.
|
||||
*
|
||||
* @return the scaled and grid-fitted outline of the specified
|
||||
* glyph, or <code>null</code> for bitmap fonts.
|
||||
*/
|
||||
public synchronized GeneralPath getGlyphOutline(int glyph,
|
||||
float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics)
|
||||
{
|
||||
/* The synchronization is needed because the scaler is not
|
||||
* synchronized.
|
||||
*/
|
||||
return scaler.getOutline(glyph, pointSize, transform,
|
||||
antialias, fractionalMetrics);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a name for the specified glyph. This is useful for
|
||||
* generating PostScript or PDF files that embed some glyphs of a
|
||||
* font.
|
||||
*
|
||||
* <p><b>Names are not unique:</b> Under some rare circumstances,
|
||||
* the same name can be returned for different glyphs. It is
|
||||
* therefore recommended that printer drivers check whether the same
|
||||
* name has already been returned for antoher glyph, and make the
|
||||
* name unique by adding the string ".alt" followed by the glyph
|
||||
* index.</p>
|
||||
*
|
||||
* <p>This situation would occur for an OpenType or TrueType font
|
||||
* that has a <code>post</code> table of format 3 and provides a
|
||||
* mapping from glyph IDs to Unicode sequences through a
|
||||
* <code>Zapf</code> table. If the same sequence of Unicode
|
||||
* codepoints leads to different glyphs (depending on contextual
|
||||
* position, for example, or on typographic sophistication level),
|
||||
* the same name would get synthesized for those glyphs.
|
||||
*
|
||||
* @param glyphIndex the glyph whose name the caller wants to
|
||||
* retrieve.
|
||||
*/
|
||||
public synchronized String getGlyphName(int glyphIndex)
|
||||
{
|
||||
if (glyphNamer == null)
|
||||
glyphNamer = GlyphNamer.forTables(numGlyphs,
|
||||
getFontTable(OpenType.TAG_POST),
|
||||
getFontTable(TAG_ZAPF));
|
||||
|
||||
return glyphNamer.getGlyphName(glyphIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the distance between the base line and the highest
|
||||
* ascender.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialiased <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the ascent, which usually is a positive number.
|
||||
*/
|
||||
public synchronized float getAscent(float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialiased,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal)
|
||||
{
|
||||
return scaler.getAscent(pointSize, transform,
|
||||
antialiased, fractionalMetrics,
|
||||
horizontal);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the distance between the base line and the lowest
|
||||
* descender.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialiased <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the descent, which usually is a nagative number.
|
||||
*/
|
||||
public synchronized float getDescent(float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialiased,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal)
|
||||
{
|
||||
return scaler.getDescent(pointSize, transform,
|
||||
antialiased, fractionalMetrics,
|
||||
horizontal);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts a four-byte tag identifier into a String that can be
|
||||
* displayed when debugging this class.
|
||||
*
|
||||
* @param tag the tag as an <code>int</code>.
|
||||
*
|
||||
* @return the tag in human-readable form, for example
|
||||
* <code>name</code> or <code>glyf</code>.
|
||||
*/
|
||||
static String tagToString(int tag)
|
||||
{
|
||||
char[] c = new char[4];
|
||||
c[0] = (char) ((tag >> 24) & 0xff);
|
||||
c[1] = (char) ((tag >> 16) & 0xff);
|
||||
c[2] = (char) ((tag >> 8) & 0xff);
|
||||
c[3] = (char) (tag & 0xff);
|
||||
return new String(c);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
/* OpenTypeFontFactory.java -- Creates OpenType and TrueType fonts.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.java.awt.font.opentype;
|
||||
|
||||
import gnu.java.awt.font.FontDelegate;
|
||||
import java.awt.FontFormatException;
|
||||
import java.awt.font.OpenType;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
|
||||
/**
|
||||
* A factory for creating fonts that are stored in an
|
||||
* <i>sfnt</i>-housed format, for example OpenType or TrueType.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
public final class OpenTypeFontFactory
|
||||
{
|
||||
/**
|
||||
* The constructor is private so nobody can construct an instance
|
||||
* of this class.
|
||||
*/
|
||||
private OpenTypeFontFactory()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates FontDelegate objects for the fonts in the specified
|
||||
* buffer. The following font formats are currently recognized:
|
||||
*
|
||||
* <p><ul>
|
||||
* <li>OpenType (*.otf);</li>
|
||||
* <li>TrueType (*.ttf);</li>
|
||||
* <li>TrueType Collections (*.ttc);</li>
|
||||
* <li>Apple MacOS X data-fork font (*.dfont).</li></ul>
|
||||
*
|
||||
* <p>Some formats may contain more than a single font, for example
|
||||
* *.ttc and *.dfont files. This is the reason why this function
|
||||
* returns an array.
|
||||
*
|
||||
* <p>The implementation reads data from the buffer only when
|
||||
* needed. Therefore, it greatly increases efficiency if
|
||||
* <code>buf</code> has been obtained through mapping a file into
|
||||
* the virtual address space.
|
||||
*
|
||||
* @throws FontFormatException if the font data is not in one of the
|
||||
* known formats.
|
||||
*/
|
||||
public static FontDelegate[] createFonts(ByteBuffer buf)
|
||||
throws FontFormatException
|
||||
{
|
||||
OpenTypeFont[] fonts;
|
||||
int version;
|
||||
|
||||
version = buf.getInt(0);
|
||||
switch (version)
|
||||
{
|
||||
case 0x00010000: // Microsoft Windows TrueType
|
||||
case OpenType.TAG_TYP1: // Apple MacOS PostScript ('typ1')
|
||||
case OpenTypeFont.TAG_SFNT: // Apple MacOS TrueType ('sfnt')
|
||||
case OpenTypeFont.TAG_TRUE: // Apple MacOS TrueType ('true')
|
||||
case OpenTypeFont.TAG_OTTO: // OpenType
|
||||
return new OpenTypeFont[] { new OpenTypeFont(buf, 0) };
|
||||
}
|
||||
|
||||
|
||||
/* TrueType Collection, see "TrueType Collections" in
|
||||
* http://partners.adobe.com/asn/tech/type/opentype/otff.html
|
||||
*/
|
||||
if (version == OpenTypeFont.TAG_TTCF)
|
||||
{
|
||||
// This code has never been tested.
|
||||
fonts = new OpenTypeFont[buf.getInt(8)];
|
||||
for (int i = 0; i < fonts.length; i++)
|
||||
fonts[i] = new OpenTypeFont(buf, buf.getInt(16 + 4 * i));
|
||||
return fonts;
|
||||
}
|
||||
|
||||
|
||||
/* The MacOS X .dfont format is a Macintosh resource fork in
|
||||
* a normal file, contaning one or several 'sfnt' resources.
|
||||
* Unfortunately, MacOS resource forks have no magic code
|
||||
* that could be used for identification. Instead, we just try
|
||||
* to extract at least one 'sfnt'.
|
||||
*/
|
||||
try
|
||||
{
|
||||
MacResourceFork fork = new MacResourceFork(buf);
|
||||
MacResourceFork.Resource[] rsrc;
|
||||
|
||||
rsrc = fork.getResources(OpenTypeFont.TAG_SFNT);
|
||||
fonts = new OpenTypeFont[rsrc.length];
|
||||
for (int i = 0; i < fonts.length; i++)
|
||||
fonts[i] = new OpenTypeFont(rsrc[i].getContent(), 0);
|
||||
|
||||
return fonts;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
|
||||
throw new FontFormatException("not in OpenType or TrueType format");
|
||||
}
|
||||
}
|
192
libjava/classpath/gnu/java/awt/font/opentype/Scaler.java
Normal file
192
libjava/classpath/gnu/java/awt/font/opentype/Scaler.java
Normal file
|
@ -0,0 +1,192 @@
|
|||
/* Scaler.java -- Common superclass for font scalers.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.java.awt.font.opentype;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
|
||||
/**
|
||||
* An common superclass for all font scalers. The main task of font
|
||||
* scaler is to retrieve a scaled and hinted outline for a glyph.
|
||||
*
|
||||
* <p>To make text more legible, high-quality fonts contain
|
||||
* instructions (sometimes also called “hints”) for
|
||||
* moving the scaled control points towards the coordinate grid of the
|
||||
* display device.
|
||||
*
|
||||
* <p><b>Lack of Thread Safety:</b> Font scalers are intentionally
|
||||
* <i>not</i> safe to access from multiple concurrent
|
||||
* threads. Synchronization needs to be performed externally. Usually,
|
||||
* the font that uses this scaler already has obtained a lock before
|
||||
* calling the scaler.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
public abstract class Scaler
|
||||
{
|
||||
/**
|
||||
* Retrieves the scaled outline of a glyph, adjusting control points
|
||||
* to the raster grid if necessary.
|
||||
*
|
||||
* @param glyph the glyph number whose outline is retrieved.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialias whether or not the rasterizer will perform
|
||||
* anti-aliasing on the returned path.
|
||||
*
|
||||
* @param fractionalMetrics <code>false</code> for adjusting glyph
|
||||
* positions to the raster grid of device space.
|
||||
*
|
||||
* @return the scaled and grid-fitted outline of the specified
|
||||
* glyph, or <code>null</code> for bitmap fonts.
|
||||
*/
|
||||
public abstract GeneralPath getOutline(int glyph,
|
||||
float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics);
|
||||
|
||||
|
||||
/**
|
||||
* Determines the advance width and height for a glyph.
|
||||
*
|
||||
* @param glyphIndex the glyph whose advance width is to be
|
||||
* determined.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialias <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @param advance a point whose <code>x</code> and <code>y</code>
|
||||
* fields will hold the advance in each direction. It is well
|
||||
* possible that both values are non-zero, for example for rotated
|
||||
* text or for Urdu fonts.
|
||||
*/
|
||||
public abstract void getAdvance(int glyphIndex,
|
||||
float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal,
|
||||
Point2D advance);
|
||||
|
||||
|
||||
/**
|
||||
* Determines the distance between the base line and the highest
|
||||
* ascender.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialias <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the ascent, which usually is a positive number.
|
||||
*/
|
||||
public abstract float getAscent(float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal);
|
||||
|
||||
|
||||
/**
|
||||
* Determines the distance between the base line and the lowest
|
||||
* descender.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialiased <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the descent, which usually is a nagative number.
|
||||
*/
|
||||
public abstract float getDescent(float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialiased,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal);
|
||||
}
|
161
libjava/classpath/gnu/java/awt/font/opentype/truetype/Fixed.java
Normal file
161
libjava/classpath/gnu/java/awt/font/opentype/truetype/Fixed.java
Normal file
|
@ -0,0 +1,161 @@
|
|||
/* Fixed.java -- Fixed-point arithmetics for TrueType coordinates.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.font.opentype.truetype;
|
||||
|
||||
|
||||
/**
|
||||
* A utility class for fixed-point arithmetics, where numbers are
|
||||
* represented with 26 dot 6 digits. This representation is used by
|
||||
* TrueType coordinates.
|
||||
*
|
||||
* <p>A good compiler will inline calls of methods in this class.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
final class Fixed
|
||||
{
|
||||
public static final int ONE = 1<<6;
|
||||
|
||||
|
||||
/**
|
||||
* The constructor is private so nobody can use it.
|
||||
*/
|
||||
private Fixed()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Multiplies two fixed-point numbers.
|
||||
*/
|
||||
public static int mul(int a, int b)
|
||||
{
|
||||
return (int) ((((long) a) * b) >> 6);
|
||||
}
|
||||
|
||||
|
||||
public static int div(int a, int b)
|
||||
{
|
||||
return (int) ((((long) a) << 6) / b);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static int ceil(int a)
|
||||
{
|
||||
return (a + 63) & -64;
|
||||
}
|
||||
|
||||
|
||||
public static int floor(int a)
|
||||
{
|
||||
return a & -64;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the length of a fixed-point vector.
|
||||
*/
|
||||
public static int vectorLength(int x, int y)
|
||||
{
|
||||
int shift;
|
||||
float fx, fy;
|
||||
|
||||
if (x == 0)
|
||||
return Math.abs(y);
|
||||
else if (y == 0)
|
||||
return Math.abs(x);
|
||||
|
||||
/* Use the FPU. */
|
||||
fx = ((float) x) / 64.0f;
|
||||
fy = ((float) y) / 64.0f;
|
||||
return (int) (Math.sqrt(fx * fx + fy * fy) * 64.0);
|
||||
}
|
||||
|
||||
|
||||
public static int intValue(int f)
|
||||
{
|
||||
return f >> 6;
|
||||
}
|
||||
|
||||
|
||||
public static float floatValue(int f)
|
||||
{
|
||||
return ((float) f) / 64;
|
||||
}
|
||||
|
||||
|
||||
public static double doubleValue(int f)
|
||||
{
|
||||
return ((double) f) / 64;
|
||||
}
|
||||
|
||||
|
||||
public static int valueOf(float f)
|
||||
{
|
||||
return (int) (f * 64);
|
||||
}
|
||||
|
||||
|
||||
public static int valueOf(double d)
|
||||
{
|
||||
return (int) (d * 64);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Makes a string representation of a fixed-point number.
|
||||
*/
|
||||
public static String toString(int f)
|
||||
{
|
||||
return String.valueOf(floatValue(f));
|
||||
}
|
||||
|
||||
|
||||
public static String toString(int x, int y)
|
||||
{
|
||||
StringBuffer sbuf = new StringBuffer(40);
|
||||
sbuf.append('(');
|
||||
sbuf.append(((float) x) / 64);
|
||||
sbuf.append(", ");
|
||||
sbuf.append(((float) y) / 64);
|
||||
sbuf.append(')');
|
||||
return sbuf.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,437 @@
|
|||
/* GlyphLoader.java -- Helper for loading TrueType glyph outlines.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.font.opentype.truetype;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
|
||||
/**
|
||||
* A class for loading scaled and hinted glyph outlines.
|
||||
*
|
||||
* <p><b>Lack of Thread Safety:</b> Glyph loaders are intentionally
|
||||
* <i>not</i> safe to access from multiple concurrent
|
||||
* threads. Synchronization needs to be performed externally. Usually,
|
||||
* the font has already obtained a lock before calling the scaler,
|
||||
* which in turn calls the GlyphLoader. It would thus be wasteful to
|
||||
* acquire additional locks for the GlyphLoader.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
final class GlyphLoader
|
||||
{
|
||||
/**
|
||||
* A helper object for locating glyph data. GlyphLocator is an
|
||||
* abstract superclass, and there is a concretization for each glyph
|
||||
* location table ('loca') format.
|
||||
*/
|
||||
private final GlyphLocator glyphLocator;
|
||||
|
||||
|
||||
/**
|
||||
* A helper object for measuring the advance width and height of a
|
||||
* glyph.
|
||||
*/
|
||||
private final GlyphMeasurer glyphMeasurer;
|
||||
|
||||
|
||||
/**
|
||||
* The virtual machine for executing TrueType bytecodes.
|
||||
*/
|
||||
private final VirtualMachine vm;
|
||||
|
||||
|
||||
/**
|
||||
* The number of font units in one em. A typical value is 2048,
|
||||
* but this depends on the font.
|
||||
*/
|
||||
private final int unitsPerEm;
|
||||
|
||||
private final int[] contourEndPoints;
|
||||
private final byte[] pointFlags;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a GlyphLoader.
|
||||
*/
|
||||
GlyphLoader(GlyphLocator glyphLocator, VirtualMachine vm,
|
||||
int unitsPerEm, int maxContours, int maxPoints,
|
||||
GlyphMeasurer glyphMeasurer)
|
||||
{
|
||||
this.glyphLocator = glyphLocator;
|
||||
this.glyphMeasurer = glyphMeasurer;
|
||||
this.unitsPerEm = unitsPerEm;
|
||||
this.vm = vm;
|
||||
|
||||
contourEndPoints = new int[maxContours];
|
||||
pointFlags = new byte[maxPoints];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param glyphIndex the number of the glyph whose outlines are to be
|
||||
* retrieved.
|
||||
*/
|
||||
public void loadGlyph(int glyphIndex,
|
||||
double pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
Zone glyphZone)
|
||||
{
|
||||
glyphZone.setNumPoints(4);
|
||||
loadSubGlyph(glyphIndex, pointSize, transform, antialias, glyphZone,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
|
||||
private void loadSubGlyph(int glyphIndex,
|
||||
double pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
Zone glyphZone,
|
||||
int preTranslateX,
|
||||
int preTranslateY)
|
||||
{
|
||||
ByteBuffer glyph;
|
||||
int numContours;
|
||||
int xMin, yMin, xMax, yMax;
|
||||
byte flag;
|
||||
|
||||
glyph = glyphLocator.getGlyphData(glyphIndex);
|
||||
|
||||
if (glyph == null)
|
||||
{
|
||||
glyphZone.setNumPoints(4);
|
||||
setPhantomPoints(glyphIndex, 0, glyphZone);
|
||||
glyphZone.transform(pointSize, transform, unitsPerEm,
|
||||
preTranslateX, preTranslateY);
|
||||
return;
|
||||
}
|
||||
|
||||
numContours = glyph.getShort();
|
||||
xMin = glyph.getChar();
|
||||
yMin = glyph.getChar();
|
||||
xMax = glyph.getChar();
|
||||
yMax = glyph.getChar();
|
||||
|
||||
|
||||
if (numContours >= 0)
|
||||
loadSimpleGlyph(glyphIndex, pointSize, transform, antialias,
|
||||
numContours, glyph, glyphZone,
|
||||
preTranslateX, preTranslateY);
|
||||
else
|
||||
loadCompoundGlyph(glyphIndex, pointSize, transform, antialias,
|
||||
glyph, glyphZone,
|
||||
preTranslateX, preTranslateY);
|
||||
}
|
||||
|
||||
|
||||
private void loadSimpleGlyph(int glyphIndex,
|
||||
double pointSize, AffineTransform transform,
|
||||
boolean antialias,
|
||||
int numContours, ByteBuffer glyph,
|
||||
Zone glyphZone,
|
||||
int preTranslateX, int preTranslateY)
|
||||
{
|
||||
int numPoints;
|
||||
int posInstructions, numInstructions;
|
||||
boolean execInstructions;
|
||||
|
||||
execInstructions = vm.setup(pointSize, transform, antialias);
|
||||
|
||||
/* Load the contour end points and determine the number of
|
||||
* points.
|
||||
*/
|
||||
for (int i = 0; i < numContours; i++)
|
||||
contourEndPoints[i] = glyph.getChar();
|
||||
if (numContours > 0)
|
||||
numPoints = 1 + contourEndPoints[numContours - 1];
|
||||
else
|
||||
numPoints = 0;
|
||||
glyphZone.setNumPoints(numPoints + 4);
|
||||
|
||||
numInstructions = glyph.getChar();
|
||||
posInstructions = glyph.position();
|
||||
glyph.position(posInstructions + numInstructions);
|
||||
loadFlags(numPoints, glyph);
|
||||
loadCoordinates(numPoints, glyph, glyphZone);
|
||||
for (int i = 0; i < numContours; i++)
|
||||
glyphZone.setContourEnd(contourEndPoints[i], true);
|
||||
|
||||
setPhantomPoints(glyphIndex, numPoints, glyphZone);
|
||||
glyphZone.transform(pointSize, transform, unitsPerEm,
|
||||
preTranslateX, preTranslateY);
|
||||
|
||||
if (execInstructions)
|
||||
{
|
||||
// FIXME: Hint the glyph.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final short ARGS_ARE_WORDS = 1;
|
||||
private static final short ARGS_ARE_XY_VALUES = 2;
|
||||
private static final short ROUND_XY_TO_GRID = 4;
|
||||
private static final short WE_HAVE_A_SCALE = 8;
|
||||
private static final short MORE_COMPONENTS = 32;
|
||||
private static final short WE_HAVE_AN_X_AND_Y_SCALE = 64;
|
||||
private static final short WE_HAVE_A_TWO_BY_TWO = 128;
|
||||
private static final short WE_HAVE_INSTRUCTIONS = 256;
|
||||
private static final short USE_MY_METRICS = 512;
|
||||
private static final short OVERLAP_COMPOUND = 1024;
|
||||
private static final short SCALED_COMPONENT_OFFSET = 2048;
|
||||
private static final short UNSCALED_COMPONENT_OFFSET = 4096;
|
||||
|
||||
private void loadCompoundGlyph(int glyphIndex,
|
||||
double pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
ByteBuffer glyph,
|
||||
Zone glyphZone,
|
||||
int preTranslateX, int preTranslateY)
|
||||
{
|
||||
short flags;
|
||||
int subGlyphIndex;
|
||||
int metricsGlyphIndex;
|
||||
Zone subGlyphZone = new Zone(glyphZone.getCapacity());
|
||||
int arg1, arg2;
|
||||
double a, b, c, d, e, f;
|
||||
AffineTransform componentTransform = new AffineTransform();
|
||||
|
||||
/* By default, use the metrics of the compound glyph. The default
|
||||
* is overridden if some component glyph has the USE_MY_METRICS
|
||||
* flag set.
|
||||
*/
|
||||
metricsGlyphIndex = glyphIndex;
|
||||
|
||||
do
|
||||
{
|
||||
flags = glyph.getShort();
|
||||
subGlyphIndex = glyph.getChar();
|
||||
|
||||
if ((flags & USE_MY_METRICS) != 0)
|
||||
metricsGlyphIndex = subGlyphIndex;
|
||||
|
||||
if ((flags & ARGS_ARE_WORDS) != 0)
|
||||
{
|
||||
arg1 = glyph.getShort();
|
||||
arg2 = glyph.getShort();
|
||||
}
|
||||
else
|
||||
{
|
||||
arg1 = glyph.get();
|
||||
arg2 = glyph.get();
|
||||
}
|
||||
|
||||
if ((flags & WE_HAVE_A_SCALE) != 0)
|
||||
{
|
||||
a = d = getDouble214(glyph);
|
||||
b = c = 0.0;
|
||||
}
|
||||
else if ((flags & WE_HAVE_AN_X_AND_Y_SCALE) != 0)
|
||||
{
|
||||
a = getDouble214(glyph);
|
||||
d = getDouble214(glyph);
|
||||
b = c = 0.0;
|
||||
}
|
||||
else if ((flags & WE_HAVE_A_TWO_BY_TWO) != 0)
|
||||
{
|
||||
a = getDouble214(glyph);
|
||||
b = getDouble214(glyph);
|
||||
c = getDouble214(glyph);
|
||||
d = getDouble214(glyph);
|
||||
}
|
||||
else
|
||||
{
|
||||
a = d = 1.0;
|
||||
b = c = 0.0;
|
||||
}
|
||||
|
||||
double m = Math.max(Math.abs(a), Math.abs(b));
|
||||
double n = Math.max(Math.abs(c), Math.abs(d));
|
||||
|
||||
/* The Apple TrueType specification actually says that m is
|
||||
* multiplied by two if
|
||||
*
|
||||
* abs(abs(a) - abs(c)) <= 33/65536,
|
||||
*
|
||||
* but this is probably a typo. On 2003-07-23, Sascha Brawer
|
||||
* wrote an e-mail message to applefonts@apple.com, asking
|
||||
* whether this might possibly be an error in the specification.
|
||||
*/
|
||||
if (Math.abs(Math.abs(a) - Math.abs(b)) <= 33.0/65536.0)
|
||||
m = m * 2;
|
||||
|
||||
if (Math.abs(Math.abs(c) - Math.abs(d)) <= 33.0/65536.0)
|
||||
n = n * 2;
|
||||
|
||||
if ((flags & ARGS_ARE_XY_VALUES) != 0)
|
||||
{
|
||||
e = m * arg1;
|
||||
f = n * arg2;
|
||||
}
|
||||
else
|
||||
e = f = 0.0;
|
||||
|
||||
componentTransform.setTransform(a, b, c, d, 0.0, 0.0);
|
||||
|
||||
// System.out.println("componentTransform = " + componentTransform
|
||||
// + ", e=" + e + ", f=" + f);
|
||||
componentTransform.concatenate(transform);
|
||||
|
||||
int pos = glyph.position();
|
||||
int lim = glyph.limit();
|
||||
|
||||
loadSubGlyph(subGlyphIndex, pointSize, componentTransform,
|
||||
antialias, subGlyphZone,
|
||||
Math.round((float) e + preTranslateX),
|
||||
Math.round(-((float) f + preTranslateY)));
|
||||
glyphZone.combineWithSubGlyph(subGlyphZone, 4);
|
||||
glyph.limit(lim).position(pos);
|
||||
}
|
||||
while ((flags & MORE_COMPONENTS) != 0);
|
||||
|
||||
setPhantomPoints(metricsGlyphIndex, glyphZone.getSize() - 4, glyphZone);
|
||||
}
|
||||
|
||||
|
||||
private double getDouble214(ByteBuffer buf)
|
||||
{
|
||||
return ((double) buf.getShort()) / (1 << 14);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Loads the per-point flags of a glyph into the
|
||||
* <code>pointFlags</code> field.
|
||||
*/
|
||||
private void loadFlags(int numPoints, ByteBuffer glyph)
|
||||
{
|
||||
byte flag;
|
||||
int numRepetitions;
|
||||
|
||||
for (int i = 0; i < numPoints; i++)
|
||||
{
|
||||
pointFlags[i] = flag = glyph.get();
|
||||
if ((flag & 8) != 0)
|
||||
{
|
||||
numRepetitions = ((int) glyph.get()) & 0xff;
|
||||
while (numRepetitions > 0)
|
||||
{
|
||||
pointFlags[++i] = flag;
|
||||
--numRepetitions;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void loadCoordinates(int numPoints, ByteBuffer glyph,
|
||||
Zone glyphZone)
|
||||
{
|
||||
int x, y;
|
||||
byte flag;
|
||||
|
||||
x = 0;
|
||||
for (int i = 0; i < numPoints; i++)
|
||||
{
|
||||
flag = pointFlags[i];
|
||||
if ((flag & 2) == 0)
|
||||
{
|
||||
if ((flag & 16) == 0)
|
||||
x += glyph.getShort();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((flag & 16) != 0)
|
||||
x += (glyph.get() & 0xff);
|
||||
else
|
||||
x -= (glyph.get() & 0xff);
|
||||
}
|
||||
glyphZone.setOriginalX(i, x);
|
||||
glyphZone.setOnCurve(i, (flag & 1) == 1);
|
||||
}
|
||||
|
||||
y = 0;
|
||||
for (int i = 0; i < numPoints; i++)
|
||||
{
|
||||
flag = pointFlags[i];
|
||||
if ((flag & 4) == 0)
|
||||
{
|
||||
if ((flag & 32) == 0)
|
||||
y += glyph.getShort();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((flag & 32) != 0)
|
||||
y += (glyph.get() & 0xff);
|
||||
else
|
||||
y -= (glyph.get() & 0xff);
|
||||
}
|
||||
glyphZone.setOriginalY(i, -y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setPhantomPoints(int glyphIndex, int numPoints,
|
||||
Zone glyphZone)
|
||||
{
|
||||
/* Phantom point 0: Character origin. */
|
||||
glyphZone.setOriginalX(numPoints, 0);
|
||||
glyphZone.setOriginalY(numPoints, 0);
|
||||
|
||||
/* Phantom point 1: Horizontal advance point. */
|
||||
glyphZone.setOriginalX(numPoints + 1,
|
||||
glyphMeasurer.getAdvanceWidth(glyphIndex, true));
|
||||
glyphZone.setOriginalY(numPoints + 1,
|
||||
glyphMeasurer.getAdvanceHeight(glyphIndex, true));
|
||||
|
||||
/* Phantom point 2: Vertical origin. */
|
||||
int vertX = glyphMeasurer.getAscent(/* vertical */ false);
|
||||
int vertY = glyphMeasurer.getAscent(/* horizontal */ true);
|
||||
glyphZone.setOriginalX(numPoints + 2, vertX);
|
||||
glyphZone.setOriginalY(numPoints + 2, vertY);
|
||||
|
||||
/* Phantom point 3: Vertical advance point. */
|
||||
glyphZone.setOriginalX(numPoints + 3,
|
||||
vertX + glyphMeasurer.getAdvanceWidth(glyphIndex, false));
|
||||
glyphZone.setOriginalY(numPoints + 3,
|
||||
vertY + glyphMeasurer.getAdvanceHeight(glyphIndex, false));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,187 @@
|
|||
/* GlyphLocator.java -- Locates outlines of TrueType glyphs.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.java.awt.font.opentype.truetype;
|
||||
|
||||
import java.awt.FontFormatException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
|
||||
/**
|
||||
* Locates glyph outlines in a TrueType or OpenType <code>glyf</code>
|
||||
* table.
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://partners.adobe.com/asn/tech/type/opentype/loca.html"
|
||||
* >Adobe’s specification of the OpenType ‘loca’
|
||||
* table</a>
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
abstract class GlyphLocator
|
||||
{
|
||||
/**
|
||||
* The actual glyph data of the font, which is contained in the
|
||||
* 'glyf' table.
|
||||
*/
|
||||
protected ByteBuffer glyfTable;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new GlyphLocator for a <code>loca</code> table.
|
||||
*
|
||||
* @param format the format of the <code>loca</code> table. The
|
||||
* value must be 0 for two-byte offsets, or 1 for four-byte
|
||||
* offsets. TrueType and OpenType fonts indicate the format in the
|
||||
* <code>indexToLoc</code> field of the <a href=
|
||||
* "http://partners.adobe.com/asn/tech/type/opentype/head.html"
|
||||
* >font header</a>.
|
||||
*
|
||||
* @param loca the <code>loca</code> table of the font, which
|
||||
* contains the position of each glyph in the <code>glyf</code>
|
||||
* table.
|
||||
*
|
||||
* @param glyf the <code>glyf</code> table of the font, which
|
||||
* contains the outline data of each glyph.
|
||||
*
|
||||
* @throws FontFormatException if <code>format</code> is neither 0
|
||||
* nor 1.
|
||||
*/
|
||||
public static GlyphLocator forTable(int format, ByteBuffer loca,
|
||||
ByteBuffer glyf)
|
||||
throws FontFormatException
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case 0:
|
||||
return new GlyphLocator.TwoByte(loca, glyf);
|
||||
|
||||
case 1:
|
||||
return new GlyphLocator.FourByte(loca, glyf);
|
||||
|
||||
default:
|
||||
throw new FontFormatException("unsupported loca format");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Locates the outline data for a glyph.
|
||||
*
|
||||
* <p>For efficiency, the glyph locator does not create a new buffer
|
||||
* for each invocation. Instead, this method always returns the same
|
||||
* buffer object. Therefore, the data of a glyph must have been read
|
||||
* completely before another glyph of the same font gets requested
|
||||
* through this method.
|
||||
*
|
||||
* @param glyph the number of the glyph whose outlines are to be
|
||||
* retrieved.
|
||||
*
|
||||
* @return a buffer whose position is set to the first byte of glyph
|
||||
* data, and whose limit is set to disallow accessing any data that
|
||||
* does not belong to the glyph. If there is no outline data for the
|
||||
* requested glyph, as would be the case for the space glyph, the
|
||||
* result will be <code>null</code>.
|
||||
*/
|
||||
public abstract ByteBuffer getGlyphData(int glyph);
|
||||
|
||||
|
||||
/**
|
||||
* A GlyphLocator that locates glyphs using two-byte offsets,
|
||||
* interpreting <code>loca</code> tables of format 0.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
private final static class TwoByte
|
||||
extends GlyphLocator
|
||||
{
|
||||
final CharBuffer indexToLoc;
|
||||
|
||||
TwoByte(ByteBuffer loca, ByteBuffer glyf)
|
||||
{
|
||||
this.glyfTable = glyf;
|
||||
indexToLoc = loca.asCharBuffer();
|
||||
}
|
||||
|
||||
|
||||
public ByteBuffer getGlyphData(int glyph)
|
||||
{
|
||||
int offset, limit;
|
||||
offset = ((int) indexToLoc.get(glyph)) << 1;
|
||||
limit = ((int) indexToLoc.get(glyph + 1)) << 1;
|
||||
if (offset >= limit)
|
||||
return null;
|
||||
|
||||
glyfTable.limit(limit).position(offset);
|
||||
return glyfTable;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A GlyphLocator that locates glyphs using four-byte offsets,
|
||||
* interpreting <code>loca</code> tables of format 1.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
private final static class FourByte
|
||||
extends GlyphLocator
|
||||
{
|
||||
final IntBuffer indexToLoc;
|
||||
|
||||
FourByte(ByteBuffer loca, ByteBuffer glyf)
|
||||
{
|
||||
this.glyfTable = glyf;
|
||||
indexToLoc = loca.asIntBuffer();
|
||||
}
|
||||
|
||||
|
||||
public ByteBuffer getGlyphData(int glyph)
|
||||
{
|
||||
int offset, limit;
|
||||
offset = indexToLoc.get(glyph);
|
||||
limit = indexToLoc.get(glyph + 1);
|
||||
if (offset >= limit)
|
||||
return null;
|
||||
|
||||
glyfTable.limit(limit).position(offset);
|
||||
return glyfTable;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,228 @@
|
|||
/* GlyphMeasurer.java -- Helper for measuring TrueType glyphs.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.font.opentype.truetype;
|
||||
|
||||
import java.awt.FontFormatException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
|
||||
/**
|
||||
* A class for measuring TrueType and OpenType glyphs.
|
||||
*
|
||||
* <p><b>Lack of Thread Safety:</b> Glyph measurers are intentionally
|
||||
* <i>not</i> safe to access from multiple concurrent
|
||||
* threads. Synchronization needs to be performed externally. Usually,
|
||||
* the font has already obtained a lock before calling the scaler,
|
||||
* which in turn calls the GlyphMeasurer. It would thus be wasteful to
|
||||
* acquire additional locks for the GlyphMeasurer.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
final class GlyphMeasurer
|
||||
{
|
||||
/**
|
||||
* A view buffer that allows accessing the contents of the
|
||||
* font’s <code>hmtx</code> table as shorts.
|
||||
*/
|
||||
private final ShortBuffer horizontalGlyphMetrics;
|
||||
|
||||
|
||||
/**
|
||||
* A view buffer that allows accessing the contents of the
|
||||
* font’s <code>vmtx</code> table as shorts.
|
||||
*/
|
||||
private final ShortBuffer verticalGlyphMetrics;
|
||||
|
||||
|
||||
private final int numLongHorizontalMetricsEntries;
|
||||
private final int numLongVerticalMetricsEntries;
|
||||
|
||||
private final int horizontalAscent;
|
||||
private final int verticalAscent;
|
||||
|
||||
private final int horizontalDescent;
|
||||
private final int verticalDescent;
|
||||
|
||||
private final int horizontalLineGap;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a GlyphMeasurer from TrueType/OpenType font tables.
|
||||
*
|
||||
* @param hhea the <code>hhea</code> table, which contains
|
||||
* information about horizontal metrics that is common to all
|
||||
* glyphs.
|
||||
*
|
||||
* @param hmtx the <code>hmtx</code> table, which contains
|
||||
* glyph-specific information about horizontal metrics.
|
||||
*
|
||||
* @param vhea the <code>vhea</code> table, which contains
|
||||
* information about vertical metrics that is common to all
|
||||
* glyphs. If a font does not provide such a table, pass
|
||||
* <code>null</code>.
|
||||
*
|
||||
* @param vmtx the <code>vmtx</code> table, which contains
|
||||
* glyph-specific information about vertical metrics. If a font
|
||||
* does not provide such a table, pass <code>null</code>.
|
||||
*/
|
||||
GlyphMeasurer(ByteBuffer hhea, ByteBuffer hmtx,
|
||||
ByteBuffer vhea, ByteBuffer vmtx)
|
||||
throws FontFormatException
|
||||
{
|
||||
if ((hhea.getInt(0) != 0x00010000) || (hhea.getInt(30) != 0))
|
||||
throw new FontFormatException("unsupported hhea format");
|
||||
|
||||
horizontalAscent = hhea.getShort(4);
|
||||
horizontalDescent = hhea.getShort(6);
|
||||
horizontalLineGap = hhea.getShort(8);
|
||||
|
||||
numLongHorizontalMetricsEntries = hhea.getChar(34);
|
||||
horizontalGlyphMetrics = hmtx.asShortBuffer();
|
||||
|
||||
if (vhea != null)
|
||||
{
|
||||
verticalAscent = vhea.getShort(4);
|
||||
verticalDescent = vhea.getShort(6);
|
||||
numLongVerticalMetricsEntries = vhea.getChar(34);
|
||||
verticalGlyphMetrics = vmtx.asShortBuffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
verticalAscent = /* advanceWidthMax */ hhea.getChar(10) / 2;
|
||||
verticalDescent = -verticalAscent;
|
||||
numLongVerticalMetricsEntries = 0;
|
||||
verticalGlyphMetrics = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the distance from the baseline to the highest ascender.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the maximal ascent, in font units.
|
||||
*/
|
||||
public int getAscent(boolean horizontal)
|
||||
{
|
||||
return horizontal ? horizontalAscent : verticalAscent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the distance from the baseline to the lowest descender.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the maximal descent, in font units.
|
||||
*/
|
||||
public int getDescent(boolean horizontal)
|
||||
{
|
||||
return horizontal ? horizontalDescent : verticalDescent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the typographic line gap.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the line gap, in font units.
|
||||
*/
|
||||
public int getLineGap(boolean horizontal)
|
||||
{
|
||||
return horizontalLineGap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the advance width of a glyph, without considering
|
||||
* hinting.
|
||||
*
|
||||
* @param glyphIndex the index of the glyph whose advance width is
|
||||
* to be determined.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the advance width, in font units.
|
||||
*/
|
||||
public int getAdvanceWidth(int glyphIndex, boolean horizontal)
|
||||
{
|
||||
if (!horizontal)
|
||||
return 0;
|
||||
|
||||
glyphIndex = Math.min(glyphIndex,
|
||||
numLongHorizontalMetricsEntries - 1);
|
||||
return horizontalGlyphMetrics.get(glyphIndex << 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the advance width of a glyph, without considering
|
||||
* hinting.
|
||||
*
|
||||
* @param glyphIndex the index of the glyph whose advance width is
|
||||
* to be determined.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the advance width, in font units.
|
||||
*/
|
||||
public int getAdvanceHeight(int glyphIndex, boolean horizontal)
|
||||
{
|
||||
if (horizontal)
|
||||
return 0;
|
||||
|
||||
/* If a font does not provide vertical glyph metrics, advance
|
||||
* by the height of one horizontal line.
|
||||
*/
|
||||
if (verticalGlyphMetrics == null)
|
||||
return horizontalAscent - horizontalDescent + horizontalLineGap;
|
||||
|
||||
glyphIndex = Math.min(glyphIndex,
|
||||
numLongVerticalMetricsEntries - 1);
|
||||
return verticalGlyphMetrics.get(glyphIndex << 1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,372 @@
|
|||
/* TrueTypeScaler.java -- Font scaler for TrueType outlines.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.java.awt.font.opentype.truetype;
|
||||
|
||||
import gnu.java.awt.font.opentype.Scaler;
|
||||
|
||||
import java.awt.FontFormatException;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
|
||||
/**
|
||||
* A scaler for fonts whose outlines are described in the TrueType
|
||||
* format.
|
||||
*
|
||||
* <p><b>Lack of Thread Safety:</b> Font scalers are intentionally
|
||||
* <i>not</i> safe to access from multiple concurrent threads.
|
||||
* Synchronization needs to be performed externally. Usually, the font
|
||||
* that uses this scaler already has obtained a lock before calling
|
||||
* the scaler.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
public final class TrueTypeScaler
|
||||
extends Scaler
|
||||
{
|
||||
/**
|
||||
* The TrueType or OpenType table that contains the glyph outlines.
|
||||
*/
|
||||
private ByteBuffer glyfTable;
|
||||
|
||||
|
||||
/**
|
||||
* A helper object for loading glyph outlines.
|
||||
*/
|
||||
private GlyphLoader glyphLoader;
|
||||
|
||||
|
||||
/**
|
||||
* A helper object for measuring the advance width and height of a
|
||||
* glyph.
|
||||
*/
|
||||
private final GlyphMeasurer glyphMeasurer;
|
||||
|
||||
private final Zone glyphZone;
|
||||
|
||||
|
||||
/**
|
||||
* The number of units per em. A typical value is 2048, but some
|
||||
* font use other numbers as well.
|
||||
*/
|
||||
private int unitsPerEm;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new TrueTypeScaler.
|
||||
*
|
||||
* @param unitsPerEm the number of font units per em. This value can
|
||||
* be retrieved from the font’s <code>head</code> table.
|
||||
*
|
||||
* @param maxp the <code>maxp</code> table of the font, which
|
||||
* contains various constants needed for setting up the virtual
|
||||
* machine that interprets TrueType bytecodes.
|
||||
*
|
||||
* @param controlValueTable the <code>cvt</code> table of the font,
|
||||
* which contains the initial values of the control value table.
|
||||
*
|
||||
* @param fpgm the <code>fpgm</code> table of the font, which
|
||||
* contains a font program that is executed exactly once. The
|
||||
* purpose of the font program is to define functions and to patch
|
||||
* the interpreter.
|
||||
*
|
||||
* @param locaFormat the format of the <code>loca</code> table. The
|
||||
* value must be 0 for two-byte offsets, or 1 for four-byte
|
||||
* offsets. TrueType and OpenType fonts indicate the format in the
|
||||
* <code>indexToLoc</code> field of the <a href=
|
||||
* "http://partners.adobe.com/asn/tech/type/opentype/head.html"
|
||||
* >font header</a>.
|
||||
*
|
||||
* @param loca the <code>loca</code> table of the font, which
|
||||
* contains for each glyph the offset of its outline data
|
||||
* in <code>glyf</code>.
|
||||
*
|
||||
* @param glyf the <code>glyf</code> table of the font, which
|
||||
* contains the outline data for all glyphs in the font.
|
||||
*
|
||||
* @param preProgram the <code>prep</code> table of the font, which
|
||||
* contains a program that is executed whenever the point size or
|
||||
* the device transform have changed. This program is called
|
||||
* pre-program because it gets executed before the instructions of
|
||||
* the individual glyphs. If the font does not contain a
|
||||
* pre-program, pass <code>null</code>.
|
||||
*
|
||||
* @throws FontFormatException if <code>format</code> is neither 0
|
||||
* nor 1.
|
||||
*/
|
||||
public TrueTypeScaler(int unitsPerEm,
|
||||
ByteBuffer hhea,
|
||||
ByteBuffer htmx,
|
||||
ByteBuffer vhea,
|
||||
ByteBuffer vtmx,
|
||||
ByteBuffer maxp,
|
||||
ByteBuffer controlValueTable,
|
||||
ByteBuffer fpgm,
|
||||
int locaFormat, ByteBuffer loca,
|
||||
ByteBuffer glyf,
|
||||
ByteBuffer preProgram)
|
||||
throws FontFormatException
|
||||
{
|
||||
int maxContours, maxPoints;
|
||||
VirtualMachine vm;
|
||||
|
||||
maxContours = Math.max(/* maxContours */ (int) maxp.getChar(8),
|
||||
/* maxCompositeContours */ (int) maxp.getChar(12))
|
||||
+ /* fix for some broken fonts */ 8;
|
||||
maxPoints = Math.max(/* maxPoints */ (int) maxp.getChar(6),
|
||||
/* maxCompositePoints */ (int) maxp.getChar(10))
|
||||
+ /* fix for some broken fonts */ 12;
|
||||
|
||||
|
||||
glyphZone = new Zone(maxPoints + /* four phantom points */ 4);
|
||||
this.glyfTable = glyf;
|
||||
vm = new VirtualMachine(unitsPerEm, maxp,
|
||||
controlValueTable, fpgm,
|
||||
preProgram);
|
||||
|
||||
GlyphLocator locator = GlyphLocator.forTable(locaFormat, loca, glyf);
|
||||
glyphMeasurer = new GlyphMeasurer(hhea, htmx, vhea, vtmx);
|
||||
glyphLoader = new GlyphLoader(locator, vm, unitsPerEm,
|
||||
maxContours, maxPoints,
|
||||
glyphMeasurer);
|
||||
|
||||
this.unitsPerEm = unitsPerEm;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the scaled outline of a glyph, adjusting control points
|
||||
* to the raster grid if necessary.
|
||||
*
|
||||
* @param glyphIndex the glyph number whose outline is retrieved.
|
||||
*
|
||||
* @param pointSize the point size for the glyph.
|
||||
*
|
||||
* @param deviceTransform an affine transformation for the device.
|
||||
*
|
||||
* @param antialias whether or not the rasterizer will perform
|
||||
* anti-aliasing on the returned path.
|
||||
*
|
||||
* @param fractionalMetrics <code>false</code> for adjusting glyph
|
||||
* positions to the raster grid of device space.
|
||||
*/
|
||||
public GeneralPath getOutline(int glyphIndex,
|
||||
float pointSize,
|
||||
AffineTransform deviceTransform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics)
|
||||
{
|
||||
glyphLoader.loadGlyph(glyphIndex, pointSize, deviceTransform,
|
||||
antialias, glyphZone);
|
||||
return glyphZone.getPath();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the advance width and height for a glyph.
|
||||
*
|
||||
* @param glyphIndex the glyph whose advance width and height is to
|
||||
* be determined.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialias <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @param advance a point whose <code>x</code> and <code>y</code>
|
||||
* fields will hold the advance in each direction. It is possible
|
||||
* that both values are non-zero, for example if
|
||||
* <code>transform</code> is a rotation, or in the case of Urdu
|
||||
* fonts.
|
||||
*/
|
||||
public void getAdvance(int glyphIndex,
|
||||
float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal,
|
||||
Point2D advance)
|
||||
{
|
||||
double x, y;
|
||||
double scaleFactor = (double) pointSize / unitsPerEm;
|
||||
|
||||
/* FIXME: Should grid-fit if needed. Also, use cache if present
|
||||
* in the font.
|
||||
*/
|
||||
advance.setLocation(
|
||||
scaleFactor * glyphMeasurer.getAdvanceWidth(glyphIndex, horizontal),
|
||||
scaleFactor * glyphMeasurer.getAdvanceHeight(glyphIndex, horizontal));
|
||||
|
||||
transform.transform(advance, advance);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Scales a value from font units to pixels, given the point size
|
||||
* and the transform.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional
|
||||
* metrics, <code>false</code> for rounding the result to a pixel
|
||||
* boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> if the <code>funits</code>
|
||||
* value is along the x axis, <code>false</code> if it is along the
|
||||
* y axis.
|
||||
*/
|
||||
private float scaleFromFUnits(int funits,
|
||||
float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal)
|
||||
{
|
||||
double s;
|
||||
|
||||
s = (double) pointSize / unitsPerEm;
|
||||
if (transform != null)
|
||||
s *= horizontal ? transform.getScaleY() : transform.getScaleX();
|
||||
s *= funits;
|
||||
if (!fractionalMetrics)
|
||||
s = Math.round(s);
|
||||
return (float) s;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the distance between the base line and the highest
|
||||
* ascender.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialias <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the ascent, which usually is a positive number.
|
||||
*/
|
||||
public float getAscent(float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal)
|
||||
{
|
||||
/* Note that the ascent is orthogonal to the direction of line
|
||||
* layout: If the line direction is horizontal, the measurement of
|
||||
* ascent is along the vertical axis, and vice versa.
|
||||
*/
|
||||
return scaleFromFUnits(glyphMeasurer.getAscent(horizontal),
|
||||
pointSize,
|
||||
transform,
|
||||
fractionalMetrics,
|
||||
/* reverse */ !horizontal);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the distance between the base line and the lowest
|
||||
* descender.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialiased <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the descent, which usually is a nagative number.
|
||||
*/
|
||||
public float getDescent(float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialiased,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal)
|
||||
{
|
||||
/* Note that the descent is orthogonal to the direction of line
|
||||
* layout: If the line direction is horizontal, the measurement of
|
||||
* descent is along the vertical axis, and vice versa.
|
||||
*/
|
||||
return scaleFromFUnits(glyphMeasurer.getDescent(horizontal),
|
||||
pointSize,
|
||||
transform,
|
||||
fractionalMetrics,
|
||||
/* reverse */ !horizontal);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
243
libjava/classpath/gnu/java/awt/font/opentype/truetype/Zone.java
Normal file
243
libjava/classpath/gnu/java/awt/font/opentype/truetype/Zone.java
Normal file
|
@ -0,0 +1,243 @@
|
|||
/* Zone.java -- A collection of points with some additional information.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.java.awt.font.opentype.truetype;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.PathIterator;
|
||||
|
||||
|
||||
/**
|
||||
* A collection of points with some additional information.
|
||||
*/
|
||||
final class Zone
|
||||
{
|
||||
private final int[] pos;
|
||||
private final int[] origPos;
|
||||
private final byte[] flags;
|
||||
private int numPoints;
|
||||
|
||||
private static final int FLAG_TOUCHED_X = 1;
|
||||
private static final int FLAG_TOUCHED_Y = 2;
|
||||
private static final int FLAG_ON_CURVE = 4;
|
||||
private static final int FLAG_CONTOUR_END = 8;
|
||||
|
||||
public Zone(int maxNumPoints)
|
||||
{
|
||||
origPos = new int[maxNumPoints * 2];
|
||||
pos = new int[maxNumPoints * 2];
|
||||
flags = new byte[maxNumPoints];
|
||||
}
|
||||
|
||||
|
||||
public int getCapacity()
|
||||
{
|
||||
return flags.length;
|
||||
}
|
||||
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return numPoints;
|
||||
}
|
||||
|
||||
|
||||
public int getX(int point)
|
||||
{
|
||||
return pos[2 * point];
|
||||
}
|
||||
|
||||
|
||||
public void setX(int point, int value, boolean touch)
|
||||
{
|
||||
pos[2 * point] = value;
|
||||
if (touch)
|
||||
flags[point] |= FLAG_TOUCHED_X;
|
||||
}
|
||||
|
||||
|
||||
public void setY(int point, int value, boolean touch)
|
||||
{
|
||||
pos[2 * point + 1] = value;
|
||||
if (touch)
|
||||
flags[point] |= FLAG_TOUCHED_Y;
|
||||
}
|
||||
|
||||
|
||||
public int getY(int point)
|
||||
{
|
||||
return pos[2 * point + 1];
|
||||
}
|
||||
|
||||
|
||||
public int getOriginalX(int point)
|
||||
{
|
||||
return origPos[2 * point];
|
||||
}
|
||||
|
||||
|
||||
public int getOriginalY(int point)
|
||||
{
|
||||
return origPos[2 * point + 1];
|
||||
}
|
||||
|
||||
|
||||
public void setOriginalX(int point, int x)
|
||||
{
|
||||
origPos[2 * point] = x;
|
||||
}
|
||||
|
||||
public void setOriginalY(int point, int y)
|
||||
{
|
||||
origPos[2 * point + 1] = y;
|
||||
}
|
||||
|
||||
public void setNumPoints(int numPoints)
|
||||
{
|
||||
this.numPoints = numPoints;
|
||||
for (int i = 0; i < numPoints; i++)
|
||||
flags[i] = 0;
|
||||
for (int i = 0; i < 2 * numPoints; i++)
|
||||
origPos[i] = pos[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
public boolean isOnCurve(int point)
|
||||
{
|
||||
return (flags[point] & FLAG_ON_CURVE) != 0;
|
||||
}
|
||||
|
||||
|
||||
public void setOnCurve(int point, boolean onCurve)
|
||||
{
|
||||
if (onCurve)
|
||||
flags[point] |= FLAG_ON_CURVE;
|
||||
else
|
||||
flags[point] &= ~FLAG_ON_CURVE;
|
||||
}
|
||||
|
||||
|
||||
public boolean isContourEnd(int point)
|
||||
{
|
||||
return (flags[point] & FLAG_CONTOUR_END) != 0;
|
||||
}
|
||||
|
||||
|
||||
public void setContourEnd(int point, boolean segEnd)
|
||||
{
|
||||
if (segEnd)
|
||||
flags[point] |= FLAG_CONTOUR_END;
|
||||
else
|
||||
flags[point] &= ~FLAG_CONTOUR_END;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void transform(double pointSize, AffineTransform deviceTransform,
|
||||
int unitsPerEm, int preTranslateX, int preTranslateY)
|
||||
{
|
||||
double scaleX, scaleY, shearX, shearY;
|
||||
double factor;
|
||||
|
||||
factor = pointSize / (double) unitsPerEm;
|
||||
scaleX = deviceTransform.getScaleX() * factor;
|
||||
scaleY = deviceTransform.getScaleY() * factor;
|
||||
shearX = deviceTransform.getShearX() * factor;
|
||||
shearY = deviceTransform.getShearY() * factor;
|
||||
|
||||
for (int i = 0; i < numPoints; i++)
|
||||
{
|
||||
int x = origPos[2 * i] + preTranslateX;
|
||||
int y = origPos[2 * i + 1] + preTranslateY;
|
||||
|
||||
origPos[2*i] = pos[2 * i] = Fixed.valueOf(scaleX * x + shearX * y);
|
||||
origPos[2*i+1] = pos[2 * i + 1] = Fixed.valueOf(shearY * x + scaleY * y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void combineWithSubGlyph(Zone zone, int numPhantomPoints)
|
||||
{
|
||||
int offset = this.numPoints - numPhantomPoints;
|
||||
int count = zone.numPoints;
|
||||
System.arraycopy(zone.origPos, 0, this.origPos, 2 * offset,
|
||||
count * 2);
|
||||
System.arraycopy(zone.pos, 0, this.pos, 2 * offset,
|
||||
count * 2);
|
||||
System.arraycopy(zone.flags, 0, this.flags, offset, count);
|
||||
this.numPoints += count - numPhantomPoints;
|
||||
}
|
||||
|
||||
|
||||
private void dump()
|
||||
{
|
||||
for (int i = 0; i < numPoints; i++)
|
||||
{
|
||||
System.out.print(" " + i + ": ");
|
||||
System.out.print(Fixed.toString(pos[i*2], pos[i*2+1]));
|
||||
System.out.print(' ');
|
||||
System.out.print(Fixed.toString(origPos[i*2], origPos[i*2+1]));
|
||||
System.out.print(' ');
|
||||
if (isOnCurve(i))
|
||||
System.out.print('.');
|
||||
else
|
||||
System.out.print('c');
|
||||
if (isContourEnd(i))
|
||||
System.out.print('E');
|
||||
System.out.println();
|
||||
if (isContourEnd(i))
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public PathIterator getPathIterator()
|
||||
{
|
||||
return new ZonePathIterator(this);
|
||||
}
|
||||
|
||||
|
||||
public GeneralPath getPath()
|
||||
{
|
||||
GeneralPath p = new GeneralPath(GeneralPath.WIND_NON_ZERO, numPoints);
|
||||
p.append(getPathIterator(), /* connect */ false);
|
||||
return p;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,391 @@
|
|||
/* ZonePathIterator.java -- A PathIterator over glyph zones.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.java.awt.font.opentype.truetype;
|
||||
|
||||
import java.awt.geom.PathIterator;
|
||||
|
||||
|
||||
/**
|
||||
* A PathIterator that enumerates the non-phantom points in a zone.
|
||||
*
|
||||
* <p><b>Lack of thread safety:</b> Instances of this class are
|
||||
* <i>not</i> safe to access from multiple concurrent threads.
|
||||
*
|
||||
* @see Zone
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
final class ZonePathIterator
|
||||
implements PathIterator
|
||||
{
|
||||
/**
|
||||
* If <code>state</code> has this value, <code>currentSegment</code>
|
||||
* will emit a <code>SEG_LINETO</code> or <code>SEG_QUADTO</code> segment
|
||||
* to the current point. For a discussion of subtleties of on-curve
|
||||
* and off-curve points, please refer to the documentation for
|
||||
* {@link #getSegment}.
|
||||
*/
|
||||
private static final int EMIT_SEGMENT = 0;
|
||||
|
||||
|
||||
/**
|
||||
* If <code>state</code> has this value, <code>currentSegment</code>
|
||||
* will emit a <code>SEG_CLOSE</code> in order to close the sub-path
|
||||
* for the current contour.
|
||||
*/
|
||||
private static final int EMIT_CLOSE = 1;
|
||||
|
||||
|
||||
/**
|
||||
* If <code>state</code> has this value, <code>currentSegment</code>
|
||||
* will emit a <code>SEG_MOVETO</code> segment to the first point in
|
||||
* the current contour. If the first point is off-curve, a suitable
|
||||
* on-curve point is calculated.
|
||||
*
|
||||
* @see #getStartSegment
|
||||
*/
|
||||
private static final int EMIT_MOVETO = 2;
|
||||
|
||||
|
||||
/**
|
||||
* The state of the iterator, which is one of
|
||||
* <code>EMIT_SEGMENT</code>, <code>EMIT_CLOSE</code>, or
|
||||
* <code>EMIT_MOVETO</code>.
|
||||
*/
|
||||
private int state;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The zone whose segments are enumerated by this iterator.
|
||||
*/
|
||||
private Zone zone;
|
||||
|
||||
|
||||
/**
|
||||
* The total number of points in the zone, not including the four
|
||||
* phantom points at its end.
|
||||
*/
|
||||
private int numPoints;
|
||||
|
||||
|
||||
/**
|
||||
* The number of the current point.
|
||||
*/
|
||||
private int curPoint;
|
||||
|
||||
|
||||
/**
|
||||
* The number of the first point in the current contour.
|
||||
*/
|
||||
private int contourStart;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a ZonePathIterator for the specified zone.
|
||||
*
|
||||
* @param zone the zone whose segments will be enumerated
|
||||
* by this iterator.
|
||||
*/
|
||||
ZonePathIterator(Zone zone)
|
||||
{
|
||||
this.zone = zone;
|
||||
numPoints = zone.getSize() - /* four phantom points */ 4;
|
||||
|
||||
// The first segment that needs to be emitted is a SEG_MOVETO.
|
||||
state = EMIT_MOVETO;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the winding rule. TrueType glyphs always use the non-zero
|
||||
* winding rule, so this method will always return {@link
|
||||
* PathIterator#WIND_NON_ZERO}.
|
||||
*/
|
||||
public int getWindingRule()
|
||||
{
|
||||
return PathIterator.WIND_NON_ZERO;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean isDone()
|
||||
{
|
||||
return (state != EMIT_CLOSE) && (curPoint >= numPoints);
|
||||
}
|
||||
|
||||
|
||||
public void next()
|
||||
{
|
||||
boolean onCurve;
|
||||
|
||||
/* If the current point is the end of a segment, and no SEG_CLOSE
|
||||
* has been emitted yet, this will be the next segment.
|
||||
*/
|
||||
if (zone.isContourEnd(curPoint) && (state != EMIT_CLOSE))
|
||||
{
|
||||
state = EMIT_CLOSE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the previously emitted segment was a SEG_CLOSE, we are now
|
||||
* at the beginning of a new contour.
|
||||
*/
|
||||
if (state == EMIT_CLOSE)
|
||||
{
|
||||
contourStart = ++curPoint;
|
||||
state = EMIT_MOVETO;
|
||||
return;
|
||||
}
|
||||
|
||||
onCurve = zone.isOnCurve(curPoint);
|
||||
|
||||
/* If the last segment was a moveto, and the current point
|
||||
* (which is the first point in the contour) is off-curve,
|
||||
* we need to emit a quadto segment for the first point.
|
||||
*/
|
||||
if ((state == EMIT_MOVETO) && !onCurve)
|
||||
{
|
||||
state = EMIT_SEGMENT;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
curPoint++;
|
||||
|
||||
/* If the last point has been off-curve, and the now current
|
||||
* point is on-curve, the last segment was a quadto that
|
||||
* had the now current point at its end. In this case, we can
|
||||
* skip a segment.
|
||||
*/
|
||||
if (!onCurve && zone.isOnCurve(curPoint))
|
||||
{
|
||||
/* But if the skipped point is the end of a contour, we must not
|
||||
* skip the SEG_CLOSE. An example where this matters is the 'o'
|
||||
* glyph in the Helvetica font face that comes with MacOS X
|
||||
* 10.1.5.
|
||||
*/
|
||||
if (zone.isContourEnd(curPoint))
|
||||
{
|
||||
state = EMIT_CLOSE;
|
||||
return;
|
||||
}
|
||||
|
||||
curPoint++;
|
||||
}
|
||||
|
||||
state = EMIT_SEGMENT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the successor of the current point in the current
|
||||
* contour. The successor of the last point in a contour is the
|
||||
* start of that contour.
|
||||
*
|
||||
* @return the number of the point that follows the current point in
|
||||
* the same contour.
|
||||
*/
|
||||
private int getSuccessor(int p)
|
||||
{
|
||||
if (zone.isContourEnd(p))
|
||||
return contourStart;
|
||||
else
|
||||
return p + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the current path segment using single-precision
|
||||
* coordinate values.
|
||||
*/
|
||||
public int currentSegment(float[] coords)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case EMIT_CLOSE:
|
||||
return PathIterator.SEG_CLOSE;
|
||||
|
||||
case EMIT_MOVETO:
|
||||
return getStartSegment(curPoint, coords);
|
||||
|
||||
default:
|
||||
return getSegment(curPoint, coords);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A helper array that is used by {@link
|
||||
* #currentSegment(double[])}.
|
||||
*/
|
||||
float[] floats;
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the current path segment using double-precision
|
||||
* coordinate values.
|
||||
*/
|
||||
public int currentSegment(double[] coords)
|
||||
{
|
||||
if (floats == null)
|
||||
floats = new float[6];
|
||||
int result;
|
||||
|
||||
result = currentSegment(floats);
|
||||
for (int i = 0; i < 6; i++)
|
||||
coords[i] = floats[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the segment for the specified point.
|
||||
*
|
||||
* <p><img src="doc-files/ZonePathIterator-1.png" width="426"
|
||||
* height="194" alt="An example curve" /></p>
|
||||
*
|
||||
* <p>If <code>cur</code> is an on-curve point, the returned segment
|
||||
* is a straight line to <code>cur</code>. In the illustration, this
|
||||
* would be the case for <code>cur = 4</code>.</p>
|
||||
*
|
||||
* <p>If <code>cur</code> is an off-curve point, and
|
||||
* <code>cur</code>’s successor <code>succ</code> is also
|
||||
* off-curve, the returned segment is a quadratic Bézier
|
||||
* spline whose control point is <code>cur</code>, and whose end
|
||||
* point is located at the middle of the line connecting
|
||||
* <code>cur</code> and <code>succ</code>. In the illustration,
|
||||
* this would be the case for <code>cur = 5</code>.</p>
|
||||
*
|
||||
* <p>If <code>cur</code> is an off-curve point, and
|
||||
* <code>cur</code>’s successor <code>succ</code> is
|
||||
* on-curve, the returned segment is a quadratic Bézier
|
||||
* spline whose control point is <code>cur</code>, and whose end
|
||||
* point is <code>succ</code>. In the illustration, this would
|
||||
* be the case for <code>cur = 6</code>.</p>
|
||||
*
|
||||
* @return either <code>PathIterator.SEG_LINETO</code> or
|
||||
* <code>PathIterator.SEG_QUADTO</code>.
|
||||
*/
|
||||
private int getSegment(int cur, float[] coords)
|
||||
{
|
||||
int curX, curY;
|
||||
int succ, succX, succY;
|
||||
|
||||
curX = zone.getX(cur);
|
||||
curY = zone.getY(cur);
|
||||
coords[0] = Fixed.floatValue(curX);
|
||||
coords[1] = Fixed.floatValue(curY);
|
||||
|
||||
if (zone.isOnCurve(cur))
|
||||
return PathIterator.SEG_LINETO;
|
||||
|
||||
succ = getSuccessor(cur);
|
||||
succX = zone.getX(succ);
|
||||
succY = zone.getY(succ);
|
||||
|
||||
if (zone.isOnCurve(succ))
|
||||
{
|
||||
coords[2] = Fixed.floatValue(succX);
|
||||
coords[3] = Fixed.floatValue(succY);
|
||||
}
|
||||
else
|
||||
{
|
||||
coords[2] = Fixed.floatValue((curX + succX) / 2);
|
||||
coords[3] = Fixed.floatValue((curY + succY) / 2);
|
||||
}
|
||||
return PathIterator.SEG_QUADTO;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the start segment for the contour which starts
|
||||
* at the specified point.
|
||||
*
|
||||
* <p>If the contour starts with an on-curve point, the returned
|
||||
* segment is a <code>SEG_MOVETO</code> to that point.</p>
|
||||
*
|
||||
* <p>If the contour starts with an off-curve point, and the contour
|
||||
* ends with an on-curve point, the returned segment is a
|
||||
* <code>SEG_MOVETO</code> to the end point.</p>
|
||||
*
|
||||
* <p>If the contour starts with an off-curve point, and the contour
|
||||
* also ends with an off-curve point, the returned segment is a
|
||||
* <code>SEG_MOVETO</code> to the location at the middle between the
|
||||
* start and end points of the contour.</p>
|
||||
*
|
||||
* @return <code>PathIterator.SEG_MOVETO</code>.
|
||||
*/
|
||||
private int getStartSegment(int contourStart, float[] coords)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
if (zone.isOnCurve(contourStart))
|
||||
{
|
||||
x = zone.getX(contourStart);
|
||||
y = zone.getY(contourStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Find the last point of the current contour. */
|
||||
int contourEnd = contourStart;
|
||||
while (!zone.isContourEnd(contourEnd))
|
||||
++contourEnd;
|
||||
|
||||
if (zone.isOnCurve(contourEnd))
|
||||
{
|
||||
/* An example is the 'o' glyph of the Helvetica which comes
|
||||
* with Apple MacOS X 10.1.5.
|
||||
*/
|
||||
x = zone.getX(contourEnd);
|
||||
y = zone.getY(contourEnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = (zone.getX(contourStart) + zone.getX(contourEnd)) / 2;
|
||||
y = (zone.getY(contourStart) + zone.getY(contourEnd)) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
coords[0] = Fixed.floatValue(x);
|
||||
coords[1] = Fixed.floatValue(y);
|
||||
return PathIterator.SEG_MOVETO;
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
1951
libjava/classpath/gnu/java/awt/java2d/AbstractGraphics2D.java
Normal file
1951
libjava/classpath/gnu/java/awt/java2d/AbstractGraphics2D.java
Normal file
File diff suppressed because it is too large
Load diff
316
libjava/classpath/gnu/java/awt/java2d/AlphaCompositeContext.java
Normal file
316
libjava/classpath/gnu/java/awt/java2d/AlphaCompositeContext.java
Normal file
|
@ -0,0 +1,316 @@
|
|||
/* AlphaCompositeContext.java -- CompositeContext impl for AlphaComposite
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.java2d;
|
||||
|
||||
import java.awt.AWTError;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.CompositeContext;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
|
||||
/**
|
||||
* A CompositeContext implementation for {@link AlphaComposite}.
|
||||
*
|
||||
* @author Roman Kennke (kennke@aicas.com)
|
||||
*/
|
||||
public class AlphaCompositeContext
|
||||
implements CompositeContext
|
||||
{
|
||||
|
||||
/**
|
||||
* The Composite object for which we perform compositing.
|
||||
*/
|
||||
private AlphaComposite composite;
|
||||
|
||||
/**
|
||||
* The source color model.
|
||||
*/
|
||||
private ColorModel srcColorModel;
|
||||
|
||||
/**
|
||||
* The destination color model.
|
||||
*/
|
||||
private ColorModel dstColorModel;
|
||||
|
||||
/**
|
||||
* The blending factor for the source.
|
||||
*/
|
||||
private float fs;
|
||||
|
||||
/**
|
||||
* The blending factor for the destination.
|
||||
*/
|
||||
private float fd;
|
||||
|
||||
/**
|
||||
* Creates a new AlphaCompositeContext.
|
||||
*
|
||||
* @param aComp the AlphaComposite object
|
||||
* @param srcCM the source color model
|
||||
* @param dstCM the destination color model
|
||||
*/
|
||||
public AlphaCompositeContext(AlphaComposite aComp, ColorModel srcCM,
|
||||
ColorModel dstCM)
|
||||
{
|
||||
composite = aComp;
|
||||
srcColorModel = srcCM;
|
||||
dstColorModel = dstCM;
|
||||
|
||||
|
||||
// Determine the blending factors according to the rule in the
|
||||
// AlphaComposite. For some rules the factors must be determined
|
||||
// dynamically because they depend on the actual pixel value.
|
||||
switch (composite.getRule())
|
||||
{
|
||||
case AlphaComposite.CLEAR:
|
||||
fs = 0.F;
|
||||
fd= 0.F;
|
||||
break;
|
||||
case AlphaComposite.DST:
|
||||
fs = 0.F;
|
||||
fd= 1.F;
|
||||
break;
|
||||
case AlphaComposite.DST_ATOP:
|
||||
fs = 1.F; // Determined later as 1 - alpha_dst;
|
||||
fd = 1.F; // Determined later as alpha_src;
|
||||
break;
|
||||
case AlphaComposite.DST_IN:
|
||||
fs = 0.F;
|
||||
fd = 0.F; // Determined later as alpha_src;
|
||||
break;
|
||||
case AlphaComposite.DST_OUT:
|
||||
fs = 0.F;
|
||||
fd = 0.F; // Determined later as 1 - alpha_src;
|
||||
break;
|
||||
case AlphaComposite.DST_OVER:
|
||||
fs = 1.F; // Determined later as 1 - alpha_dst.
|
||||
fd= 1.F;
|
||||
break;
|
||||
case AlphaComposite.SRC:
|
||||
fs = 1.F;
|
||||
fd= 0.F;
|
||||
break;
|
||||
case AlphaComposite.SRC_ATOP:
|
||||
fs = 1.F; // Determined later as alpha_dst;
|
||||
fd = 1.F; // Determined later as 1 - alpha_src;
|
||||
break;
|
||||
case AlphaComposite.SRC_IN:
|
||||
fs = 0.F; // Determined later as alpha_dst;
|
||||
fd = 0.F;
|
||||
break;
|
||||
case AlphaComposite.SRC_OUT:
|
||||
fs = 0.F; // Determined later as 1 - alpha_dst;
|
||||
fd = 0.F;
|
||||
break;
|
||||
case AlphaComposite.SRC_OVER:
|
||||
fs = 1.F;
|
||||
fd= 1.F; // Determined later as 1 - alpha_src.
|
||||
break;
|
||||
case AlphaComposite.XOR:
|
||||
fs = 1.F; // Determined later as 1 - alpha_dst.
|
||||
fd= 1.F; // Determined later as 1 - alpha_src.
|
||||
break;
|
||||
default:
|
||||
throw new AWTError("Illegal AlphaComposite rule");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases all resources held by this composite object.
|
||||
*/
|
||||
public void dispose()
|
||||
{
|
||||
// Nothing to do here yet.
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs compositing according to the rules specified in the
|
||||
* AlphaComposite from the constructor.
|
||||
*/
|
||||
public void compose(Raster src, Raster dstIn, WritableRaster dstOut)
|
||||
{
|
||||
|
||||
// TODO: This implementation is very general and highly inefficient. There
|
||||
// are two possible ways to optimize this:
|
||||
// 1. Special cased implementations for common ColorModels and transfer
|
||||
// types.
|
||||
// 2. Native implementation.
|
||||
|
||||
int x0 = src.getMinX();
|
||||
int y0 = src.getMinY();
|
||||
int width = src.getWidth();
|
||||
int height = src.getHeight();
|
||||
int x1 = x0 + width;
|
||||
int y1 = y0 + height;
|
||||
|
||||
Object srcPixel = null;
|
||||
Object dstPixel = null;
|
||||
|
||||
// Prepare the array that holds the color and alpha components of the
|
||||
// source pixels.
|
||||
float[] srcComponents;
|
||||
int srcComponentsLength = srcColorModel.getNumComponents();
|
||||
if (! srcColorModel.hasAlpha())
|
||||
srcComponentsLength += 1;
|
||||
srcComponents = new float[srcComponentsLength];
|
||||
|
||||
// Prepare the array that holds the color and alpha components of the
|
||||
// destination pixels.
|
||||
float[] dstComponents;
|
||||
int dstComponentsLength = dstColorModel.getNumComponents();
|
||||
if (! dstColorModel.hasAlpha())
|
||||
dstComponentsLength += 1;
|
||||
dstComponents = new float[dstComponentsLength];
|
||||
|
||||
if (srcComponentsLength != dstComponentsLength)
|
||||
throw new AWTError("The color models of the source and destination have"
|
||||
+ "incompatible number of color components");
|
||||
|
||||
int srcTransferType = srcColorModel.getTransferType();
|
||||
int dstTransferType = dstColorModel.getTransferType();
|
||||
|
||||
for (int y = y0; y < y1; y++)
|
||||
{
|
||||
for (int x = x0; x < x1; x++)
|
||||
{
|
||||
// Fetch source pixel.
|
||||
srcPixel = src.getDataElements(x, y, (int[]) srcPixel);
|
||||
// Fetch destination pixel.
|
||||
dstPixel = dstIn.getDataElements(x, y, dstPixel);
|
||||
// Get normalized components. This is the only type that is
|
||||
// guaranteed to be supported by all ColorModels.
|
||||
srcComponents =
|
||||
srcColorModel.getNormalizedComponents(srcPixel, srcComponents, 0);
|
||||
if (! srcColorModel.hasAlpha())
|
||||
srcComponents[srcComponentsLength - 1] = 1.0F;
|
||||
dstComponents =
|
||||
dstColorModel.getNormalizedComponents(dstPixel, dstComponents, 0);
|
||||
if (! dstColorModel.hasAlpha())
|
||||
dstComponents[dstComponentsLength - 1] = 1.0F;
|
||||
|
||||
// Prepare the input.
|
||||
float compositeAlpha = composite.getAlpha();
|
||||
srcComponents[srcComponentsLength - 1] *= compositeAlpha;
|
||||
if (srcColorModel.isAlphaPremultiplied())
|
||||
{
|
||||
for (int i = srcComponentsLength - 2; i >= 0; i--)
|
||||
srcComponents[i] *= compositeAlpha;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = srcComponentsLength - 1; i >= 0; i--)
|
||||
srcComponents[i] *= srcComponents[srcComponentsLength - 1];
|
||||
}
|
||||
if (! dstColorModel.isAlphaPremultiplied())
|
||||
{
|
||||
for (int i = dstComponentsLength - 2; i >= 0; i--)
|
||||
dstComponents[i] *= dstComponents[dstComponents.length - 1];
|
||||
}
|
||||
|
||||
// Determine the blending factors according to the rule in the
|
||||
// AlphaComposite. For some rules the factors must be determined
|
||||
// dynamically because they depend on the actual pixel value.
|
||||
float srcAlpha = srcComponents[srcComponentsLength - 1];
|
||||
float dstAlpha = dstComponents[dstComponentsLength - 1];
|
||||
switch (composite.getRule())
|
||||
{
|
||||
case AlphaComposite.DST_ATOP:
|
||||
fs = 1.F - dstAlpha;
|
||||
fd = srcAlpha;
|
||||
break;
|
||||
case AlphaComposite.DST_IN:
|
||||
fd = srcAlpha;
|
||||
break;
|
||||
case AlphaComposite.DST_OUT:
|
||||
fd = 1.F - srcAlpha;
|
||||
break;
|
||||
case AlphaComposite.DST_OVER:
|
||||
fs = 1.F - dstAlpha;
|
||||
break;
|
||||
case AlphaComposite.SRC_ATOP:
|
||||
fs = srcAlpha;
|
||||
fd = 1.F - srcAlpha;
|
||||
break;
|
||||
case AlphaComposite.SRC_IN:
|
||||
fs = dstAlpha;
|
||||
break;
|
||||
case AlphaComposite.SRC_OUT:
|
||||
fs = 1.F - dstAlpha;
|
||||
break;
|
||||
case AlphaComposite.SRC_OVER:
|
||||
fd= 1.F - srcAlpha;
|
||||
break;
|
||||
case AlphaComposite.XOR:
|
||||
fs = 1.F - dstAlpha;
|
||||
fd= 1.F - srcAlpha;
|
||||
break;
|
||||
default:
|
||||
// For the other cases the factors have already been determined
|
||||
// in the constructor.
|
||||
}
|
||||
|
||||
// Apply the blending equation to the pixels.
|
||||
for (int i = 0; i < srcComponentsLength; i++)
|
||||
{
|
||||
dstComponents[i] = srcComponents[i] * fs
|
||||
+ dstComponents[i] * fd;
|
||||
}
|
||||
|
||||
// Convert the result back when the destination is not
|
||||
// alpha-premultiplied.
|
||||
dstAlpha = dstComponents[dstComponentsLength - 1];
|
||||
if (!dstColorModel.isAlphaPremultiplied() && dstAlpha != 0.F)
|
||||
{
|
||||
for (int i = 0; i < dstComponentsLength - 1; i++)
|
||||
{
|
||||
dstComponents[i] = dstComponents[i] / dstAlpha;
|
||||
}
|
||||
}
|
||||
|
||||
// Store the result in the destination raster.
|
||||
dstPixel = dstColorModel.getDataElements(dstComponents, 0,
|
||||
dstPixel);
|
||||
dstOut.setDataElements(x, y, dstPixel);
|
||||
} // End X loop.
|
||||
} // End Y loop.
|
||||
}
|
||||
|
||||
}
|
128
libjava/classpath/gnu/java/awt/java2d/CubicSegment.java
Normal file
128
libjava/classpath/gnu/java/awt/java2d/CubicSegment.java
Normal file
|
@ -0,0 +1,128 @@
|
|||
/* CubicSegment.java -- Cubic segment used for BasicStroke
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.java2d;
|
||||
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
/**
|
||||
* Cubic Bezier curve segment
|
||||
*/
|
||||
public class CubicSegment extends Segment
|
||||
{
|
||||
public Point2D cp1; // control points
|
||||
public Point2D cp2; // control points
|
||||
|
||||
/**
|
||||
* Constructor - takes coordinates of the starting point,
|
||||
* first control point, second control point and end point,
|
||||
* respecively.
|
||||
*/
|
||||
public CubicSegment(double x1, double y1, double c1x, double c1y,
|
||||
double c2x, double c2y, double x2, double y2)
|
||||
{
|
||||
super();
|
||||
P1 = new Point2D.Double(x1, y1);
|
||||
P2 = new Point2D.Double(x2, y2);
|
||||
cp1 = new Point2D.Double(c1x, c1y);
|
||||
cp2 = new Point2D.Double(c2x, c2y);
|
||||
}
|
||||
|
||||
public CubicSegment(Point2D p1, Point2D cp1, Point2D cp2, Point2D p2)
|
||||
{
|
||||
super();
|
||||
P1 = p1;
|
||||
P2 = p2;
|
||||
this.cp1 = cp1;
|
||||
this.cp2 = cp2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones this segment
|
||||
*/
|
||||
public Object clone()
|
||||
{
|
||||
return new CubicSegment(P1.getX(), P1.getY(), cp1.getX(), cp1.getY(),
|
||||
cp2.getX(), cp2.getY(), P2.getX(), P2.getY());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "top" and "bottom" segments of this segment.
|
||||
* First array element is p0 + normal, second is p0 - normal.
|
||||
*/
|
||||
public Segment[] getDisplacedSegments(double radius)
|
||||
{
|
||||
this.radius = radius;
|
||||
double x0 = P1.getX();
|
||||
double y0 = P1.getY();
|
||||
double x1 = cp1.getX();
|
||||
double y1 = cp1.getY();
|
||||
double x2 = cp2.getX();
|
||||
double y2 = cp2.getY();
|
||||
double x3 = P2.getX();
|
||||
double y3 = P2.getY();
|
||||
double[] p1 = normal(x0, y0, x1, y1);
|
||||
double[] p2 = normal(x2, y2, x3, y3);
|
||||
|
||||
|
||||
// FIXME: Doesn't compile.
|
||||
// return new Segment[]{s1, s2};
|
||||
return new Segment[0];
|
||||
}
|
||||
|
||||
public void reverse()
|
||||
{
|
||||
Point2D temp = P1;
|
||||
P1 = P2;
|
||||
P2 = temp;
|
||||
temp = cp1;
|
||||
cp1 = cp2;
|
||||
cp2 = temp;
|
||||
}
|
||||
|
||||
public double[] first()
|
||||
{
|
||||
return new double[]{cp1.getX(), cp1.getY()};
|
||||
}
|
||||
|
||||
public double[] last()
|
||||
{
|
||||
return new double[]{cp2.getX(), cp2.getY()};
|
||||
}
|
||||
} // class CubicSegment
|
103
libjava/classpath/gnu/java/awt/java2d/LineSegment.java
Normal file
103
libjava/classpath/gnu/java/awt/java2d/LineSegment.java
Normal file
|
@ -0,0 +1,103 @@
|
|||
/* LineSegment.java -- Line segment used for BasicStroke
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.java2d;
|
||||
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
public class LineSegment extends Segment
|
||||
{
|
||||
public LineSegment(double x1, double y1, double x2, double y2)
|
||||
{
|
||||
super();
|
||||
P1 = new Point2D.Double(x1, y1);
|
||||
P2 = new Point2D.Double(x2, y2);
|
||||
}
|
||||
|
||||
public LineSegment(Point2D p1, Point2D p2)
|
||||
{
|
||||
super();
|
||||
P1 = (Point2D) p1.clone();
|
||||
P2 = (Point2D) p2.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones this segment
|
||||
*/
|
||||
public Object clone()
|
||||
{
|
||||
return new LineSegment(P1, P2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "top" and "bottom" segments of this segment.
|
||||
* First array element is p0 + normal, second is p0 - normal.
|
||||
*/
|
||||
public Segment[] getDisplacedSegments(double radius)
|
||||
{
|
||||
this.radius = radius;
|
||||
double x0 = P1.getX();
|
||||
double y0 = P1.getY();
|
||||
double x1 = P2.getX();
|
||||
double y1 = P2.getY();
|
||||
double[] p = normal(x0, y0, x1, y1);
|
||||
Segment s1 = (new LineSegment(x0 + p[0], y0 + p[1],
|
||||
x1 + p[0], y1 + p[1] ));
|
||||
Segment s2 = (new LineSegment(x0 - p[0], y0 - p[1],
|
||||
x1 - p[0], y1 - p[1] ));
|
||||
return new Segment[]{s1, s2};
|
||||
}
|
||||
|
||||
public void reverse()
|
||||
{
|
||||
Point2D p = P1;
|
||||
P1 = P2;
|
||||
P2 = p;
|
||||
}
|
||||
|
||||
public double[] first()
|
||||
{
|
||||
return new double[]{P2.getX(), P2.getY()};
|
||||
}
|
||||
|
||||
public double[] last()
|
||||
{
|
||||
return new double[]{P1.getX(), P1.getY()};
|
||||
}
|
||||
} // class LineSegment
|
117
libjava/classpath/gnu/java/awt/java2d/PolyEdge.java
Normal file
117
libjava/classpath/gnu/java/awt/java2d/PolyEdge.java
Normal file
|
@ -0,0 +1,117 @@
|
|||
/* PolyEdge.java -- An edge in a polygon, used for polygon filling
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.java2d;
|
||||
|
||||
/**
|
||||
* An edge in a polygon. This is used by the scanline conversion algorithm
|
||||
* implemented in {@link AbstractGraphics2D#rawFillShape}.
|
||||
*
|
||||
* @author Roman Kennke (kennke@aicas.com)
|
||||
*/
|
||||
public class PolyEdge
|
||||
implements Comparable
|
||||
{
|
||||
|
||||
/**
|
||||
* The start and end coordinates of the edge. y0 is always smaller or equal
|
||||
* than y1.
|
||||
*/
|
||||
public double x0, y0, x1, y1;
|
||||
|
||||
/**
|
||||
* The slope of the edge. This is dx / dy.
|
||||
*/
|
||||
double slope;
|
||||
|
||||
/**
|
||||
* The intersection of this edge with the current scanline.
|
||||
*/
|
||||
double xIntersection;
|
||||
|
||||
/**
|
||||
* Creates a new PolyEdge with the specified coordinates.
|
||||
*
|
||||
* @param x0 the starting point, x coordinate
|
||||
* @param y0 the starting point, y coordinate
|
||||
* @param x1 the end point, x coordinate
|
||||
* @param y1 the end point, y coordinate
|
||||
*/
|
||||
PolyEdge(double x0, double y0, double x1, double y1)
|
||||
{
|
||||
if (y0 < y1)
|
||||
{
|
||||
this.x0 = x0;
|
||||
this.y0 = y0;
|
||||
this.x1 = x1;
|
||||
this.y1 = y1;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.x0 = x1;
|
||||
this.y0 = y1;
|
||||
this.x1 = x0;
|
||||
this.y1 = y0;
|
||||
}
|
||||
slope = (this.x1 - this.x0) / (this.y1 - this.y0);
|
||||
if (this.y0 == this.y1) // Horizontal edge.
|
||||
xIntersection = Math.min(this.x0, this.x1);
|
||||
else
|
||||
xIntersection = this.x0 + slope * (Math.ceil(this.y0) - this.y0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts PolyEdges by the x coordinate from the minimum x value.
|
||||
*/
|
||||
public int compareTo(Object o)
|
||||
{
|
||||
PolyEdge other = (PolyEdge) o;
|
||||
int comp = 0;
|
||||
if (x0 < other.x0)
|
||||
comp = -1;
|
||||
else if (x0 > other.x0)
|
||||
comp = 1;
|
||||
return comp;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "Edge: " + x0 + ", " + y0 + ", " + x1 + ", " + y1 + ", slope: "
|
||||
+ slope + ", xIntersection: " + xIntersection;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/* PolyEdgeComparator.java -- Sorts PolyEdges by their current intersection
|
||||
points
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.java2d;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Sorts {@link PolyEdge}s by their current intersection points.
|
||||
*
|
||||
* @author Roman Kennke (kennke@aicas.com)
|
||||
*/
|
||||
public class PolyEdgeComparator
|
||||
implements Comparator
|
||||
{
|
||||
|
||||
/**
|
||||
* The current scanline.
|
||||
*/
|
||||
int y;
|
||||
|
||||
public int compare(Object o1, Object o2)
|
||||
{
|
||||
PolyEdge edge1 = (PolyEdge) o1;
|
||||
PolyEdge edge2 = (PolyEdge) o2;
|
||||
int comp = 0;
|
||||
if (edge1.xIntersection < edge2.xIntersection)
|
||||
comp = -1;
|
||||
else if (edge1.xIntersection > edge2.xIntersection)
|
||||
comp = 1;
|
||||
return comp;
|
||||
}
|
||||
|
||||
}
|
213
libjava/classpath/gnu/java/awt/java2d/QuadSegment.java
Normal file
213
libjava/classpath/gnu/java/awt/java2d/QuadSegment.java
Normal file
|
@ -0,0 +1,213 @@
|
|||
/* QuadSegment.java -- QuadCurve segment used for BasicStroke
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.java2d;
|
||||
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.QuadCurve2D;
|
||||
|
||||
/**
|
||||
* Quadratic Bezier curve segment
|
||||
*
|
||||
* Note: Most peers don't support quadratics directly, so it might make
|
||||
* sense to represent them as cubics internally and just be done with it.
|
||||
* I think we should be peer-agnostic, however, and stay faithful to the
|
||||
* input geometry types as far as possible.
|
||||
*/
|
||||
public class QuadSegment extends Segment
|
||||
{
|
||||
public Point2D cp; // control point
|
||||
|
||||
/**
|
||||
* Constructor, takes the coordinates of the start, control,
|
||||
* and end point, respectively.
|
||||
*/
|
||||
public QuadSegment(double x1, double y1, double cx, double cy, double x2,
|
||||
double y2)
|
||||
{
|
||||
super();
|
||||
P1 = new Point2D.Double(x1, y1);
|
||||
P2 = new Point2D.Double(x2, y2);
|
||||
cp = new Point2D.Double(cx, cy);
|
||||
}
|
||||
|
||||
public QuadSegment(Point2D p1, Point2D cp, Point2D p2)
|
||||
{
|
||||
super();
|
||||
P1 = p1;
|
||||
P2 = p2;
|
||||
this.cp = cp;
|
||||
}
|
||||
|
||||
public QuadSegment(QuadCurve2D curve)
|
||||
{
|
||||
super();
|
||||
P1 = curve.getP1();
|
||||
P2 = curve.getP2();
|
||||
this.cp = curve.getCtrlPt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones this segment
|
||||
*/
|
||||
public Object clone()
|
||||
{
|
||||
return new QuadSegment(P1.getX(), P1.getY(), cp.getX(), cp.getY(),
|
||||
P2.getX(), P2.getY());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "top" and "bottom" segments of a given segment.
|
||||
* First array element is p0 + normal, second is p0 - normal.
|
||||
*/
|
||||
public Segment[] getDisplacedSegments(double radius)
|
||||
{
|
||||
this.radius = radius;
|
||||
double x0 = P1.getX();
|
||||
double y0 = P1.getY();
|
||||
double x1 = cp.getX();
|
||||
double y1 = cp.getY();
|
||||
double x2 = P2.getX();
|
||||
double y2 = P2.getY();
|
||||
|
||||
QuadCurve2D left = new QuadCurve2D.Double();
|
||||
QuadCurve2D right = new QuadCurve2D.Double();
|
||||
QuadCurve2D orig = new QuadCurve2D.Double(x0, y0, x1, y1, x2, y2);
|
||||
orig.subdivide(left, right);
|
||||
|
||||
QuadSegment s1 = offsetSubdivided(left, true);
|
||||
QuadSegment s2 = offsetSubdivided(left, false);
|
||||
|
||||
s1.add( offsetSubdivided(right, true) );
|
||||
s2.add( offsetSubdivided(right, false) );
|
||||
|
||||
return new Segment[]{s1, s2};
|
||||
}
|
||||
|
||||
private QuadSegment offsetSubdivided(QuadCurve2D curve, boolean plus)
|
||||
{
|
||||
double[] n1 = normal(curve.getX1(), curve.getY1(),
|
||||
curve.getCtrlX(), curve.getCtrlY());
|
||||
double[] n2 = normal(curve.getCtrlX(), curve.getCtrlY(),
|
||||
curve.getX2(), curve.getY2());
|
||||
|
||||
Point2D cp;
|
||||
QuadSegment s;
|
||||
if( plus )
|
||||
{
|
||||
cp = lineIntersection(curve.getX1() + n1[0],
|
||||
curve.getY1() + n1[1],
|
||||
curve.getCtrlX() + n1[0],
|
||||
curve.getCtrlY() + n1[1],
|
||||
curve.getCtrlX() + n2[0],
|
||||
curve.getCtrlY() + n2[1],
|
||||
curve.getX2() + n2[0],
|
||||
curve.getY2() + n2[1], true);
|
||||
s = new QuadSegment(curve.getX1() + n1[0], curve.getY1() + n1[1],
|
||||
cp.getX(), cp.getY(),
|
||||
curve.getX2() + n2[0], curve.getY2() + n2[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
cp = lineIntersection(curve.getX1() - n1[0],
|
||||
curve.getY1() - n1[1],
|
||||
curve.getCtrlX() - n1[0],
|
||||
curve.getCtrlY() - n1[1],
|
||||
curve.getCtrlX() - n2[0],
|
||||
curve.getCtrlY() - n2[1],
|
||||
curve.getX2() - n2[0],
|
||||
curve.getY2() - n2[1], true);
|
||||
|
||||
s = new QuadSegment(curve.getX1() - n1[0], curve.getY1() - n1[1],
|
||||
cp.getX(), cp.getY(),
|
||||
curve.getX2() - n2[0], curve.getY2() - n2[1]);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private Point2D lineIntersection(double X1, double Y1,
|
||||
double X2, double Y2,
|
||||
double X3, double Y3,
|
||||
double X4, double Y4,
|
||||
boolean infinite)
|
||||
{
|
||||
double x1 = X1;
|
||||
double y1 = Y1;
|
||||
double rx = X2 - x1;
|
||||
double ry = Y2 - y1;
|
||||
|
||||
double x2 = X3;
|
||||
double y2 = Y3;
|
||||
double sx = X4 - x2;
|
||||
double sy = Y4 - y2;
|
||||
|
||||
double determinant = sx * ry - sy * rx;
|
||||
double nom = (sx * (y2 - y1) + sy * (x1 - x2));
|
||||
|
||||
// lines can be considered parallel.
|
||||
if (Math.abs(determinant) < 1E-6)
|
||||
return null;
|
||||
|
||||
nom = nom / determinant;
|
||||
|
||||
// check if lines are within the bounds
|
||||
if(!infinite && (nom > 1.0 || nom < 0.0))
|
||||
return null;
|
||||
|
||||
return new Point2D.Double(x1 + nom * rx, y1 + nom * ry);
|
||||
}
|
||||
|
||||
public void reverse()
|
||||
{
|
||||
Point2D p = P1;
|
||||
P1 = P2;
|
||||
P2 = p;
|
||||
}
|
||||
|
||||
public double[] first()
|
||||
{
|
||||
return new double[]{cp.getX(), cp.getY()};
|
||||
}
|
||||
|
||||
public double[] last()
|
||||
{
|
||||
return new double[]{cp.getX(), cp.getY()};
|
||||
}
|
||||
}
|
101
libjava/classpath/gnu/java/awt/java2d/RasterGraphics.java
Normal file
101
libjava/classpath/gnu/java/awt/java2d/RasterGraphics.java
Normal file
|
@ -0,0 +1,101 @@
|
|||
/* RasterGraphics.java -- A Graphics2D impl for Rasters
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.java2d;
|
||||
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.WritableRaster;
|
||||
|
||||
/**
|
||||
* A Graphics2D implementation that operates on Raster objects. This is
|
||||
* primarily used for BufferedImages, but can theoretically be used on
|
||||
* arbitrary WritableRasters.
|
||||
*
|
||||
* @author Roman Kennke (kennke@aicas.com)
|
||||
*/
|
||||
public class RasterGraphics
|
||||
extends AbstractGraphics2D
|
||||
{
|
||||
|
||||
/**
|
||||
* The raster on which we operate.
|
||||
*/
|
||||
private WritableRaster raster;
|
||||
|
||||
/**
|
||||
* The color model of this Graphics instance.
|
||||
*/
|
||||
private ColorModel colorModel;
|
||||
|
||||
public RasterGraphics(WritableRaster r, ColorModel cm)
|
||||
{
|
||||
raster = r;
|
||||
colorModel = cm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color model of this Graphics object.
|
||||
*
|
||||
* @return the color model of this Graphics object
|
||||
*/
|
||||
protected ColorModel getColorModel()
|
||||
{
|
||||
return colorModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a WritableRaster that is used by this class to perform the
|
||||
* rendering in. It is not necessary that the target surface immediately
|
||||
* reflects changes in the raster. Updates to the raster are notified via
|
||||
* {@link AbstractGraphics2D#updateRaster}.
|
||||
*
|
||||
* @return the destination raster
|
||||
*/
|
||||
protected WritableRaster getDestinationRaster()
|
||||
{
|
||||
return raster;
|
||||
}
|
||||
|
||||
public GraphicsConfiguration getDeviceConfiguration()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
131
libjava/classpath/gnu/java/awt/java2d/Segment.java
Normal file
131
libjava/classpath/gnu/java/awt/java2d/Segment.java
Normal file
|
@ -0,0 +1,131 @@
|
|||
/* Segment.java -- Abstract segment used for BasicStroke
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.java2d;
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
public abstract class Segment implements Cloneable
|
||||
{
|
||||
// segment type, PathIterator segment types are used.
|
||||
public Point2D P1;
|
||||
public Point2D P2;
|
||||
public Segment next;
|
||||
public Segment last;
|
||||
protected double radius;
|
||||
|
||||
public Segment()
|
||||
{
|
||||
P1 = P2 = null;
|
||||
next = null;
|
||||
last = this;
|
||||
}
|
||||
|
||||
public void add(Segment newsegment)
|
||||
{
|
||||
last.next = newsegment;
|
||||
last = last.next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverses the orientation of the whole polygon
|
||||
*/
|
||||
public void reverseAll()
|
||||
{
|
||||
reverse();
|
||||
Segment v = next;
|
||||
Segment former = this;
|
||||
next = null;
|
||||
|
||||
while (v != null)
|
||||
{
|
||||
v.reverse();
|
||||
v.last = this;
|
||||
Segment oldnext = v.next;
|
||||
v.next = former;
|
||||
|
||||
former = v;
|
||||
v = oldnext; // move to the next in list
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "Segment:"+P1+", "+P2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the normal vector to the slope of the line.
|
||||
* Returns: 0.5*width*(norm of derivative of the (x0,y0)-(x1,y1) vector)
|
||||
*/
|
||||
protected double[] normal(double x0, double y0, double x1, double y1)
|
||||
{
|
||||
double dx = (x1 - x0);
|
||||
double dy = (y1 - y0);
|
||||
if( dy == 0 )
|
||||
{
|
||||
dy = radius * ((dx > 0)?1:-1);
|
||||
dx = 0;
|
||||
}
|
||||
else if( dx == 0 )
|
||||
{
|
||||
dx = radius * ((dy > 0)?-1:1);
|
||||
dy = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
double N = Math.sqrt(dx * dx + dy * dy);
|
||||
double odx = dx;
|
||||
dx = -radius * dy / N;
|
||||
dy = radius * odx / N;
|
||||
}
|
||||
return new double[]{ dx, dy };
|
||||
}
|
||||
|
||||
public abstract void reverse();
|
||||
|
||||
/**
|
||||
* Get the "top" and "bottom" segments of a segment.
|
||||
* First array element is p0 + normal, second is p0 - normal.
|
||||
*/
|
||||
public abstract Segment[] getDisplacedSegments(double radius);
|
||||
|
||||
public abstract double[] first();
|
||||
public abstract double[] last();
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/* GLightweightPeer.java --
|
||||
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
|
@ -54,11 +54,14 @@ import java.awt.Insets;
|
|||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.PaintEvent;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.awt.image.ImageProducer;
|
||||
import java.awt.image.VolatileImage;
|
||||
import java.awt.peer.ComponentPeer;
|
||||
import java.awt.peer.ContainerPeer;
|
||||
import java.awt.peer.LightweightPeer;
|
||||
|
||||
|
@ -79,7 +82,7 @@ import java.awt.peer.LightweightPeer;
|
|||
* Lightweight components are painted directly onto their parent
|
||||
* containers through an Image object provided by the toolkit.
|
||||
*/
|
||||
public class GLightweightPeer
|
||||
public class GLightweightPeer
|
||||
implements LightweightPeer, ContainerPeer
|
||||
{
|
||||
private Component comp;
|
||||
|
@ -247,7 +250,25 @@ public class GLightweightPeer
|
|||
|
||||
public void setBounds(int x, int y, int width, int height) {}
|
||||
|
||||
public void setCursor(Cursor cursor) {}
|
||||
/**
|
||||
* Sets the cursor on the heavy-weight parent peer.
|
||||
* Called by the MouseListener on mouse enter.
|
||||
*/
|
||||
public void setCursor(Cursor cursor)
|
||||
{
|
||||
Component p = comp.getParent();
|
||||
while (p != null && p.isLightweight())
|
||||
p = p.getParent();
|
||||
|
||||
if (p != null)
|
||||
{
|
||||
// Don't actually change the cursor of the component
|
||||
// otherwise other childs inherit this cursor.
|
||||
ComponentPeer peer = p.getPeer();
|
||||
if (peer != null)
|
||||
peer.setCursor(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {}
|
||||
|
||||
|
|
|
@ -110,14 +110,10 @@ public class GdkFontMetrics extends FontMetrics
|
|||
return stringWidth (new String (data, off, len));
|
||||
}
|
||||
|
||||
/*
|
||||
Sun's Motif implementation always returns 0 or 1 here (???), but
|
||||
going by the X11 man pages, it seems as though we should return
|
||||
font.ascent + font.descent.
|
||||
*/
|
||||
public int getLeading ()
|
||||
{
|
||||
return 1;
|
||||
// Sun always returns 0.
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getAscent ()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* GdkFontPeer.java -- Implements FontPeer with GTK+
|
||||
Copyright (C) 1999, 2004, 2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
|
@ -43,6 +43,7 @@ import gnu.java.awt.peer.ClasspathFontPeer;
|
|||
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.font.LineMetrics;
|
||||
|
@ -157,7 +158,7 @@ public class GdkFontPeer extends ClasspathFontPeer
|
|||
|
||||
public String getPostScriptName(Font font)
|
||||
{
|
||||
return null;
|
||||
return this.familyName;
|
||||
}
|
||||
|
||||
public boolean canDisplay (Font font, char c)
|
||||
|
@ -301,7 +302,9 @@ public class GdkFontPeer extends ClasspathFontPeer
|
|||
|
||||
public FontMetrics getFontMetrics (Font font)
|
||||
{
|
||||
return new GdkFontMetrics (font);
|
||||
// Get the font metrics through GtkToolkit to take advantage of
|
||||
// the metrics cache.
|
||||
return Toolkit.getDefaultToolkit().getFontMetrics (font);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ import java.awt.Graphics;
|
|||
import java.awt.Image;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
|
||||
|
@ -218,8 +219,10 @@ public class GdkGraphics extends Graphics
|
|||
public boolean drawImage (Image img, int x, int y,
|
||||
Color bgcolor, ImageObserver observer)
|
||||
{
|
||||
return drawImage(img, x, y, img.getWidth(null), img.getHeight(null),
|
||||
bgcolor, observer);
|
||||
if (img != null)
|
||||
return drawImage(img, x, y, img.getWidth(null), img.getHeight(null),
|
||||
bgcolor, observer);
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean drawImage (Image img, int x, int y, ImageObserver observer)
|
||||
|
@ -227,16 +230,19 @@ public class GdkGraphics extends Graphics
|
|||
return drawImage (img, x, y, null, observer);
|
||||
}
|
||||
|
||||
public boolean drawImage (Image img, int x, int y, int width, int height,
|
||||
Color bgcolor, ImageObserver observer)
|
||||
public boolean drawImage(Image img, int x, int y, int width, int height,
|
||||
Color bgcolor, ImageObserver observer)
|
||||
{
|
||||
if (img instanceof GtkImage)
|
||||
return ((GtkImage)img).drawImage (this, x, y, width, height,
|
||||
bgcolor, observer);
|
||||
else
|
||||
return (new GtkImage(img.getSource())).drawImage (this, x, y,
|
||||
width, height,
|
||||
bgcolor, observer);
|
||||
if (img != null)
|
||||
{
|
||||
if (img instanceof GtkImage)
|
||||
return ((GtkImage) img).drawImage(this, x, y, width, height, bgcolor,
|
||||
observer);
|
||||
return (new GtkImage(img.getSource())).drawImage(this, x, y, width,
|
||||
height, bgcolor,
|
||||
observer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean drawImage (Image img, int x, int y, int width, int height,
|
||||
|
@ -249,14 +255,16 @@ public class GdkGraphics extends Graphics
|
|||
int sx1, int sy1, int sx2, int sy2,
|
||||
Color bgcolor, ImageObserver observer)
|
||||
{
|
||||
if (img instanceof GtkImage)
|
||||
return ((GtkImage)img).drawImage(this, dx1, dy1, dx2, dy2,
|
||||
sx1, sy1, sx2, sy2, bgcolor, observer);
|
||||
else
|
||||
return (new GtkImage(img.getSource())).drawImage(this, dx1, dy1,
|
||||
dx2, dy2,
|
||||
sx1, sy1, sx2, sy2,
|
||||
bgcolor, observer);
|
||||
if (img != null)
|
||||
{
|
||||
if (img instanceof GtkImage)
|
||||
return ((GtkImage) img).drawImage(this, dx1, dy1, dx2, dy2, sx1, sy1,
|
||||
sx2, sy2, bgcolor, observer);
|
||||
return (new GtkImage(img.getSource())).drawImage(this, dx1, dy1, dx2,
|
||||
dy2, sx1, sy1, sx2,
|
||||
sy2, bgcolor, observer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean drawImage (Image img, int dx1, int dy1, int dx2, int dy2,
|
||||
|
@ -373,7 +381,9 @@ public class GdkGraphics extends Graphics
|
|||
|
||||
public FontMetrics getFontMetrics (Font font)
|
||||
{
|
||||
return new GdkFontMetrics (font);
|
||||
// Get the font metrics through GtkToolkit to take advantage of
|
||||
// the metrics cache.
|
||||
return Toolkit.getDefaultToolkit().getFontMetrics (font);
|
||||
}
|
||||
|
||||
native void setClipRectangle (int x, int y, int width, int height);
|
||||
|
|
|
@ -1229,7 +1229,10 @@ public class GdkGraphics2D extends Graphics2D
|
|||
drawPixels(pixels, r.getWidth(), r.getHeight(), r.getWidth(), i2u);
|
||||
|
||||
updateBufferedImage();
|
||||
|
||||
|
||||
// Cairo seems loosing the current color.
|
||||
setColor(fg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* GdkPixbufDecoder.java -- Image data decoding object
|
||||
Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
|
@ -82,6 +82,14 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
|
|||
initStaticState ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock that should be held for all gdkpixbuf operations. We don't use
|
||||
* the global gdk_threads_enter/leave functions since gdkpixbuf
|
||||
* operations can be done in parallel to drawing and manipulating gtk
|
||||
* widgets.
|
||||
*/
|
||||
static Object pixbufLock = new Object();
|
||||
|
||||
static native void initStaticState();
|
||||
private final int native_state = GtkGenericPeer.getUniqueInteger ();
|
||||
|
||||
|
@ -92,6 +100,7 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
|
|||
Vector curr;
|
||||
|
||||
// interface to GdkPixbuf
|
||||
// These native functions should be called with the pixbufLock held.
|
||||
native void initState ();
|
||||
native void pumpBytes (byte[] bytes, int len) throws IOException;
|
||||
native void pumpDone () throws IOException;
|
||||
|
@ -171,11 +180,26 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
|
|||
|
||||
byte bytes[] = new byte[4096];
|
||||
int len = 0;
|
||||
initState();
|
||||
synchronized(pixbufLock)
|
||||
{
|
||||
initState();
|
||||
}
|
||||
needsClose = true;
|
||||
|
||||
// Note: We don't want the pixbufLock while reading from the InputStream.
|
||||
while ((len = is.read (bytes)) != -1)
|
||||
pumpBytes (bytes, len);
|
||||
pumpDone();
|
||||
{
|
||||
synchronized(pixbufLock)
|
||||
{
|
||||
pumpBytes (bytes, len);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized(pixbufLock)
|
||||
{
|
||||
pumpDone();
|
||||
}
|
||||
|
||||
needsClose = false;
|
||||
|
||||
for (int i = 0; i < curr.size (); i++)
|
||||
|
@ -189,7 +213,10 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
|
|||
|
||||
public void finalize()
|
||||
{
|
||||
finish(needsClose);
|
||||
synchronized(pixbufLock)
|
||||
{
|
||||
finish(needsClose);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -495,8 +522,11 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
|
|||
}
|
||||
|
||||
processImageStarted(1);
|
||||
streamImage(pixels, this.ext, width, height, model.hasAlpha(),
|
||||
(DataOutput) this.getOutput());
|
||||
synchronized(pixbufLock)
|
||||
{
|
||||
streamImage(pixels, this.ext, width, height, model.hasAlpha(),
|
||||
(DataOutput) this.getOutput());
|
||||
}
|
||||
processImageComplete();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,61 +38,22 @@ exception statement from your version. */
|
|||
|
||||
package gnu.java.awt.peer.gtk;
|
||||
|
||||
import java.awt.AWTEvent;
|
||||
import java.awt.Canvas;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.event.PaintEvent;
|
||||
import java.awt.peer.CanvasPeer;
|
||||
|
||||
public class GtkCanvasPeer extends GtkComponentPeer implements CanvasPeer
|
||||
{
|
||||
native void create ();
|
||||
native void realize ();
|
||||
|
||||
public GtkCanvasPeer (Canvas c)
|
||||
{
|
||||
super (c);
|
||||
}
|
||||
|
||||
public Graphics getGraphics ()
|
||||
{
|
||||
if (GtkToolkit.useGraphics2D ())
|
||||
return new GdkGraphics2D (this);
|
||||
else
|
||||
return new GdkGraphics (this);
|
||||
}
|
||||
|
||||
public void handleEvent (AWTEvent event)
|
||||
{
|
||||
int id = event.getID();
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case PaintEvent.PAINT:
|
||||
case PaintEvent.UPDATE:
|
||||
{
|
||||
try
|
||||
{
|
||||
Graphics g = getGraphics ();
|
||||
g.setClip (((PaintEvent)event).getUpdateRect());
|
||||
|
||||
if (id == PaintEvent.PAINT)
|
||||
awtComponent.paint (g);
|
||||
else
|
||||
awtComponent.update (g);
|
||||
|
||||
g.dispose ();
|
||||
}
|
||||
catch (InternalError e)
|
||||
{
|
||||
System.err.println (e);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Preferred size for a drawing widget is always what the user requested */
|
||||
// Preferred size for a drawing widget is always what the user
|
||||
// requested.
|
||||
public Dimension getPreferredSize ()
|
||||
{
|
||||
return awtComponent.getSize ();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* GtkClipboard.java
|
||||
Copyright (C) 1999, 2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999, 2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
|
@ -48,59 +48,85 @@ import java.util.Iterator;
|
|||
|
||||
public class GtkClipboard extends Clipboard
|
||||
{
|
||||
/**
|
||||
* The one and only gtk+ clipboard instance for the CLIPBOARD selection.
|
||||
*/
|
||||
final static GtkClipboard clipboard = new GtkClipboard("System Clipboard");
|
||||
|
||||
/**
|
||||
* The one and only gtk+ clipboard instance for the PRIMARY selection.
|
||||
*/
|
||||
final static GtkClipboard selection = new GtkClipboard("System Selection");
|
||||
|
||||
// Given to the native side so it can signal special targets that
|
||||
// can be converted to one of the special predefined DataFlavors.
|
||||
static final String stringMimeType;
|
||||
static final String imageMimeType;
|
||||
static final String filesMimeType;
|
||||
static final String stringMimeType
|
||||
= DataFlavor.stringFlavor.getMimeType();
|
||||
static final String imageMimeType
|
||||
= DataFlavor.imageFlavor.getMimeType();
|
||||
static final String filesMimeType
|
||||
= DataFlavor.javaFileListFlavor.getMimeType();
|
||||
|
||||
// Indicates whether the results of the clipboard selection can be
|
||||
// cached by GtkSelection. True if
|
||||
// gdk_display_supports_selection_notification.
|
||||
static final boolean canCache;
|
||||
|
||||
static
|
||||
{
|
||||
stringMimeType = DataFlavor.stringFlavor.getMimeType();
|
||||
imageMimeType = DataFlavor.imageFlavor.getMimeType();
|
||||
filesMimeType = DataFlavor.javaFileListFlavor.getMimeType();
|
||||
|
||||
canCache = initNativeState(stringMimeType, imageMimeType, filesMimeType);
|
||||
}
|
||||
|
||||
/**
|
||||
* The one and only gtk+ clipboard instance.
|
||||
*/
|
||||
private static GtkClipboard instance = new GtkClipboard();
|
||||
static final boolean canCache = initNativeState(clipboard, selection,
|
||||
stringMimeType,
|
||||
imageMimeType,
|
||||
filesMimeType);
|
||||
|
||||
/**
|
||||
* Creates the clipboard and sets the initial contents to the
|
||||
* current gtk+ selection.
|
||||
*/
|
||||
private GtkClipboard()
|
||||
private GtkClipboard(String name)
|
||||
{
|
||||
super("System Clipboard");
|
||||
setContents(new GtkSelection(), null);
|
||||
super(name);
|
||||
setContents(new GtkSelection(this), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the one and only GtkClipboard instance.
|
||||
* Returns the one and only GtkClipboard instance for the CLIPBOARD
|
||||
* selection.
|
||||
*/
|
||||
|
||||
static GtkClipboard getInstance()
|
||||
static GtkClipboard getClipboardInstance()
|
||||
{
|
||||
return instance;
|
||||
return clipboard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the one and only GtkClipboard instance for the PRIMARY
|
||||
* selection.
|
||||
*/
|
||||
static GtkClipboard getSelectionInstance()
|
||||
{
|
||||
return selection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the GtkSelection facade as new contents of the clipboard.
|
||||
* Called from gtk+ when another application grabs the clipboard and
|
||||
* we loose ownership.
|
||||
*
|
||||
* @param cleared If true this is a clear event (someone takes the
|
||||
* clipboard from us) otherwise it is an owner changed event.
|
||||
*/
|
||||
private static void setSystemContents()
|
||||
private synchronized void setSystemContents(boolean cleared)
|
||||
{
|
||||
GtkClipboardNotifier.announce();
|
||||
// We need to notify clipboard owner listeners when we were the
|
||||
// owner (the selection was explictly set) and someone takes the
|
||||
// clipboard away from us and asks us the clear any held storage,
|
||||
// or if we weren't the owner of the clipboard to begin with, but
|
||||
// the clipboard contents changed. We could refine this and check
|
||||
// whether the actual available formats did in fact change, but we
|
||||
// assume listeners will check for that anyway (and if possible we
|
||||
// ask to cache the available formats so even if multiple
|
||||
// listeners check after a notification the overhead should be
|
||||
// minimal).
|
||||
boolean owner = ! (contents instanceof GtkSelection);
|
||||
boolean needNotification = (cleared && owner) || (! cleared && ! owner);
|
||||
if (needNotification)
|
||||
GtkClipboardNotifier.announce(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -146,15 +172,12 @@ public class GtkClipboard extends Clipboard
|
|||
|| flavor.isRepresentationClassReader())
|
||||
text = true;
|
||||
|
||||
// XXX - We only support automatic image conversion for
|
||||
// GtkImages at the moment. So explicitly check that we have
|
||||
// one.
|
||||
if (! images && flavors[i].equals(DataFlavor.imageFlavor))
|
||||
{
|
||||
try
|
||||
{
|
||||
Object o = contents.getTransferData(DataFlavor.imageFlavor);
|
||||
if (o instanceof GtkImage)
|
||||
if (o instanceof Image)
|
||||
images = true;
|
||||
}
|
||||
catch (UnsupportedFlavorException ufe)
|
||||
|
@ -265,7 +288,11 @@ public class GtkClipboard extends Clipboard
|
|||
|
||||
try
|
||||
{
|
||||
return (GtkImage) contents.getTransferData(DataFlavor.imageFlavor);
|
||||
Object o = contents.getTransferData(DataFlavor.imageFlavor);
|
||||
if( o instanceof GtkImage )
|
||||
return (GtkImage) o;
|
||||
else
|
||||
return new GtkImage(((Image)o).getSource());
|
||||
}
|
||||
catch (UnsupportedFlavorException ufe)
|
||||
{
|
||||
|
@ -384,11 +411,13 @@ public class GtkClipboard extends Clipboard
|
|||
}
|
||||
|
||||
/**
|
||||
* Initializes the gtk+ clipboard and caches any native side
|
||||
* Initializes the gtk+ clipboards and caches any native side
|
||||
* structures needed. Returns whether or not the contents of the
|
||||
* Clipboard can be cached (gdk_display_supports_selection_notification).
|
||||
*/
|
||||
private static native boolean initNativeState(String stringTarget,
|
||||
private static native boolean initNativeState(GtkClipboard clipboard,
|
||||
GtkClipboard selection,
|
||||
String stringTarget,
|
||||
String imageTarget,
|
||||
String filesTarget);
|
||||
}
|
||||
|
|
|
@ -39,11 +39,15 @@ exception statement from your version. */
|
|||
package gnu.java.awt.peer.gtk;
|
||||
|
||||
import java.awt.datatransfer.*;
|
||||
import java.util.*;
|
||||
|
||||
class GtkClipboardNotifier extends Thread
|
||||
{
|
||||
/** Whether or not to announce a GtkSelection change. */
|
||||
private static boolean announceChange;
|
||||
/** Whether to announce a new GtkSelection has been set for CLIPBOARD. */
|
||||
static private boolean announceClipboardChange;
|
||||
|
||||
/** Whether to announce a new GtkSelection has been set for PRIMARY. */
|
||||
static private boolean announcePrimaryChange;
|
||||
|
||||
/**
|
||||
* The one and only instance. All operations are synchronized on
|
||||
|
@ -64,24 +68,30 @@ class GtkClipboardNotifier extends Thread
|
|||
|
||||
/**
|
||||
* Notifies that a new GtkSelection has to be announced.
|
||||
*
|
||||
* @param clipboard either the GtkClipboard.clipboard or the
|
||||
* GtkClipboard.selection.
|
||||
*/
|
||||
static void announce()
|
||||
static void announce(GtkClipboard clipboard)
|
||||
{
|
||||
synchronized (notifier)
|
||||
{
|
||||
announceChange = true;
|
||||
if (clipboard == GtkClipboard.clipboard)
|
||||
announceClipboardChange = true;
|
||||
else
|
||||
announcePrimaryChange = true;
|
||||
notifier.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
final GtkClipboard clipboard = GtkClipboard.getInstance();
|
||||
GtkClipboard clipboard;
|
||||
while (true)
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
while (!announceChange)
|
||||
while (! announceClipboardChange && ! announcePrimaryChange)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -92,14 +102,24 @@ class GtkClipboardNotifier extends Thread
|
|||
// ignore
|
||||
}
|
||||
}
|
||||
announceChange = false;
|
||||
|
||||
if (announceClipboardChange)
|
||||
{
|
||||
clipboard = GtkClipboard.clipboard;
|
||||
announceClipboardChange = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
clipboard = GtkClipboard.selection;
|
||||
announcePrimaryChange = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Do the actual announcement without the lock held. We will
|
||||
// notice a new change after this notification has finished.
|
||||
try
|
||||
{
|
||||
clipboard.setContents(new GtkSelection(), null);
|
||||
clipboard.setContents(new GtkSelection(clipboard), null);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
|
|
|
@ -63,6 +63,7 @@ import java.awt.event.FocusEvent;
|
|||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.event.PaintEvent;
|
||||
import java.awt.event.TextEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
@ -86,8 +87,6 @@ public class GtkComponentPeer extends GtkGenericPeer
|
|||
|
||||
Insets insets;
|
||||
|
||||
boolean isInRepaint;
|
||||
|
||||
/* this isEnabled differs from Component.isEnabled, in that it
|
||||
knows if a parent is disabled. In that case Component.isEnabled
|
||||
may return true, but our isEnabled will always return false */
|
||||
|
@ -100,8 +99,9 @@ public class GtkComponentPeer extends GtkGenericPeer
|
|||
native void gtkWidgetGetPreferredDimensions (int[] dim);
|
||||
native void gtkWindowGetLocationOnScreen (int[] point);
|
||||
native void gtkWidgetGetLocationOnScreen (int[] point);
|
||||
native void gtkWidgetSetCursor (int type);
|
||||
native void gtkWidgetSetCursorUnlocked (int type);
|
||||
native void gtkWidgetSetCursor (int type, GtkImage image, int x, int y);
|
||||
native void gtkWidgetSetCursorUnlocked (int type, GtkImage image,
|
||||
int x, int y);
|
||||
native void gtkWidgetSetBackground (int red, int green, int blue);
|
||||
native void gtkWidgetSetForeground (int red, int green, int blue);
|
||||
native void gtkWidgetSetSensitive (boolean sensitive);
|
||||
|
@ -150,6 +150,9 @@ public class GtkComponentPeer extends GtkGenericPeer
|
|||
setNativeEventMask ();
|
||||
|
||||
realize ();
|
||||
|
||||
if (awtComponent.isCursorSet())
|
||||
setCursor ();
|
||||
}
|
||||
|
||||
void setParentAndBounds ()
|
||||
|
@ -176,16 +179,6 @@ public class GtkComponentPeer extends GtkGenericPeer
|
|||
gtkWidgetSetParent (p);
|
||||
}
|
||||
|
||||
void beginNativeRepaint ()
|
||||
{
|
||||
isInRepaint = true;
|
||||
}
|
||||
|
||||
void endNativeRepaint ()
|
||||
{
|
||||
isInRepaint = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the bounds of this peer's AWT Component based on dimensions
|
||||
* returned by the native windowing system. Most Components impose
|
||||
|
@ -250,6 +243,8 @@ public class GtkComponentPeer extends GtkGenericPeer
|
|||
return getToolkit().getFontMetrics(font);
|
||||
}
|
||||
|
||||
// getGraphics may be overridden by derived classes but it should
|
||||
// never return null.
|
||||
public Graphics getGraphics ()
|
||||
{
|
||||
if (GtkToolkit.useGraphics2D ())
|
||||
|
@ -291,30 +286,10 @@ public class GtkComponentPeer extends GtkGenericPeer
|
|||
switch (id)
|
||||
{
|
||||
case PaintEvent.PAINT:
|
||||
paintComponent((PaintEvent) event);
|
||||
break;
|
||||
case PaintEvent.UPDATE:
|
||||
{
|
||||
try
|
||||
{
|
||||
Graphics g = getGraphics();
|
||||
|
||||
if (!awtComponent.isShowing() || awtComponent.getWidth() < 1
|
||||
|| awtComponent.getHeight() < 1 || g == null)
|
||||
break;
|
||||
|
||||
g.setClip(((PaintEvent) event).getUpdateRect());
|
||||
|
||||
if (id == PaintEvent.PAINT)
|
||||
awtComponent.paint(g);
|
||||
else
|
||||
awtComponent.update(g);
|
||||
|
||||
g.dispose();
|
||||
}
|
||||
catch (InternalError e)
|
||||
{
|
||||
System.err.println(e);
|
||||
}
|
||||
}
|
||||
updateComponent((PaintEvent) event);
|
||||
break;
|
||||
case KeyEvent.KEY_PRESSED:
|
||||
ke = (KeyEvent) event;
|
||||
|
@ -328,7 +303,49 @@ public class GtkComponentPeer extends GtkGenericPeer
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This method and its overrides are the only methods in the peers
|
||||
// that should call awtComponent.paint.
|
||||
protected void paintComponent (PaintEvent event)
|
||||
{
|
||||
// Do not call Component.paint if the component is not showing or
|
||||
// if its bounds form a degenerate rectangle.
|
||||
if (!awtComponent.isShowing()
|
||||
|| (awtComponent.getWidth() < 1 || awtComponent.getHeight() < 1))
|
||||
return;
|
||||
|
||||
// Creating and disposing a GdkGraphics every time paint is called
|
||||
// seems expensive. However, the graphics state does not carry
|
||||
// over between calls to paint, and resetting the graphics object
|
||||
// may even be more costly than simply creating a new one.
|
||||
Graphics g = getGraphics();
|
||||
|
||||
g.setClip(event.getUpdateRect());
|
||||
|
||||
awtComponent.paint(g);
|
||||
|
||||
g.dispose();
|
||||
}
|
||||
|
||||
// This method and its overrides are the only methods in the peers
|
||||
// that should call awtComponent.update.
|
||||
protected void updateComponent (PaintEvent event)
|
||||
{
|
||||
// Do not call Component.update if the component is not showing or
|
||||
// if its bounds form a degenerate rectangle.
|
||||
if (!awtComponent.isShowing()
|
||||
|| (awtComponent.getWidth() < 1 || awtComponent.getHeight() < 1))
|
||||
return;
|
||||
|
||||
Graphics g = getGraphics();
|
||||
|
||||
g.setClip(event.getUpdateRect());
|
||||
|
||||
awtComponent.update(g);
|
||||
|
||||
g.dispose();
|
||||
}
|
||||
|
||||
public boolean isFocusTraversable ()
|
||||
{
|
||||
return true;
|
||||
|
@ -369,7 +386,7 @@ public class GtkComponentPeer extends GtkGenericPeer
|
|||
|
||||
public void repaint (long tm, int x, int y, int width, int height)
|
||||
{
|
||||
if (x == 0 && y == 0 && width == 0 && height == 0)
|
||||
if (width < 1 || height < 1)
|
||||
return;
|
||||
|
||||
if (tm <= 0)
|
||||
|
@ -490,10 +507,28 @@ public class GtkComponentPeer extends GtkGenericPeer
|
|||
|
||||
public void setCursor (Cursor cursor)
|
||||
{
|
||||
if (Thread.currentThread() == GtkToolkit.mainThread)
|
||||
gtkWidgetSetCursorUnlocked (cursor.getType ());
|
||||
int x, y;
|
||||
GtkImage image;
|
||||
int type = cursor.getType();
|
||||
if (cursor instanceof GtkCursor)
|
||||
{
|
||||
GtkCursor gtkCursor = (GtkCursor) cursor;
|
||||
image = gtkCursor.getGtkImage();
|
||||
Point hotspot = gtkCursor.getHotspot();
|
||||
x = hotspot.x;
|
||||
y = hotspot.y;
|
||||
}
|
||||
else
|
||||
gtkWidgetSetCursor (cursor.getType ());
|
||||
{
|
||||
image = null;
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if (Thread.currentThread() == GtkToolkit.mainThread)
|
||||
gtkWidgetSetCursorUnlocked(cursor.getType(), image, x, y);
|
||||
else
|
||||
gtkWidgetSetCursor(cursor.getType(), image, x, y);
|
||||
}
|
||||
|
||||
public void setEnabled (boolean b)
|
||||
|
@ -532,7 +567,7 @@ public class GtkComponentPeer extends GtkGenericPeer
|
|||
public void setVisible (boolean b)
|
||||
{
|
||||
// Only really set visible when component is bigger than zero pixels.
|
||||
if (b)
|
||||
if (b && ! (awtComponent instanceof Window))
|
||||
{
|
||||
Rectangle bounds = awtComponent.getBounds();
|
||||
b = (bounds.width > 0) && (bounds.height > 0);
|
||||
|
@ -561,10 +596,22 @@ public class GtkComponentPeer extends GtkGenericPeer
|
|||
clickCount, popupTrigger));
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for component_scroll_cb.
|
||||
*/
|
||||
protected void postMouseWheelEvent(int id, long when, int mods,
|
||||
int x, int y, int clickCount,
|
||||
boolean popupTrigger,
|
||||
int type, int amount, int rotation)
|
||||
{
|
||||
q().postEvent(new MouseWheelEvent(awtComponent, id, when, mods,
|
||||
x, y, clickCount, popupTrigger,
|
||||
type, amount, rotation));
|
||||
}
|
||||
|
||||
protected void postExposeEvent (int x, int y, int width, int height)
|
||||
{
|
||||
if (!isInRepaint)
|
||||
q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT,
|
||||
q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT,
|
||||
new Rectangle (x, y, width, height)));
|
||||
}
|
||||
|
||||
|
|
|
@ -99,11 +99,6 @@ public class GtkContainerPeer extends GtkComponentPeer
|
|||
}
|
||||
}
|
||||
|
||||
public Graphics getGraphics ()
|
||||
{
|
||||
return super.getGraphics();
|
||||
}
|
||||
|
||||
public void beginLayout () { }
|
||||
public void endLayout () { }
|
||||
public boolean isPaintPending () { return false; }
|
||||
|
|
72
libjava/classpath/gnu/java/awt/peer/gtk/GtkCursor.java
Normal file
72
libjava/classpath/gnu/java/awt/peer/gtk/GtkCursor.java
Normal file
|
@ -0,0 +1,72 @@
|
|||
/* GtkCursor.java -- Simple wrapper for custom cursor.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.peer.gtk;
|
||||
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Image;
|
||||
import java.awt.Point;
|
||||
|
||||
/**
|
||||
* Simple wrapper for custom Cursor.
|
||||
*/
|
||||
public class GtkCursor extends Cursor
|
||||
{
|
||||
private final GtkImage image;
|
||||
private final Point hotspot;
|
||||
|
||||
GtkCursor(Image image, Point hotspot, String name)
|
||||
{
|
||||
super(name);
|
||||
if (image instanceof GtkImage)
|
||||
this.image = (GtkImage) image;
|
||||
else
|
||||
this.image = new GtkImage(image.getSource());
|
||||
this.hotspot = hotspot;
|
||||
}
|
||||
|
||||
GtkImage getGtkImage()
|
||||
{
|
||||
return image;
|
||||
}
|
||||
|
||||
Point getHotspot()
|
||||
{
|
||||
return hotspot;
|
||||
}
|
||||
}
|
|
@ -51,34 +51,6 @@ public class GtkDialogPeer extends GtkWindowPeer
|
|||
{
|
||||
super (dialog);
|
||||
}
|
||||
|
||||
public Graphics getGraphics ()
|
||||
{
|
||||
Graphics g;
|
||||
if (GtkToolkit.useGraphics2D ())
|
||||
g = new GdkGraphics2D (this);
|
||||
else
|
||||
g = new GdkGraphics (this);
|
||||
g.translate (-insets.left, -insets.top);
|
||||
return g;
|
||||
}
|
||||
|
||||
protected void postMouseEvent(int id, long when, int mods, int x, int y,
|
||||
int clickCount, boolean popupTrigger)
|
||||
{
|
||||
super.postMouseEvent (id, when, mods,
|
||||
x + insets.left, y + insets.top,
|
||||
clickCount, popupTrigger);
|
||||
}
|
||||
|
||||
protected void postExposeEvent (int x, int y, int width, int height)
|
||||
{
|
||||
if (!isInRepaint)
|
||||
q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT,
|
||||
new Rectangle (x + insets.left,
|
||||
y + insets.top,
|
||||
width, height)));
|
||||
}
|
||||
|
||||
void create ()
|
||||
{
|
||||
|
|
|
@ -41,6 +41,7 @@ package gnu.java.awt.peer.gtk;
|
|||
import java.awt.Dialog;
|
||||
import java.awt.FileDialog;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.event.PaintEvent;
|
||||
import java.awt.peer.FileDialogPeer;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
|
@ -166,10 +167,10 @@ public class GtkFileDialogPeer extends GtkDialogPeer implements FileDialogPeer
|
|||
return filter.accept(dir, filename);
|
||||
}
|
||||
|
||||
public Graphics getGraphics ()
|
||||
// Sun does not call FileDialog.update.
|
||||
protected void updateComponent (PaintEvent event)
|
||||
{
|
||||
// GtkFileDialog will repaint by itself
|
||||
return null;
|
||||
// Override GtkComponetPeer.updateComponent to do nothing.
|
||||
}
|
||||
|
||||
// called back by native side: handle_response_cb
|
||||
|
|
|
@ -1,225 +0,0 @@
|
|||
/* GtkFontPeer.java -- Implements FontPeer with GTK+
|
||||
Copyright (C) 1999, 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.peer.gtk;
|
||||
|
||||
import gnu.java.awt.peer.ClasspathFontPeer;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.font.LineMetrics;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.text.CharacterIterator;
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class GtkFontPeer extends ClasspathFontPeer
|
||||
{
|
||||
private static ResourceBundle bundle;
|
||||
|
||||
static
|
||||
{
|
||||
try
|
||||
{
|
||||
bundle = ResourceBundle.getBundle ("gnu.java.awt.peer.gtk.font");
|
||||
}
|
||||
catch (Throwable ignored)
|
||||
{
|
||||
bundle = null;
|
||||
}
|
||||
}
|
||||
|
||||
private final String Xname;
|
||||
|
||||
public GtkFontPeer (String name, int style)
|
||||
{
|
||||
// All fonts get a default size of 12 if size is not specified.
|
||||
this(name, style, 12);
|
||||
}
|
||||
|
||||
public GtkFontPeer (String name, int style, int size)
|
||||
{
|
||||
super(name, style, size);
|
||||
|
||||
String Xname = null;
|
||||
if (bundle != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Xname = bundle.getString (name.toLowerCase () + "." + style);
|
||||
}
|
||||
catch (MissingResourceException mre)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
if (Xname == null)
|
||||
{
|
||||
String weight;
|
||||
String slant;
|
||||
String spacing;
|
||||
|
||||
if (style == Font.ITALIC || (style == (Font.BOLD+Font.ITALIC)))
|
||||
slant = "i";
|
||||
else
|
||||
slant = "r";
|
||||
if (style == Font.BOLD || (style == (Font.BOLD+Font.ITALIC)))
|
||||
weight = "bold";
|
||||
else
|
||||
weight = "medium";
|
||||
if (name.equals("Serif") || name.equals("SansSerif")
|
||||
|| name.equals("Helvetica") || name.equals("Times"))
|
||||
spacing = "p";
|
||||
else
|
||||
spacing = "c";
|
||||
|
||||
Xname = "-*-*-" + weight + "-" + slant + "-normal-*-*-" + size + "-*-*-" + spacing + "-*-*-*";
|
||||
}
|
||||
|
||||
this.Xname = Xname;
|
||||
}
|
||||
|
||||
public String getXLFD ()
|
||||
{
|
||||
return Xname;
|
||||
}
|
||||
|
||||
|
||||
/* remaining methods are for static compatibility with the newer
|
||||
ClasspathFontPeer superclass; none of these methods ever existed or
|
||||
worked on the older FontPeer interface, but we need to pretend to
|
||||
support them anyways. */
|
||||
|
||||
public boolean canDisplay (Font font, char c)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public int canDisplayUpTo (Font font, CharacterIterator i, int start, int limit)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String getSubFamilyName (Font font, Locale locale)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String getPostScriptName (Font font)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public int getNumGlyphs (Font font)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public int getMissingGlyphCode (Font font)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public byte getBaselineFor (Font font, char c)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String getGlyphName (Font font, int glyphIndex)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public GlyphVector createGlyphVector (Font font,
|
||||
FontRenderContext frc,
|
||||
CharacterIterator ci)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public GlyphVector createGlyphVector (Font font,
|
||||
FontRenderContext ctx,
|
||||
int[] glyphCodes)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public GlyphVector layoutGlyphVector (Font font,
|
||||
FontRenderContext frc,
|
||||
char[] chars, int start,
|
||||
int limit, int flags)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public FontMetrics getFontMetrics (Font font)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean hasUniformLineMetrics (Font font)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public LineMetrics getLineMetrics (Font font,
|
||||
CharacterIterator ci,
|
||||
int begin, int limit,
|
||||
FontRenderContext rc)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Rectangle2D getMaxCharBounds (Font font,
|
||||
FontRenderContext rc)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Rectangle2D getStringBounds (Font font,
|
||||
CharacterIterator ci,
|
||||
int begin, int limit,
|
||||
FontRenderContext frc)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/* GtkFramePeer.java -- Implements FramePeer with GTK
|
||||
Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999, 2002, 2004, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
|
@ -122,25 +122,11 @@ public class GtkFramePeer extends GtkWindowPeer
|
|||
|
||||
public void setBounds (int x, int y, int width, int height)
|
||||
{
|
||||
// prevent window_configure_cb -> awtComponent.setSize ->
|
||||
// peer.setBounds -> nativeSetBounds self-deadlock on GDK lock.
|
||||
if (Thread.currentThread() == GtkToolkit.mainThread)
|
||||
{
|
||||
int menuBarWidth = width - insets.left - insets.right;
|
||||
if (menuBar != null && menuBarWidth > 0)
|
||||
setMenuBarWidthUnlocked (menuBar, menuBarWidth);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int menuBarWidth = width - insets.left - insets.right;
|
||||
if (menuBar != null && menuBarWidth > 0)
|
||||
setMenuBarWidth (menuBar, menuBarWidth);
|
||||
|
||||
nativeSetBounds (x, y,
|
||||
width - insets.left - insets.right,
|
||||
height - insets.top - insets.bottom
|
||||
+ menuBarHeight);
|
||||
super.setBounds(x, y, width, height + menuBarHeight);
|
||||
}
|
||||
|
||||
public void setResizable (boolean resizable)
|
||||
|
@ -196,56 +182,21 @@ public class GtkFramePeer extends GtkWindowPeer
|
|||
}
|
||||
}
|
||||
|
||||
public Graphics getGraphics ()
|
||||
{
|
||||
Graphics g;
|
||||
if (GtkToolkit.useGraphics2D ())
|
||||
g = new GdkGraphics2D (this);
|
||||
else
|
||||
g = new GdkGraphics (this);
|
||||
g.translate (-insets.left, -insets.top);
|
||||
return g;
|
||||
}
|
||||
|
||||
protected void postConfigureEvent (int x, int y, int width, int height)
|
||||
{
|
||||
int frame_width = width + insets.left + insets.right;
|
||||
if (menuBar != null && width > 0)
|
||||
setMenuBarWidthUnlocked (menuBar, width);
|
||||
|
||||
// Since insets.top already includes the MenuBar's height, we need
|
||||
// to subtract the MenuBar's height from the top inset.
|
||||
int frame_height = height + insets.top + insets.bottom - menuBarHeight;
|
||||
int frame_height = height - menuBarHeight;
|
||||
|
||||
if (frame_width != awtComponent.getWidth()
|
||||
|| frame_height != awtComponent.getHeight())
|
||||
awtComponent.setSize(frame_width, frame_height);
|
||||
|
||||
int frame_x = x - insets.left;
|
||||
// Likewise, since insets.top includes the MenuBar height, we need
|
||||
// to add back the MenuBar height to the frame's y position. If
|
||||
// no MenuBar exists in this frame, the MenuBar height will be 0.
|
||||
int frame_y = y - insets.top + menuBarHeight;
|
||||
int frame_y = y + menuBarHeight;
|
||||
|
||||
if (frame_x != awtComponent.getX()
|
||||
|| frame_y != awtComponent.getY())
|
||||
{
|
||||
// awtComponent.setLocation(frame_x, frame_y);
|
||||
}
|
||||
}
|
||||
|
||||
protected void postMouseEvent(int id, long when, int mods, int x, int y,
|
||||
int clickCount, boolean popupTrigger)
|
||||
{
|
||||
super.postMouseEvent (id, when, mods,
|
||||
x + insets.left, y + insets.top,
|
||||
clickCount, popupTrigger);
|
||||
}
|
||||
|
||||
protected void postExposeEvent (int x, int y, int width, int height)
|
||||
{
|
||||
if (!isInRepaint)
|
||||
q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT,
|
||||
new Rectangle (x + insets.left,
|
||||
y + insets.top,
|
||||
width, height)));
|
||||
super.postConfigureEvent(x, frame_y, width, frame_height);
|
||||
}
|
||||
|
||||
public int getState ()
|
||||
|
|
|
@ -123,41 +123,50 @@ public class GtkImage extends Image
|
|||
|
||||
/**
|
||||
* Returns a copy of the pixel data as a java array.
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
*/
|
||||
private native int[] getPixels();
|
||||
|
||||
/**
|
||||
* Sets the pixel data from a java array.
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
*/
|
||||
private native void setPixels(int[] pixels);
|
||||
|
||||
/**
|
||||
* Loads an image using gdk-pixbuf from a file.
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
*/
|
||||
private native boolean loadPixbuf(String name);
|
||||
|
||||
/**
|
||||
* Loads an image using gdk-pixbuf from data.
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
*/
|
||||
private native boolean loadImageFromData(byte[] data);
|
||||
|
||||
/**
|
||||
* Allocates a Gtk Pixbuf or pixmap
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
*/
|
||||
private native void createPixmap();
|
||||
|
||||
/**
|
||||
* Frees the above.
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
*/
|
||||
private native void freePixmap();
|
||||
|
||||
/**
|
||||
* Sets the pixmap to scaled copy of src image. hints are rendering hints.
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
*/
|
||||
private native void createScaledPixmap(GtkImage src, int hints);
|
||||
|
||||
/**
|
||||
* Draws the image, optionally scaled and composited.
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
* Also acquires global gdk lock for drawing.
|
||||
*/
|
||||
private native void drawPixelsScaled (GdkGraphics gc,
|
||||
int bg_red, int bg_green, int bg_blue,
|
||||
|
@ -166,6 +175,8 @@ public class GtkImage extends Image
|
|||
|
||||
/**
|
||||
* Draws the image, optionally scaled flipped and composited.
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
* Also acquires global gdk lock for drawing.
|
||||
*/
|
||||
private native void drawPixelsScaledFlipped (GdkGraphics gc,
|
||||
int bg_red, int bg_green,
|
||||
|
@ -219,12 +230,21 @@ public class GtkImage extends Image
|
|||
File f = new File(filename);
|
||||
try
|
||||
{
|
||||
if (loadPixbuf(f.getCanonicalPath()) != true)
|
||||
throw new IllegalArgumentException("Couldn't load image: "+filename);
|
||||
String path = f.getCanonicalPath();
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
if (loadPixbuf(f.getCanonicalPath()) != true)
|
||||
throw new IllegalArgumentException("Couldn't load image: "
|
||||
+ filename);
|
||||
}
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
throw new IllegalArgumentException("Couldn't load image: "+filename);
|
||||
IllegalArgumentException iae;
|
||||
iae = new IllegalArgumentException("Couldn't load image: "
|
||||
+ filename);
|
||||
iae.initCause(e);
|
||||
throw iae;
|
||||
}
|
||||
|
||||
isLoaded = true;
|
||||
|
@ -241,8 +261,11 @@ public class GtkImage extends Image
|
|||
*/
|
||||
public GtkImage (byte[] data)
|
||||
{
|
||||
if (loadImageFromData (data) != true)
|
||||
throw new IllegalArgumentException ("Couldn't load image.");
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
if (loadImageFromData (data) != true)
|
||||
throw new IllegalArgumentException ("Couldn't load image.");
|
||||
}
|
||||
|
||||
isLoaded = true;
|
||||
observers = null;
|
||||
|
@ -277,8 +300,12 @@ public class GtkImage extends Image
|
|||
{
|
||||
throw new IllegalArgumentException ("Couldn't load image.");
|
||||
}
|
||||
if (loadImageFromData (baos.toByteArray()) != true)
|
||||
throw new IllegalArgumentException ("Couldn't load image.");
|
||||
byte[] array = baos.toByteArray();
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
if (loadImageFromData(array) != true)
|
||||
throw new IllegalArgumentException ("Couldn't load image.");
|
||||
}
|
||||
|
||||
isLoaded = true;
|
||||
observers = null;
|
||||
|
@ -296,7 +323,10 @@ public class GtkImage extends Image
|
|||
isLoaded = true;
|
||||
observers = null;
|
||||
offScreen = true;
|
||||
createPixmap();
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
createPixmap();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -312,7 +342,10 @@ public class GtkImage extends Image
|
|||
offScreen = false;
|
||||
|
||||
// Use the GDK scaling method.
|
||||
createScaledPixmap(src, hints);
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
createScaledPixmap(src, hints);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -322,7 +355,10 @@ public class GtkImage extends Image
|
|||
GtkImage (Pointer pixbuf)
|
||||
{
|
||||
pixmap = pixbuf;
|
||||
createFromPixbuf();
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
createFromPixbuf();
|
||||
}
|
||||
isLoaded = true;
|
||||
observers = null;
|
||||
offScreen = false;
|
||||
|
@ -349,6 +385,7 @@ public class GtkImage extends Image
|
|||
|
||||
/**
|
||||
* Native helper function for constructor that takes a pixbuf Pointer.
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
*/
|
||||
private native void createFromPixbuf();
|
||||
|
||||
|
@ -370,8 +407,11 @@ public class GtkImage extends Image
|
|||
|
||||
isLoaded = true;
|
||||
deliver();
|
||||
createPixmap();
|
||||
setPixels(pixels);
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
createPixmap();
|
||||
setPixels(pixels);
|
||||
}
|
||||
}
|
||||
|
||||
// java.awt.Image methods ////////////////////////////////////////////////
|
||||
|
@ -408,7 +448,13 @@ public class GtkImage extends Image
|
|||
{
|
||||
if (!isLoaded)
|
||||
return null;
|
||||
return new MemoryImageSource(width, height, nativeModel, getPixels(),
|
||||
|
||||
int[] pixels;
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
pixels = getPixels();
|
||||
}
|
||||
return new MemoryImageSource(width, height, nativeModel, pixels,
|
||||
0, width);
|
||||
}
|
||||
|
||||
|
@ -454,7 +500,10 @@ public class GtkImage extends Image
|
|||
{
|
||||
observers = new Vector();
|
||||
isLoaded = false;
|
||||
freePixmap();
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
freePixmap();
|
||||
}
|
||||
source.startProduction(new GtkImageConsumer(this, source));
|
||||
}
|
||||
}
|
||||
|
@ -462,7 +511,12 @@ public class GtkImage extends Image
|
|||
public void finalize()
|
||||
{
|
||||
if (isLoaded)
|
||||
freePixmap();
|
||||
{
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
freePixmap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -529,23 +583,29 @@ public class GtkImage extends Image
|
|||
srcHeight = height - srcY;
|
||||
}
|
||||
|
||||
if ( this.width <= 0 || this.height <= 0 )
|
||||
return true;
|
||||
|
||||
if ( srcWidth <= 0 || srcHeight <= 0 || dstWidth <= 0 || dstHeight <= 0)
|
||||
return true;
|
||||
|
||||
if(bgcolor != null)
|
||||
drawPixelsScaledFlipped (g, bgcolor.getRed (), bgcolor.getGreen (),
|
||||
bgcolor.getBlue (),
|
||||
flipX, flipY,
|
||||
srcX, srcY,
|
||||
srcWidth, srcHeight,
|
||||
dstX, dstY,
|
||||
dstWidth, dstHeight,
|
||||
true);
|
||||
else
|
||||
drawPixelsScaledFlipped (g, 0, 0, 0, flipX, flipY,
|
||||
srcX, srcY, srcWidth, srcHeight,
|
||||
dstX, dstY, dstWidth, dstHeight,
|
||||
false);
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
if(bgcolor != null)
|
||||
drawPixelsScaledFlipped (g, bgcolor.getRed (), bgcolor.getGreen (),
|
||||
bgcolor.getBlue (),
|
||||
flipX, flipY,
|
||||
srcX, srcY,
|
||||
srcWidth, srcHeight,
|
||||
dstX, dstY,
|
||||
dstWidth, dstHeight,
|
||||
true);
|
||||
else
|
||||
drawPixelsScaledFlipped (g, 0, 0, 0, flipX, flipY,
|
||||
srcX, srcY, srcWidth, srcHeight,
|
||||
dstX, dstY, dstWidth, dstHeight,
|
||||
false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -559,11 +619,17 @@ public class GtkImage extends Image
|
|||
if (addObserver(observer))
|
||||
return false;
|
||||
|
||||
if(bgcolor != null)
|
||||
drawPixelsScaled(g, bgcolor.getRed (), bgcolor.getGreen (),
|
||||
bgcolor.getBlue (), x, y, width, height, true);
|
||||
else
|
||||
drawPixelsScaled(g, 0, 0, 0, x, y, width, height, false);
|
||||
if ( this.width <= 0 || this.height <= 0 )
|
||||
return true;
|
||||
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
if(bgcolor != null)
|
||||
drawPixelsScaled(g, bgcolor.getRed (), bgcolor.getGreen (),
|
||||
bgcolor.getBlue (), x, y, width, height, true);
|
||||
else
|
||||
drawPixelsScaled(g, 0, 0, 0, x, y, width, height, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ package gnu.java.awt.peer.gtk;
|
|||
|
||||
import java.awt.AWTEvent;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.List;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
@ -120,11 +121,12 @@ public class GtkListPeer extends GtkComponentPeer
|
|||
|
||||
public Dimension preferredSize (int rows)
|
||||
{
|
||||
int dims[] = new int[2];
|
||||
|
||||
int visibleRows = ((List) awtComponent).getRows();
|
||||
getSize (rows, visibleRows, dims);
|
||||
return new Dimension (dims[0], dims[1]);
|
||||
// getSize returns the minimum size of the list.
|
||||
// The width is too narrow for a typical list.
|
||||
List l = (List) awtComponent;
|
||||
Dimension d = getMinimumSize();
|
||||
FontMetrics fm = l.getFontMetrics(l.getFont());
|
||||
return new Dimension(d.width + fm.stringWidth("1234567890"), d.height);
|
||||
}
|
||||
|
||||
public void removeAll ()
|
||||
|
|
|
@ -39,9 +39,7 @@ exception statement from your version. */
|
|||
package gnu.java.awt.peer.gtk;
|
||||
|
||||
import java.awt.AWTEvent;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Panel;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.PaintEvent;
|
||||
import java.awt.peer.PanelPeer;
|
||||
|
@ -59,35 +57,10 @@ public class GtkPanelPeer extends GtkContainerPeer
|
|||
public void handleEvent(AWTEvent event)
|
||||
{
|
||||
int id = event.getID();
|
||||
switch (id)
|
||||
{
|
||||
case MouseEvent.MOUSE_PRESSED:
|
||||
awtComponent.requestFocusInWindow();
|
||||
break;
|
||||
case PaintEvent.UPDATE:
|
||||
case PaintEvent.PAINT:
|
||||
{
|
||||
try
|
||||
{
|
||||
Graphics g = getGraphics();
|
||||
if (! awtComponent.isShowing() || awtComponent.getWidth() < 1
|
||||
|| awtComponent.getHeight() < 1 || g == null)
|
||||
return;
|
||||
|
||||
g.setClip(((PaintEvent) event).getUpdateRect());
|
||||
|
||||
// Do not want to clear anything before painting.);
|
||||
awtComponent.paint(g);
|
||||
|
||||
g.dispose();
|
||||
return;
|
||||
}
|
||||
catch (InternalError e)
|
||||
{
|
||||
System.err.println(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (id == MouseEvent.MOUSE_PRESSED)
|
||||
awtComponent.requestFocusInWindow();
|
||||
|
||||
super.handleEvent(event);
|
||||
}
|
||||
|
||||
|
|
|
@ -55,9 +55,6 @@ import java.awt.Image;
|
|||
* that the available flavors might have changed. When requested it
|
||||
* (lazily) caches the targets, and (text, image, or files/uris)
|
||||
* clipboard contents.
|
||||
*
|
||||
* XXX - should only cache when
|
||||
* gdk_display_supports_selection_notification is true.
|
||||
*/
|
||||
public class GtkSelection implements Transferable
|
||||
{
|
||||
|
@ -66,6 +63,11 @@ public class GtkSelection implements Transferable
|
|||
*/
|
||||
static private Object requestLock = new Object();
|
||||
|
||||
/**
|
||||
* Whether we belong to the Clipboard (true) or to the Primary selection.
|
||||
*/
|
||||
private final boolean clipboard;
|
||||
|
||||
/**
|
||||
* Whether a request for mimetypes, text, images, uris or byte[] is
|
||||
* currently in progress. Should only be tested or set with
|
||||
|
@ -143,10 +145,13 @@ public class GtkSelection implements Transferable
|
|||
private byte[] bytes;
|
||||
|
||||
/**
|
||||
* Should only be created by the GtkClipboard class.
|
||||
* Should only be created by the GtkClipboard class. The clipboard
|
||||
* should be either GtkClipboard.clipboard or
|
||||
* GtkClipboard.selection.
|
||||
*/
|
||||
GtkSelection()
|
||||
GtkSelection(GtkClipboard clipboard)
|
||||
{
|
||||
this.clipboard = (clipboard == GtkClipboard.clipboard);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -181,7 +186,7 @@ public class GtkSelection implements Transferable
|
|||
if (! mimeTypesDelivered)
|
||||
{
|
||||
requestInProgress = true;
|
||||
requestMimeTypes();
|
||||
requestMimeTypes(clipboard);
|
||||
while (! mimeTypesDelivered)
|
||||
{
|
||||
try
|
||||
|
@ -312,7 +317,7 @@ public class GtkSelection implements Transferable
|
|||
if (! textDelivered)
|
||||
{
|
||||
requestInProgress = true;
|
||||
requestText();
|
||||
requestText(clipboard);
|
||||
while (! textDelivered)
|
||||
{
|
||||
try
|
||||
|
@ -385,7 +390,7 @@ public class GtkSelection implements Transferable
|
|||
if (! imageDelivered)
|
||||
{
|
||||
requestInProgress = true;
|
||||
requestImage();
|
||||
requestImage(clipboard);
|
||||
while (! imageDelivered)
|
||||
{
|
||||
try
|
||||
|
@ -464,7 +469,7 @@ public class GtkSelection implements Transferable
|
|||
if (! urisDelivered)
|
||||
{
|
||||
requestInProgress = true;
|
||||
requestURIs();
|
||||
requestURIs(clipboard);
|
||||
while (! urisDelivered)
|
||||
{
|
||||
try
|
||||
|
@ -547,7 +552,7 @@ public class GtkSelection implements Transferable
|
|||
|
||||
// Request bytes and wait till they are available.
|
||||
requestInProgress = true;
|
||||
requestBytes(target);
|
||||
requestBytes(clipboard, target);
|
||||
while (! bytesDelivered)
|
||||
{
|
||||
try
|
||||
|
@ -653,12 +658,14 @@ public class GtkSelection implements Transferable
|
|||
* content is available the contentLock will be notified through
|
||||
* textAvailable, imageAvailable, urisAvailable or bytesAvailable and the
|
||||
* appropriate field is set.
|
||||
* The clipboard argument is true if we want the Clipboard, and false
|
||||
* if we want the (primary) selection.
|
||||
*/
|
||||
private native void requestText();
|
||||
private native void requestImage();
|
||||
private native void requestURIs();
|
||||
private native void requestBytes(String target);
|
||||
private native void requestText(boolean clipboard);
|
||||
private native void requestImage(boolean clipboard);
|
||||
private native void requestURIs(boolean clipboard);
|
||||
private native void requestBytes(boolean clipboard, String target);
|
||||
|
||||
/* Similar to the above but for requesting the supported targets. */
|
||||
private native void requestMimeTypes();
|
||||
private native void requestMimeTypes(boolean clipboard);
|
||||
}
|
||||
|
|
|
@ -361,7 +361,16 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
|
|||
if (secman != null)
|
||||
secman.checkSystemClipboardAccess();
|
||||
|
||||
return GtkClipboard.getInstance();
|
||||
return GtkClipboard.getClipboardInstance();
|
||||
}
|
||||
|
||||
public Clipboard getSystemSelection()
|
||||
{
|
||||
SecurityManager secman = System.getSecurityManager();
|
||||
if (secman != null)
|
||||
secman.checkSystemClipboardAccess();
|
||||
|
||||
return GtkClipboard.getSelectionInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -570,6 +579,11 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
|
|||
return q;
|
||||
}
|
||||
|
||||
public Cursor createCustomCursor(Image image, Point hotspot, String name)
|
||||
{
|
||||
return new GtkCursor(image, hotspot, name);
|
||||
}
|
||||
|
||||
protected native void loadSystemColors (int[] systemColors);
|
||||
|
||||
public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent e)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* GtkWindowPeer.java -- Implements WindowPeer with GTK
|
||||
Copyright (C) 1998, 1999, 2002, 2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 1998, 1999, 2002, 2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
|
@ -42,7 +42,9 @@ import java.awt.AWTEvent;
|
|||
import java.awt.Component;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.PaintEvent;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.peer.WindowPeer;
|
||||
|
@ -62,20 +64,37 @@ public class GtkWindowPeer extends GtkContainerPeer
|
|||
private boolean hasBeenShown = false;
|
||||
private int oldState = Frame.NORMAL;
|
||||
|
||||
// Cached awt window component location, width and height.
|
||||
private int x, y, width, height;
|
||||
|
||||
native void gtkWindowSetTitle (String title);
|
||||
native void gtkWindowSetResizable (boolean resizable);
|
||||
native void gtkWindowSetModal (boolean modal);
|
||||
|
||||
native void realize ();
|
||||
|
||||
int getWidth ()
|
||||
/** Returns the cached width of the AWT window component. */
|
||||
int getX ()
|
||||
{
|
||||
return awtComponent.getWidth();
|
||||
return x;
|
||||
}
|
||||
|
||||
/** Returns the cached width of the AWT window component. */
|
||||
int getY ()
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
/** Returns the cached width of the AWT window component. */
|
||||
int getWidth ()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
/** Returns the cached height of the AWT window component. */
|
||||
int getHeight ()
|
||||
{
|
||||
return awtComponent.getHeight();
|
||||
return height;
|
||||
}
|
||||
|
||||
native void create (int type, boolean decorated, GtkWindowPeer parent);
|
||||
|
@ -85,6 +104,10 @@ public class GtkWindowPeer extends GtkContainerPeer
|
|||
Window window = (Window) awtComponent;
|
||||
GtkWindowPeer parent_peer = null;
|
||||
Component parent = awtComponent.getParent();
|
||||
x = awtComponent.getX();
|
||||
y = awtComponent.getY();
|
||||
height = awtComponent.getHeight();
|
||||
width = awtComponent.getWidth();
|
||||
|
||||
if (!window.isFocusableWindow())
|
||||
type = GDK_WINDOW_TYPE_HINT_MENU;
|
||||
|
@ -129,37 +152,28 @@ public class GtkWindowPeer extends GtkContainerPeer
|
|||
native void nativeSetLocation (int x, int y);
|
||||
native void nativeSetLocationUnlocked (int x, int y);
|
||||
|
||||
public void setLocation (int x, int y)
|
||||
// Called from show.
|
||||
protected void setLocation (int x, int y)
|
||||
{
|
||||
// prevent window_configure_cb -> awtComponent.setSize ->
|
||||
// peer.setBounds -> nativeSetBounds self-deadlock on GDK lock.
|
||||
if (Thread.currentThread() == GtkToolkit.mainThread)
|
||||
return;
|
||||
nativeSetLocation (x, y);
|
||||
}
|
||||
|
||||
public void setLocationUnlocked (int x, int y)
|
||||
{
|
||||
nativeSetLocationUnlocked (x, y);
|
||||
}
|
||||
|
||||
public void setBounds (int x, int y, int width, int height)
|
||||
{
|
||||
// prevent window_configure_cb -> awtComponent.setSize ->
|
||||
// peer.setBounds -> nativeSetBounds self-deadlock on GDK lock.
|
||||
if (Thread.currentThread() == GtkToolkit.mainThread)
|
||||
return;
|
||||
|
||||
nativeSetBounds (x, y,
|
||||
width - insets.left - insets.right,
|
||||
height - insets.top - insets.bottom);
|
||||
}
|
||||
|
||||
public void setBoundsUnlocked (int x, int y, int width, int height)
|
||||
{
|
||||
nativeSetBoundsUnlocked (x, y,
|
||||
width - insets.left - insets.right,
|
||||
height - insets.top - insets.bottom);
|
||||
if (x != getX()
|
||||
|| y != getY()
|
||||
|| width != getWidth()
|
||||
|| height != getHeight())
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
nativeSetBounds (x, y,
|
||||
width - insets.left - insets.right,
|
||||
height - insets.top - insets.bottom);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTitle (String title)
|
||||
|
@ -167,15 +181,25 @@ public class GtkWindowPeer extends GtkContainerPeer
|
|||
gtkWindowSetTitle (title);
|
||||
}
|
||||
|
||||
native void setSize (int width, int height);
|
||||
|
||||
// Called from setResizable
|
||||
protected native void setSize (int width, int height);
|
||||
|
||||
/**
|
||||
* Needed by both GtkFramePeer and GtkDialogPeer subclasses, so
|
||||
* implemented here. But never actually called on a GtkWindowPeer
|
||||
* itself.
|
||||
*/
|
||||
public void setResizable (boolean resizable)
|
||||
{
|
||||
// Call setSize; otherwise when resizable is changed from true to
|
||||
// false the window will shrink to the dimensions it had before it
|
||||
// was resizable.
|
||||
setSize (awtComponent.getWidth() - insets.left - insets.right,
|
||||
awtComponent.getHeight() - insets.top - insets.bottom);
|
||||
x = awtComponent.getX();
|
||||
y = awtComponent.getY();
|
||||
width = awtComponent.getWidth();
|
||||
height = awtComponent.getHeight();
|
||||
setSize (width - insets.left - insets.right,
|
||||
height - insets.top - insets.bottom);
|
||||
gtkWindowSetResizable (resizable);
|
||||
}
|
||||
|
||||
|
@ -195,23 +219,35 @@ public class GtkWindowPeer extends GtkContainerPeer
|
|||
int frame_width = width + insets.left + insets.right;
|
||||
int frame_height = height + insets.top + insets.bottom;
|
||||
|
||||
if (frame_width != awtComponent.getWidth()
|
||||
|| frame_height != awtComponent.getHeight())
|
||||
awtComponent.setSize(frame_width, frame_height);
|
||||
if (frame_width != getWidth()
|
||||
|| frame_height != getHeight())
|
||||
{
|
||||
this.width = frame_width;
|
||||
this.height = frame_height;
|
||||
q().postEvent(new ComponentEvent(awtComponent,
|
||||
ComponentEvent.COMPONENT_RESIZED));
|
||||
}
|
||||
|
||||
int frame_x = x - insets.left;
|
||||
int frame_y = y - insets.top;
|
||||
|
||||
if (frame_x != awtComponent.getX()
|
||||
|| frame_y != awtComponent.getY())
|
||||
if (frame_x != getX()
|
||||
|| frame_y != getY())
|
||||
{
|
||||
// awtComponent.setLocation(frame_x, frame_y);
|
||||
this.x = frame_x;
|
||||
this.y = frame_y;
|
||||
q().postEvent(new ComponentEvent(awtComponent,
|
||||
ComponentEvent.COMPONENT_MOVED));
|
||||
}
|
||||
}
|
||||
|
||||
public void show ()
|
||||
{
|
||||
setLocation(awtComponent.getX(), awtComponent.getY());
|
||||
x = awtComponent.getX();
|
||||
y = awtComponent.getY();
|
||||
width = awtComponent.getWidth();
|
||||
height = awtComponent.getHeight();
|
||||
setLocation(x, y);
|
||||
setVisible (true);
|
||||
}
|
||||
|
||||
|
@ -244,37 +280,62 @@ public class GtkWindowPeer extends GtkContainerPeer
|
|||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
protected void postExposeEvent (int x, int y, int width, int height)
|
||||
{
|
||||
// Translate GTK co-ordinates, which do not include a window
|
||||
// frame's insets, to AWT co-ordinates, which do include a window
|
||||
// frame's insets. GtkWindowPeer should always have all-zero
|
||||
// insets but GtkFramePeer and GtkDialogPeer insets will be
|
||||
// non-zero.
|
||||
q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT,
|
||||
new Rectangle (x + insets.left,
|
||||
y + insets.top,
|
||||
width, height)));
|
||||
}
|
||||
|
||||
public boolean requestWindowFocus()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
public void handleEvent(AWTEvent event)
|
||||
public Graphics getGraphics ()
|
||||
{
|
||||
int id = event.getID();
|
||||
if (id == PaintEvent.UPDATE || id == PaintEvent.PAINT)
|
||||
{
|
||||
try
|
||||
{
|
||||
Graphics g = getGraphics();
|
||||
if (! awtComponent.isShowing() || awtComponent.getWidth() < 1
|
||||
|| awtComponent.getHeight() < 1 || g == null)
|
||||
return;
|
||||
Graphics g = super.getGraphics ();
|
||||
// Translate AWT co-ordinates, which include a window frame's
|
||||
// insets, to GTK co-ordinates, which do not include a window
|
||||
// frame's insets. GtkWindowPeer should always have all-zero
|
||||
// insets but GtkFramePeer and GtkDialogPeer insets will be
|
||||
// non-zero.
|
||||
g.translate (-insets.left, -insets.top);
|
||||
return g;
|
||||
}
|
||||
|
||||
g.setClip(((PaintEvent) event).getUpdateRect());
|
||||
protected void updateComponent (PaintEvent event)
|
||||
{
|
||||
// Do not clear anything before painting. Sun never calls
|
||||
// Window.update, only Window.paint.
|
||||
paintComponent(event);
|
||||
}
|
||||
|
||||
// Do not want to clear anything before painting.
|
||||
awtComponent.paint(g);
|
||||
protected void postMouseEvent(int id, long when, int mods, int x, int y,
|
||||
int clickCount, boolean popupTrigger)
|
||||
{
|
||||
// Translate AWT co-ordinates, which include a window frame's
|
||||
// insets, to GTK co-ordinates, which do not include a window
|
||||
// frame's insets. GtkWindowPeer should always have all-zero
|
||||
// insets but GtkFramePeer and GtkDialogPeer insets will be
|
||||
// non-zero.
|
||||
super.postMouseEvent (id, when, mods,
|
||||
x + insets.left, y + insets.top,
|
||||
clickCount, popupTrigger);
|
||||
}
|
||||
|
||||
g.dispose();
|
||||
return;
|
||||
}
|
||||
catch (InternalError e)
|
||||
{
|
||||
System.err.println(e);
|
||||
}
|
||||
}
|
||||
super.handleEvent(event);
|
||||
// We override this to keep it in sync with our internal
|
||||
// representation.
|
||||
public Rectangle getBounds()
|
||||
{
|
||||
return new Rectangle(x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -590,8 +590,7 @@ public class SwingComponentPeer
|
|||
*/
|
||||
public void setBounds(int x, int y, int width, int height)
|
||||
{
|
||||
if (swingComponent != null)
|
||||
swingComponent.getJComponent().setBounds(x, y, width, height);
|
||||
reshape(x, y, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -61,7 +61,7 @@ public class SwingContainerPeer
|
|||
*
|
||||
* @param awtCont
|
||||
*/
|
||||
public SwingContainerPeer(Container awtCont)
|
||||
public SwingContainerPeer(Component awtCont)
|
||||
{
|
||||
init(awtCont, null);
|
||||
}
|
||||
|
@ -92,12 +92,7 @@ public class SwingContainerPeer
|
|||
*/
|
||||
public Insets getInsets()
|
||||
{
|
||||
Insets retVal;
|
||||
if (swingComponent != null)
|
||||
retVal = swingComponent.getJComponent().getInsets();
|
||||
else
|
||||
retVal = new Insets(0, 0, 0, 0);
|
||||
return retVal;
|
||||
return insets();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -214,12 +209,15 @@ public class SwingContainerPeer
|
|||
protected void handleMouseEvent(MouseEvent ev)
|
||||
{
|
||||
Component comp = awtComponent.getComponentAt(ev.getPoint());
|
||||
ComponentPeer peer = comp.getPeer();
|
||||
if (awtComponent != comp && !comp.isLightweight() && peer instanceof SwingComponentPeer)
|
||||
if (comp != null)
|
||||
{
|
||||
ev.translatePoint(comp.getX(), comp.getY());
|
||||
ev.setSource(comp);
|
||||
((SwingComponentPeer) peer).handleMouseEvent(ev);
|
||||
ComponentPeer peer = comp.getPeer();
|
||||
if (awtComponent != comp && !comp.isLightweight() && peer instanceof SwingComponentPeer)
|
||||
{
|
||||
ev.translatePoint(comp.getX(), comp.getY());
|
||||
ev.setSource(comp);
|
||||
((SwingComponentPeer) peer).handleMouseEvent(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,11 +229,14 @@ public class SwingContainerPeer
|
|||
protected void handleMouseMotionEvent(MouseEvent ev)
|
||||
{
|
||||
Component comp = awtComponent.getComponentAt(ev.getPoint());
|
||||
ComponentPeer peer = comp.getPeer();
|
||||
if (awtComponent != comp && !comp.isLightweight() && peer instanceof SwingComponentPeer)
|
||||
if (comp != null)
|
||||
{
|
||||
ev.translatePoint(comp.getX(), comp.getY());
|
||||
((SwingComponentPeer) peer).handleMouseMotionEvent(ev);
|
||||
ComponentPeer peer = comp.getPeer();
|
||||
if (awtComponent != comp && !comp.isLightweight() && peer instanceof SwingComponentPeer)
|
||||
{
|
||||
ev.translatePoint(comp.getX(), comp.getY());
|
||||
((SwingComponentPeer) peer).handleMouseMotionEvent(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue