summaryrefslogtreecommitdiff
path: root/libjava/classpath/gnu/java/awt
diff options
context:
space:
mode:
authorMatthias Klose <doko@gcc.gnu.org>2007-06-03 23:18:43 +0000
committerMatthias Klose <doko@gcc.gnu.org>2007-06-03 23:18:43 +0000
commite1bea0c0687c5f4551b3a6058ec37ce3705fa6cc (patch)
treea9c9e7d91c484d53fe154f9285fc57325572ce50 /libjava/classpath/gnu/java/awt
parentaf333b9a7f9e1cc1029bec56d48f2de63acdf686 (diff)
downloadgcc-e1bea0c0687c5f4551b3a6058ec37ce3705fa6cc.tar.gz
libjava/classpath/ChangeLog.gcj:
2007-05-31 Matthias Klose <doko@ubuntu.com> * javax/management/NotificationBroadcasterSupport.java (getNotificationInfo): Add cast. * native/jni/qt-peer/Makefile.am (AM_CXXFLAGS): Add libstdc++ include directories. * native/jni/qt-peer/Makefile.in: Regenerate. libjava/ChangeLog: 2007-06-03 Matthias Klose <doko@ubuntu.com> * java/io/natFileWin32.cc (setFilePermissions): New (stub only). _access: Handle EXEC query, stub only. 2007-06-03 Matthias Klose <doko@ubuntu.com> Merged from classpath: * gnu/java/nio/SelectorProviderImpl.java: Whitespace merge. * java/lang/System.java(inheritedChannel): New. * java/lang/Character.java: Remove stray`;'. * java/net/MulticastSocket.java: Merged. * java/text/DateFormatSymbols.java(getInstance): New, comment updates. * java/text/Collator.java(getInstance): Merged. * java/util/Calendar.java: New attributes ALL_STYLES, SHORT, LONG. getDisplayName, getDisplayNames: New. * java/util/logging/Logger.java: Merged. * Regenerate .class and .h files. 2007-06-03 Matthias Klose <doko@ubuntu.com> * java/io/File.java: Merge with classpath-0.95, new method setFilePermissions, new attribute EXEC. * java/io/natFilePosix.cc (setFilePermissions): New. _access: Handle EXEC query. * classpath/lib/java/io/File.class, java/io/File.h: Regenerate. 2007-06-03 Matthias Klose <doko@ubuntu.com> Imported GNU Classpath 0.95. * classpath/Makefile.in, classpath/native/jni/midi-dssi/Makefile.in, classpath/native/jni/classpath/Makefile.in, classpath/native/jni/Makefile.in, classpath/native/jni/gconf-peer/Makefile.in, classpath/native/jni/java-io/Makefile.in, classpath/native/jni/native-lib/Makefile.in, classpath/native/jni/java-util/Makefile.in, classpath/native/jni/midi-alsa/Makefile.in, classpath/native/jni/java-lang/Makefile.in, classpath/native/jni/java-nio/Makefile.in, classpath/native/jni/java-net/Makefile.in, classpath/native/jni/xmlj/Makefile.in, classpath/native/jni/qt-peer/Makefile.in, classpath/native/jni/gtk-peer/Makefile.in, classpath/native/Makefile.in, classpath/native/jawt/Makefile.in, classpath/native/fdlibm/Makefile.in, classpath/native/plugin/Makefile.in, classpath/resource/Makefile.in, classpath/scripts/Makefile.in, classpath/tools/Makefile.in, classpath/doc/Makefile.in, classpath/doc/api/Makefile.in, classpath/lib/Makefile.in, classpath/external/Makefile.in, classpath/external/jsr166/Makefile.in, classpath/external/sax/Makefile.in, classpath/external/w3c_dom/Makefile.in, classpath/external/relaxngDatatype/Makefile.in, classpath/include/Makefile.in, classpath/examples/Makefile.in: Regenerate. * classpath/config.guess, classpath/config.sub, classpath/ltmain.sh : Update. * classpath/configure, classpath/depcomp, classpath/missing, classpath/aclocal.m4, classpath/install-sh: Regenerate. * gnu/classpath/Configuration.java (CLASSPATH_VERSION): Now 0.95. * sources.am: Regenerate. * Makefile.in: Regenerate. * Update the .class files and generated CNI header files, add new .class and generated CNI header files. * Remove generated files for removed java source files: classpath/gnu/java/net/BASE64.java, classpath/gnu/java/security/util/Base64.java, classpath/gnu/java/awt/peer/gtk/GThreadMutex.java, classpath/gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java, classpath/gnu/java/awt/font/autofit/Scaler.java, classpath/gnu/classpath/jdwp/util/Value.java, classpath/gnu/javax/net/ssl/Base64.java. * Remove empty directories. * Makefile.am(nat_source_files): Add natVMOperatingSystemMXBeanImpl.cc. * java/lang/Class.java(setAccessible): Merge from classpath. * java/util/Locale.java: Remove. * gnu/java/lang/management/VMOperatingSystemMXBeanImpl.java, gnu/java/lang/management/natVMOperatingSystemMXBeanImpl.cc: New. * gcj/javaprims.h: Update class declarations. * scripts/classes.pl: Update usage. * HACKING: Mention to build all peers. From-SVN: r125302
Diffstat (limited to 'libjava/classpath/gnu/java/awt')
-rw-r--r--libjava/classpath/gnu/java/awt/AWTUtilities.java203
-rw-r--r--libjava/classpath/gnu/java/awt/ClasspathGraphicsEnvironment.java67
-rw-r--r--libjava/classpath/gnu/java/awt/ClasspathToolkit.java45
-rw-r--r--libjava/classpath/gnu/java/awt/font/FontDelegate.java10
-rw-r--r--libjava/classpath/gnu/java/awt/font/GNUGlyphVector.java49
-rw-r--r--libjava/classpath/gnu/java/awt/font/autofit/AutoHinter.java83
-rw-r--r--libjava/classpath/gnu/java/awt/font/autofit/AxisHints.java69
-rw-r--r--libjava/classpath/gnu/java/awt/font/autofit/Constants.java25
-rw-r--r--libjava/classpath/gnu/java/awt/font/autofit/Edge.java80
-rw-r--r--libjava/classpath/gnu/java/awt/font/autofit/GlyphHints.java579
-rw-r--r--libjava/classpath/gnu/java/awt/font/autofit/HintScaler.java (renamed from libjava/classpath/gnu/java/awt/font/autofit/Scaler.java)5
-rw-r--r--libjava/classpath/gnu/java/awt/font/autofit/Latin.java1214
-rw-r--r--libjava/classpath/gnu/java/awt/font/autofit/LatinAxis.java11
-rw-r--r--libjava/classpath/gnu/java/awt/font/autofit/LatinBlue.java59
-rw-r--r--libjava/classpath/gnu/java/awt/font/autofit/LatinMetrics.java15
-rw-r--r--libjava/classpath/gnu/java/awt/font/autofit/Script.java6
-rw-r--r--libjava/classpath/gnu/java/awt/font/autofit/ScriptMetrics.java6
-rw-r--r--libjava/classpath/gnu/java/awt/font/autofit/Segment.java50
-rw-r--r--libjava/classpath/gnu/java/awt/font/autofit/Utils.java255
-rw-r--r--libjava/classpath/gnu/java/awt/font/autofit/Width.java16
-rw-r--r--libjava/classpath/gnu/java/awt/font/opentype/Hinter.java63
-rw-r--r--libjava/classpath/gnu/java/awt/font/opentype/OpenTypeFont.java38
-rw-r--r--libjava/classpath/gnu/java/awt/font/opentype/Scaler.java3
-rw-r--r--libjava/classpath/gnu/java/awt/font/opentype/truetype/Fixed.java20
-rw-r--r--libjava/classpath/gnu/java/awt/font/opentype/truetype/GlyphLoader.java33
-rw-r--r--libjava/classpath/gnu/java/awt/font/opentype/truetype/Point.java285
-rw-r--r--libjava/classpath/gnu/java/awt/font/opentype/truetype/TrueTypeScaler.java10
-rw-r--r--libjava/classpath/gnu/java/awt/font/opentype/truetype/Zone.java146
-rw-r--r--libjava/classpath/gnu/java/awt/font/opentype/truetype/ZonePathIterator.java24
-rw-r--r--libjava/classpath/gnu/java/awt/java2d/AbstractGraphics2D.java494
-rw-r--r--libjava/classpath/gnu/java/awt/java2d/ActiveEdges.java195
-rw-r--r--libjava/classpath/gnu/java/awt/java2d/PolyEdge.java71
-rw-r--r--libjava/classpath/gnu/java/awt/java2d/Scanline.java91
-rw-r--r--libjava/classpath/gnu/java/awt/java2d/ScanlineConverter.java404
-rw-r--r--libjava/classpath/gnu/java/awt/peer/ClasspathDesktopPeer.java301
-rw-r--r--libjava/classpath/gnu/java/awt/peer/ClasspathFontPeer.java32
-rw-r--r--libjava/classpath/gnu/java/awt/peer/GnomeDesktopPeer.java153
-rw-r--r--libjava/classpath/gnu/java/awt/peer/KDEDesktopPeer.java135
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/AsyncImage.java10
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/BufferedImageGraphics.java116
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java527
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/CairoSurface.java299
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java123
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java108
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java157
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GThreadMutex.java109
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java303
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java40
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java16
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java137
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java4
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java19
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkChoicePeer.java26
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboard.java202
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboardNotifier.java85
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java70
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java20
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java20
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java138
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkImageConsumer.java74
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java6
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkListPeer.java26
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkMainThread.java14
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java16
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java6
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java8
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java6
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollPanePeer.java6
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java14
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkSelection.java642
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java12
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java4
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java114
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java60
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/VolatileImageGraphics.java20
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtToolkit.java49
-rw-r--r--libjava/classpath/gnu/java/awt/print/JavaPrinterGraphics.java3
-rw-r--r--libjava/classpath/gnu/java/awt/print/PostScriptGraphics2D.java3
78 files changed, 6549 insertions, 2408 deletions
diff --git a/libjava/classpath/gnu/java/awt/AWTUtilities.java b/libjava/classpath/gnu/java/awt/AWTUtilities.java
index ca7b5511853..1b68703697f 100644
--- a/libjava/classpath/gnu/java/awt/AWTUtilities.java
+++ b/libjava/classpath/gnu/java/awt/AWTUtilities.java
@@ -1,5 +1,5 @@
/* AWTUtilities.java -- Common utility methods for AWT and Swing.
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -47,6 +47,7 @@ import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
+import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.AbstractSequentialList;
import java.util.List;
@@ -694,4 +695,204 @@ public class AWTUtilities
{
return java.awt.EventQueue.isDispatchThread();
}
+
+ /**
+ * Returns whether the specified key code is valid.
+ */
+ public static boolean isValidKey(int keyCode)
+ {
+ switch (keyCode)
+ {
+ case KeyEvent.VK_ENTER:
+ case KeyEvent.VK_BACK_SPACE:
+ case KeyEvent.VK_TAB:
+ case KeyEvent.VK_CANCEL:
+ case KeyEvent.VK_CLEAR:
+ case KeyEvent.VK_SHIFT:
+ case KeyEvent.VK_CONTROL:
+ case KeyEvent.VK_ALT:
+ case KeyEvent.VK_PAUSE:
+ case KeyEvent.VK_CAPS_LOCK:
+ case KeyEvent.VK_ESCAPE:
+ case KeyEvent.VK_SPACE:
+ case KeyEvent.VK_PAGE_UP:
+ case KeyEvent.VK_PAGE_DOWN:
+ case KeyEvent.VK_END:
+ case KeyEvent.VK_HOME:
+ case KeyEvent.VK_LEFT:
+ case KeyEvent.VK_UP:
+ case KeyEvent.VK_RIGHT:
+ case KeyEvent.VK_DOWN:
+ case KeyEvent.VK_COMMA:
+ case KeyEvent.VK_MINUS:
+ case KeyEvent.VK_PERIOD:
+ case KeyEvent.VK_SLASH:
+ case KeyEvent.VK_0:
+ case KeyEvent.VK_1:
+ case KeyEvent.VK_2:
+ case KeyEvent.VK_3:
+ case KeyEvent.VK_4:
+ case KeyEvent.VK_5:
+ case KeyEvent.VK_6:
+ case KeyEvent.VK_7:
+ case KeyEvent.VK_8:
+ case KeyEvent.VK_9:
+ case KeyEvent.VK_SEMICOLON:
+ case KeyEvent.VK_EQUALS:
+ case KeyEvent.VK_A:
+ case KeyEvent.VK_B:
+ case KeyEvent.VK_C:
+ case KeyEvent.VK_D:
+ case KeyEvent.VK_E:
+ case KeyEvent.VK_F:
+ case KeyEvent.VK_G:
+ case KeyEvent.VK_H:
+ case KeyEvent.VK_I:
+ case KeyEvent.VK_J:
+ case KeyEvent.VK_K:
+ case KeyEvent.VK_L:
+ case KeyEvent.VK_M:
+ case KeyEvent.VK_N:
+ case KeyEvent.VK_O:
+ case KeyEvent.VK_P:
+ case KeyEvent.VK_Q:
+ case KeyEvent.VK_R:
+ case KeyEvent.VK_S:
+ case KeyEvent.VK_T:
+ case KeyEvent.VK_U:
+ case KeyEvent.VK_V:
+ case KeyEvent.VK_W:
+ case KeyEvent.VK_X:
+ case KeyEvent.VK_Y:
+ case KeyEvent.VK_Z:
+ case KeyEvent.VK_OPEN_BRACKET:
+ case KeyEvent.VK_BACK_SLASH:
+ case KeyEvent.VK_CLOSE_BRACKET:
+ case KeyEvent.VK_NUMPAD0:
+ case KeyEvent.VK_NUMPAD1:
+ case KeyEvent.VK_NUMPAD2:
+ case KeyEvent.VK_NUMPAD3:
+ case KeyEvent.VK_NUMPAD4:
+ case KeyEvent.VK_NUMPAD5:
+ case KeyEvent.VK_NUMPAD6:
+ case KeyEvent.VK_NUMPAD7:
+ case KeyEvent.VK_NUMPAD8:
+ case KeyEvent.VK_NUMPAD9:
+ case KeyEvent.VK_MULTIPLY:
+ case KeyEvent.VK_ADD:
+ case KeyEvent.VK_SEPARATOR:
+ case KeyEvent.VK_SUBTRACT:
+ case KeyEvent.VK_DECIMAL:
+ case KeyEvent.VK_DIVIDE:
+ case KeyEvent.VK_DELETE:
+ case KeyEvent.VK_NUM_LOCK:
+ case KeyEvent.VK_SCROLL_LOCK:
+ case KeyEvent.VK_F1:
+ case KeyEvent.VK_F2:
+ case KeyEvent.VK_F3:
+ case KeyEvent.VK_F4:
+ case KeyEvent.VK_F5:
+ case KeyEvent.VK_F6:
+ case KeyEvent.VK_F7:
+ case KeyEvent.VK_F8:
+ case KeyEvent.VK_F9:
+ case KeyEvent.VK_F10:
+ case KeyEvent.VK_F11:
+ case KeyEvent.VK_F12:
+ case KeyEvent.VK_F13:
+ case KeyEvent.VK_F14:
+ case KeyEvent.VK_F15:
+ case KeyEvent.VK_F16:
+ case KeyEvent.VK_F17:
+ case KeyEvent.VK_F18:
+ case KeyEvent.VK_F19:
+ case KeyEvent.VK_F20:
+ case KeyEvent.VK_F21:
+ case KeyEvent.VK_F22:
+ case KeyEvent.VK_F23:
+ case KeyEvent.VK_F24:
+ case KeyEvent.VK_PRINTSCREEN:
+ case KeyEvent.VK_INSERT:
+ case KeyEvent.VK_HELP:
+ case KeyEvent.VK_META:
+ case KeyEvent.VK_BACK_QUOTE:
+ case KeyEvent.VK_QUOTE:
+ case KeyEvent.VK_KP_UP:
+ case KeyEvent.VK_KP_DOWN:
+ case KeyEvent.VK_KP_LEFT:
+ case KeyEvent.VK_KP_RIGHT:
+ case KeyEvent.VK_DEAD_GRAVE:
+ case KeyEvent.VK_DEAD_ACUTE:
+ case KeyEvent.VK_DEAD_CIRCUMFLEX:
+ case KeyEvent.VK_DEAD_TILDE:
+ case KeyEvent.VK_DEAD_MACRON:
+ case KeyEvent.VK_DEAD_BREVE:
+ case KeyEvent.VK_DEAD_ABOVEDOT:
+ case KeyEvent.VK_DEAD_DIAERESIS:
+ case KeyEvent.VK_DEAD_ABOVERING:
+ case KeyEvent.VK_DEAD_DOUBLEACUTE:
+ case KeyEvent.VK_DEAD_CARON:
+ case KeyEvent.VK_DEAD_CEDILLA:
+ case KeyEvent.VK_DEAD_OGONEK:
+ case KeyEvent.VK_DEAD_IOTA:
+ case KeyEvent.VK_DEAD_VOICED_SOUND:
+ case KeyEvent.VK_DEAD_SEMIVOICED_SOUND:
+ case KeyEvent.VK_AMPERSAND:
+ case KeyEvent.VK_ASTERISK:
+ case KeyEvent.VK_QUOTEDBL:
+ case KeyEvent.VK_LESS:
+ case KeyEvent.VK_GREATER:
+ case KeyEvent.VK_BRACELEFT:
+ case KeyEvent.VK_BRACERIGHT:
+ case KeyEvent.VK_AT:
+ case KeyEvent.VK_COLON:
+ case KeyEvent.VK_CIRCUMFLEX:
+ case KeyEvent.VK_DOLLAR:
+ case KeyEvent.VK_EURO_SIGN:
+ case KeyEvent.VK_EXCLAMATION_MARK:
+ case KeyEvent.VK_INVERTED_EXCLAMATION_MARK:
+ case KeyEvent.VK_LEFT_PARENTHESIS:
+ case KeyEvent.VK_NUMBER_SIGN:
+ case KeyEvent.VK_PLUS:
+ case KeyEvent.VK_RIGHT_PARENTHESIS:
+ case KeyEvent.VK_UNDERSCORE:
+ case KeyEvent.VK_FINAL:
+ case KeyEvent.VK_CONVERT:
+ case KeyEvent.VK_NONCONVERT:
+ case KeyEvent.VK_ACCEPT:
+ case KeyEvent.VK_MODECHANGE:
+ case KeyEvent.VK_KANA:
+ case KeyEvent.VK_KANJI:
+ case KeyEvent.VK_ALPHANUMERIC:
+ case KeyEvent.VK_KATAKANA:
+ case KeyEvent.VK_HIRAGANA:
+ case KeyEvent.VK_FULL_WIDTH:
+ case KeyEvent.VK_HALF_WIDTH:
+ case KeyEvent.VK_ROMAN_CHARACTERS:
+ case KeyEvent.VK_ALL_CANDIDATES:
+ case KeyEvent.VK_PREVIOUS_CANDIDATE:
+ case KeyEvent.VK_CODE_INPUT:
+ case KeyEvent.VK_JAPANESE_KATAKANA:
+ case KeyEvent.VK_JAPANESE_HIRAGANA:
+ case KeyEvent.VK_JAPANESE_ROMAN:
+ case KeyEvent.VK_KANA_LOCK:
+ case KeyEvent.VK_INPUT_METHOD_ON_OFF:
+ case KeyEvent.VK_CUT:
+ case KeyEvent.VK_COPY:
+ case KeyEvent.VK_PASTE:
+ case KeyEvent.VK_UNDO:
+ case KeyEvent.VK_AGAIN:
+ case KeyEvent.VK_FIND:
+ case KeyEvent.VK_PROPS:
+ case KeyEvent.VK_STOP:
+ case KeyEvent.VK_COMPOSE:
+ case KeyEvent.VK_ALT_GRAPH:
+ case KeyEvent.VK_BEGIN:
+ case KeyEvent.VK_CONTEXT_MENU:
+ case KeyEvent.VK_WINDOWS:
+ return true;
+ default:
+ return false;
+ }
+ }
}
diff --git a/libjava/classpath/gnu/java/awt/ClasspathGraphicsEnvironment.java b/libjava/classpath/gnu/java/awt/ClasspathGraphicsEnvironment.java
new file mode 100644
index 00000000000..865da1d9594
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/ClasspathGraphicsEnvironment.java
@@ -0,0 +1,67 @@
+/* ClasspathGraphicsEnvironment.java
+ Copyright (C) 2007 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;
+
+import java.awt.GraphicsEnvironment;
+import java.awt.image.ColorModel;
+import java.awt.image.SampleModel;
+import java.awt.image.WritableRaster;
+
+/**
+ * This class extends the GraphicsEnvironment API with some Classpath-specific
+ * methods, in order to provide optimized graphics handling.
+ *
+ * @author Francis Kung <fkung@redhat.com>
+ */
+public abstract class ClasspathGraphicsEnvironment
+ extends GraphicsEnvironment
+{
+ /**
+ * Returns an appropriate Raster that can efficiently back a
+ * BufferedImage with the given ColorModel and SampleModel.
+ *
+ * @param cm The color model.
+ * @param sm The samepl model.
+ * @return An appropriate WritableRaster, or null if acceleration/optimization
+ * is not available for the given colour model / sample model.
+ */
+ public WritableRaster createRaster(ColorModel cm, SampleModel sm)
+ {
+ return null;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/ClasspathToolkit.java b/libjava/classpath/gnu/java/awt/ClasspathToolkit.java
index 968cc3b1643..d78fbab4e1e 100644
--- a/libjava/classpath/gnu/java/awt/ClasspathToolkit.java
+++ b/libjava/classpath/gnu/java/awt/ClasspathToolkit.java
@@ -38,36 +38,28 @@ exception statement from your version. */
package gnu.java.awt;
-import gnu.java.awt.EmbeddedWindow;
+import gnu.java.awt.peer.ClasspathDesktopPeer;
import gnu.java.awt.peer.ClasspathFontPeer;
import gnu.java.awt.peer.EmbeddedWindowPeer;
import gnu.java.security.action.SetAccessibleAction;
import java.awt.AWTException;
-import java.awt.Component;
-import java.awt.Dimension;
-import java.awt.DisplayMode;
+import java.awt.Desktop;
import java.awt.Font;
-import java.awt.FontMetrics;
+import java.awt.FontFormatException;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
-import java.awt.Image;
-import java.awt.Point;
+import java.awt.HeadlessException;
import java.awt.Toolkit;
-import java.awt.font.FontRenderContext;
-import java.awt.image.ColorModel;
-import java.awt.image.ImageProducer;
+import java.awt.font.TextAttribute;
+import java.awt.peer.DesktopPeer;
import java.awt.peer.RobotPeer;
-import java.io.File;
+import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.text.AttributedString;
-import java.util.HashMap;
-import java.util.Map;
import java.security.AccessController;
+import java.util.Map;
import javax.imageio.spi.IIORegistry;
@@ -118,7 +110,8 @@ public abstract class ClasspathToolkit
* this font peer should have, such as size, weight, family name, or
* transformation.
*/
- public abstract ClasspathFontPeer getClasspathFontPeer (String name, Map attrs);
+ public abstract ClasspathFontPeer getClasspathFontPeer (String name,
+ Map<?,?> attrs);
/**
* Creates a {@link Font}, in a platform-specific manner.
@@ -137,9 +130,8 @@ public abstract class ClasspathToolkit
try
{
Constructor fontConstructor = Font.class.getDeclaredConstructor
- (new Class[] { String.class, Map.class });
- AccessController.doPrivileged
- (new SetAccessibleAction(fontConstructor));
+ (new Class[] { String.class, Map.class });
+ AccessController.doPrivileged(new SetAccessibleAction(fontConstructor));
f = (Font) fontConstructor.newInstance(new Object[] { name, attrs });
}
catch (IllegalAccessException e)
@@ -224,5 +216,18 @@ public abstract class ClasspathToolkit
{
return -1;
}
+
+ /* (non-Javadoc)
+ * @see java.awt.Toolkit#createDesktopPeer(java.awt.Desktop)
+ */
+ protected DesktopPeer createDesktopPeer(Desktop target)
+ throws HeadlessException
+ {
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException();
+
+ return ClasspathDesktopPeer.getDesktop();
+ }
+
}
diff --git a/libjava/classpath/gnu/java/awt/font/FontDelegate.java b/libjava/classpath/gnu/java/awt/font/FontDelegate.java
index a26510ee2de..030f9d3bca5 100644
--- a/libjava/classpath/gnu/java/awt/font/FontDelegate.java
+++ b/libjava/classpath/gnu/java/awt/font/FontDelegate.java
@@ -61,6 +61,13 @@ import java.util.Locale;
*/
public interface FontDelegate
{
+ public static final int FLAG_FITTED = 1 << 0;
+ public static final int FLAG_NO_HINT_HORIZONTAL = 1 << 1;
+ public static final int FLAG_NO_HINT_VERTICAL = 1 << 2;
+ public static final int FLAG_NO_HINT_EDGE_POINTS = 1 << 3;
+ public static final int FLAG_NO_HINT_STRONG_POINTS = 1 << 4;
+ public static final int FLAG_NO_HINT_WEAK_POINTS = 1 << 5;
+
/**
* Returns the full name of this font face in the specified
* locale, for example <i>&#x201c;Univers Light&#x201d;</i>.
@@ -221,7 +228,8 @@ public interface FontDelegate
float pointSize,
AffineTransform transform,
boolean antialias,
- boolean fractionalMetrics);
+ boolean fractionalMetrics,
+ int type);
/**
diff --git a/libjava/classpath/gnu/java/awt/font/GNUGlyphVector.java b/libjava/classpath/gnu/java/awt/font/GNUGlyphVector.java
index f17a4511375..2f73dce77b0 100644
--- a/libjava/classpath/gnu/java/awt/font/GNUGlyphVector.java
+++ b/libjava/classpath/gnu/java/awt/font/GNUGlyphVector.java
@@ -164,7 +164,9 @@ public class GNUGlyphVector
renderContext.usesFractionalMetrics(),
/* horizontal */ true,
advance);
- pos[p] = x += advance.x;
+ // FIXME: We shouldn't round here, but instead hint the metrics
+ // correctly.
+ pos[p] = x += Math.round(advance.x);
pos[p + 1] = y += advance.y;
}
valid = true;
@@ -284,6 +286,22 @@ public class GNUGlyphVector
return outline;
}
+ public Shape getOutline(float x, float y, int type)
+ {
+ validate();
+
+ GeneralPath outline = new GeneralPath();
+ int len = glyphs.length;
+ for (int i = 0; i < len; i++)
+ {
+ GeneralPath p = new GeneralPath(getGlyphOutline(i, type));
+ outline.append(p, false);
+ }
+ AffineTransform t = new AffineTransform();
+ t.translate(x, y);
+ outline.transform(t);
+ return outline;
+ }
/**
* Determines the shape of the specified glyph.
@@ -309,7 +327,8 @@ public class GNUGlyphVector
path = fontDelegate.getGlyphOutline(glyphs[glyphIndex], fontSize, tx,
renderContext.isAntiAliased(),
- renderContext.usesFractionalMetrics());
+ renderContext.usesFractionalMetrics(),
+ FontDelegate.FLAG_FITTED);
tx = new AffineTransform();
tx.translate(pos[glyphIndex * 2], pos[glyphIndex * 2 + 1]);
@@ -317,6 +336,32 @@ public class GNUGlyphVector
return path;
}
+ public Shape getGlyphOutline(int glyphIndex, int type)
+ {
+ 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(),
+ type);
+
+ 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
diff --git a/libjava/classpath/gnu/java/awt/font/autofit/AutoHinter.java b/libjava/classpath/gnu/java/awt/font/autofit/AutoHinter.java
new file mode 100644
index 00000000000..b0420ab7a2d
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/font/autofit/AutoHinter.java
@@ -0,0 +1,83 @@
+/* AutoHinter.java -- The entry point into the hinter implementation.
+ 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.autofit;
+
+import gnu.java.awt.font.opentype.Hinter;
+import gnu.java.awt.font.opentype.OpenTypeFont;
+import gnu.java.awt.font.opentype.truetype.Fixed;
+import gnu.java.awt.font.opentype.truetype.Zone;
+
+/**
+ * The public interface to the automatic gridfitter.
+ */
+public class AutoHinter
+ implements Hinter
+{
+ Latin latinScript;
+ LatinMetrics metrics;
+ GlyphHints hints;
+
+ HintScaler scaler = new HintScaler();
+ public void init(OpenTypeFont font)
+ {
+ // TODO: Should support other scripts too.
+ latinScript = new Latin();
+ metrics = new LatinMetrics(font);
+ latinScript.initMetrics(metrics, font);
+ scaler.face = font;
+ }
+
+ public void applyHints(Zone outline)
+ {
+ if (hints == null)
+ hints = new GlyphHints();
+ scaler.xScale = Fixed.valueOf16(outline.scaleX * 64);
+ scaler.yScale = Fixed.valueOf16(outline.scaleY * 64);
+ latinScript.scaleMetrics(metrics, scaler);
+ latinScript.applyHints(hints, outline, metrics);
+ }
+
+ public void setFlags(int flags)
+ {
+ if (hints == null)
+ hints = new GlyphHints();
+ hints.flags = flags;
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/font/autofit/AxisHints.java b/libjava/classpath/gnu/java/awt/font/autofit/AxisHints.java
index b2c9912342b..87f2abcc3df 100644
--- a/libjava/classpath/gnu/java/awt/font/autofit/AxisHints.java
+++ b/libjava/classpath/gnu/java/awt/font/autofit/AxisHints.java
@@ -1,4 +1,4 @@
-/* AxisHints.java -- FIXME: briefly describe file purpose
+/* AxisHints.java -- Hints specific to an axis
Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -42,4 +42,71 @@ class AxisHints
{
Segment[] segments;
+ int majorDir;
+ int numSegments;
+ int numEdges;
+ Edge[] edges;
+
+ AxisHints()
+ {
+ segments = new Segment[4];
+ edges = new Edge[4];
+ }
+
+ Segment newSegment()
+ {
+ if (numSegments >= segments.length)
+ {
+ // Grow array.
+ int newMax = segments.length;
+ newMax += (newMax >> 2) + 4; // From FreeType.
+ Segment[] newSegs = new Segment[newMax];
+ System.arraycopy(segments, 0, newSegs, 0, numSegments);
+ segments = newSegs;
+ }
+ Segment seg = new Segment();
+ segments[numSegments] = seg;
+ numSegments++;
+ return seg;
+ }
+
+ public Edge newEdge(int pos)
+ {
+ if (numEdges >= edges.length)
+ {
+ // Grow array.
+ int newMax = edges.length;
+ newMax += (newMax >> 2) + 4; // From FreeType.
+ Edge[] newEdges = new Edge[newMax];
+ System.arraycopy(edges, 0, newEdges, 0, numEdges);
+ edges = newEdges;
+ }
+ int edgeIndex = numEdges;
+ Edge edge = edges[edgeIndex] = new Edge();
+ while (edgeIndex > 0 && edges[edgeIndex - 1].fpos > pos)
+ {
+ edges[edgeIndex] = edges[edgeIndex - 1];
+ edgeIndex--;
+ }
+ edges[edgeIndex] = edge;
+ numEdges++;
+ edge.fpos = pos;
+
+ return edge;
+
+ }
+
+ int getEdgeIndex(Edge edge2)
+ {
+ int idx = -1;
+ for (int i = 0; i < numEdges; i++)
+ {
+ if (edges[i] == edge2)
+ {
+ idx = i;
+ break;
+ }
+ }
+ return idx;
+ }
}
diff --git a/libjava/classpath/gnu/java/awt/font/autofit/Constants.java b/libjava/classpath/gnu/java/awt/font/autofit/Constants.java
index cb3992825ab..c5b90fa5485 100644
--- a/libjava/classpath/gnu/java/awt/font/autofit/Constants.java
+++ b/libjava/classpath/gnu/java/awt/font/autofit/Constants.java
@@ -58,4 +58,29 @@ interface Constants
* The number of dimensions.
*/
static final int DIMENSION_MAX = 2;
+
+ /**
+ * Indicates a vector with no specific direction.
+ */
+ static final int DIR_NONE = 0;
+
+ /**
+ * Right direction.
+ */
+ static final int DIR_RIGHT = 1;
+
+ /**
+ * Left direction.
+ */
+ static final int DIR_LEFT = -1;
+
+ /**
+ * Up direction.
+ */
+ static final int DIR_UP = 2;
+
+ /**
+ * Down direction.
+ */
+ static final int DIR_DOWN = -2;
}
diff --git a/libjava/classpath/gnu/java/awt/font/autofit/Edge.java b/libjava/classpath/gnu/java/awt/font/autofit/Edge.java
new file mode 100644
index 00000000000..d9736650b5f
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/font/autofit/Edge.java
@@ -0,0 +1,80 @@
+/* Edge.java -- An edge of segments
+ 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.autofit;
+
+class Edge
+{
+ int fpos;
+ Segment first;
+ Segment last;
+ int opos;
+ Edge link;
+ Edge serif;
+ int flags;
+ int dir;
+ Width blueEdge;
+ int pos;
+ int scale;
+
+ public String toString()
+ {
+ StringBuilder s = new StringBuilder();
+ s.append("[Edge] id");
+ s.append(hashCode());
+ s.append(", fpos: ");
+ s.append(fpos);
+ s.append(", opos: ");
+ s.append(opos);
+ s.append(", pos: ");
+ s.append(pos);
+ s.append(", dir: ");
+ s.append(dir);
+ s.append(", serif: ");
+ s.append(serif != null ? serif.hashCode() : "null");
+ s.append(", link: ");
+ s.append(link != null ? link.hashCode() : "null");
+ s.append(", flags: " + flags);
+ s.append(", blue: " + blueEdge);
+ s.append(", first: ");
+ s.append(first == null ? "null" : first.hashCode());
+ s.append(", last: ");
+ s.append(last == null ? "null" : last.hashCode());
+ return s.toString();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/font/autofit/GlyphHints.java b/libjava/classpath/gnu/java/awt/font/autofit/GlyphHints.java
index ad73a04a69b..72f07ed81fc 100644
--- a/libjava/classpath/gnu/java/awt/font/autofit/GlyphHints.java
+++ b/libjava/classpath/gnu/java/awt/font/autofit/GlyphHints.java
@@ -38,12 +38,16 @@ exception statement from your version. */
package gnu.java.awt.font.autofit;
+import gnu.java.awt.font.FontDelegate;
+import gnu.java.awt.font.opentype.truetype.Fixed;
+import gnu.java.awt.font.opentype.truetype.Point;
import gnu.java.awt.font.opentype.truetype.Zone;
/**
* The data and methods used for the actual hinting process.
*/
class GlyphHints
+ implements Constants
{
int xScale;
@@ -53,23 +57,584 @@ class GlyphHints
AxisHints[] axis;
- void rescale(ScriptMetrics metrics)
+ Point[] points;
+ int numPoints;
+ int maxPoints;
+
+ Point[] contours;
+ int numContours;
+ int maxContours;
+
+ ScriptMetrics metrics;
+
+ int flags;
+
+ GlyphHints()
+ {
+ axis = new AxisHints[Constants.DIMENSION_MAX];
+ axis[Constants.DIMENSION_VERT] = new AxisHints();
+ axis[Constants.DIMENSION_HORZ] = new AxisHints();
+
+ xScale = Fixed.ONE;
+ yScale = Fixed.ONE;
+ }
+
+ void rescale(ScriptMetrics m)
{
- // TODO: Implement.
+ metrics = m;
+ // TODO: Copy scalerFlags.
}
void reload(Zone outline)
{
- // TODO: Implement.
+ numPoints = 0;
+ numContours = 0;
+ axis[0].numSegments = 0;
+ axis[0].numEdges = 0;
+ axis[1].numSegments = 0;
+ axis[1].numEdges = 0;
+
+ // Create/reallocate the contours array.
+ int newMax = outline.getNumContours();
+ if (newMax > maxContours || contours == null)
+ {
+ newMax = (newMax + 3) & ~3; // Taken from afhints.c .
+ Point[] newContours = new Point[newMax];
+ if (contours != null)
+ {
+ System.arraycopy(contours, 0, newContours, 0, maxContours);
+ }
+ contours = newContours;
+ maxContours = newMax;
+ }
+
+ // Create/reallocate the points array.
+ newMax = outline.getSize() + 2;
+ if (newMax > maxPoints || points == null)
+ {
+ newMax = (newMax + 2 + 7) & ~7; // Taken from afhints.c .
+ Point[] newPoints = new Point[newMax];
+ if (points != null)
+ {
+ System.arraycopy(points, 0, newPoints, 0, maxPoints);
+ }
+ points = newPoints;
+ maxPoints = newMax;
+ }
+
+ numPoints = outline.getSize() - 4; // 4 phantom points.
+ numContours = outline.getNumContours();
+
+ // Set major direction. We don't handle Type 1 fonts yet.
+ axis[DIMENSION_HORZ].majorDir = DIR_UP;
+ axis[DIMENSION_VERT].majorDir = DIR_LEFT;
+
+ // TODO: Freetype seems to scale and translate the glyph at that point.
+ // I suppose that this is not really needed.
+ // The scales are scaling from font units to 1/64 device pixels.
+ xScale = Fixed.valueOf16(outline.scaleX * 64);
+ yScale = Fixed.valueOf16(outline.scaleY * 64);
+
+ // FIXME: What is that xDelta and yDelta used for?
+ System.arraycopy(outline.getPoints(), 0, points, 0, numPoints);
+
+ // Setup prev and next and contours array.
+ // TODO: Probably cache this.
+ contours = new Point[numContours];
+ Point currentContour = points[0];
+ for (int i = 0, cIndex = 0; i < numPoints; i++)
+ {
+ // Start new contour when the last point has been a contour end.
+ if (outline.isContourEnd(i))
+ {
+ // Connect the contour end point to the start point.
+ points[i].setNext(currentContour);
+ currentContour.setPrev(points[i]);
+ contours[cIndex] = currentContour;
+ cIndex++;
+ currentContour = i < numPoints - 1 ? points[i + 1] : null;
+ }
+ else
+ {
+ // Connect the current and the previous point.
+ points[i].setNext(points[i + 1]);
+ points[i + 1].setPrev(points[i]);
+ }
+ }
+ // Compute directions of in and out vectors of all points as well
+ // as the weak point flag.
+ for (int i = 0; i < numPoints; i++)
+ {
+ // Compute in and out dir.
+ Point p = points[i];
+ Point prev = p.getPrev();
+ int inX = p.getOrigX() - prev.getOrigX();
+ int inY = p.getOrigY() - prev.getOrigY();
+ p.setInDir(Utils.computeDirection(inX, inY));
+ Point next = p.getNext();
+ int outX = next.getOrigX() - p.getOrigX();
+ int outY = next.getOrigY() - p.getOrigY();
+ p.setOutDir(Utils.computeDirection(outX, outY));
+
+ if (p.isControlPoint())
+ {
+ setWeakPoint(p);
+ }
+ else if (p.getOutDir() == p.getInDir())
+ {
+ if (p.getOutDir() != DIR_NONE)
+ setWeakPoint(p);
+ else
+ {
+ int angleIn = Utils.atan(inY, inX);
+ int angleOut = Utils.atan(outY, outX);
+ int delta = Utils.angleDiff(angleIn, angleOut);
+ if (delta < 2 && delta > -2)
+ setWeakPoint(p);
+ }
+ }
+ else if (p.getInDir() == - p.getOutDir())
+ {
+ setWeakPoint(p);
+ }
+ }
+ computeInflectionPoints();
+ }
+
+ private void setWeakPoint(Point p)
+ {
+ p.setFlags((byte) (p.getFlags() | Point.FLAG_WEAK_INTERPOLATION));
+ }
+
+ /**
+ * Computes the inflection points for a glyph.
+ */
+ private void computeInflectionPoints()
+ {
+ // Do each contour separately.
+ contours : for (int c = 0; c < contours.length; c++)
+ {
+ Point point = contours[c];
+ Point first = point;
+ Point start = point;
+ Point end = point;
+ do
+ {
+ end = end.getNext();
+ if (end == first)
+ continue contours;
+ } while (end.getOrigX() == first.getOrigX()
+ && end.getOrigY() == first.getOrigY());
+
+ // Extend segment start whenever possible.
+ Point before = start;
+ int angleIn;
+ int angleSeg = Utils.atan(end.getOrigX() - start.getOrigX(),
+ end.getOrigY() - start.getOrigY());
+ do
+ {
+ do
+ {
+ start = before;
+ before = before.getPrev();
+ if (before == first)
+ continue contours;
+ } while (before.getOrigX() == start.getOrigX()
+ && before.getOrigY() == start.getOrigY());
+ angleIn = Utils.atan(start.getOrigX() - before.getOrigX(),
+ start.getOrigY() - before.getOrigY());
+ } while (angleIn == angleSeg);
+
+ first = start;
+ int diffIn = Utils.angleDiff(angleIn, angleSeg);
+ // Now, process all segments in the contour.
+ Point after;
+ boolean finished = false;
+ int angleOut, diffOut;
+ do
+ {
+ // First, extend the current segment's end whenever possible.
+ after = end;
+ do
+ {
+ do
+ {
+ end = after;
+ after = after.getNext();
+ if (after == first)
+ finished = true;
+ } while (end.getOrigX() == after.getOrigX()
+ && end.getOrigY() == after.getOrigY());
+ angleOut = Utils.atan(after.getOrigX() - end.getOrigX(),
+ after.getOrigY() - end.getOrigY());
+ } while (angleOut == angleSeg);
+ diffOut = Utils.angleDiff(angleSeg, angleOut);
+ if ((diffIn ^ diffOut) < 0)
+ {
+ // diffIn and diffOut have different signs, we have
+ // inflection points here.
+ do
+ {
+ start.addFlags(Point.FLAG_INFLECTION);
+ start = start.getNext();
+ } while (start != end);
+ start.addFlags(Point.FLAG_INFLECTION);
+ }
+ start = end;
+ end = after;
+ angleSeg = angleOut;
+ diffIn = diffOut;
+ } while (! finished);
+ }
+ }
+
+ boolean doHorizontal()
+ {
+ return (flags & FontDelegate.FLAG_NO_HINT_HORIZONTAL) == 0;
+ }
+
+ boolean doVertical()
+ {
+ return (flags & FontDelegate.FLAG_NO_HINT_VERTICAL) == 0;
+ }
+
+ void alignWeakPoints(int dim)
+ {
+ short touchFlag;
+ Point point;
+ // PASS 1 : Move segments to edge positions.
+ if (dim == DIMENSION_HORZ)
+ {
+ touchFlag = Point.FLAG_DONE_X;
+ for (int p = 0; p < numPoints; p++)
+ {
+ point = points[p];
+ point.setU(point.getX());
+ point.setV(point.getScaledX());
+ }
+ }
+ else
+ {
+ touchFlag = Point.FLAG_DONE_Y;
+ for (int p = 0; p < numPoints; p++)
+ {
+ point = points[p];
+ point.setU(point.getY());
+ point.setV(point.getScaledY());
+ }
+ }
+ point = points[0];
+ for (int c = 0; c < numContours; c++)
+ {
+ point = contours[c];
+ int idx = getPointIndex(point);
+ Point endPoint = point.getPrev();
+ int endIdx = getPointIndex(endPoint);
+ int firstIdx = idx;
+ while (idx <= endIdx
+ && (point.getFlags() & touchFlag) == 0)
+ {
+ idx++;
+ point = points[idx];
+ }
+ if (idx <= endIdx)
+ {
+ int firstTouched = idx;
+ int curTouched = idx;
+ idx++;
+ point = points[idx];
+ while (idx <= endIdx)
+ {
+ if ((point.getFlags() & touchFlag) != 0)
+ {
+ // We found two successive touch points. We interpolate
+ // all contour points between them.
+ iupInterp(curTouched + 1, idx - 1, curTouched, idx);
+ curTouched = idx;
+ }
+ idx++;
+ point = points[idx];
+ }
+ if (curTouched == firstTouched)
+ {
+ // This is a special case: Only one point was touched in the
+ // contour. We thus simply shift the whole contour.
+ iupShift(firstIdx, endIdx, curTouched);
+ }
+ else
+ {
+ // Now interpolate after the last touched point to the end
+ // of the contour.
+ iupInterp(curTouched + 1, endIdx, curTouched, firstTouched);
+ // If the first contour point isn't touched, interpolate
+ // from the contour start to the first touched point.
+ if (firstTouched > 0)
+ {
+ iupInterp(firstIdx, firstTouched - 1, curTouched,
+ firstTouched);
+ }
+ }
+ }
+ }
+ // Now store the values back.
+ if (dim == DIMENSION_HORZ)
+ {
+ for (int p = 0; p < numPoints; p++)
+ {
+ point = points[p];
+ point.setX(point.getU());
+ }
+ }
+ else
+ {
+ for (int p = 0; p < numPoints; p++)
+ {
+ point = points[p];
+ point.setY(point.getU());
+ }
+ }
+ }
+
+ private void iupShift(int p1, int p2, int ref)
+ {
+ int delta = points[ref].getU() - points[ref].getV();
+ for (int p = p1; p < ref; p++)
+ {
+ points[p].setU(points[p].getV() + delta);
+ }
+ for (int p = ref + 1; p <= p2; p++)
+ {
+ points[p].setU(points[p].getV() + delta);
+ }
+ }
+
+ private void iupInterp(int p1, int p2, int ref1, int ref2)
+ {
+ int v1 = points[ref1].getV();
+ int v2 = points[ref2].getV();
+ int d1 = points[ref1].getU() - v1;
+ int d2 = points[ref2].getU() - v2;
+ if (p1 > p2)
+ return;
+ if (v1 == v2)
+ {
+ for (int p = p1; p <= p2; p++)
+ {
+ int u = points[p].getV();
+ if (u <= v1)
+ u += d1;
+ else
+ u += d2;
+ points[p].setU(u);
+ }
+ }
+ else if (v1 < v2)
+ {
+ for (int p = p1; p <= p2; p++)
+ {
+ int u = points[p].getV();
+ if (u <= v1)
+ u += d1;
+ else if (u >= v2)
+ u += d2;
+ else
+ {
+ u = points[ref1].getU() + Utils.mulDiv(u - v1,
+ points[ref2].getU()
+ - points[ref1].getU(),
+ v2 - v1);
+ }
+ points[p].setU(u);
+ }
+ }
+ else
+ {
+ for (int p = p1; p <= p2; p++)
+ {
+ int u = points[p].getV();
+ if (u <= v2)
+ u += d2;
+ else if (u >= v1)
+ u += d1;
+ else
+ {
+ u = points[ref1].getU() + Utils.mulDiv(u - v1,
+ points[ref2].getU()
+ - points[ref1].getU(),
+ v2 - v1);
+ }
+ points[p].setU(u);
+ }
+ }
+ }
+
+ void alignStrongPoints(int dim)
+ {
+ AxisHints ax = axis[dim];
+ Edge[] edges = ax.edges;
+ int numEdges = ax.numEdges;
+ short touchFlag;
+ if (dim == DIMENSION_HORZ)
+ touchFlag = Point.FLAG_DONE_X;
+ else
+ touchFlag = Point.FLAG_DONE_Y;
+
+ if (numEdges > 0)
+ {
+ for (int p = 0; p < numPoints; p++)
+ {
+ Point point = points[p];
+ if ((point.getFlags() & touchFlag) != 0)
+ continue;
+ // If this point is a candidate for weak interpolation, we
+ // interpolate it after all strong points have been processed.
+ if ((point.getFlags() & Point.FLAG_WEAK_INTERPOLATION) != 0
+ && (point.getFlags() & Point.FLAG_INFLECTION) == 0)
+ continue;
+
+ int u, ou, fu, delta;
+ if (dim == DIMENSION_VERT)
+ {
+ u = point.getOrigY();
+ ou = point.getScaledY();
+ }
+ else
+ {
+ u = point.getOrigX();
+ ou = point.getScaledX();
+ }
+ fu = u;
+ // Is the point before the first edge?
+ Edge edge = edges[0];
+ // Inversed vertical dimension.
+ delta = edge.fpos - u;
+ if (delta >= 0)
+ {
+ u = edge.pos - (edge.opos - ou);
+ storePoint(point, u, dim, touchFlag);
+ }
+ else
+ {
+ // Is the point after the last edge?
+ edge = edges[numEdges - 1];
+ delta = u - edge.fpos;
+ if (delta >= 0)
+ {
+ u = edge.pos + (ou - edge.opos);
+ storePoint(point, u, dim, touchFlag);
+ }
+ else
+ {
+ // Find enclosing edges.
+ int min = 0;
+ int max = numEdges;
+ int mid, fpos;
+ boolean found = false;
+ while (min < max)
+ {
+ mid = (max + min) / 2;
+ edge = edges[mid];
+ fpos = edge.fpos;
+ if (u < fpos)
+ max = mid;
+ else if (u > fpos)
+ min = mid + 1;
+ else
+ {
+ // Directly on the edge.
+ u = edge.pos;
+ storePoint(point, u, dim, touchFlag);
+ found = true;
+ break;
+ }
+ }
+ if (! found)
+ {
+ Edge before = edges[min - 1];
+ Edge after = edges[min];
+ if (before.scale == 0)
+ {
+ before.scale = Fixed.div16(after.pos - before.pos,
+ after.fpos - before.fpos);
+ }
+ u = before.pos + Fixed.mul16(fu - before.fpos,
+ before.scale);
+ }
+ storePoint(point, u, dim, touchFlag);
+ }
+ }
+ }
+ }
+ }
+
+ private void storePoint(Point p, int u, int dim, short touchFlag)
+ {
+ if (dim == DIMENSION_HORZ)
+ p.setX(u);
+ else
+ p.setY(u);
+ p.addFlags(touchFlag);
+ }
+
+ void alignEdgePoints(int dim)
+ {
+ AxisHints ax = axis[dim];
+ Edge[] edges = ax.edges;
+ int numEdges = ax.numEdges;
+ for (int e = 0; e < numEdges; e++)
+ {
+ Edge edge = edges[e];
+ Segment seg = edge.first;
+ do
+ {
+ Point point = seg.first;
+ while (true)
+ {
+ if (dim == DIMENSION_HORZ)
+ {
+ point.setX(edge.pos);
+ point.addFlags(Point.FLAG_DONE_X);
+ }
+ else
+ {
+ point.setY(edge.pos);
+ point.addFlags(Point.FLAG_DONE_Y);
+ }
+ if (point == seg.last)
+ break;
+ point = point.getNext();
+ }
+ seg = seg.edgeNext;
+ } while (seg != edge.first);
+ }
+ }
+
+ private int getPointIndex(Point p)
+ {
+ int idx = -1;
+ for (int i = 0; i < numPoints; i++)
+ {
+ if (p == points[i])
+ {
+ idx = i;
+ break;
+ }
+ }
+ return idx;
+ }
+
+ public boolean doAlignEdgePoints()
+ {
+ return (flags & FontDelegate.FLAG_NO_HINT_EDGE_POINTS) == 0;
}
- void computeSegments(int dim)
+ public boolean doAlignStrongPoints()
{
- // TODO: Implement.
+ return (flags & FontDelegate.FLAG_NO_HINT_STRONG_POINTS) == 0;
}
- void linkSegments(int dim)
+ public boolean doAlignWeakPoints()
{
- // TODO: Implement.
+ return (flags & FontDelegate.FLAG_NO_HINT_WEAK_POINTS) == 0;
}
}
diff --git a/libjava/classpath/gnu/java/awt/font/autofit/Scaler.java b/libjava/classpath/gnu/java/awt/font/autofit/HintScaler.java
index 10518512578..01276b4db01 100644
--- a/libjava/classpath/gnu/java/awt/font/autofit/Scaler.java
+++ b/libjava/classpath/gnu/java/awt/font/autofit/HintScaler.java
@@ -40,7 +40,7 @@ package gnu.java.awt.font.autofit;
import gnu.java.awt.font.opentype.OpenTypeFont;
-class Scaler
+class HintScaler
{
int xScale;
@@ -48,5 +48,6 @@ class Scaler
int yScale;
int yDelta;
OpenTypeFont face;
-
+ int renderMode;
+
}
diff --git a/libjava/classpath/gnu/java/awt/font/autofit/Latin.java b/libjava/classpath/gnu/java/awt/font/autofit/Latin.java
index 0352b41a45a..8951e8b19db 100644
--- a/libjava/classpath/gnu/java/awt/font/autofit/Latin.java
+++ b/libjava/classpath/gnu/java/awt/font/autofit/Latin.java
@@ -39,8 +39,11 @@ exception statement from your version. */
package gnu.java.awt.font.autofit;
import java.awt.geom.AffineTransform;
+import java.util.HashSet;
import gnu.java.awt.font.opentype.OpenTypeFont;
+import gnu.java.awt.font.opentype.truetype.Fixed;
+import gnu.java.awt.font.opentype.truetype.Point;
import gnu.java.awt.font.opentype.truetype.Zone;
/**
@@ -50,12 +53,476 @@ class Latin
implements Script, Constants
{
- private static final int MAX_WIDTHS = 16;
+ static final int MAX_WIDTHS = 16;
- public void applyHints(GlyphHints hints, ScriptMetrics metrics)
+ private final static int MAX_TEST_CHARS = 12;
+
+ /**
+ * The types of the 6 blue zones.
+ */
+ private static final int CAPITAL_TOP = 0;
+ private static final int CAPITAL_BOTTOM = 1;
+ private static final int SMALL_F_TOP = 2;
+ private static final int SMALL_TOP = 3;
+ private static final int SMALL_BOTTOM = 4;
+ private static final int SMALL_MINOR = 5;
+ static final int BLUE_MAX = 6;
+
+ /**
+ * The test chars for the blue zones.
+ *
+ * @see #initBlues(LatinMetrics, OpenTypeFont)
+ */
+ private static final String[] TEST_CHARS =
+ new String[]{"THEZOCQS", "HEZLOCUS", "fijkdbh",
+ "xzroesc", "xzroesc", "pqgjy"};
+
+ public void applyHints(GlyphHints hints, Zone outline, ScriptMetrics metrics)
+ {
+ hints.reload(outline);
+ hints.rescale(metrics);
+ if (hints.doHorizontal())
+ {
+ detectFeatures(hints, DIMENSION_HORZ);
+ }
+ if (hints.doVertical())
+ {
+ detectFeatures(hints, DIMENSION_VERT);
+ computeBlueEdges(hints, (LatinMetrics) metrics);
+ }
+ // Grid-fit the outline.
+ for (int dim = 0; dim < DIMENSION_MAX; dim++)
+ {
+ if (dim == DIMENSION_HORZ && hints.doHorizontal()
+ || dim == DIMENSION_VERT && hints.doVertical())
+ {
+ hintEdges(hints, dim);
+ if (hints.doAlignEdgePoints())
+ hints.alignEdgePoints(dim);
+ if (hints.doAlignStrongPoints())
+ hints.alignStrongPoints(dim);
+ if (hints.doAlignWeakPoints())
+ hints.alignWeakPoints(dim);
+
+ }
+ }
+ // FreeType does a save call here. I guess that's not needed as we operate
+ // on the live glyph data anyway.
+ }
+
+ private void hintEdges(GlyphHints hints, int dim)
+ {
+ AxisHints axis = hints.axis[dim];
+ Edge[] edges = axis.edges;
+ int numEdges = axis.numEdges;
+ Edge anchor = null;
+ int hasSerifs = 0;
+
+ // We begin by aligning all stems relative to the blue zone if
+ // needed -- that's only for horizontal edges.
+ if (dim == DIMENSION_VERT)
+ {
+ for (int e = 0; e < numEdges; e++)
+ {
+ Edge edge = edges[e];
+ if ((edge.flags & Segment.FLAG_EDGE_DONE) != 0)
+ continue;
+
+ Width blue = edge.blueEdge;
+ Edge edge1 = null;
+ Edge edge2 = edge.link;
+ if (blue != null)
+ {
+ edge1 = edge;
+ }
+ else if (edge2 != null && edge2.blueEdge != null)
+ {
+ blue = edge2.blueEdge;
+ edge1 = edge2;
+ edge2 = edge;
+ }
+ if (edge1 == null)
+ continue;
+
+ edge1.pos = blue.fit;
+ edge1.flags |= Segment.FLAG_EDGE_DONE;
+
+ if (edge2 != null && edge2.blueEdge == null)
+ {
+ alignLinkedEdge(hints, dim, edge1, edge2);
+ edge2.flags |= Segment.FLAG_EDGE_DONE;
+ }
+ if (anchor == null)
+ anchor = edge;
+ }
+ }
+
+ // Now we will align all stem edges, trying to maintain the
+ // relative order of stems in the glyph.
+ for (int e = 0; e < numEdges; e++)
+ {
+ Edge edge = edges[e];
+ if ((edge.flags & Segment.FLAG_EDGE_DONE) != 0)
+ continue;
+ Edge edge2 = edge.link;
+ if (edge2 == null)
+ {
+ hasSerifs++;
+ continue;
+ }
+ // Now align the stem.
+ // This should not happen, but it's better to be safe.
+ if (edge2.blueEdge != null || axis.getEdgeIndex(edge2) < e)
+ {
+ alignLinkedEdge(hints, dim, edge2, edge);
+ edge.flags |= Segment.FLAG_EDGE_DONE;
+ continue;
+ }
+
+ if (anchor == null)
+ {
+ int orgLen = edge2.opos - edge.opos;
+ int curLen = computeStemWidth(hints, dim, orgLen, edge.flags,
+ edge2.flags);
+ int uOff, dOff, orgCenter, curPos1, error1, error2;
+ if (curLen <= 64) // < 1 Pixel.
+ {
+ uOff = 32;
+ dOff = 32;
+ }
+ else
+ {
+ uOff = 38;
+ dOff = 26;
+ }
+ if (curLen < 96)
+ {
+ orgCenter = edge.opos + (orgLen >> 1);
+ curPos1 = Utils.pixRound(orgCenter);
+ error1 = orgCenter - (curPos1 - uOff);
+ if (error1 < 0)
+ error1 = -error1;
+ error2 = orgCenter - (curPos1 + dOff);
+ if (error2 < 0)
+ error2 = -error2;
+ if (error1 < error2)
+ {
+ curPos1 -= uOff;
+ }
+ else
+ {
+ curPos1 += dOff;
+ }
+ edge.pos = curPos1 - curLen / 2;
+ edge2.pos = curPos1 + curLen / 2;
+ }
+ else
+ {
+ edge.pos = Utils.pixRound(edge.opos);
+ }
+ anchor = edge;
+ edge.flags |= Segment.FLAG_EDGE_DONE;
+ alignLinkedEdge(hints, dim, edge, edge2);
+ }
+ else
+ {
+ int aDiff = edge.opos - anchor.opos;
+ int orgPos = anchor.pos + aDiff;
+ int orgLen = edge2.opos - edge.opos;
+ int orgCenter = orgPos + (orgLen >> 1);
+ int curLen = computeStemWidth(hints, dim, orgLen, edge.flags,
+ edge2.flags);
+ //System.err.println("stem width: " + curLen);
+ if (curLen < 96)
+ {
+ int uOff, dOff;
+ int curPos1 = Utils.pixRound(orgCenter);
+ if (curLen <= 64)
+ {
+ uOff = 32;
+ dOff = 32;
+ }
+ else
+ {
+ uOff = 38;
+ dOff = 26;
+ }
+ int delta1 = orgCenter - (curPos1 - uOff);
+ if (delta1 < 0)
+ delta1 = -delta1;
+ int delta2 = orgCenter - (curPos1 + dOff);
+ if (delta2 < 0)
+ delta2 = -delta2;
+ if (delta1 < delta2)
+ {
+ curPos1 -= uOff;
+ }
+ else
+ {
+ curPos1 += dOff;
+ }
+ edge.pos = curPos1 - curLen / 2;
+ edge2.pos = curPos1 + curLen / 2;
+ }
+ else
+ {
+ orgPos = anchor.pos + (edge.opos - anchor.opos);
+ orgLen = edge2.opos - edge.opos;
+ orgCenter = orgPos + (orgLen >> 1);
+ curLen = computeStemWidth(hints, dim, orgLen, edge.flags,
+ edge2.flags);
+ int curPos1 = Utils.pixRound(orgPos);
+ int delta1 = curPos1 + (curLen >> 1) - orgCenter;
+ if (delta1 < 0)
+ delta1 = -delta1;
+ int curPos2 = Utils.pixRound(orgPos + orgLen) - curLen;
+ int delta2 = curPos2 + (curLen >> 1) - orgCenter;
+ if (delta2 < 0)
+ delta2 = -delta2;
+ edge.pos = (delta1 < delta2) ? curPos1 : curPos2;
+ edge2.pos = edge.pos + curLen;
+ }
+ edge.flags |= Segment.FLAG_EDGE_DONE;
+ edge2.flags |= Segment.FLAG_EDGE_DONE;
+
+ if (e > 0 && edge.pos < edges[e - 1].pos)
+ {
+ edge.pos = edges[e - 1].pos;
+ }
+ }
+ }
+ // TODO: Implement the lowercase m symmetry thing.
+
+ // Now we hint the remaining edges (serifs and singles) in order
+ // to complete our processing.
+ if (hasSerifs > 0 || anchor == null)
+ {
+ for (int e = 0; e < numEdges; e++)
+ {
+ Edge edge = edges[e];
+ if ((edge.flags & Segment.FLAG_EDGE_DONE) != 0)
+ continue;
+ if (edge.serif != null)
+ {
+ alignSerifEdge(hints, edge.serif, edge);
+ }
+ else if (anchor == null)
+ {
+ edge.pos = Utils.pixRound(edge.opos);
+ anchor = edge;
+ }
+ else
+ {
+ edge.pos = anchor.pos
+ + Utils.pixRound(edge.opos - anchor.opos);
+ }
+ edge.flags |= Segment.FLAG_EDGE_DONE;
+
+ if (e > 0 && edge.pos < edges[e - 1].pos)
+ {
+ edge.pos = edges[e - 1].pos;
+ }
+ if (e + 1 < numEdges
+ && (edges[e + 1].flags & Segment.FLAG_EDGE_DONE) != 0
+ && edge.pos > edges[e + 1].pos)
+ {
+ edge.pos = edges[e + 1].pos;
+ }
+ }
+ }
+
+ // Debug: print all hinted edges.
+ // System.err.println("hinted edges: " );
+ // for (int i = 0; i < numEdges; i++)
+ // {
+ // System.err.println("edge#" + i + ": " + edges[i]);
+ // }
+ }
+
+ private void alignSerifEdge(GlyphHints hints, Edge base, Edge serif)
+ {
+ serif.pos = base.pos + (serif.opos - base.opos);
+ }
+
+ private int computeStemWidth(GlyphHints hints, int dim, int width,
+ int baseFlags, int stemFlags)
+ {
+ LatinMetrics metrics = (LatinMetrics) hints.metrics;
+ LatinAxis axis = metrics.axis[dim];
+ int dist = width;
+ int sign = 0;
+ boolean vertical = dim == DIMENSION_VERT;
+ if (! doStemAdjust(hints))
+ return width;
+ if (dist < 0)
+ {
+ dist = -width;
+ sign = 1;
+ }
+ if ((vertical && ! doVertSnap(hints)) || ! vertical && ! doHorzSnap(hints))
+ {
+ // Smooth hinting process. Very lightly quantize the stem width.
+ // Leave the widths of serifs alone.
+ if ((stemFlags & Segment.FLAG_EDGE_SERIF) != 0 && vertical
+ && dist < 3 * 64)
+ {
+ return doneWidth(dist, sign);
+ }
+ else if ((baseFlags & Segment.FLAG_EDGE_ROUND) != 0)
+ {
+ if (dist < 80)
+ dist = 64;
+ }
+ else if (dist < 56)
+ {
+ dist = 56;
+ }
+ if (axis.widthCount > 0)
+ {
+ int delta;
+ if (axis.widthCount > 0)
+ {
+ delta = dist - axis.widths[0].cur;
+ if (delta < 0)
+ {
+ delta = -delta;
+ }
+ if (delta < 40)
+ {
+ dist = axis.widths[0].cur;
+ if (dist < 48)
+ dist = 48;
+ return doneWidth(dist, sign);
+ }
+ }
+ if (dist < 3 * 64) // < 3 pixels.
+ {
+ delta = dist & 63;
+ dist &= -64;
+ if (delta < 10)
+ dist += delta;
+ else if (delta < 32)
+ dist += 10;
+ else if (delta < 54)
+ dist += 54;
+ else
+ dist += delta;
+
+ }
+ else
+ {
+ dist = (dist + 32) & ~63;
+ }
+ }
+ }
+ else
+ {
+ // Strong hinting process: Snap the stem width to integer pixels.
+ dist = snapWidth(axis.widths, axis.widthCount, dist);
+ if (vertical)
+ {
+ // In the case of vertical hinting, always round
+ // the stem heights to integer pixels.
+ if (dist >= 64)
+ dist = (dist + 16) & ~63;
+ else
+ dist = 64;
+ }
+ else
+ {
+ if (doMono(hints))
+ {
+ // Monochrome horizontal hinting: Snap widths to integer pixels
+ // with a different threshold.
+ if (dist < 64)
+ dist = 64;
+ else
+ dist = (dist + 32) & ~63;
+ }
+ else
+ {
+ // For anti-aliased hinting, we adopt a more subtle
+ // approach: We strengthen small stems, round those stems
+ // whose size is between 1 and 2 pixels to an integer,
+ // otherwise nothing.
+ if (dist < 48)
+ dist = (dist + 64) >> 1;
+ else if (dist < 128)
+ dist = (dist + 22) & ~63;
+ else
+ // Round otherwise to prevent color fringes in LCD mode.
+ dist = (dist + 32) & ~63;
+ }
+ }
+ }
+ return doneWidth(dist, sign);
+ }
+
+ private boolean doMono(GlyphHints hints)
+ {
+ return true;
+ }
+
+ private int snapWidth(Width[] widths, int count, int width)
+ {
+ int best = 64 + 32 + 2;
+ int reference = width;
+ for (int n = 0; n < count; n++)
+ {
+ int w = widths[n].cur;
+ int dist = width - w;
+ if (dist < 0)
+ dist = -dist;
+ if (dist < best)
+ {
+ best = dist;
+ reference = w;
+ }
+ }
+ int scaled = Utils.pixRound(reference);
+ if (width >= reference)
+ {
+ if (width < scaled + 48)
+ width = reference;
+ }
+ else
+ {
+ if (width > scaled + 48)
+ width = reference;
+ }
+ return width;
+ }
+
+ private int doneWidth(int w, int s)
+ {
+ if (s == 1)
+ w = -w;
+ return w;
+ }
+
+ private boolean doVertSnap(GlyphHints hints)
+ {
+ // TODO Auto-generated method stub
+ return true;
+ }
+
+ private boolean doHorzSnap(GlyphHints hints)
{
// TODO Auto-generated method stub
+ return true;
+ }
+ private boolean doStemAdjust(GlyphHints hints)
+ {
+ // TODO Auto-generated method stub
+ return true;
+ }
+
+ private void alignLinkedEdge(GlyphHints hints, int dim, Edge base, Edge stem)
+ {
+ int dist = stem.opos - base.opos;
+ int fitted = computeStemWidth(hints, dim, dist, base.flags, stem.flags);
+ stem.pos = base.pos + fitted;
}
public void doneMetrics(ScriptMetrics metrics)
@@ -99,10 +566,119 @@ class Latin
initBlues(lm, face);
}
- public void scaleMetrics(ScriptMetrics metrics)
+ public void scaleMetrics(ScriptMetrics metrics, HintScaler scaler)
{
- // TODO Auto-generated method stub
+ LatinMetrics lm = (LatinMetrics) metrics;
+ lm.scaler.renderMode = scaler.renderMode;
+ lm.scaler.face = scaler.face;
+ scaleMetricsDim(lm, scaler, DIMENSION_HORZ);
+ scaleMetricsDim(lm, scaler, DIMENSION_VERT);
+ }
+ private void scaleMetricsDim(LatinMetrics lm, HintScaler scaler, int dim)
+ {
+ int scale;
+ int delta;
+ if (dim == DIMENSION_HORZ)
+ {
+ scale = scaler.xScale;
+ delta = scaler.xDelta;
+ }
+ else
+ {
+ scale = scaler.yScale;
+ delta = scaler.yDelta;
+ }
+ LatinAxis axis = lm.axis[dim];
+ if (axis.orgScale == scale && axis.orgDelta == delta)
+ // No change, no need to adjust.
+ return;
+ axis.orgScale = scale;
+ axis.orgDelta = delta;
+
+ // Correct X and Y scale to optimize the alignment of the top small
+ // letters to the pixel grid.
+ LatinAxis axis2 = lm.axis[DIMENSION_VERT];
+ LatinBlue blue = null;
+// for (int nn = 0; nn < axis2.blueCount; nn++)
+// {
+// if ((axis2.blues[nn].flags & LatinBlue.FLAG_ADJUSTMENT) != 0)
+// {
+// blue = axis2.blues[nn];
+// break;
+// }
+// }
+// if (blue != null)
+// {
+// int scaled = Fixed.mul16(blue.shoot.org, scaler.yScale);
+// int fitted = Utils.pixRound(scaled);
+// if (scaled != fitted)
+// {
+// if (dim == DIMENSION_HORZ)
+// {
+// if (fitted < scaled)
+// {
+// scale -= scale / 50;
+// }
+// }
+// else
+// {
+// scale = Utils.mulDiv(scale, fitted, scaled);
+// }
+// }
+// }
+ axis.scale = scale;
+ axis.delta = delta;
+ if (dim == DIMENSION_HORZ)
+ {
+ lm.scaler.xScale = scale;
+ lm.scaler.xDelta = delta;
+ }
+ else
+ {
+ lm.scaler.yScale = scale;
+ lm.scaler.yDelta = delta;
+ }
+ // Scale the standard widths.
+ for (int nn = 0; nn < axis.widthCount; nn++)
+ {
+ Width w = axis.widths[nn];
+ w.cur = Fixed.mul16(w.org, scale);
+ w.fit = w.cur;
+ }
+ // Scale blue zones.
+ if (dim == DIMENSION_VERT)
+ {
+ for (int nn = 0; nn < axis.blueCount; nn++)
+ {
+ blue = axis.blues[nn];
+ blue.ref.cur = Fixed.mul16(blue.ref.org, scale) + delta;
+ blue.ref.fit = blue.ref.cur;
+ blue.shoot.cur = Fixed.mul16(blue.ref.org, scale) + delta;
+ blue.flags &= ~LatinBlue.FLAG_BLUE_ACTIVE;
+ // A blue zone is only active if it is less than 3/4 pixels tall.
+ int dist = Fixed.mul16(blue.ref.org - blue.shoot.org, scale);
+ if (dist <= 48 && dist >= -48)
+ {
+ int delta1 = blue.shoot.org - blue.ref.org;
+ int delta2 = delta1;
+ if (delta1 < 0)
+ delta2 = -delta2;
+ delta2 = Fixed.mul16(delta2, scale);
+ if (delta2 < 32)
+ delta2 = 0;
+ else if (delta2 < 64)
+ delta2 = 32 + (((delta2 - 32) + 16) & ~31);
+ else
+ delta2 = Utils.pixRound(delta2);
+ if (delta1 < 0)
+ delta2 = -delta2;
+ blue.ref.fit = Utils.pixRound(blue.ref.cur);
+ blue.shoot.fit = blue.ref.fit + delta2;
+ blue.flags |= LatinBlue.FLAG_BLUE_ACTIVE;
+ }
+ }
+ }
}
/**
@@ -118,12 +694,9 @@ class Latin
metrics.axis[DIMENSION_HORZ].widthCount = 0;
metrics.axis[DIMENSION_VERT].widthCount = 0;
int glyphIndex = face.getGlyph(ch);
- // TODO: Avoid that AffineTransform constructor and change
- // getRawGlyphOutline() to accept null or remove that parameter altogether.
- // Consider this when the thing is done and we know what we need that for.
- Zone outline = face.getRawGlyphOutline(glyphIndex, new AffineTransform());
+ Zone outline = face.getRawGlyphOutline(glyphIndex, IDENTITY);
LatinMetrics dummy = new LatinMetrics();
- Scaler scaler = dummy.scaler;
+ HintScaler scaler = dummy.scaler;
dummy.unitsPerEm = metrics.unitsPerEm;
scaler.xScale = scaler.yScale = 10000;
scaler.xDelta = scaler.yDelta = 0;
@@ -135,20 +708,24 @@ class Latin
LatinAxis axis = metrics.axis[dim];
AxisHints axHints = hints.axis[dim];
int numWidths = 0;
- hints.computeSegments(dim);
- hints.linkSegments(dim);
+ computeSegments(hints, dim);
+ linkSegments(hints, dim);
Segment[] segs = axHints.segments;
+ HashSet<Segment> touched = new HashSet<Segment>();
for (int i = 0; i < segs.length; i++)
{
Segment seg = segs[i];
Segment link = seg.link;
- if (link != null && link.link == seg && link.index > i)
+ if (link != null && link.link == seg && ! touched.contains(link))
{
int dist = Math.abs(seg.pos - link.pos);
if (numWidths < MAX_WIDTHS)
- axis.widths[numWidths++].org = dist;
+ axis.widths[numWidths++] = new Width(dist);
}
+ touched.add(seg);
}
+ Utils.sort(numWidths, axis.widths);
+ axis.widthCount = numWidths;
}
for (int dim = 0; dim < DIMENSION_MAX; dim++)
{
@@ -159,6 +736,78 @@ class Latin
}
}
+ void linkSegments(GlyphHints hints, int dim)
+ {
+ AxisHints axis = hints.axis[dim];
+ Segment[] segments = axis.segments;
+ int numSegs = axis.numSegments;
+ int majorDir = axis.majorDir;
+ int lenThreshold = constant((LatinMetrics) hints.metrics, 8);
+ lenThreshold = Math.min(1, lenThreshold);
+ int lenScore = constant((LatinMetrics) hints.metrics, 3000);
+ for (int i1 = 0; i1 < numSegs; i1++)
+ {
+ Segment seg1 = segments[i1];
+ // The fake segments are introduced to hint the metrics.
+ // Never link them to anything.
+ if (seg1.first == seg1.last || seg1.dir != majorDir)
+ continue;
+ for (int i2 = 0; i2 < numSegs; i2++)
+ {
+ Segment seg2 = segments[i2];
+ if (seg2 != seg1 && seg1.dir + seg2.dir == 0)
+ {
+ int pos1 = seg1.pos;
+ int pos2 = seg2.pos;
+ // The vertical coords are swapped compared to how FT handles
+ // this.
+ int dist = dim == DIMENSION_VERT ? pos1 - pos2 : pos2 - pos1;
+ if (dist >= 0)
+ {
+ int min = seg1.minPos;
+ int max = seg1.maxPos;
+ int len, score;
+ if (min < seg2.minPos)
+ min = seg2.minPos;
+ if (max > seg2.maxPos)
+ max = seg2.maxPos;
+ len = max - min;
+ if (len > lenThreshold)
+ {
+ score = dist + lenScore / len;
+ if (score < seg1.score)
+ {
+ seg1.score = score;
+ seg1.link = seg2;
+ }
+ if (score < seg2.score)
+ {
+ seg2.score = score;
+ seg2.link = seg1;
+ }
+ }
+ }
+ }
+ }
+ }
+ for (int i1 = 0; i1 < numSegs; i1++)
+ {
+ Segment seg1 = segments[i1];
+ Segment seg2 = seg1.link;
+ if (seg2 != null)
+ {
+ seg2.numLinked++;
+ if (seg2.link != seg1)
+ {
+ seg1.link = null;
+ seg1.serif = seg2.link;
+ }
+ }
+ // Uncomment to show all segments.
+ // System.err.println("segment#" + i1 + ": " + seg1);
+ }
+ }
+
/**
* Initializes the blue zones of the font.
*
@@ -167,11 +816,548 @@ class Latin
*/
private void initBlues(LatinMetrics metrics, OpenTypeFont face)
{
- // TODO: Implement.
+ int[] flats = new int[MAX_TEST_CHARS];
+ int[] rounds = new int[MAX_TEST_CHARS];
+ int numFlats;
+ int numRounds;
+ LatinBlue blue;
+ LatinAxis axis = metrics.axis[DIMENSION_VERT];
+ // We compute the blues simply by loading each character in the test
+ // strings, then compute its topmost or bottommost points.
+ for (int bb = 0; bb < BLUE_MAX; bb++)
+ {
+ String p = TEST_CHARS[bb];
+ int blueRef;
+ int blueShoot;
+ numFlats = 0;
+ numRounds = 0;
+ for (int i = 0; i < p.length(); i++)
+ {
+ // Load the character.
+ int glyphIndex = face.getGlyph(p.charAt(i));
+ Zone glyph =
+ face.getRawGlyphOutline(glyphIndex, IDENTITY);
+
+ // Now compute the min and max points.
+ int numPoints = glyph.getSize() - 4; // 4 phantom points.
+ Point[] points = glyph.getPoints();
+ Point point = points[0];
+ int extremum = 0;
+ int index = 1;
+ if (isTopBlue(bb))
+ {
+ for (; index < numPoints; index++)
+ {
+ point = points[index];
+ // We have the vertical direction swapped. The higher
+ // points have smaller (negative) Y.
+ if (point.getOrigY() < points[extremum].getOrigY())
+ extremum = index;
+ }
+ }
+ else
+ {
+ for (; index < numPoints; index++)
+ {
+ point = points[index];
+ // We have the vertical direction swapped. The higher
+ // points have smaller (negative) Y.
+ if (point.getOrigY() > points[extremum].getOrigY())
+ extremum = index;
+ }
+ }
+ // Debug, prints out the maxima.
+ // System.err.println("extremum for " + bb + " / "+ p.charAt(i)
+ // + ": " + points[extremum]);
+
+ // Now determine if the point is part of a straight or round
+ // segment.
+ boolean round;
+ int idx = extremum;
+ int first, last, prev, next, end;
+ int dist;
+ last = -1;
+ first = 0;
+ for (int n = 0; n < glyph.getNumContours(); n++)
+ {
+ end = glyph.getContourEnd(n);
+ // System.err.println("contour end for " + n + ": " + end);
+ if (end >= idx)
+ {
+ last = end;
+ break;
+ }
+ first = end + 1;
+ }
+ // Should never happen.
+ assert last >= 0;
+
+ // Now look for the previous and next points that are not on the
+ // same Y coordinate. Threshold the 'closeness'.
+ prev = idx;
+ next = prev;
+ do
+ {
+ if (prev > first)
+ prev--;
+ else
+ prev = last;
+ dist = points[prev].getOrigY() - points[extremum].getOrigY();
+ if (dist < -5 || dist > 5)
+ break;
+ } while (prev != idx);
+ do
+ {
+ if (next < last)
+ next++;
+ else
+ next = first;
+ dist = points[next].getOrigY() - points[extremum].getOrigY();
+ if (dist < -5 || dist > 5)
+ break;
+ } while (next != idx);
+ round = points[prev].isControlPoint()
+ || points[next].isControlPoint();
+
+ if (round)
+ {
+ rounds[numRounds++] = points[extremum].getOrigY();
+ // System.err.println("new round extremum: " + bb + ": "
+ // + points[extremum].getOrigY());
+ }
+ else
+ {
+ flats[numFlats++] = points[extremum].getOrigY();
+ // System.err.println("new flat extremum: " + bb + ": "
+ // + points[extremum].getOrigY());
+ }
+ }
+ // We have computed the contents of the rounds and flats tables.
+ // Now determine the reference and overshoot position of the blues --
+ // we simply take the median after a simple sort.
+ Utils.sort(numRounds, rounds);
+ Utils.sort(numFlats, flats);
+ blue = axis.blues[axis.blueCount] = new LatinBlue();
+ axis.blueCount++;
+ if (numFlats == 0)
+ {
+ blue.ref = blue.shoot = new Width(rounds[numRounds / 2]);
+ }
+ else if (numRounds == 0)
+ {
+ blue.ref = blue.shoot = new Width(flats[numFlats / 2]);
+ }
+ else
+ {
+ blue.ref = new Width(flats[numFlats / 2]);
+ blue.shoot = new Width(rounds[numRounds / 2]);
+ }
+ // There are sometimes problems: if the overshoot position of top
+ // zones is under its reference position, or the opposite for bottom
+ // zones. We must check everything there and correct problems.
+ if (blue.shoot != blue.ref)
+ {
+ int ref = blue.ref.org;
+ int shoot = blue.shoot.org;
+ // Inversed vertical coordinates!
+ boolean overRef = shoot < ref;
+ if (isTopBlue(bb) ^ overRef)
+ {
+ blue.shoot = blue.ref = new Width((shoot + ref) / 2);
+ }
+ }
+ blue.flags = 0;
+ if (isTopBlue(bb))
+ blue.flags |= LatinBlue.FLAG_TOP;
+ // The following flag is used later to adjust y and x scales in
+ // order to optimize the pixel grid alignment of the top small
+ // letters.
+ if (bb == SMALL_TOP)
+ {
+ blue.flags |= LatinBlue.FLAG_ADJUSTMENT;
+ }
+ // Debug: print out the blue zones.
+ // System.err.println("blue zone #" + bb + ": " + blue);
+ }
}
+ private static final AffineTransform IDENTITY = new AffineTransform();
+
private int constant(LatinMetrics metrics, int c)
{
return c * (metrics.unitsPerEm / 2048);
}
+
+ private void computeSegments(GlyphHints hints, int dim)
+ {
+ Point[] points = hints.points;
+ if (dim == DIMENSION_HORZ)
+ {
+ for (int i = 0; i < hints.numPoints; i++)
+ {
+ points[i].setU(points[i].getOrigX());
+ points[i].setV(points[i].getOrigY());
+ }
+ }
+ else
+ {
+ for (int i = 0; i < hints.numPoints; i++)
+ {
+ points[i].setU(points[i].getOrigY());
+ points[i].setV(points[i].getOrigX());
+ }
+ }
+ // Now look at each contour.
+ AxisHints axis = hints.axis[dim];
+ int majorDir = Math.abs(axis.majorDir);
+ int segmentDir = majorDir;
+ Point[] contours = hints.contours;
+ int numContours = hints.numContours;
+ Segment segment = null;
+ for (int i = 0; i < numContours; i++)
+ {
+ int minPos = 32000;
+ int maxPos = -32000;
+
+ Point point = contours[i];
+ Point last = point.getPrev();
+ if (point == last) // Skip singletons.
+ continue;
+ if (Math.abs(last.getOutDir()) == majorDir
+ && Math.abs(point.getOutDir()) == majorDir)
+ {
+ // We are already on an edge. Locate its start.
+ last = point;
+ while (true)
+ {
+ point = point.getPrev();
+ if (Math.abs(point.getOutDir()) != majorDir)
+ {
+ point = point.getNext();
+ break;
+ }
+ if (point == last)
+ break;
+ }
+ }
+ last = point;
+ boolean passed = false;
+ boolean onEdge = false;
+ while (true)
+ {
+ int u, v;
+ if (onEdge)
+ {
+ u = point.getU();
+ if (u < minPos)
+ minPos = u;
+ if (u > maxPos)
+ maxPos = u;
+ if (point.getOutDir() != segmentDir || point == last)
+ {
+ // Leaving an edge. Record new segment.
+ segment.last = point;
+ // (minPos + maxPos) / 2.
+ segment.pos = (minPos + maxPos) >> 1;
+ if (segment.first.isControlPoint()
+ || point.isControlPoint())
+ segment.flags |= Segment.FLAG_EDGE_ROUND;
+ minPos = maxPos = point.getV();
+ v = segment.first.getV();
+ if (v < minPos)
+ minPos = v;
+ if (v > maxPos)
+ maxPos = v;
+ segment.minPos = minPos;
+ segment.maxPos = maxPos;
+ onEdge = false;
+ segment = null;
+ }
+ }
+ if (point == last)
+ {
+ if (passed)
+ break;
+ passed = true;
+ }
+ if (! onEdge && Math.abs(point.getOutDir()) == majorDir)
+ {
+ // This is the start of a new segment.
+ segmentDir = point.getOutDir();
+ segment = axis.newSegment();
+ segment.dir = segmentDir;
+ segment.flags = Segment.FLAG_EDGE_NORMAL;
+ minPos = maxPos = point.getU();
+ segment.first = point;
+ segment.last = point;
+ segment.contour = contours[i];
+ segment.score = 32000;
+ segment.len = 0;
+ segment.link = null;
+ onEdge = true;
+ }
+ point = point.getNext();
+ }
+ }
+
+ }
+
+ private boolean isTopBlue(int b)
+ {
+ return b == CAPITAL_TOP || b == SMALL_F_TOP || b == SMALL_TOP;
+ }
+
+ private void detectFeatures(GlyphHints hints, int dim)
+ {
+ computeSegments(hints, dim);
+ linkSegments(hints, dim);
+ computeEdges(hints, dim);
+ }
+
+ private void computeEdges(GlyphHints hints, int dim)
+ {
+ AxisHints axis = hints.axis[dim];
+ LatinAxis laxis = ((LatinMetrics) hints.metrics).axis[dim];
+ Segment[] segments = axis.segments;
+ int numSegments = axis.numSegments;
+ Segment seg;
+ int upDir;
+ int scale;
+ int edgeDistanceThreshold;
+ axis.numEdges = 0;
+ scale = dim == DIMENSION_HORZ ? hints.xScale : hints.yScale;
+ upDir = dim == DIMENSION_HORZ ? DIR_UP : DIR_RIGHT;
+
+ // We will begin by generating a sorted table of edges for the
+ // current direction. To do so, we simply scan each segment and try
+ // to find an edge in our table that corresponds to its position.
+ //
+ // If no edge is found, we create one and insert a new edge in the
+ // sorted table. Otherwise, we simply add the segment to the egde's
+ // list which will be processed in the second step to compute the
+ // edge's properties.
+ //
+ // Note that the edge table is sorted along the segment/edge
+ // position.
+
+ edgeDistanceThreshold = Fixed.mul16(laxis.edgeDistanceTreshold, scale);
+ if (edgeDistanceThreshold > 64 / 4)
+ edgeDistanceThreshold = 64 / 4;
+ edgeDistanceThreshold = Fixed.div16(edgeDistanceThreshold, scale);
+ for (int i = 0; i < numSegments; i++)
+ {
+ seg = segments[i];
+ Edge found = null;
+ for (int ee = 0; ee < axis.numEdges; ee++)
+ {
+ Edge edge = axis.edges[ee];
+ int dist = seg.pos - edge.fpos;
+ if (dist < 0)
+ dist = -dist;
+ if (dist < edgeDistanceThreshold)
+ {
+ found = edge;
+ break;
+ }
+ }
+ if (found == null)
+ {
+ // Insert new edge in the list and sort according to
+ // the position.
+ Edge edge = axis.newEdge(seg.pos);
+ edge.first = seg;
+ edge.last = seg;
+ edge.fpos = seg.pos;
+ edge.opos = edge.pos = Fixed.mul16(seg.pos, scale);
+ seg.edgeNext = seg;
+ seg.edge = edge;
+ }
+ else
+ {
+ seg.edgeNext = found.first;
+ found.last.edgeNext = seg;
+ found.last = seg;
+ seg.edge = found;
+ }
+ }
+ // Good. We will now compute each edge's properties according to
+ // segments found on its position. Basically these are:
+ // - Edge's main direction.
+ // - Stem edge, serif edge, or both (which defaults to stem edge).
+ // - Rounded edge, straight or both (which defaults to straight).
+ // - Link for edge.
+
+ // Now, compute each edge properties.
+ for (int e = 0; e < axis.numEdges; e++)
+ {
+ Edge edge = axis.edges[e];
+ // Does it contain round segments?
+ int isRound = 0;
+ // Does it contain straight segments?
+ int isStraight = 0;
+ // Number of upward segments.
+ int ups = 0;
+ // Number of downward segments.
+ int downs = 0;
+
+ seg = edge.first;
+ do
+ {
+ // Check for roundness of segment.
+ if ((seg.flags & Segment.FLAG_EDGE_ROUND) != 0)
+ isRound++;
+ else
+ isStraight++;
+
+ // Check for segment direction.
+ if (seg.dir == upDir)
+ ups += seg.maxPos - seg.minPos;
+ else
+ downs += seg.maxPos - seg.minPos;
+
+ // Check for links. If seg.serif is set, then seg.link must
+ // be ignored.
+ boolean isSerif = seg.serif != null && seg.serif.edge != edge;
+ if (seg.link != null || isSerif)
+ {
+ Edge edge2 = edge.link;
+ Segment seg2 = seg.link;
+ if (isSerif)
+ {
+ seg2 = seg.serif;
+ edge2 = edge.serif;
+ }
+ if (edge2 != null)
+ {
+ int edgeDelta = edge.fpos - edge2.fpos;
+ if (edgeDelta < 0)
+ edgeDelta = -edgeDelta;
+ int segDelta = seg.pos - seg2.pos;
+ if (segDelta < 0)
+ segDelta = -segDelta;
+ if (segDelta < edgeDelta)
+ edge2 = seg2.edge;
+ }
+ else
+ {
+ edge2 = seg2.edge;
+ }
+ if (isSerif)
+ {
+ edge.serif = edge2;
+ edge2.flags |= Segment.FLAG_EDGE_SERIF;
+ }
+ else
+ {
+ edge.link = edge2;
+ }
+ }
+ seg = seg.edgeNext;
+ } while (seg != edge.first);
+ edge.flags = Segment.FLAG_EDGE_NORMAL;
+ if (isRound > 0 && isRound > isStraight)
+ edge.flags |= Segment.FLAG_EDGE_ROUND;
+
+ // Set the edge's main direction.
+ edge.dir = DIR_NONE;
+ if (ups > downs)
+ edge.dir = upDir;
+ else if (ups < downs)
+ edge.dir = -upDir;
+ else if (ups == downs)
+ edge.dir = 0;
+
+ // Gets rid of serif if link is set. This gets rid of many
+ // unpleasant artifacts.
+ if (edge.serif != null && edge.link != null)
+ {
+ edge.serif = null;
+ }
+
+ // Debug: Print out all edges.
+ // System.err.println("edge# " + e + ": " + edge);
+ }
+ }
+
+ private void computeBlueEdges(GlyphHints hints, LatinMetrics metrics)
+ {
+ AxisHints axis = hints.axis[DIMENSION_VERT];
+ Edge[] edges = axis.edges;
+ int numEdges = axis.numEdges;
+ LatinAxis latin = metrics.axis[DIMENSION_VERT];
+ int scale = latin.scale;
+
+ // Compute which blue zones are active. I.e. have their scaled
+ // size < 3/4 pixels.
+
+ // For each horizontal edge search the blue zone that is closest.
+ for (int e = 0; e < numEdges; e++)
+ {
+ Edge edge = edges[e];
+ // System.err.println("checking edge: " + edge);
+ Width bestBlue = null;
+ int bestDist = Fixed.mul16(metrics.unitsPerEm / 40, scale);
+
+ if (bestDist > 64 / 2)
+ bestDist = 64 / 2;
+ for (int bb = 0; bb < BLUE_MAX; bb++)
+ {
+ LatinBlue blue = latin.blues[bb];
+ // System.err.println("checking blue: " + blue);
+ // Skip inactive blue zones, i.e. those that are too small.
+ if ((blue.flags & LatinBlue.FLAG_BLUE_ACTIVE) == 0)
+ continue;
+ // If it is a top zone, check for right edges. If it is a bottom
+ // zone, check for left edges.
+ boolean isTopBlue = (blue.flags & LatinBlue.FLAG_TOP) != 0;
+ boolean isMajorDir = edge.dir == axis.majorDir;
+
+ // If it is a top zone, the edge must be against the major
+ // direction. If it is a bottom zone it must be in the major
+ // direction.
+ if (isTopBlue ^ isMajorDir)
+ {
+ int dist = edge.fpos - blue.ref.org;
+ if (dist < 0)
+ dist = -dist;
+ dist = Fixed.mul16(dist, scale);
+ if (dist < bestDist)
+ {
+ bestDist = dist;
+ bestBlue = blue.ref;
+ }
+
+ // Now, compare it to the overshoot position if the edge is
+ // rounded, and if the edge is over the reference position of
+ // a top zone, or under the reference position of a bottom
+ // zone.
+ if ((edge.flags & Segment.FLAG_EDGE_ROUND) != 0 && dist != 0)
+ {
+ // Inversed vertical coordinates!
+ boolean isUnderRef = edge.fpos > blue.ref.org;
+ if (isTopBlue ^ isUnderRef)
+ {
+ blue = latin.blues[bb]; // Needed?
+ dist = edge.fpos - blue.shoot.org;
+ if (dist < 0)
+ dist = -dist;
+ dist = Fixed.mul16(dist, scale);
+ if (dist < bestDist)
+ {
+ bestDist = dist;
+ bestBlue = blue.shoot;
+ }
+ }
+ }
+
+ }
+ }
+ if (bestBlue != null)
+ {
+ edge.blueEdge = bestBlue;
+ // Debug: Print out the blue edges.
+ // System.err.println("blue edge for: " + edge + ": " + bestBlue);
+ }
+ }
+ }
}
diff --git a/libjava/classpath/gnu/java/awt/font/autofit/LatinAxis.java b/libjava/classpath/gnu/java/awt/font/autofit/LatinAxis.java
index 8ca1e6d9ed2..9237d0ee5b1 100644
--- a/libjava/classpath/gnu/java/awt/font/autofit/LatinAxis.java
+++ b/libjava/classpath/gnu/java/awt/font/autofit/LatinAxis.java
@@ -49,5 +49,14 @@ class LatinAxis
int widthCount;
Width[] widths;
- float edgeDistanceTreshold;
+ int edgeDistanceTreshold;
+ LatinBlue[] blues;
+ int blueCount;
+ int orgDelta;
+ int orgScale;
+ LatinAxis()
+ {
+ widths = new Width[Latin.MAX_WIDTHS];
+ blues = new LatinBlue[Latin.BLUE_MAX];
+ }
}
diff --git a/libjava/classpath/gnu/java/awt/font/autofit/LatinBlue.java b/libjava/classpath/gnu/java/awt/font/autofit/LatinBlue.java
new file mode 100644
index 00000000000..694fb24fe07
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/font/autofit/LatinBlue.java
@@ -0,0 +1,59 @@
+/* LatinBlue.java -- FIXME: briefly describe file purpose
+ 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.autofit;
+
+public class LatinBlue
+{
+ static final int FLAG_BLUE_ACTIVE = 1 << 0;
+ static final int FLAG_TOP = 1 << 1;
+ static final int FLAG_ADJUSTMENT = 1 << 2;
+ Width ref;
+ Width shoot;
+ int flags;
+ public String toString()
+ {
+ StringBuilder s = new StringBuilder();
+ s.append("[BlueZone]");
+ s.append(" ref: ");
+ s.append(ref.org);
+ s.append(", shoot: ");
+ s.append(shoot.org);
+ return s.toString();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/font/autofit/LatinMetrics.java b/libjava/classpath/gnu/java/awt/font/autofit/LatinMetrics.java
index cd955348b37..33fc63ad4ba 100644
--- a/libjava/classpath/gnu/java/awt/font/autofit/LatinMetrics.java
+++ b/libjava/classpath/gnu/java/awt/font/autofit/LatinMetrics.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package gnu.java.awt.font.autofit;
+import gnu.java.awt.font.opentype.OpenTypeFont;
+
/**
* Latin specific metrics data.
*/
@@ -48,4 +50,17 @@ class LatinMetrics
LatinAxis[] axis;
int unitsPerEm;
+
+ LatinMetrics()
+ {
+ super();
+ axis = new LatinAxis[Constants.DIMENSION_MAX];
+ axis[Constants.DIMENSION_HORZ] = new LatinAxis();
+ axis[Constants.DIMENSION_VERT] = new LatinAxis();
+ }
+ LatinMetrics(OpenTypeFont face)
+ {
+ this();
+ unitsPerEm = face.unitsPerEm;
+ }
}
diff --git a/libjava/classpath/gnu/java/awt/font/autofit/Script.java b/libjava/classpath/gnu/java/awt/font/autofit/Script.java
index 3b353010f2d..c223f0a26af 100644
--- a/libjava/classpath/gnu/java/awt/font/autofit/Script.java
+++ b/libjava/classpath/gnu/java/awt/font/autofit/Script.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package gnu.java.awt.font.autofit;
import gnu.java.awt.font.opentype.OpenTypeFont;
+import gnu.java.awt.font.opentype.truetype.Zone;
/**
* Defines script specific methods for the auto fitter.
@@ -51,12 +52,11 @@ interface Script
*/
void initMetrics(ScriptMetrics metrics, OpenTypeFont face);
- void scaleMetrics(ScriptMetrics metrics/* , scaler, map this */);
+ void scaleMetrics(ScriptMetrics metrics , HintScaler scaler);
void doneMetrics(ScriptMetrics metrics);
void initHints(GlyphHints hints, ScriptMetrics metrics);
- void applyHints(GlyphHints hints, /* some outline object, */
- ScriptMetrics metrics);
+ void applyHints(GlyphHints hints, Zone outline, ScriptMetrics metrics);
}
diff --git a/libjava/classpath/gnu/java/awt/font/autofit/ScriptMetrics.java b/libjava/classpath/gnu/java/awt/font/autofit/ScriptMetrics.java
index 77c815ae59d..984a06daee4 100644
--- a/libjava/classpath/gnu/java/awt/font/autofit/ScriptMetrics.java
+++ b/libjava/classpath/gnu/java/awt/font/autofit/ScriptMetrics.java
@@ -45,5 +45,9 @@ class ScriptMetrics
{
Script script;
- Scaler scaler;
+ HintScaler scaler;
+ ScriptMetrics()
+ {
+ scaler = new HintScaler();
+ }
}
diff --git a/libjava/classpath/gnu/java/awt/font/autofit/Segment.java b/libjava/classpath/gnu/java/awt/font/autofit/Segment.java
index 32032a48fcc..640e82ce2e9 100644
--- a/libjava/classpath/gnu/java/awt/font/autofit/Segment.java
+++ b/libjava/classpath/gnu/java/awt/font/autofit/Segment.java
@@ -38,10 +38,58 @@ exception statement from your version. */
package gnu.java.awt.font.autofit;
+import gnu.java.awt.font.opentype.truetype.Point;
+
class Segment
{
+ static final int FLAG_EDGE_NORMAL = 0;
+ static final int FLAG_EDGE_ROUND = 1;
+ static final int FLAG_EDGE_SERIF = 2;
+ static final int FLAG_EDGE_DONE = 4;
+ int dir;
+ int flags;
Segment link;
- int index;
+ Segment serif;
+ int numLinked;
int pos;
+ Point first;
+ Point last;
+ Point contour;
+ int minPos;
+ int maxPos;
+ int score;
+ int len;
+ Segment edgeNext;
+ Edge edge;
+
+ public String toString()
+ {
+ StringBuilder s = new StringBuilder();
+ s.append("[Segment] id: ");
+ s.append(hashCode());
+ s.append(", len:");
+ s.append(len);
+ s.append(", round: ");
+ s.append(((flags & FLAG_EDGE_ROUND) != 0));
+ s.append(", dir: ");
+ s.append(dir);
+ s.append(", pos: ");
+ s.append(pos);
+ s.append(", minPos: ");
+ s.append(minPos);
+ s.append(", maxPos: ");
+ s.append(maxPos);
+ s.append(", first: ");
+ s.append(first);
+ s.append(", last: ");
+ s.append(last);
+ s.append(", contour: ");
+ s.append(contour);
+ s.append(", link: ");
+ s.append(link == null ? "null" : link.hashCode());
+ s.append(", serif: ");
+ s.append(serif == null ? "null" : serif.hashCode());
+ return s.toString();
+ }
}
diff --git a/libjava/classpath/gnu/java/awt/font/autofit/Utils.java b/libjava/classpath/gnu/java/awt/font/autofit/Utils.java
new file mode 100644
index 00000000000..4df4705a8d1
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/font/autofit/Utils.java
@@ -0,0 +1,255 @@
+/* Utils.java -- A collection of utility functions for the autofitter
+ 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.autofit;
+
+import gnu.java.awt.font.opentype.truetype.Fixed;
+
+/**
+ * A collection of utility methods used all around the auto fitter.
+ */
+class Utils
+ implements Constants
+{
+
+ private static final int ATAN_BITS = 8;
+ private static final byte[] ATAN = new byte[]
+ {
+ 0, 0, 1, 1, 1, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 5,
+ 5, 5, 6, 6, 6, 7, 7, 7,
+ 8, 8, 8, 9, 9, 9, 10, 10,
+ 10, 10, 11, 11, 11, 12, 12, 12,
+ 13, 13, 13, 14, 14, 14, 14, 15,
+ 15, 15, 16, 16, 16, 17, 17, 17,
+ 18, 18, 18, 18, 19, 19, 19, 20,
+ 20, 20, 21, 21, 21, 21, 22, 22,
+ 22, 23, 23, 23, 24, 24, 24, 24,
+ 25, 25, 25, 26, 26, 26, 26, 27,
+ 27, 27, 28, 28, 28, 28, 29, 29,
+ 29, 30, 30, 30, 30, 31, 31, 31,
+ 31, 32, 32, 32, 33, 33, 33, 33,
+ 34, 34, 34, 34, 35, 35, 35, 35,
+ 36, 36, 36, 36, 37, 37, 37, 38,
+ 38, 38, 38, 39, 39, 39, 39, 40,
+ 40, 40, 40, 41, 41, 41, 41, 42,
+ 42, 42, 42, 42, 43, 43, 43, 43,
+ 44, 44, 44, 44, 45, 45, 45, 45,
+ 46, 46, 46, 46, 46, 47, 47, 47,
+ 47, 48, 48, 48, 48, 48, 49, 49,
+ 49, 49, 50, 50, 50, 50, 50, 51,
+ 51, 51, 51, 51, 52, 52, 52, 52,
+ 52, 53, 53, 53, 53, 53, 54, 54,
+ 54, 54, 54, 55, 55, 55, 55, 55,
+ 56, 56, 56, 56, 56, 57, 57, 57,
+ 57, 57, 57, 58, 58, 58, 58, 58,
+ 59, 59, 59, 59, 59, 59, 60, 60,
+ 60, 60, 60, 61, 61, 61, 61, 61,
+ 61, 62, 62, 62, 62, 62, 62, 63,
+ 63, 63, 63, 63, 63, 64, 64, 64
+ };
+
+ private static final int ANGLE_PI = 256;
+ private static final int ANGLE_PI2 = ANGLE_PI / 2;
+ private static final int ANGLE_PI4 = ANGLE_PI / 4;
+ private static final int ANGLE_2PI = ANGLE_PI * 2;
+
+ /**
+ * Computes the direction constant for the specified vector. The vector is
+ * given as differential value already.
+ *
+ * @param dx the x vector
+ * @param dy the y vector
+ *
+ * @return the direction of that vector, or DIR_NONE, if that vector is not
+ * approximating against one of the major axises
+ */
+ static int computeDirection(int dx, int dy)
+ {
+ int dir = DIR_NONE;
+ if (dx < 0)
+ {
+ if (dy < 0)
+ {
+ if (-dx * 12 < -dy)
+ dir = DIR_UP;
+ else if (-dy * 12 < -dx)
+ dir = DIR_LEFT;
+ }
+ else // dy >= 0 .
+ {
+ if (-dx * 12 < dy)
+ dir = DIR_DOWN;
+ else if (dy * 12 < -dx)
+ dir = DIR_LEFT;
+ }
+ }
+ else // dx >= 0 .
+ {
+ if (dy < 0)
+ {
+ if (dx * 12 < -dy)
+ dir = DIR_UP;
+ else if (-dy * 12 < dx)
+ dir = DIR_RIGHT;
+ }
+ else // dy >= 0 .
+ {
+ if (dx * 12 < dy)
+ dir = DIR_DOWN;
+ else if (dy * 12 < dx)
+ dir = DIR_RIGHT;
+ }
+ }
+ return dir;
+ }
+
+ public static int atan(int dx, int dy)
+ {
+ int angle;
+ // Trivial cases.
+ if (dy == 0)
+ {
+ angle = 0;
+ if (dx < 0)
+ angle = ANGLE_PI;
+ return angle;
+ }
+ else if (dx == 0)
+ {
+ angle = ANGLE_PI2;
+ if (dy < 0)
+ angle = - ANGLE_PI2;
+ return angle;
+ }
+
+
+ angle = 0;
+ if (dx < 0)
+ {
+ dx = -dx;
+ dy = -dy;
+ angle = ANGLE_PI;
+ }
+ if (dy < 0)
+ {
+ int tmp = dx;
+ dx = -dy;
+ dy = tmp;
+ angle -= ANGLE_PI2;
+ }
+ if (dx == 0 && dy == 0)
+ return 0;
+
+ if (dx == dy)
+ angle += ANGLE_PI4;
+ else if (dx > dy)
+ {
+ angle += ATAN[Fixed.div(dy, dx) << (ATAN_BITS - 6)];
+ }
+ else
+ {
+ angle += ANGLE_PI2 - ATAN[Fixed.div(dx, dy) << (ATAN_BITS - 6)];
+ }
+
+ if (angle > ANGLE_PI)
+ angle -= ANGLE_2PI;
+ return angle;
+ }
+
+ public static int angleDiff(int ang1, int ang2)
+ {
+ int delta = ang2 - ang1;
+ delta %= ANGLE_2PI;
+ if (delta < 0)
+ delta += ANGLE_2PI;
+ if (delta > ANGLE_PI)
+ delta -= ANGLE_2PI;
+ return delta;
+ }
+
+ static void sort(int num, int[] array)
+ {
+ int swap;
+ for (int i = 1; i < num; i++)
+ {
+ for (int j = i; j > 0; j--)
+ {
+ if (array[j] > array[j - 1])
+ break;
+ swap = array[j];
+ array[j] = array[j - 1];
+ array[j - 1] = swap;
+ }
+ }
+ }
+
+ static void sort(int num, Width[] array)
+ {
+ Width swap;
+ for (int i = 1; i < num; i++)
+ {
+ for (int j = 1; j > 0; j--)
+ {
+ if (array[j].org > array[j - 1].org)
+ break;
+ swap = array[j];
+ array[j] = array[j - 1];
+ array[j - 1] = swap;
+ }
+ }
+ }
+
+ static int pixRound(int val)
+ {
+ return pixFloor(val + 32);
+ }
+
+ static int pixFloor(int val)
+ {
+ return val & ~63;
+ }
+
+ public static int mulDiv(int a, int b, int c)
+ {
+ long prod = a * b;
+ long div = (prod / c);
+ return (int) div;
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/font/autofit/Width.java b/libjava/classpath/gnu/java/awt/font/autofit/Width.java
index d4d540069ee..c890cf3de3d 100644
--- a/libjava/classpath/gnu/java/awt/font/autofit/Width.java
+++ b/libjava/classpath/gnu/java/awt/font/autofit/Width.java
@@ -43,4 +43,20 @@ public class Width
int org;
int cur;
int fit;
+ Width(int dist)
+ {
+ org = dist;
+ }
+
+ public String toString()
+ {
+ StringBuilder s = new StringBuilder();
+ s.append("[Width] org: ");
+ s.append(org);
+ s.append(", cur: ");
+ s.append(cur);
+ s.append(", fit: ");
+ s.append(fit);
+ return s.toString();
+ }
}
diff --git a/libjava/classpath/gnu/java/awt/font/opentype/Hinter.java b/libjava/classpath/gnu/java/awt/font/opentype/Hinter.java
new file mode 100644
index 00000000000..9758a2896b7
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/font/opentype/Hinter.java
@@ -0,0 +1,63 @@
+/* Hinter.java -- The interface to a hinting implementation
+ 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.opentype.truetype.Zone;
+
+/**
+ * The interface to a hinting implementation.
+ */
+public interface Hinter
+{
+ /**
+ * Initializes the hinter.
+ *
+ * @param face the font for which the hinter should be used
+ */
+ void init(OpenTypeFont face);
+
+ /**
+ * Hints the specified outline.
+ *
+ * @param outline the outline to hint
+ */
+ void applyHints(Zone outline);
+
+ void setFlags(int flags);
+}
diff --git a/libjava/classpath/gnu/java/awt/font/opentype/OpenTypeFont.java b/libjava/classpath/gnu/java/awt/font/opentype/OpenTypeFont.java
index efc30811f7b..a270ce7d96d 100644
--- a/libjava/classpath/gnu/java/awt/font/opentype/OpenTypeFont.java
+++ b/libjava/classpath/gnu/java/awt/font/opentype/OpenTypeFont.java
@@ -51,6 +51,7 @@ import java.util.Locale;
import gnu.java.awt.font.FontDelegate;
import gnu.java.awt.font.GNUGlyphVector;
+import gnu.java.awt.font.autofit.AutoHinter;
import gnu.java.awt.font.opentype.truetype.TrueTypeScaler;
import gnu.java.awt.font.opentype.truetype.Zone;
@@ -146,7 +147,8 @@ public final class OpenTypeFont
*/
private GlyphNamer glyphNamer;
-
+ private Hinter hinter;
+
/**
* Constructs an OpenType or TrueType font.
*
@@ -579,6 +581,9 @@ public final class OpenTypeFont
FontRenderContext frc,
CharacterIterator ci)
{
+ // Initialize hinter if necessary.
+ checkHinter(FontDelegate.FLAG_FITTED);
+
CharGlyphMap cmap;
int numGlyphs;
int[] glyphs;
@@ -689,13 +694,15 @@ public final class OpenTypeFont
float pointSize,
AffineTransform transform,
boolean antialias,
- boolean fractionalMetrics)
+ boolean fractionalMetrics,
+ int flags)
{
/* The synchronization is needed because the scaler is not
* synchronized.
*/
+ checkHinter(flags);
return scaler.getOutline(glyph, pointSize, transform,
- antialias, fractionalMetrics);
+ antialias, fractionalMetrics, hinter, flags);
}
/**
@@ -837,4 +844,29 @@ public final class OpenTypeFont
c[3] = (char) (tag & 0xff);
return new String(c);
}
+
+ /**
+ * Checks if a hinter is installed and installs one when not.
+ */
+ private void checkHinter(int flags)
+ {
+ // When another hinting impl gets added (maybe a true TrueType hinter)
+ // then add some options here. The Hinter interface might need to be
+ // tweaked.
+ if (hinter == null)
+ {
+ try
+ {
+ hinter = new AutoHinter();
+ hinter.init(this);
+ }
+ catch (Exception ex)
+ {
+ // Protect from problems inside hinter.
+ hinter = null;
+ ex.printStackTrace();
+ }
+ }
+ hinter.setFlags(flags);
+ }
}
diff --git a/libjava/classpath/gnu/java/awt/font/opentype/Scaler.java b/libjava/classpath/gnu/java/awt/font/opentype/Scaler.java
index 83a31c576c7..c7582b66657 100644
--- a/libjava/classpath/gnu/java/awt/font/opentype/Scaler.java
+++ b/libjava/classpath/gnu/java/awt/font/opentype/Scaler.java
@@ -90,7 +90,8 @@ public abstract class Scaler
float pointSize,
AffineTransform transform,
boolean antialias,
- boolean fractionalMetrics);
+ boolean fractionalMetrics,
+ Hinter hinter, int type);
/**
diff --git a/libjava/classpath/gnu/java/awt/font/opentype/truetype/Fixed.java b/libjava/classpath/gnu/java/awt/font/opentype/truetype/Fixed.java
index 5d81c5d2e6a..287593e439c 100644
--- a/libjava/classpath/gnu/java/awt/font/opentype/truetype/Fixed.java
+++ b/libjava/classpath/gnu/java/awt/font/opentype/truetype/Fixed.java
@@ -48,7 +48,7 @@ package gnu.java.awt.font.opentype.truetype;
*
* @author Sascha Brawer (brawer@dandelis.ch)
*/
-final class Fixed
+public final class Fixed
{
public static final int ONE = 1<<6;
@@ -69,14 +69,21 @@ final class Fixed
return (int) ((((long) a) * b) >> 6);
}
+ public static int mul16(int a, int b)
+ {
+ return (int) ((((long) a) * b) >> 16);
+ }
public static int div(int a, int b)
{
return (int) ((((long) a) << 6) / b);
}
+ public static int div16(int a, int b)
+ {
+ return (int) ((((long) a) << 16) / b);
+ }
-
public static int ceil(int a)
{
return (a + 63) & -64;
@@ -119,7 +126,10 @@ final class Fixed
{
return ((float) f) / 64;
}
-
+ public static float floatValue16(int f)
+ {
+ return ((float) f) / 65536;
+ }
public static double doubleValue(int f)
{
@@ -138,6 +148,10 @@ final class Fixed
return (int) (d * 64);
}
+ public static int valueOf16(double d)
+ {
+ return (int) (d * (1 << 16));
+ }
/**
* Makes a string representation of a fixed-point number.
diff --git a/libjava/classpath/gnu/java/awt/font/opentype/truetype/GlyphLoader.java b/libjava/classpath/gnu/java/awt/font/opentype/truetype/GlyphLoader.java
index 3733afe92d8..249a87dd403 100644
--- a/libjava/classpath/gnu/java/awt/font/opentype/truetype/GlyphLoader.java
+++ b/libjava/classpath/gnu/java/awt/font/opentype/truetype/GlyphLoader.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package gnu.java.awt.font.opentype.truetype;
+import gnu.java.awt.font.opentype.Hinter;
+
import java.awt.geom.AffineTransform;
import java.nio.ByteBuffer;
@@ -112,17 +114,17 @@ final class GlyphLoader
double pointSize,
AffineTransform transform,
boolean antialias,
- Zone glyphZone)
+ Zone glyphZone, Hinter hinter)
{
glyphZone.setNumPoints(4);
loadSubGlyph(glyphIndex, pointSize, transform, antialias, glyphZone,
- 0, 0);
+ 0, 0, hinter);
}
public void loadGlyph(int glyphIndex, AffineTransform transform,
- Zone glyphZone)
+ Zone glyphZone, Hinter hinter)
{
- loadGlyph(glyphIndex, unitsPerEm, transform, false, glyphZone);
+ loadGlyph(glyphIndex, unitsPerEm, transform, false, glyphZone, hinter);
}
private void loadSubGlyph(int glyphIndex,
@@ -131,7 +133,8 @@ final class GlyphLoader
boolean antialias,
Zone glyphZone,
int preTranslateX,
- int preTranslateY)
+ int preTranslateY,
+ Hinter hinter)
{
ByteBuffer glyph;
int numContours;
@@ -159,11 +162,11 @@ final class GlyphLoader
if (numContours >= 0)
loadSimpleGlyph(glyphIndex, pointSize, transform, antialias,
numContours, glyph, glyphZone,
- preTranslateX, preTranslateY);
+ preTranslateX, preTranslateY, hinter);
else
loadCompoundGlyph(glyphIndex, pointSize, transform, antialias,
glyph, glyphZone,
- preTranslateX, preTranslateY);
+ preTranslateX, preTranslateY, hinter);
}
@@ -172,7 +175,8 @@ final class GlyphLoader
boolean antialias,
int numContours, ByteBuffer glyph,
Zone glyphZone,
- int preTranslateX, int preTranslateY)
+ int preTranslateX, int preTranslateY,
+ Hinter hinter)
{
int numPoints;
int posInstructions, numInstructions;
@@ -203,10 +207,10 @@ final class GlyphLoader
glyphZone.transform(pointSize, transform, unitsPerEm,
preTranslateX, preTranslateY);
- if (execInstructions)
- {
- // FIXME: Hint the glyph.
- }
+ if (execInstructions && hinter != null)
+ {
+ hinter.applyHints(glyphZone);
+ }
}
@@ -229,7 +233,8 @@ final class GlyphLoader
boolean antialias,
ByteBuffer glyph,
Zone glyphZone,
- int preTranslateX, int preTranslateY)
+ int preTranslateX, int preTranslateY,
+ Hinter hinter)
{
short flags;
int subGlyphIndex;
@@ -326,7 +331,7 @@ final class GlyphLoader
loadSubGlyph(subGlyphIndex, pointSize, componentTransform,
antialias, subGlyphZone,
Math.round((float) e + preTranslateX),
- Math.round(-((float) f + preTranslateY)));
+ Math.round(-((float) f + preTranslateY)), hinter);
glyphZone.combineWithSubGlyph(subGlyphZone, 4);
glyph.limit(lim).position(pos);
}
diff --git a/libjava/classpath/gnu/java/awt/font/opentype/truetype/Point.java b/libjava/classpath/gnu/java/awt/font/opentype/truetype/Point.java
new file mode 100644
index 00000000000..c9664d2dc07
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/font/opentype/truetype/Point.java
@@ -0,0 +1,285 @@
+/* Point.java -- Holds information for one point on a glyph outline
+ 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;
+
+/**
+ * Encapsulates information regarding one point on a glyph outline.
+ */
+public class Point
+{
+ public static final short FLAG_TOUCHED_X = 1;
+ public static final short FLAG_TOUCHED_Y = 2;
+ public static final short FLAG_ON_CURVE = 4;
+ public static final short FLAG_CONTOUR_END = 8;
+ public static final short FLAG_WEAK_INTERPOLATION = 16;
+ public static final short FLAG_INFLECTION = 32;
+ public static final short FLAG_DONE_X = 64;
+ public static final short FLAG_DONE_Y = 128;
+
+ /**
+ * Right direction.
+ */
+ public static final int DIR_RIGHT = 1;
+
+ /**
+ * Left direction.
+ */
+ public static final int DIR_LEFT = -1;
+
+ /**
+ * Up direction.
+ */
+ public static final int DIR_UP = 2;
+
+ /**
+ * Down direction.
+ */
+ public static final int DIR_DOWN = -2;
+
+ /**
+ * The original x coordinate in font units.
+ */
+ int origX;
+
+ /**
+ * The original y coordinate in font units.
+ */
+ int origY;
+
+ /**
+ * The x coordinate scaled to the target.
+ */
+ int scaledX;
+
+ /**
+ * The y coordinate scaled to the target.
+ */
+ int scaledY;
+
+ /**
+ * The final hinted and scaled x coordinate.
+ */
+ int x;
+
+ /**
+ * The final hinted and scaled y coordinate.
+ */
+ int y;
+
+ int u;
+ int v;
+
+ /**
+ * The glyph flags.
+ */
+ short flags;
+
+ /**
+ * The previous point in the contour.
+ */
+ private Point prev;
+
+ /**
+ * The next point in the contour.
+ */
+ private Point next;
+
+ /**
+ * The in-direction of the point, according to the DIR_* constants of this
+ * class.
+ */
+ int inDir;
+
+ /**
+ * The out-direction of the point, according to the DIR_* constants of this
+ * class.
+ */
+ int outDir;
+
+ public Point getNext()
+ {
+ return next;
+ }
+
+ public void setNext(Point next)
+ {
+ this.next = next;
+ }
+
+ public Point getPrev()
+ {
+ return prev;
+ }
+
+ public void setPrev(Point prev)
+ {
+ this.prev = prev;
+ }
+
+ public int getOrigX()
+ {
+ return origX;
+ }
+
+ public void setOrigX(int origX)
+ {
+ this.origX = origX;
+ }
+
+ public int getOrigY()
+ {
+ return origY;
+ }
+
+ public void setOrigY(int origY)
+ {
+ this.origY = origY;
+ }
+
+ public int getInDir()
+ {
+ return inDir;
+ }
+
+ public void setInDir(int inDir)
+ {
+ this.inDir = inDir;
+ }
+
+ public int getOutDir()
+ {
+ return outDir;
+ }
+
+ public void setOutDir(int outDir)
+ {
+ this.outDir = outDir;
+ }
+
+ public short getFlags()
+ {
+ return flags;
+ }
+
+ public void setFlags(short flags)
+ {
+ this.flags = flags;
+ }
+
+ public void addFlags(short flags)
+ {
+ this.flags |= flags;
+ }
+
+ public boolean isControlPoint()
+ {
+ return (flags & FLAG_ON_CURVE) == 0;
+ }
+
+ public int getU()
+ {
+ return u;
+ }
+
+ public void setU(int u)
+ {
+ this.u = u;
+ }
+
+ public int getV()
+ {
+ return v;
+ }
+
+ public void setV(int v)
+ {
+ this.v = v;
+ }
+
+ public String toString()
+ {
+ StringBuilder s = new StringBuilder();
+ s.append("[Point] origX: ");
+ s.append(origX);
+ s.append(", origY: ");
+ s.append(origY);
+ // TODO: Add more info when needed.
+ return s.toString();
+ }
+
+ public int getX()
+ {
+ return x;
+ }
+
+ public void setX(int x)
+ {
+ this.x = x;
+ }
+
+ public int getY()
+ {
+ return y;
+ }
+
+ public void setY(int y)
+ {
+ this.y = y;
+ }
+
+ public int getScaledX()
+ {
+ return scaledX;
+ }
+
+ public void setScaledX(int scaledX)
+ {
+ this.scaledX = scaledX;
+ }
+
+ public int getScaledY()
+ {
+ return scaledY;
+ }
+
+ public void setScaledY(int scaledY)
+ {
+ this.scaledY = scaledY;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/font/opentype/truetype/TrueTypeScaler.java b/libjava/classpath/gnu/java/awt/font/opentype/truetype/TrueTypeScaler.java
index 8dfdeff0790..5f5cc0001d9 100644
--- a/libjava/classpath/gnu/java/awt/font/opentype/truetype/TrueTypeScaler.java
+++ b/libjava/classpath/gnu/java/awt/font/opentype/truetype/TrueTypeScaler.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package gnu.java.awt.font.opentype.truetype;
+import gnu.java.awt.font.opentype.Hinter;
import gnu.java.awt.font.opentype.Scaler;
import java.awt.FontFormatException;
@@ -191,17 +192,18 @@ public final class TrueTypeScaler
float pointSize,
AffineTransform deviceTransform,
boolean antialias,
- boolean fractionalMetrics)
+ boolean fractionalMetrics, Hinter hinter,
+ int type)
{
glyphLoader.loadGlyph(glyphIndex, pointSize, deviceTransform,
- antialias, glyphZone);
- return glyphZone.getPath();
+ antialias, glyphZone, hinter);
+ return glyphZone.getPath(type);
}
public Zone getRawOutline(int glyphIndex, AffineTransform transform)
{
Zone zone = new Zone(glyphZone.getCapacity());
- glyphLoader.loadGlyph(glyphIndex, transform, zone);
+ glyphLoader.loadGlyph(glyphIndex, transform, zone, null);
return zone;
}
diff --git a/libjava/classpath/gnu/java/awt/font/opentype/truetype/Zone.java b/libjava/classpath/gnu/java/awt/font/opentype/truetype/Zone.java
index ff5bb631619..7c25a0a6a49 100644
--- a/libjava/classpath/gnu/java/awt/font/opentype/truetype/Zone.java
+++ b/libjava/classpath/gnu/java/awt/font/opentype/truetype/Zone.java
@@ -37,6 +37,8 @@ exception statement from your version. */
package gnu.java.awt.font.opentype.truetype;
+import gnu.java.awt.font.FontDelegate;
+
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
@@ -47,27 +49,19 @@ import java.awt.geom.PathIterator;
*/
public final class Zone
{
- private final int[] pos;
- private final int[] origPos;
- private final byte[] flags;
+ private Point[] points;
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 double scaleX, scaleY, shearX, shearY;
public Zone(int maxNumPoints)
{
- origPos = new int[maxNumPoints * 2];
- pos = new int[maxNumPoints * 2];
- flags = new byte[maxNumPoints];
+ points = new Point[maxNumPoints];
}
-
public int getCapacity()
{
- return flags.length;
+ return points.length;
}
@@ -79,91 +73,110 @@ public final class Zone
public int getX(int point)
{
- return pos[2 * point];
+ return getX(point, FontDelegate.FLAG_FITTED);
+ }
+
+ public int getX(int point, int flags)
+ {
+ int x;
+ if ((flags & FontDelegate.FLAG_FITTED) != 0)
+ x = points[point].x;
+ else
+ x = points[point].scaledX;
+ return x;
}
public void setX(int point, int value, boolean touch)
{
- pos[2 * point] = value;
+ points[point].scaledX = value;
+ points[point].x = value;
if (touch)
- flags[point] |= FLAG_TOUCHED_X;
+ points[point].flags |= Point.FLAG_TOUCHED_X;
}
public void setY(int point, int value, boolean touch)
{
- pos[2 * point + 1] = value;
+ points[point].scaledY = value;
+ points[point].y = value;
if (touch)
- flags[point] |= FLAG_TOUCHED_Y;
+ points[point].flags |= Point.FLAG_TOUCHED_Y;
}
-
public int getY(int point)
{
- return pos[2 * point + 1];
+ return getY(point, FontDelegate.FLAG_FITTED);
+ }
+
+ public int getY(int point, int flags)
+ {
+ int y;
+ if ((flags & FontDelegate.FLAG_FITTED) != 0)
+ y = points[point].y;
+ else
+ y = points[point].scaledY;
+ return y;
}
public int getOriginalX(int point)
{
- return origPos[2 * point];
+ return points[point].origX;
}
public int getOriginalY(int point)
{
- return origPos[2 * point + 1];
+ return points[point].origY;
}
public void setOriginalX(int point, int x)
{
- origPos[2 * point] = x;
+ points[point].origX = x;
}
public void setOriginalY(int point, int y)
{
- origPos[2 * point + 1] = y;
+ points[point].origY = 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;
+ points[i] = new Point();
+ this.numPoints = numPoints;
}
public boolean isOnCurve(int point)
{
- return (flags[point] & FLAG_ON_CURVE) != 0;
+ return (points[point].flags & Point.FLAG_ON_CURVE) != 0;
}
public void setOnCurve(int point, boolean onCurve)
{
if (onCurve)
- flags[point] |= FLAG_ON_CURVE;
+ points[point].flags |= Point.FLAG_ON_CURVE;
else
- flags[point] &= ~FLAG_ON_CURVE;
+ points[point].flags &= ~Point.FLAG_ON_CURVE;
}
public boolean isContourEnd(int point)
{
- return (flags[point] & FLAG_CONTOUR_END) != 0;
+ return (points[point].flags & Point.FLAG_CONTOUR_END) != 0;
}
public void setContourEnd(int point, boolean segEnd)
{
if (segEnd)
- flags[point] |= FLAG_CONTOUR_END;
+ points[point].flags |= Point.FLAG_CONTOUR_END;
else
- flags[point] &= ~FLAG_CONTOUR_END;
+ points[point].flags &= ~Point.FLAG_CONTOUR_END;
}
@@ -172,7 +185,6 @@ public final class Zone
void transform(double pointSize, AffineTransform deviceTransform,
int unitsPerEm, int preTranslateX, int preTranslateY)
{
- double scaleX, scaleY, shearX, shearY;
double factor;
factor = pointSize / (double) unitsPerEm;
@@ -183,11 +195,13 @@ public final class Zone
for (int i = 0; i < numPoints; i++)
{
- int x = origPos[2 * i] + preTranslateX;
- int y = origPos[2 * i + 1] + preTranslateY;
+ int x = points[i].origX + preTranslateX;
+ int y = points[i].origY + 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);
+ points[i].scaledX = points[i].x = Fixed.valueOf(scaleX * x
+ + shearX * y);
+ points[i].scaledY = points[i].y = Fixed.valueOf(shearY * x
+ + scaleY * y);
}
}
@@ -197,11 +211,7 @@ public final class Zone
{
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);
+ System.arraycopy(zone.points, 0, this.points, offset, count);
this.numPoints += count - numPhantomPoints;
}
@@ -211,9 +221,9 @@ public final class Zone
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(Fixed.toString(points[i].scaledX, points[i].scaledY));
System.out.print(' ');
- System.out.print(Fixed.toString(origPos[i*2], origPos[i*2+1]));
+ System.out.print(Fixed.toString(points[i].origX, points[i].origY));
System.out.print(' ');
if (isOnCurve(i))
System.out.print('.');
@@ -228,16 +238,54 @@ public final class Zone
}
- public PathIterator getPathIterator()
+ public PathIterator getPathIterator(int type)
{
- return new ZonePathIterator(this);
+ return new ZonePathIterator(this, type);
}
- public GeneralPath getPath()
+ public GeneralPath getPath(int type)
{
GeneralPath p = new GeneralPath(GeneralPath.WIND_NON_ZERO, numPoints);
- p.append(getPathIterator(), /* connect */ false);
+ p.append(getPathIterator(type), /* connect */ false);
return p;
}
+
+ /**
+ * Returns the number of contours in this outline.
+ *
+ * @return the number of contours in this outline
+ */
+ public int getNumContours()
+ {
+ int num = 0;
+ for (int i = 0; i < numPoints; i++)
+ {
+ if (isContourEnd(i))
+ num++;
+ }
+ return num;
+ }
+
+ public int getContourEnd(int n)
+ {
+ int idx = -1;
+ int num = 0;
+ for (int i = 0; i < numPoints; i++)
+ {
+ if (isContourEnd(i))
+ {
+ idx = i;
+ if (num == n)
+ break;
+ num++;
+ }
+ }
+ return idx;
+ }
+
+ public Point[] getPoints()
+ {
+ return points;
+ }
}
diff --git a/libjava/classpath/gnu/java/awt/font/opentype/truetype/ZonePathIterator.java b/libjava/classpath/gnu/java/awt/font/opentype/truetype/ZonePathIterator.java
index d000b9c3e42..0f60828b892 100644
--- a/libjava/classpath/gnu/java/awt/font/opentype/truetype/ZonePathIterator.java
+++ b/libjava/classpath/gnu/java/awt/font/opentype/truetype/ZonePathIterator.java
@@ -116,6 +116,7 @@ final class ZonePathIterator
private int contourStart;
+ private int type;
/**
* Constructs a ZonePathIterator for the specified zone.
@@ -123,9 +124,10 @@ final class ZonePathIterator
* @param zone the zone whose segments will be enumerated
* by this iterator.
*/
- ZonePathIterator(Zone zone)
+ ZonePathIterator(Zone zone, int t)
{
this.zone = zone;
+ type = t;
numPoints = zone.getSize() - /* four phantom points */ 4;
// The first segment that needs to be emitted is a SEG_MOVETO.
@@ -309,8 +311,8 @@ final class ZonePathIterator
int curX, curY;
int succ, succX, succY;
- curX = zone.getX(cur);
- curY = zone.getY(cur);
+ curX = zone.getX(cur, type);
+ curY = zone.getY(cur, type);
coords[0] = Fixed.floatValue(curX);
coords[1] = Fixed.floatValue(curY);
@@ -318,8 +320,8 @@ final class ZonePathIterator
return PathIterator.SEG_LINETO;
succ = getSuccessor(cur);
- succX = zone.getX(succ);
- succY = zone.getY(succ);
+ succX = zone.getX(succ, type);
+ succY = zone.getY(succ, type);
if (zone.isOnCurve(succ))
{
@@ -359,8 +361,8 @@ final class ZonePathIterator
if (zone.isOnCurve(contourStart))
{
- x = zone.getX(contourStart);
- y = zone.getY(contourStart);
+ x = zone.getX(contourStart, type);
+ y = zone.getY(contourStart, type);
}
else
{
@@ -374,13 +376,13 @@ final class ZonePathIterator
/* 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);
+ x = zone.getX(contourEnd, type);
+ y = zone.getY(contourEnd, type);
}
else
{
- x = (zone.getX(contourStart) + zone.getX(contourEnd)) / 2;
- y = (zone.getY(contourStart) + zone.getY(contourEnd)) / 2;
+ x = (zone.getX(contourStart, type) + zone.getX(contourEnd, type)) / 2;
+ y = (zone.getY(contourStart, type) + zone.getY(contourEnd, type)) / 2;
}
}
diff --git a/libjava/classpath/gnu/java/awt/java2d/AbstractGraphics2D.java b/libjava/classpath/gnu/java/awt/java2d/AbstractGraphics2D.java
index da21253980f..f6c5ff0cb3b 100644
--- a/libjava/classpath/gnu/java/awt/java2d/AbstractGraphics2D.java
+++ b/libjava/classpath/gnu/java/awt/java2d/AbstractGraphics2D.java
@@ -67,8 +67,6 @@ import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.NoninvertibleTransformException;
-import java.awt.geom.PathIterator;
-import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
@@ -82,7 +80,6 @@ import java.awt.image.renderable.RenderableImage;
import java.text.AttributedCharacterIterator;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.Map;
/**
@@ -154,6 +151,11 @@ public abstract class AbstractGraphics2D
{
/**
+ * The default font to use on the graphics object.
+ */
+ private static final Font FONT = new Font("SansSerif", Font.PLAIN, 12);
+
+ /**
* Accuracy of the sampling in the anti-aliasing shape filler.
* Lower values give more speed, while higher values give more quality.
* It is advisable to choose powers of two.
@@ -164,7 +166,14 @@ public abstract class AbstractGraphics2D
* Caches certain shapes to avoid massive creation of such Shapes in
* the various draw* and fill* methods.
*/
- private static final ThreadLocal shapeCache = new ThreadLocal();
+ private static final ThreadLocal<ShapeCache> shapeCache =
+ new ThreadLocal<ShapeCache>();
+
+ /**
+ * The scanline converters by thread.
+ */
+ private static final ThreadLocal<ScanlineConverter> scanlineConverters =
+ new ThreadLocal<ScanlineConverter>();
/**
* The transformation for this Graphics2D instance
@@ -177,6 +186,11 @@ public abstract class AbstractGraphics2D
private Paint paint;
/**
+ * The paint context during rendering.
+ */
+ private PaintContext paintContext;
+
+ /**
* The background.
*/
private Color background;
@@ -239,6 +253,17 @@ public abstract class AbstractGraphics2D
*/
private boolean isOptimized = true;
+ private static final BasicStroke STANDARD_STROKE = new BasicStroke();
+
+ private static final HashMap STANDARD_HINTS;
+ static {
+ HashMap hints = new HashMap();
+ hints.put(RenderingHints.KEY_TEXT_ANTIALIASING,
+ RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
+ hints.put(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_DEFAULT);
+ STANDARD_HINTS = hints;
+ }
/**
* Creates a new AbstractGraphics2D instance.
*/
@@ -247,13 +272,8 @@ public abstract class AbstractGraphics2D
transform = new AffineTransform();
background = Color.WHITE;
composite = AlphaComposite.SrcOver;
- stroke = new BasicStroke();
- HashMap hints = new HashMap();
- hints.put(RenderingHints.KEY_TEXT_ANTIALIASING,
- RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
- hints.put(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_DEFAULT);
- renderingHints = new RenderingHints(hints);
+ stroke = STANDARD_STROKE;
+ renderingHints = new RenderingHints(STANDARD_HINTS);
}
/**
@@ -958,15 +978,8 @@ public abstract class AbstractGraphics2D
*/
public void drawGlyphVector(GlyphVector gv, float x, float y)
{
- int numGlyphs = gv.getNumGlyphs();
translate(x, y);
- // TODO: We could use fill(gv.getOutline()), but that seems to be
- // slightly more inefficient.
- for (int i = 0; i < numGlyphs; i++)
- {
- Shape o = gv.getGlyphOutline(i);
- fillShape(o, true);
- }
+ fillShape(gv.getOutline(), true);
translate(-x, -y);
}
@@ -1557,21 +1570,14 @@ public abstract class AbstractGraphics2D
antialias = (v == RenderingHints.VALUE_ANTIALIAS_ON);
}
- Rectangle2D userBounds = s.getBounds2D();
- Rectangle2D deviceBounds = new Rectangle2D.Double();
- ArrayList segs = getSegments(s, transform, deviceBounds, false);
- Rectangle2D clipBounds = new Rectangle2D.Double();
- ArrayList clipSegs = getSegments(clip, transform, clipBounds, true);
- segs.addAll(clipSegs);
- Rectangle2D inclClipBounds = new Rectangle2D.Double();
- Rectangle2D.union(clipBounds, deviceBounds, inclClipBounds);
- if (segs.size() > 0)
+ ScanlineConverter sc = getScanlineConverter();
+ int resolution = 0;
+ if (antialias)
{
- if (antialias)
- fillShapeAntialias(segs, deviceBounds, userBounds, inclClipBounds);
- else
- fillShapeImpl(segs, deviceBounds, userBounds, inclClipBounds);
+ // Adjust resolution according to rendering hints.
+ resolution = 2;
}
+ sc.renderShape(this, s, clip, transform, resolution);
}
/**
@@ -1705,141 +1711,6 @@ public abstract class AbstractGraphics2D
}
/**
- * Fills the specified polygon without anti-aliasing.
- */
- private void fillShapeImpl(ArrayList segs, Rectangle2D deviceBounds2D,
- Rectangle2D userBounds,
- Rectangle2D inclClipBounds)
- {
- // This is an implementation of a polygon scanline conversion algorithm
- // described here:
- // http://www.cs.berkeley.edu/~ug/slide/pipeline/assignments/scan/
-
- // Create table of all edges.
- // The edge buckets, sorted and indexed by their Y values.
-
- double minX = deviceBounds2D.getMinX();
- double minY = deviceBounds2D.getMinY();
- double maxX = deviceBounds2D.getMaxX();
- double maxY = deviceBounds2D.getMaxY();
- double icMinY = inclClipBounds.getMinY();
- double icMaxY = inclClipBounds.getMaxY();
- Rectangle deviceBounds = new Rectangle((int) minX, (int) minY,
- (int) Math.ceil(maxX) - (int) minX,
- (int) Math.ceil(maxY) - (int) minY);
- PaintContext pCtx = paint.createContext(getColorModel(), deviceBounds,
- userBounds, transform, renderingHints);
-
- ArrayList[] edgeTable = new ArrayList[(int) Math.ceil(icMaxY)
- - (int) Math.ceil(icMinY) + 1];
-
- for (Iterator i = segs.iterator(); i.hasNext();)
- {
- PolyEdge edge = (PolyEdge) i.next();
- int yindex = (int) Math.ceil(edge.y0) - (int) Math.ceil(icMinY);
- if (edgeTable[yindex] == null) // Create bucket when needed.
- edgeTable[yindex] = new ArrayList();
- edgeTable[yindex].add(edge); // Add edge to the bucket of its line.
- }
-
- // TODO: The following could be useful for a future optimization.
-// // Sort all the edges in the edge table within their buckets.
-// for (int y = 0; y < edgeTable.length; y++)
-// {
-// if (edgeTable[y] != null)
-// Collections.sort(edgeTable[y]);
-// }
-
- // The activeEdges list contains all the edges of the current scanline
- // ordered by their intersection points with this scanline.
- ArrayList activeEdges = new ArrayList();
- PolyEdgeComparator comparator = new PolyEdgeComparator();
-
- // Scan all relevant lines.
- int minYInt = (int) Math.ceil(icMinY);
-
- Rectangle devClip = getDeviceBounds();
- int scanlineMax = (int) Math.min(maxY, devClip.getMaxY());
- for (int y = minYInt; y < scanlineMax; y++)
- {
- ArrayList bucket = edgeTable[y - minYInt];
- // Update all the x intersections in the current activeEdges table
- // and remove entries that are no longer in the scanline.
- for (Iterator i = activeEdges.iterator(); i.hasNext();)
- {
- PolyEdge edge = (PolyEdge) i.next();
- if (y > edge.y1)
- i.remove();
- else
- {
- edge.xIntersection += edge.slope;
- //edge.xIntersection = edge.x0 + edge.slope * (y - edge.y0);
- //System.err.println("edge.xIntersection: " + edge.xIntersection);
- }
- }
-
- if (bucket != null)
- activeEdges.addAll(bucket);
-
- // Sort current edges. We are using a bubble sort, because the order
- // of the intersections will not change in most situations. They
- // will only change, when edges intersect each other.
- int size = activeEdges.size();
- if (size > 1)
- {
- for (int i = 1; i < size; i++)
- {
- PolyEdge e1 = (PolyEdge) activeEdges.get(i - 1);
- PolyEdge e2 = (PolyEdge) activeEdges.get(i);
- if (comparator.compare(e1, e2) > 0)
- {
- // Swap e2 with its left neighbor until it 'fits'.
- int j = i;
- do
- {
- activeEdges.set(j, e1);
- activeEdges.set(j - 1, e2);
- j--;
- if (j >= 1)
- e1 = (PolyEdge) activeEdges.get(j - 1);
- } while (j >= 1 && comparator.compare(e1, e2) > 0);
- }
- }
- }
-
- // Now draw all pixels inside the polygon.
- // This is the last edge that intersected the scanline.
- PolyEdge previous = null; // Gets initialized below.
- boolean insideShape = false;
- boolean insideClip = false;
- //System.err.println("scanline: " + y);
- for (Iterator i = activeEdges.iterator(); i.hasNext();)
- {
- PolyEdge edge = (PolyEdge) i.next();
- if (edge.y1 <= y)
- continue;
-
- // Draw scanline when we are inside the shape AND inside the
- // clip.
- if (insideClip && insideShape)
- {
- int x0 = (int) previous.xIntersection;
- int x1 = (int) edge.xIntersection;
- if (x0 < x1)
- fillScanline(pCtx, x0, x1, y);
- }
- // Update state.
- previous = edge;
- if (edge.isClip)
- insideClip = ! insideClip;
- else
- insideShape = ! insideShape;
- }
- }
- pCtx.dispose();
- }
-
- /**
* Paints a scanline between x0 and x1. Override this when your backend
* can efficiently draw/fill horizontal lines.
*
@@ -1847,8 +1718,9 @@ public abstract class AbstractGraphics2D
* @param x1 the right offset
* @param y the scanline
*/
- protected void fillScanline(PaintContext pCtx, int x0, int x1, int y)
+ protected void fillScanline(int x0, int x1, int y)
{
+ PaintContext pCtx = paintContext;
Raster paintRaster = pCtx.getRaster(x0, y, x1 - x0, 1);
ColorModel paintColorModel = pCtx.getColorModel();
CompositeContext cCtx = composite.createContext(paintColorModel,
@@ -1860,198 +1732,6 @@ public abstract class AbstractGraphics2D
cCtx.dispose();
}
- /**
- * Fills arbitrary shapes in an anti-aliased fashion.
- *
- * @param segs the line segments which define the shape which is to be filled
- */
- private void fillShapeAntialias(ArrayList segs, Rectangle2D deviceBounds2D,
- Rectangle2D userBounds,
- Rectangle2D inclClipBounds)
- {
- // This is an implementation of a polygon scanline conversion algorithm
- // described here:
- // http://www.cs.berkeley.edu/~ug/slide/pipeline/assignments/scan/
- // The antialiasing is implemented using a sampling technique, we do
- // not scan whole lines but fractions of the line.
-
- double minX = deviceBounds2D.getMinX();
- double minY = deviceBounds2D.getMinY();
- double maxX = deviceBounds2D.getMaxX();
- double maxY = deviceBounds2D.getMaxY();
- double icMinY = inclClipBounds.getMinY();
- double icMaxY = inclClipBounds.getMaxY();
- double icMinX = inclClipBounds.getMinX();
- double icMaxX = inclClipBounds.getMaxX();
- Rectangle deviceBounds = new Rectangle((int) minX, (int) minY,
- (int) Math.ceil(maxX) - (int) minX,
- (int) Math.ceil(maxY) - (int) minY);
- PaintContext pCtx = paint.createContext(ColorModel.getRGBdefault(),
- deviceBounds,
- userBounds, transform,
- renderingHints);
-
- // This array will contain the oversampled transparency values for
- // each pixel in the scanline.
- int numScanlines = (int) Math.ceil(icMaxY) - (int) icMinY;
- int numScanlinePixels = (int) Math.ceil(icMaxX) - (int) icMinX + 1;
- if (alpha == null || alpha.length < (numScanlinePixels + 1))
- alpha = new int[numScanlinePixels + 1];
-
- int firstLine = (int) icMinY;
- //System.err.println("minY: " + minY);
- int firstSubline = (int) (Math.ceil((icMinY - Math.floor(icMinY)) * AA_SAMPLING));
- double firstLineDouble = firstLine + firstSubline / (double) AA_SAMPLING;
- //System.err.println("firstSubline: " + firstSubline);
-
- // Create table of all edges.
- // The edge buckets, sorted and indexed by their Y values.
- //System.err.println("numScanlines: " + numScanlines);
- if (edgeTable == null
- || edgeTable.length < numScanlines * AA_SAMPLING + AA_SAMPLING)
- edgeTable = new ArrayList[numScanlines * AA_SAMPLING + AA_SAMPLING];
-
- //System.err.println("firstLineDouble: " + firstLineDouble);
-
- for (Iterator i = segs.iterator(); i.hasNext();)
- {
- PolyEdge edge = (PolyEdge) i.next();
- int yindex = (int) (Math.ceil((edge.y0 - firstLineDouble) * AA_SAMPLING));
- //System.err.println("yindex: " + yindex + " for y0: " + edge.y0);
- // Initialize edge's slope and initial xIntersection.
- edge.slope = ((edge.x1 - edge.x0) / (edge.y1 - edge.y0)) / AA_SAMPLING;
- if (edge.y0 == edge.y1) // Horizontal edge.
- edge.xIntersection = Math.min(edge.x0, edge.x1);
- else
- {
- double alignedFirst = Math.ceil(edge.y0 * AA_SAMPLING) / AA_SAMPLING;
- edge.xIntersection = edge.x0 + (edge.slope * AA_SAMPLING) * (alignedFirst - edge.y0);
- }
- //System.err.println(edge);
- // FIXME: Sanity check should not be needed when clipping works.
- if (yindex >= 0 && yindex < edgeTable.length)
- {
- if (edgeTable[yindex] == null) // Create bucket when needed.
- edgeTable[yindex] = new ArrayList();
- edgeTable[yindex].add(edge); // Add edge to the bucket of its line.
- }
- }
-
- // The activeEdges list contains all the edges of the current scanline
- // ordered by their intersection points with this scanline.
- ArrayList activeEdges = new ArrayList();
- PolyEdgeComparator comparator = new PolyEdgeComparator();
-
- // Scan all lines.
- int yindex = 0;
- //System.err.println("firstLine: " + firstLine + ", maxY: " + maxY + ", firstSubline: " + firstSubline);
- for (int y = firstLine; y <= icMaxY; y++)
- {
- int leftX = (int) icMaxX;
- int rightX = (int) icMinX;
- boolean emptyScanline = true;
- for (int subY = firstSubline; subY < AA_SAMPLING; subY++)
- {
- //System.err.println("scanline: " + y + ", subScanline: " + subY);
- ArrayList bucket = edgeTable[yindex];
- // Update all the x intersections in the current activeEdges table
- // and remove entries that are no longer in the scanline.
- for (Iterator i = activeEdges.iterator(); i.hasNext();)
- {
- PolyEdge edge = (PolyEdge) i.next();
- // TODO: Do the following using integer arithmetics.
- if ((y + ((double) subY / (double) AA_SAMPLING)) > edge.y1)
- i.remove();
- else
- {
- edge.xIntersection += edge.slope;
- //System.err.println("edge: " + edge);
- //edge.xIntersection = edge.x0 + edge.slope * (y - edge.y0);
- //System.err.println("edge.xIntersection: " + edge.xIntersection);
- }
- }
-
- if (bucket != null)
- {
- activeEdges.addAll(bucket);
- edgeTable[yindex].clear();
- }
-
- // Sort current edges. We are using a bubble sort, because the order
- // of the intersections will not change in most situations. They
- // will only change, when edges intersect each other.
- int size = activeEdges.size();
- if (size > 1)
- {
- for (int i = 1; i < size; i++)
- {
- PolyEdge e1 = (PolyEdge) activeEdges.get(i - 1);
- PolyEdge e2 = (PolyEdge) activeEdges.get(i);
- if (comparator.compare(e1, e2) > 0)
- {
- // Swap e2 with its left neighbor until it 'fits'.
- int j = i;
- do
- {
- activeEdges.set(j, e1);
- activeEdges.set(j - 1, e2);
- j--;
- if (j >= 1)
- e1 = (PolyEdge) activeEdges.get(j - 1);
- } while (j >= 1 && comparator.compare(e1, e2) > 0);
- }
- }
- }
-
- // Now draw all pixels inside the polygon.
- // This is the last edge that intersected the scanline.
- PolyEdge previous = null; // Gets initialized below.
- boolean insideClip = false;
- boolean insideShape = false;
- //System.err.println("scanline: " + y + ", subscanline: " + subY);
- for (Iterator i = activeEdges.iterator(); i.hasNext();)
- {
- PolyEdge edge = (PolyEdge) i.next();
- if (edge.y1 <= (y + (subY / (double) AA_SAMPLING)))
- continue;
-
- if (insideClip && insideShape)
- {
- // TODO: Use integer arithmetics here.
- if (edge.y1 > (y + (subY / (double) AA_SAMPLING)))
- {
- //System.err.println(edge);
- // TODO: Eliminate the aligments.
- int x0 = (int) Math.min(Math.max(previous.xIntersection, minX), maxX);
- int x1 = (int) Math.min(Math.max(edge.xIntersection, minX), maxX);
- //System.err.println("minX: " + minX + ", x0: " + x0 + ", x1: " + x1 + ", maxX: " + maxX);
- // TODO: Pull out cast.
- int left = x0 - (int) minX;
- int right = x1 - (int) minX + 1;
- alpha[left]++;
- alpha[right]--;
- leftX = Math.min(x0, leftX);
- rightX = Math.max(x1+2, rightX);
- emptyScanline = false;
- }
- }
- previous = edge;
- if (edge.isClip)
- insideClip = ! insideClip;
- else
- insideShape = ! insideShape;
- }
- yindex++;
- }
- firstSubline = 0;
- // Render full scanline.
- //System.err.println("scanline: " + y);
- if (! emptyScanline)
- fillScanlineAA(alpha, leftX, y, rightX - leftX, pCtx, (int) minX);
- }
-
- pCtx.dispose();
- }
/**
* Fills a horizontal line between x0 and x1 for anti aliased rendering.
@@ -2113,7 +1793,6 @@ public abstract class AbstractGraphics2D
cCtx.dispose();
}
-
/**
* Initializes this graphics object. This must be called by subclasses in
* order to correctly initialize the state of this object.
@@ -2121,13 +1800,8 @@ public abstract class AbstractGraphics2D
protected void init()
{
setPaint(Color.BLACK);
- setFont(new Font("SansSerif", Font.PLAIN, 12));
+ setFont(FONT);
isOptimized = true;
-
- // FIXME: Should not be necessary. A clip of null should mean
- // 'clip against device bounds.
- destinationRaster = getDestinationRaster();
- clip = getDeviceBounds();
}
/**
@@ -2267,91 +1941,33 @@ public abstract class AbstractGraphics2D
}
/**
- * Converts the specified shape into a list of segments.
- *
- * @param s the shape to convert
- * @param t the transformation to apply before converting
- * @param deviceBounds an output parameter; holds the bounding rectangle of
- * s in device space after return
- * @param isClip true when the shape is a clip, false for normal shapes;
- * this influences the settings in the created PolyEdge instances.
+ * Returns the ShapeCache for the calling thread.
*
- * @return a list of PolyEdge that form the shape in device space
+ * @return the ShapeCache for the calling thread
*/
- private ArrayList getSegments(Shape s, AffineTransform t,
- Rectangle2D deviceBounds, boolean isClip)
+ private ShapeCache getShapeCache()
{
- // Flatten the path. TODO: Determine the best flattening factor
- // wrt to speed and quality.
- PathIterator path = s.getPathIterator(getTransform(), 1.0);
-
- // Build up polygons and let the native backend render this using
- // rawFillShape() which would provide a default implementation for
- // drawPixel using a PolyScan algorithm.
- double[] seg = new double[6];
-
- // TODO: Use ArrayList<PolyEdge> here when availble.
- ArrayList segs = new ArrayList();
- double segX = 0.; // The start point of the current edge.
- double segY = 0.;
- double polyX = 0.; // The start point of the current polygon.
- double polyY = 0.;
-
- double minX = Integer.MAX_VALUE;
- double maxX = Integer.MIN_VALUE;
- double minY = Integer.MAX_VALUE;
- double maxY = Integer.MIN_VALUE;
-
- //System.err.println("fill polygon");
- while (! path.isDone())
+ ShapeCache sc = shapeCache.get();
+ if (sc == null)
{
- int segType = path.currentSegment(seg);
- minX = Math.min(minX, seg[0]);
- maxX = Math.max(maxX, seg[0]);
- minY = Math.min(minY, seg[1]);
- maxY = Math.max(maxY, seg[1]);
-
- //System.err.println("segment: " + segType + ", " + seg[0] + ", " + seg[1]);
- if (segType == PathIterator.SEG_MOVETO)
- {
- segX = seg[0];
- segY = seg[1];
- polyX = seg[0];
- polyY = seg[1];
- }
- else if (segType == PathIterator.SEG_CLOSE)
- {
- // Close the polyline.
- PolyEdge edge = new PolyEdge(segX, segY,
- polyX, polyY, isClip);
- segs.add(edge);
- }
- else if (segType == PathIterator.SEG_LINETO)
- {
- PolyEdge edge = new PolyEdge(segX, segY,
- seg[0], seg[1], isClip);
- segs.add(edge);
- segX = seg[0];
- segY = seg[1];
- }
- path.next();
+ sc = new ShapeCache();
+ shapeCache.set(sc);
}
- deviceBounds.setRect(minX, minY, maxX - minX, maxY - minY);
- return segs;
+ return sc;
}
/**
- * Returns the ShapeCache for the calling thread.
+ * Returns the scanline converter for this thread.
*
- * @return the ShapeCache for the calling thread
+ * @return the scanline converter for this thread
*/
- private ShapeCache getShapeCache()
+ private ScanlineConverter getScanlineConverter()
{
- ShapeCache sc = (ShapeCache) shapeCache.get();
+ ScanlineConverter sc = scanlineConverters.get();
if (sc == null)
{
- sc = new ShapeCache();
- shapeCache.set(sc);
+ sc = new ScanlineConverter();
+ scanlineConverters.set(sc);
}
return sc;
}
diff --git a/libjava/classpath/gnu/java/awt/java2d/ActiveEdges.java b/libjava/classpath/gnu/java/awt/java2d/ActiveEdges.java
new file mode 100644
index 00000000000..4d1e777ccf5
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/java2d/ActiveEdges.java
@@ -0,0 +1,195 @@
+/* ActiveEdges.java -- A collection of active edges for scanline conversion
+ 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;
+
+/**
+ * A collection of active edges for scanline conversion.
+ */
+final class ActiveEdges
+{
+
+ /**
+ * The active edges. This can contain null values at arbirary locations.
+ * The method #sort() packs this together.
+ */
+ private PolyEdge[] activeEdges;
+
+ /**
+ * The actual number of active edges. The array can be bigger than this
+ * number.
+ */
+ private int numActiveEdges;
+
+ /**
+ * Creates a new ActiveEdges object.
+ */
+ ActiveEdges()
+ {
+ activeEdges = new PolyEdge[8];
+ numActiveEdges = 0;
+ }
+
+ /**
+ * Clears out all active edges. This is cheap as it simply resets the
+ * counter to 0. It does not release all references to PolyEdge instances.
+ */
+ void clear()
+ {
+ numActiveEdges = 0;
+ }
+
+ /**
+ * Adds the specified edge to the list of active edges. This does not yet
+ * sort the edges and therefore does destroy any order of the list.
+ *
+ * @param edge the edge to add
+ */
+ void add(PolyEdge edge)
+ {
+ // Grow array when necessary.
+ int oldSize = activeEdges.length;
+ if (numActiveEdges >= oldSize)
+ {
+ int newSize = oldSize + oldSize / 4 + 1;
+ PolyEdge[] newEdges = new PolyEdge[newSize];
+ System.arraycopy(activeEdges, 0, newEdges, 0, oldSize);
+ activeEdges = newEdges;
+ }
+ activeEdges[numActiveEdges] = edge;
+ numActiveEdges++;
+ }
+
+ /**
+ * Intersects all active edges, sorts them according to their intersection
+ * points and packs the array to remove unneeded edges. This does also
+ * remove any edges that do not intersect the scanline (i.e. they end above
+ * of the scanline).
+ *
+ * @param y the scanline height
+ */
+ void intersectSortAndPack(int n, int y)
+ {
+ // Intersect and pack in one go.
+ int last = 0;
+ PolyEdge tmp;
+ for (int i = 0; i < numActiveEdges; i++)
+ {
+ PolyEdge edge = activeEdges[i];
+ // Clear out edge that ends above the scanline.
+ if (edge != null && edge.y1 >= y)
+ {
+ assert edge.y1 >= y && edge.y0 <= y : "edge must cross scanline";
+ edge.intersect(n, y);
+ activeEdges[last] = edge;
+ last++;
+
+ // Bubble up the added edge.
+ for (int j = last - 1; j > 0; j--)
+ {
+ if (activeEdges[j].xIntersection
+ < activeEdges[j - 1].xIntersection)
+ {
+ tmp = activeEdges[j];
+ activeEdges[j] = activeEdges[j - 1];
+ activeEdges[j - 1] = tmp;
+ }
+ else
+ {
+ // The beginning of the list is already sorted.
+ break;
+ }
+ }
+ }
+ }
+ numActiveEdges = last;
+
+ }
+
+ /**
+ * Returns the number of active edges. This is only reliable after a
+ * call to {@link #intersectSortAndPack(int, int)}.
+ *
+ * @return the number of active edges
+ */
+ int getNumActiveEdges()
+ {
+ return numActiveEdges;
+ }
+
+ /**
+ * Returns the active edge at the position <code>i</code>.
+ *
+ * @param i the index
+ *
+ * @return the active edge at the specified index
+ */
+ PolyEdge getActiveEdge(int i)
+ {
+ return activeEdges[i];
+ }
+
+ /**
+ * Removes all edges that end above the specified height.
+ *
+ * @param y the cut-off height
+ */
+ void remove(int y)
+ {
+ for (int i = 0; i < numActiveEdges; i++)
+ {
+ PolyEdge edge = activeEdges[i];
+ if (edge != null && edge.y1 < y)
+ {
+ activeEdges[i] = null;
+ }
+ }
+ }
+
+ public String toString()
+ {
+ StringBuilder s = new StringBuilder();
+ s.append("[ActiveEdges] ");
+ for (int i = 0; i < numActiveEdges; i++)
+ {
+ s.append(activeEdges[i]);
+ s.append(',');
+ }
+ return s.toString();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/java2d/PolyEdge.java b/libjava/classpath/gnu/java/awt/java2d/PolyEdge.java
index 6c3b546881a..eb0cc7f8f3e 100644
--- a/libjava/classpath/gnu/java/awt/java2d/PolyEdge.java
+++ b/libjava/classpath/gnu/java/awt/java2d/PolyEdge.java
@@ -38,31 +38,38 @@ exception statement from your version. */
package gnu.java.awt.java2d;
+import gnu.java.math.Fixed;
+
/**
- * An edge in a polygon. This is used by the scanline conversion algorithm
- * implemented in {@link AbstractGraphics2D#rawFillShape}.
+ * An edge in a polygon.
*
* @author Roman Kennke (kennke@aicas.com)
*/
-public class PolyEdge
+final class PolyEdge
implements Comparable
{
/**
* The start and end coordinates of the edge. y0 is always smaller or equal
* than y1.
+ *
+ * These values are stored as fixed-point decimals.
*/
- public double x0, y0, x1, y1;
+ public int x0, y0, x1, y1;
/**
* The slope of the edge. This is dx / dy.
+ *
+ * This is a fixed point decimal.
*/
- double slope;
+ private int slope;
/**
* The intersection of this edge with the current scanline.
+ *
+ * This is a fixed point decimal.
*/
- double xIntersection;
+ int xIntersection;
/**
* Indicates whether this edge is from the clip or from the target shape.
@@ -70,6 +77,24 @@ public class PolyEdge
boolean isClip;
/**
+ * Implements a linked list for the edge pool.
+ */
+ PolyEdge poolNext;
+
+ /**
+ * Implements a linked list for the scanline edge lists.
+ */
+ PolyEdge scanlineNext;
+
+ /**
+ * Create an uninitialized edge.
+ */
+ PolyEdge()
+ {
+ // Nothing to do here.
+ }
+
+ /**
* Creates a new PolyEdge with the specified coordinates.
*
* @param x0 the starting point, x coordinate
@@ -77,7 +102,20 @@ public class PolyEdge
* @param x1 the end point, x coordinate
* @param y1 the end point, y coordinate
*/
- PolyEdge(double x0, double y0, double x1, double y1, boolean clip)
+ PolyEdge(int n, int x0, int y0, int x1, int y1, boolean clip)
+ {
+ init(n, x0, y0, x1, y1, clip);
+ }
+
+ /**
+ * (Re-) Initializes this edge.
+ *
+ * @param x0
+ * @param y0
+ * @param x1
+ * @param y1
+ */
+ void init(int n, int x0, int y0, int x1, int y1, boolean clip)
{
isClip = clip;
if (y0 < y1)
@@ -94,11 +132,7 @@ public class PolyEdge
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);
+ slope = Fixed.div(n, this.x1 - this.x0, this.y1 - this.y0);
}
/**
@@ -115,6 +149,19 @@ public class PolyEdge
return comp;
}
+ /**
+ * Intersects this edge with the scanline at height y. The result is
+ * stored in {@link #xIntersection}.
+ *
+ * @param y the scanline
+ */
+ void intersect(int n, int y)
+ {
+ int dy = y - y0;
+ int dx = Fixed.mul(n, slope, dy);
+ xIntersection = x0 + dx;
+ }
+
public String toString()
{
return "Edge: " + x0 + ", " + y0 + ", " + x1 + ", " + y1 + ", slope: "
diff --git a/libjava/classpath/gnu/java/awt/java2d/Scanline.java b/libjava/classpath/gnu/java/awt/java2d/Scanline.java
new file mode 100644
index 00000000000..24c3d34d5c3
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/java2d/Scanline.java
@@ -0,0 +1,91 @@
+/* Scanline.java -- A scanline for the scanline converter
+ 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;
+
+/**
+ * Represents a scanline in the {@link ScanlineConverter}. This is basically
+ * a sorted list of {@link PolyEdge}s that is made for maximum reuse.
+ */
+class Scanline
+{
+
+ /**
+ * The actual edges array. The fields can be null.
+ */
+ private PolyEdge edges;
+
+ /**
+ * Clears this scanline. This only resets the number of edges to 0. The
+ * actual PolyEdge objects are preserved for possible later reuse.
+ */
+ void clear()
+ {
+ edges = null;
+ }
+
+ /**
+ * Create a new Scanline.
+ */
+ Scanline()
+ {
+ // Nothing to do.
+ }
+
+ /**
+ * Inserts an edge into this scanline. This is performed in a sorted fashion,
+ * and so that it reuses as much existing resources as possible.
+ */
+ void addEdge(PolyEdge edge)
+ {
+
+ // Allocate PolyEdge when necessary or reuse an old one.
+ edge.scanlineNext = edges;
+ edges = edge;
+ }
+
+ /**
+ * Returns the edges queue.
+ *
+ * @return the edges queue
+ */
+ PolyEdge getEdges()
+ {
+ return edges;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/java2d/ScanlineConverter.java b/libjava/classpath/gnu/java/awt/java2d/ScanlineConverter.java
new file mode 100644
index 00000000000..9f9d8921f59
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/java2d/ScanlineConverter.java
@@ -0,0 +1,404 @@
+/* ScanlineConverter.java -- Rasterizes Shapes
+ 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 gnu.java.math.Fixed;
+
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.PathIterator;
+
+/**
+ * Rasterizes {@link Shape} objects on an AbstractGraphics2D.
+ */
+final class ScanlineConverter
+{
+
+ /**
+ * The number of digits to use for fixed point arithmetics.
+ */
+ private static int FIXED_DIGITS = 6;
+
+ /**
+ * The fixed value for the number 1.
+ */
+ private static int ONE = Fixed.fixedValue(FIXED_DIGITS, 1);
+
+ /**
+ * The actual number of scanlines.
+ */
+ private int numScanlines;
+
+ /**
+ * The number of scanlines. This can contain more elements than we have
+ * scanlines. The real number of scanlines is stored in
+ * {@link #numScanlines}. This can also contain null values for empty
+ * scanlines.
+ */
+ private Scanline[] scanlines;
+
+ /**
+ * The upper bounds which correspond to the index 0 in the scanline array.
+ *
+ * This is a fixed point value.
+ */
+ private int upperBounds;
+
+ /**
+ * The resolution of the scanline converter.
+ *
+ * This is a fixed point value.
+ */
+ private int resolution;
+
+ /**
+ * One half step according to the resolution. This is stored to avoid
+ * unnecessary operations during rendering.
+ */
+ private int halfStep;
+
+ /**
+ * This is used in {@link #addShape(PathIterator, boolean)} to
+ * receive the coordinates of the path.
+ */
+ private float[] coords;
+
+ /**
+ * The active edges.
+ */
+ private ActiveEdges activeEdges;
+
+ private PolyEdge edgePool;
+ private PolyEdge edgePoolLast;
+
+ private int minY;
+ private int maxY;
+
+ /**
+ * Create a new ScanlineConverter.
+ */
+ ScanlineConverter()
+ {
+ scanlines = new Scanline[10];
+ coords = new float[6];
+ activeEdges = new ActiveEdges();
+ edgePool = new PolyEdge();
+ edgePoolLast = edgePool;
+ }
+
+ /**
+ * Renders the specified shape using the specified clip and transform.
+ *
+ * @param shape the shape to render
+ * @param clip the clip
+ * @param trans the transform
+ */
+ void renderShape(AbstractGraphics2D g, Shape shape, Shape clip,
+ AffineTransform trans, int res)
+ {
+ // Prepare resolution and upper bounds.
+ clear();
+ setResolution(res);
+
+ boolean haveClip = clip != null;
+
+ // Add shapes.
+ PathIterator path = shape.getPathIterator(trans, resolution);
+ addShape(path, false);
+ if (haveClip)
+ {
+ path= clip.getPathIterator(trans, resolution);
+ addShape(path, true);
+ }
+
+ setUpperBounds(minY);
+
+ PolyEdge edge = edgePool;
+ while (edge != edgePoolLast)
+ {
+ addEdge(edge);
+ edge = edge.poolNext;
+ }
+
+ int y = upperBounds;
+ int lastIndex = scanlineIndex(y - resolution);
+ int index;
+ activeEdges.clear();
+ // The render loop...
+ Scanline scanline = null;
+ while (y <= maxY)
+ {
+ // First we put together our list of active edges.
+ index = scanlineIndex(y);
+ // If we go outside the scanline array we still need to render the
+ // remaining edges until they end.
+ scanline = index < scanlines.length ? scanlines[index] : null;
+ if (scanline != null)
+ {
+ edge = scanline.getEdges();
+ while (edge != null)
+ {
+ activeEdges.add(edge);
+ edge = edge.scanlineNext;
+ }
+ }
+
+ // Then we intersect all active edges with the current scanline
+ // and sort them according to their intersection points.
+ activeEdges.intersectSortAndPack(FIXED_DIGITS, y + halfStep);
+
+ // Ok, now we can perform the actual scanlining.
+ boolean push = lastIndex != index;
+ doScanline(g, y, push, haveClip);
+
+ // Remove obsolete active edges.
+ //activeEdges.remove(y + halfStep);
+
+ // Go on with the next line...
+ y += resolution;
+ lastIndex = index;
+ }
+ }
+
+ /**
+ * Clears all scanlines.
+ */
+ private void clear()
+ {
+ // Reset edge pool.
+ edgePoolLast = edgePool;
+
+ // Reset scanlines.
+ for (int i = scanlines.length - 1; i >= 0 ; i--)
+ {
+ Scanline sl = scanlines[i];
+ if (sl != null)
+ sl.clear();
+ }
+
+ // Reset bounds.
+ minY = Integer.MAX_VALUE;
+ maxY = Integer.MIN_VALUE;
+ }
+
+ /**
+ * Performs the scanlining on the current set of active edges.
+ */
+ private void doScanline(AbstractGraphics2D g, int y, boolean push,
+ boolean haveClip)
+ {
+ // We begin outside the clip and outside the shape. We only draw when
+ // we are inside the clip AND inside the shape.
+ boolean inClip = ! haveClip;
+ boolean inShape = false;
+ PolyEdge lastEdge = null;
+ int numEdges = activeEdges.getNumActiveEdges();
+ for (int i = 0; i < numEdges; i++)
+ {
+ PolyEdge edge = activeEdges.getActiveEdge(i);
+ if (inClip && inShape)
+ {
+ assert lastEdge != null;
+ int x0 = lastEdge.xIntersection;
+ int x1 = edge.xIntersection;
+ assert x0 <= x1;
+ if (push)
+ {
+ if (resolution == ONE)
+ {
+ // Non-AA rendering.
+ g.fillScanline(Fixed.intValue(FIXED_DIGITS, x0),
+ Fixed.intValue(FIXED_DIGITS, x1 - resolution),
+ Fixed.intValue(FIXED_DIGITS, y));
+ }
+ else
+ {
+ // AA rendering.
+ // FIXME: Implement.
+ System.err.println("Implement AA rendering.");
+ }
+ }
+ }
+ if (edge.isClip)
+ inClip = ! inClip;
+ else
+ inShape = ! inShape;
+
+ lastEdge = edge;
+ }
+ }
+
+ /**
+ * Sets the resolution. A value of 0 rasterizes the shape normally without
+ * anti-aliasing. Greater values renders with a resolution of 2 ^ res.
+ *
+ * @param res the resolution
+ */
+ private void setResolution(int res)
+ {
+ int one = Fixed.fixedValue(FIXED_DIGITS, 1);
+ resolution = one / (1 << res);
+ halfStep = resolution / 2;
+ }
+
+ /**
+ * Sets the vertical bounds of that shape that is beeing rendered.
+ *
+ * @param y0 the upper bounds
+ */
+ private void setUpperBounds(int y0)
+ {
+ upperBounds = fit(y0);
+ }
+
+ /**
+ * Add a shape to the scanline converter.
+ *
+ * @param path
+ * @param clip
+ */
+ private void addShape(PathIterator path, boolean clip)
+ {
+ int startX = 0;
+ int startY = 0;
+ int lastX = 0;
+ int lastY = 0;
+ while (! path.isDone())
+ {
+ int type = path.currentSegment(coords);
+ switch (type)
+ {
+ case PathIterator.SEG_MOVETO:
+ startX = lastX = Fixed.fixedValue(FIXED_DIGITS, coords[0]);
+ startY = lastY = Fixed.fixedValue(FIXED_DIGITS, coords[1]);
+ minY = Math.min(startY, minY);
+ maxY = Math.max(startY, maxY);
+ break;
+ case PathIterator.SEG_LINETO:
+ int x = Fixed.fixedValue(FIXED_DIGITS, coords[0]);
+ int y = Fixed.fixedValue(FIXED_DIGITS, coords[1]);
+ edgePoolAdd(lastX, lastY, x, y, clip);
+ lastX = x;
+ lastY = y;
+ minY = Math.min(lastY, minY);
+ maxY = Math.max(lastY, maxY);
+ break;
+ case PathIterator.SEG_CLOSE:
+ edgePoolAdd(lastX, lastY, startX, startY, clip);
+ lastX = startX;
+ lastY = startY;
+ break;
+ case PathIterator.SEG_CUBICTO:
+ case PathIterator.SEG_QUADTO:
+ default:
+ assert false;
+ }
+ path.next();
+ }
+ }
+
+ /**
+ * Adds an edge into the scanline array.
+ */
+ private void addEdge(PolyEdge edge)
+ {
+ // Determine index.
+ int upper = Math.min(edge.y0, edge.y1);
+ // Fit to raster.
+ int index = scanlineIndex(upper);
+ // Grow array when necessary.
+ if (index >= scanlines.length)
+ {
+ int oldSize = scanlines.length;
+ int newSize = Math.max(oldSize + oldSize / 2 + 1, index + 10);
+ Scanline[] newScanlines = new Scanline[newSize];
+ System.arraycopy(scanlines, 0, newScanlines, 0, oldSize);
+ scanlines = newScanlines;
+ }
+
+ // Add edge.
+ if (scanlines[index] == null)
+ {
+ scanlines[index] = new Scanline();
+ }
+ scanlines[index].addEdge(edge);
+ }
+
+ /**
+ * Fits an Y coordinate to the grid.
+ *
+ * @param y the Y coordinate to fit
+ *
+ * @return the fitted Y coordinate
+ */
+ private int fit(int y)
+ {
+ int val1 = Fixed.div(FIXED_DIGITS, y, resolution);
+ int rounded = Fixed.round(FIXED_DIGITS, val1);
+ return Fixed.div(FIXED_DIGITS, rounded, resolution);
+ }
+
+ /**
+ * Calculates the scanline index for the specified y coordinate.
+ *
+ * @param y the y coordinate as fixed point value
+ *
+ * @return the scanline index
+ */
+ private int scanlineIndex(int y)
+ {
+ int fitted = fit(y);
+ // Cleverly skip the fixed point conversions here.
+ return (fitted - upperBounds)/ resolution;
+ }
+
+ private void edgePoolAdd(int x0, int y0, int x1, int y1, boolean clip)
+ {
+ // Don't need no horizontal edges.
+ if (y0 != y1)
+ {
+ edgePoolLast.init(FIXED_DIGITS, x0, y0, x1, y1, clip);
+ if (edgePoolLast.poolNext == null)
+ {
+ edgePoolLast.poolNext = new PolyEdge();
+ }
+ edgePoolLast = edgePoolLast.poolNext;
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/ClasspathDesktopPeer.java b/libjava/classpath/gnu/java/awt/peer/ClasspathDesktopPeer.java
new file mode 100644
index 00000000000..bef42dcea34
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/ClasspathDesktopPeer.java
@@ -0,0 +1,301 @@
+/* ClasspathDesktopPeer.java -- Offers a concrete implementation for DesktopPeer
+ Copyright (C) 2006, 2007 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;
+
+import java.awt.AWTPermission;
+import java.awt.Desktop.Action;
+import java.awt.peer.DesktopPeer;
+
+import java.io.File;
+import java.io.IOException;
+
+import java.net.URI;
+
+import java.util.prefs.Preferences;
+
+/**
+ * Offers a common implementation for the Desktop peers, that enables
+ * access to default system application within java processes.
+ *
+ * @author Mario Torre <neugens@limasoftware.net>
+ */
+public class ClasspathDesktopPeer
+ implements DesktopPeer
+{
+ /** This is the fallback browser, if no desktop was detected. */
+ protected static final String _DEFAULT_BROWSER = "firefox";
+
+ /** gnu.java.awt.peer.Desktop.html.command */
+ protected static final String _BROWSE = "html";
+
+ /** gnu.java.awt.peer.Desktop.mail.command */
+ protected static final String _MAIL = "mail";
+
+ /** gnu.java.awt.peer.Desktop.edit.command */
+ protected static final String _EDIT = "edit";
+
+ /** gnu.java.awt.peer.Desktop.print.command */
+ protected static final String _PRINT = "print";
+
+ /** gnu.java.awt.peer.Desktop.open.command */
+ protected static final String _OPEN = "open";
+
+ /** */
+ protected static final KDEDesktopPeer kde = new KDEDesktopPeer();
+
+ /** */
+ protected static final GnomeDesktopPeer gnome = new GnomeDesktopPeer();
+
+ /** */
+ protected static final ClasspathDesktopPeer classpath =
+ new ClasspathDesktopPeer();
+
+ /**
+ * Preference subsystem. Packagers and users can override the default
+ * behaviour of this class via preferences and system properties.
+ */
+ protected Preferences prefs =
+ Preferences.userNodeForPackage(ClasspathDesktopPeer.class).node("Desktop");
+
+ /**
+ * @param target
+ */
+ protected ClasspathDesktopPeer()
+ {
+ /* nothing to do */
+ }
+
+ public boolean isSupported(Action action)
+ {
+ String check = null;
+
+ switch(action)
+ {
+ case BROWSE:
+ check = _BROWSE;
+ break;
+
+ case MAIL:
+ check = _MAIL;
+ break;
+
+ case EDIT:
+ check = _EDIT;
+ break;
+
+ case PRINT:
+ check = _PRINT;
+ break;
+
+ case OPEN: default:
+ check = _OPEN;
+ break;
+ }
+
+ return this.supportCommand(check);
+ }
+
+ public void browse(URI url) throws IOException
+ {
+ checkPermissions();
+
+ String browser = getCommand(_BROWSE);
+
+ if (browser == null)
+ throw new UnsupportedOperationException();
+
+ browser = browser + " " + url.toString();
+
+ Runtime.getRuntime().exec(browser);
+ }
+
+ public void edit(File file) throws IOException
+ {
+ checkPermissions(file, false);
+
+ String edit = getCommand(_EDIT);
+
+ if (edit == null)
+ throw new UnsupportedOperationException();
+
+ edit = edit + " " + file.getAbsolutePath();
+ Runtime.getRuntime().exec(edit);
+ }
+
+ public void mail(URI mailtoURL) throws IOException
+ {
+ checkPermissions();
+
+ String scheme = mailtoURL.getScheme();
+ if (scheme == null || !scheme.equalsIgnoreCase("mailto"))
+ throw new IllegalArgumentException("URI Scheme not of type mailto");
+
+ String mail = getCommand(_MAIL);
+
+ if (mail == null)
+ throw new UnsupportedOperationException();
+
+ mail = mail + " " + mailtoURL.toString();
+
+ Runtime.getRuntime().exec(mail);
+ }
+
+ public void mail() throws IOException
+ {
+ checkPermissions();
+
+ String mail = getCommand(_MAIL);
+
+ if (mail == null)
+ throw new UnsupportedOperationException();
+
+ Runtime.getRuntime().exec(mail);
+ }
+
+ public void open(File file) throws IOException
+ {
+ checkPermissions(file, true);
+
+ String open = getCommand(_OPEN);
+
+ if (open == null)
+ throw new UnsupportedOperationException();
+
+ open = open + " " + file.getAbsolutePath();
+ Runtime.getRuntime().exec(open);
+ }
+
+ public void print(File file) throws IOException
+ {
+ checkPrintPermissions(file);
+
+ String print = getCommand(_PRINT);
+
+ if (print == null)
+ throw new UnsupportedOperationException();
+
+ print = print + " " + file.getAbsolutePath();
+ Runtime.getRuntime().exec(print);
+ }
+
+ protected String getCommand(String action)
+ {
+ // check if a system property exist
+ String command =
+ System.getProperty("gnu.java.awt.peer.Desktop." + action + ".command");
+
+ // otherwise, get it from preferences, if any
+ if (command == null)
+ {
+ command = prefs.node(action).get("command", null);
+ }
+
+ return command;
+ }
+
+ /**
+ * Note: Checks for AWTPermission("showWindowWithoutWarningBanner") only.
+ */
+ protected void checkPermissions()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new AWTPermission("showWindowWithoutWarningBanner"));
+ }
+ }
+
+ /**
+ * Calls checkPermissions() and checks for SecurityManager.checkRead()
+ * and, if readOnly is false, for SecurityManager.checkWrite()
+ */
+ protected void checkPermissions(File file, boolean readOnly)
+ {
+ checkPermissions();
+
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkRead(file.toString());
+ if (!readOnly) sm.checkWrite(file.toString());
+ }
+ }
+
+ /**
+ * Calls checkPermissions(file, true) and checks for
+ * SecurityManager.checkPrintJobAccess()
+ */
+ protected void checkPrintPermissions(File file)
+ {
+ checkPermissions(file, true);
+
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPrintJobAccess();
+ }
+ }
+
+ /**
+ * @param check
+ * @return
+ */
+ protected boolean supportCommand(String check)
+ {
+ return ((this.getCommand(check) != null) ? true : false);
+ }
+
+ /**
+ * @return
+ */
+ public static DesktopPeer getDesktop()
+ {
+ // check if we are under Gnome or KDE or anything else
+ String desktopSession = System.getenv("GNOME_DESKTOP_SESSION_ID");
+ if (desktopSession == null)
+ {
+ desktopSession = System.getenv("KDE_FULL_SESSION");
+ if (desktopSession != null)
+ return kde;
+ }
+ else
+ {
+ return gnome;
+ }
+
+ // revert to this class for default values
+ return classpath;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/ClasspathFontPeer.java b/libjava/classpath/gnu/java/awt/peer/ClasspathFontPeer.java
index 2176f34a5f1..60fde2557ac 100644
--- a/libjava/classpath/gnu/java/awt/peer/ClasspathFontPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/ClasspathFontPeer.java
@@ -54,6 +54,7 @@ import java.awt.peer.FontPeer;
import java.text.AttributedCharacterIterator;
import java.text.CharacterIterator;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
@@ -120,6 +121,23 @@ public abstract class ClasspathFontPeer
*/
protected AffineTransform transform;
+ static class LRUCache<K,V> extends LinkedHashMap<K,V>
+ {
+ int max_entries;
+ public LRUCache(int max)
+ {
+ super(max, 0.75f, true);
+ max_entries = max;
+ }
+ protected boolean removeEldestEntry(Map.Entry eldest)
+ {
+ return size() > max_entries;
+ }
+ }
+
+ private static LRUCache<AffineTransform,TransformAttribute> transCache =
+ new LRUCache<AffineTransform,TransformAttribute>(50);
+
protected static ClasspathToolkit tk()
{
return (ClasspathToolkit)(Toolkit.getDefaultToolkit ());
@@ -200,7 +218,19 @@ public abstract class ClasspathFontPeer
protected static void copyTransformToAttrs (AffineTransform trans, Map attrs)
{
if (trans != null)
- attrs.put(TextAttribute.TRANSFORM, new TransformAttribute (trans));
+ {
+ TransformAttribute ta;
+ synchronized(transCache)
+ {
+ ta = transCache.get(trans);
+ if (ta == null)
+ {
+ ta = new TransformAttribute(trans);
+ transCache.put(trans, ta);
+ }
+ }
+ attrs.put(TextAttribute.TRANSFORM, ta);
+ }
}
diff --git a/libjava/classpath/gnu/java/awt/peer/GnomeDesktopPeer.java b/libjava/classpath/gnu/java/awt/peer/GnomeDesktopPeer.java
new file mode 100644
index 00000000000..be216318140
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/GnomeDesktopPeer.java
@@ -0,0 +1,153 @@
+/* GnomeDesktopPeer.java -- Offers a GNOME Desktop peer for DesktopPeer
+ Copyright (C) 2006, 2007 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;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+
+/**
+ * @author Mario Torre <neugens@limasoftware.net>
+ */
+public class GnomeDesktopPeer
+ extends ClasspathDesktopPeer
+{
+ /**
+ * Query string to use if a GNOME desktop is detected to get the name of the
+ * default browser. This requires gconftool-2 (part of GNOME).
+ */
+ private static final String BROWSER_QUERY_GNOME =
+ "gconftool-2 -g /desktop/gnome/url-handlers/http/command";
+
+ protected String getCommand(String action)
+ {
+ // check if a command already exists
+ String command = super.getCommand(action);
+
+ if (command == null)
+ {
+ try
+ {
+ if (action == _BROWSE)
+ {
+ command = execQuery(BROWSER_QUERY_GNOME);
+ }
+ else if (action == _PRINT)
+ {
+ command = null;
+ }
+ else
+ {
+ command = "gnome-open";
+ }
+ }
+ catch (Exception e)
+ {
+ command = null;
+ }
+ }
+
+ return command;
+ }
+
+ public void browse(URI url) throws IOException
+ {
+ checkPermissions();
+
+ String browser = getCommand(_BROWSE);
+
+ if (browser == null)
+ throw new UnsupportedOperationException();
+
+ browser = browser + " " + url.toString();
+
+ Runtime.getRuntime().exec(browser);
+ }
+
+ protected boolean supportCommand(String check)
+ {
+ if (check == _PRINT)
+ {
+ return super.supportCommand(check);
+ }
+
+ return true;
+ }
+
+ public void mail() throws IOException
+ {
+ checkPermissions();
+
+ String mail = getCommand(_MAIL);
+
+ if (mail == null)
+ throw new UnsupportedOperationException();
+
+ Runtime.getRuntime().exec(mail + " mailto:");
+ }
+
+ protected String execQuery(String command) throws IOException
+ {
+ InputStream in = null;
+ StringBuilder output = new StringBuilder();
+
+ try
+ {
+ Process process = Runtime.getRuntime().exec(command);
+
+ // Get the input stream and read from it
+ in = process.getInputStream();
+ int c;
+ while ((c = in.read()) != - 1)
+ {
+ output.append((char) c);
+ }
+ }
+ finally
+ {
+ if (in != null)
+ in.close();
+ }
+
+ // remove %s from the string, leave only the command line
+ int index = output.indexOf("%s");
+ output.delete(index, index + 1);
+
+ return output.toString().trim();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/KDEDesktopPeer.java b/libjava/classpath/gnu/java/awt/peer/KDEDesktopPeer.java
new file mode 100644
index 00000000000..676bd891758
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/KDEDesktopPeer.java
@@ -0,0 +1,135 @@
+/* GnomeDesktopPeer.java -- Offers a KDE Desktop peer for DesktopPeer
+ Copyright (C) 2006, 2007 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;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+
+/**
+ * @author Mario Torre <neugens@limasoftware.net>
+ */
+public class KDEDesktopPeer
+ extends ClasspathDesktopPeer
+{
+ /**
+ * Query string to use if a GNOME desktop is detected to get the name of the
+ * default browser. This requires gconftool-2 (part of GNOME).
+ */
+ private static final String BROWSER_QUERY_GNOME =
+ "gconftool-2 -g /desktop/gnome/url-handlers/http/command";
+
+ protected String getCommand(String action)
+ {
+ // check if a command already exists
+ String command = super.getCommand(action);
+
+ if (command == null)
+ {
+ try
+ {
+ if (action == _MAIL)
+ {
+ command = "kfmclient exec";
+ }
+ else if (action == _PRINT)
+ {
+ command = "kprinter";
+ }
+ else
+ {
+ command = "kfmclient openURL";
+ }
+ }
+ catch (Exception e)
+ {
+ command = null;
+ }
+ }
+
+ return command;
+ }
+
+ protected boolean supportCommand(String check)
+ {
+ return true;
+ }
+
+ public void mail() throws IOException
+ {
+ checkPermissions();
+
+ String mail = getCommand(_MAIL);
+
+ if (mail == null)
+ throw new UnsupportedOperationException();
+
+ Runtime.getRuntime().exec(mail + " 'mailto: '");
+ }
+
+ protected String execQuery(String command) throws IOException
+ {
+ InputStream in = null;
+ StringBuilder output = new StringBuilder();
+
+ try
+ {
+ Process process = Runtime.getRuntime().exec(command);
+
+ // Get the input stream and read from it
+ in = process.getInputStream();
+ int c;
+ while ((c = in.read()) != - 1)
+ {
+ output.append((char) c);
+ }
+ }
+ finally
+ {
+ if (in != null)
+ in.close();
+ }
+
+ // remove %s from the string, leave only the command line
+ int index = output.indexOf("%s");
+ output.delete(index, index + 1);
+
+ return output.toString().trim();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/AsyncImage.java b/libjava/classpath/gnu/java/awt/peer/gtk/AsyncImage.java
index 5238bfe7410..dad537aa748 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/AsyncImage.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/AsyncImage.java
@@ -61,11 +61,11 @@ public class AsyncImage
private class NullImageSource
implements ImageProducer
{
- private ArrayList consumers;
+ private ArrayList<ImageConsumer> consumers;
NullImageSource()
{
- consumers = new ArrayList();
+ consumers = new ArrayList<ImageConsumer>();
}
public void addConsumer(ImageConsumer ic)
@@ -145,14 +145,14 @@ public class AsyncImage
*
* This is package private to avoid accessor methods.
*/
- HashSet observers;
+ HashSet<ImageObserver> observers;
/**
* Creates a new AsyncImage that loads from the specified URL.
*/
AsyncImage(URL url)
{
- observers = new HashSet();
+ observers = new HashSet<ImageObserver>();
Loader l = new Loader(url);
Thread t = new Thread(l);
t.start();
@@ -221,7 +221,7 @@ public class AsyncImage
{
// This field gets null when image loading is complete and we don't
// need to store any more observers.
- HashSet observs = observers;
+ HashSet<ImageObserver> observs = observers;
if (observs != null)
{
observs.add(obs);
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/BufferedImageGraphics.java b/libjava/classpath/gnu/java/awt/peer/gtk/BufferedImageGraphics.java
index c792645d3e8..31c5e641ec8 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/BufferedImageGraphics.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/BufferedImageGraphics.java
@@ -40,6 +40,7 @@ package gnu.java.awt.peer.gtk;
import java.awt.AlphaComposite;
import java.awt.Color;
+import java.awt.Composite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
@@ -49,7 +50,6 @@ import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
-import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
@@ -75,12 +75,6 @@ public class BufferedImageGraphics extends CairoGraphics2D
private BufferedImage image, buffer;
/**
- * Allows us to lock the image from updates (if we want to perform a few
- * intermediary operations on the cairo surface, then update it all at once)
- */
- private boolean locked;
-
- /**
* Image size.
*/
private int imageWidth, imageHeight;
@@ -93,7 +87,8 @@ public class BufferedImageGraphics extends CairoGraphics2D
/**
* Cache BufferedImageGraphics surfaces.
*/
- static WeakHashMap bufferedImages = new WeakHashMap();
+ static WeakHashMap<BufferedImage, CairoSurface> bufferedImages
+ = new WeakHashMap<BufferedImage, CairoSurface>();
/**
* Its corresponding cairo_t.
@@ -109,30 +104,30 @@ public class BufferedImageGraphics extends CairoGraphics2D
this.image = bi;
imageWidth = bi.getWidth();
imageHeight = bi.getHeight();
- locked = false;
if (!(image.getSampleModel() instanceof SinglePixelPackedSampleModel))
hasFastCM = false;
else if(bi.getColorModel().equals(CairoSurface.cairoCM_opaque))
{
- hasFastCM = true;
- hasAlpha = false;
+ hasFastCM = true;
+ hasAlpha = false;
}
- else if(bi.getColorModel().equals(CairoSurface.cairoColorModel))
+ else if(bi.getColorModel().equals(CairoSurface.cairoColorModel)
+ || bi.getColorModel().equals(CairoSurface.cairoCM_pre))
{
- hasFastCM = true;
- hasAlpha = true;
+ hasFastCM = true;
+ hasAlpha = true;
}
else
hasFastCM = false;
// Cache surfaces.
if( bufferedImages.get( bi ) != null )
- surface = (CairoSurface)bufferedImages.get( bi );
+ surface = bufferedImages.get( bi );
else
{
- surface = new CairoSurface( imageWidth, imageHeight );
- bufferedImages.put(bi, surface);
+ surface = new CairoSurface( imageWidth, imageHeight );
+ bufferedImages.put(bi, surface);
}
cairo_t = surface.newCairoContext();
@@ -148,10 +143,7 @@ public class BufferedImageGraphics extends CairoGraphics2D
int minY = image.getRaster().getSampleModelTranslateY();
// Pull pixels directly out of data buffer
- if(raster instanceof CairoSurface)
- pixels = ((CairoSurface)raster).getPixels(raster.getWidth() * raster.getHeight());
- else
- pixels = ((DataBufferInt)raster.getDataBuffer()).getData();
+ pixels = ((DataBufferInt)raster.getDataBuffer()).getData();
// Discard pixels that fall outside of the image's bounds
// (ie, this image is actually a subimage of a different image)
@@ -161,7 +153,8 @@ public class BufferedImageGraphics extends CairoGraphics2D
int scanline = sm.getScanlineStride();
for (int i = 0; i < imageHeight; i++)
- System.arraycopy(pixels, (i - minY) * scanline - minX, pixels2, i * imageWidth, imageWidth);
+ System.arraycopy(pixels, (i - minY) * scanline - minX, pixels2,
+ i * imageWidth, imageWidth);
pixels = pixels2;
}
@@ -173,11 +166,13 @@ public class BufferedImageGraphics extends CairoGraphics2D
}
else
{
- pixels = CairoGraphics2D.findSimpleIntegerArray(image.getColorModel(),image.getData());
+ pixels = CairoGraphics2D.findSimpleIntegerArray(image.getColorModel(),
+ image.getData());
+ if (pixels != null)
+ System.arraycopy(pixels, 0, surface.getData(),
+ 0, pixels.length);
}
- surface.setPixels( pixels );
-
setup( cairo_t );
setClip(0, 0, imageWidth, imageHeight);
}
@@ -189,7 +184,6 @@ public class BufferedImageGraphics extends CairoGraphics2D
cairo_t = surface.newCairoContext();
imageWidth = copyFrom.imageWidth;
imageHeight = copyFrom.imageHeight;
- locked = false;
hasFastCM = copyFrom.hasFastCM;
hasAlpha = copyFrom.hasAlpha;
@@ -202,17 +196,14 @@ public class BufferedImageGraphics extends CairoGraphics2D
*/
private void updateBufferedImage(int x, int y, int width, int height)
{
- if (locked)
- return;
-
- double[] points = new double[]{x, y, width+x, height+y};
- transform.transform(points, 0, points, 0, 2);
- x = (int)points[0];
- y = (int)points[1];
- width = (int)Math.ceil(points[2] - points[0]);
- height = (int)Math.ceil(points[3] - points[1]);
+ Rectangle bounds = new Rectangle(x, y, width, height);
+ bounds = getTransformedBounds(bounds, transform).getBounds();
+ x = bounds.x;
+ y = bounds.y;
+ width = bounds.width;
+ height = bounds.height;
- int[] pixels = surface.getPixels(imageWidth * imageHeight);
+ int[] pixels = surface.getData();
if( x > imageWidth || y > imageHeight )
return;
@@ -403,14 +394,10 @@ public class BufferedImageGraphics extends CairoGraphics2D
BufferedImage bImg = (BufferedImage) img;
// Find translated bounds
- Point2D origin = new Point2D.Double(bImg.getMinX(), bImg.getMinY());
- Point2D pt = new Point2D.Double(bImg.getWidth() + bImg.getMinX(),
- bImg.getHeight() + bImg.getMinY());
+ Rectangle2D bounds = new Rectangle(bImg.getMinX(), bImg.getMinY(),
+ bImg.getWidth(), bImg.getHeight());
if (xform != null)
- {
- origin = xform.transform(origin, origin);
- pt = xform.transform(pt, pt);
- }
+ bounds = getTransformedBounds(bounds, xform);
// Create buffer and draw image
createBuffer();
@@ -420,10 +407,7 @@ public class BufferedImageGraphics extends CairoGraphics2D
g2d.drawImage(img, xform, obs);
// Perform compositing
- return drawComposite(new Rectangle2D.Double(origin.getX(),
- origin.getY(),
- pt.getX(), pt.getY()),
- obs);
+ return drawComposite(bounds, obs);
}
}
@@ -438,6 +422,11 @@ public class BufferedImageGraphics extends CairoGraphics2D
if (comp == null || comp instanceof AlphaComposite)
{
super.drawGlyphVector(gv, x, y);
+
+ // this returns an integer-based Rectangle (rather than a
+ // Rectangle2D), which takes care of any necessary rounding for us.
+ bounds = bounds.getBounds();
+
updateBufferedImage((int)bounds.getX(), (int)bounds.getY(),
(int)bounds.getWidth(), (int)bounds.getHeight());
}
@@ -468,12 +457,7 @@ public class BufferedImageGraphics extends CairoGraphics2D
private boolean drawComposite(Rectangle2D bounds, ImageObserver observer)
{
// Find bounds in device space
- double[] points = new double[] {bounds.getX(), bounds.getY(),
- bounds.getMaxX(), bounds.getMaxY()};
- transform.transform(points, 0, points, 0, 2);
- bounds = new Rectangle2D.Double(points[0], points[1],
- (points[2] - points[0]),
- (points[3] - points[1]));
+ bounds = getTransformedBounds(bounds, transform);
// Clip bounds by the stored clip, and by the internal buffer
Rectangle2D devClip = this.getClipInDevSpace();
@@ -482,17 +466,15 @@ public class BufferedImageGraphics extends CairoGraphics2D
buffer.getWidth(), buffer.getHeight());
Rectangle2D.intersect(bounds, devClip, bounds);
- // Round bounds as needed, but be conservative in our rounding
+ // Round bounds as needed, but be careful in our rounding
// (otherwise it may leave unpainted stripes)
double x = bounds.getX();
double y = bounds.getY();
- double w = bounds.getWidth();
- double h = bounds.getHeight();
- if (Math.floor(x) != x)
- w--;
- if (Math.floor(y) != y)
- h--;
- bounds.setRect(Math.ceil(x), Math.ceil(y), Math.floor(w), Math.floor(h));
+ double maxX = x + bounds.getWidth();
+ double maxY = y + bounds.getHeight();
+ x = Math.round(x);
+ y = Math.round(y);
+ bounds.setRect(x, y, Math.round(maxX - x), Math.round(maxY - y));
// Find subimage of internal buffer for updating
BufferedImage buffer2 = buffer;
@@ -511,9 +493,10 @@ public class BufferedImageGraphics extends CairoGraphics2D
compCtx.compose(buffer2.getRaster(), current.getRaster(),
current.getRaster());
- // Prevent the clearRect in CairoGraphics2D.drawImage from clearing
- // our composited image
- locked = true;
+ // Set cairo's composite to direct SRC, since we've already done our own
+ // compositing
+ Composite oldcomp = comp;
+ setComposite(AlphaComposite.Src);
// This MUST call directly into the "action" method in CairoGraphics2D,
// not one of the wrappers, to ensure that the composite isn't processed
@@ -521,8 +504,9 @@ public class BufferedImageGraphics extends CairoGraphics2D
boolean rv = super.drawImage(current,
AffineTransform.getTranslateInstance(bounds.getX(),
bounds.getY()),
- new Color(0,0,0,0), null);
- locked = false;
+ null, null);
+ setComposite(oldcomp);
+ updateColor();
return rv;
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java b/libjava/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java
index 4a6ad008259..3a386075a69 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java
@@ -172,6 +172,12 @@ public abstract class CairoGraphics2D extends Graphics2D
* Rendering hint map.
*/
private RenderingHints hints;
+
+ /**
+ * Status of the anti-alias flag in cairo.
+ */
+ private boolean antialias = false;
+ private boolean ignoreAA = false;
/**
* Some operations (drawing rather than filling) require that their
@@ -228,6 +234,7 @@ public abstract class CairoGraphics2D extends Graphics2D
setPaint(Color.black);
setStroke(new BasicStroke());
setTransform(new AffineTransform());
+ cairoSetAntialias(nativePointer, antialias);
}
/**
@@ -244,7 +251,7 @@ public abstract class CairoGraphics2D extends Graphics2D
if (g.fg.getAlpha() != -1)
foreground = new Color(g.fg.getRed(), g.fg.getGreen(), g.fg.getBlue(),
- g.fg.getAlpha());
+ g.fg.getAlpha());
else
foreground = new Color(g.fg.getRGB());
@@ -274,6 +281,9 @@ public abstract class CairoGraphics2D extends Graphics2D
setTransformImpl(transform);
setClip(clip);
setComposite(comp);
+
+ antialias = !g.antialias;
+ setAntialias(g.antialias);
}
/**
@@ -311,8 +321,8 @@ public abstract class CairoGraphics2D extends Graphics2D
public abstract GraphicsConfiguration getDeviceConfiguration();
- protected abstract void copyAreaImpl(int x, int y,
- int width, int height, int dx, int dy);
+ protected abstract void copyAreaImpl(int x, int y, int width, int height,
+ int dx, int dy);
/**
@@ -345,8 +355,8 @@ public abstract class CairoGraphics2D extends Graphics2D
int g2, int b2, int a2, boolean cyclic);
protected native void setPaintPixels(long pointer, int[] pixels, int w,
- int h, int stride, boolean repeat,
- int x, int y);
+ int h, int stride, boolean repeat,
+ int x, int y);
/**
* Set the current transform matrix
@@ -390,9 +400,9 @@ public abstract class CairoGraphics2D extends Graphics2D
/*
* Draws a Glyph Vector
*/
- native void cairoDrawGlyphVector(long pointer, GdkFontPeer font,
+ protected native void cairoDrawGlyphVector(long pointer, GdkFontPeer font,
float x, float y, int n,
- int[] codes, float[] positions);
+ int[] codes, float[] positions, long[] fontset);
/**
* Set the font in cairo.
@@ -454,9 +464,15 @@ public abstract class CairoGraphics2D extends Graphics2D
protected native void cairoClip(long pointer);
/**
- * Save clip
+ * Clear clip
*/
protected native void cairoResetClip(long pointer);
+
+ /**
+ * Set antialias.
+ */
+ protected native void cairoSetAntialias(long pointer, boolean aa);
+
///////////////////////// TRANSFORMS ///////////////////////////////////
/**
@@ -648,33 +664,35 @@ public abstract class CairoGraphics2D extends Graphics2D
setColor((Color) paint);
customPaint = false;
}
+
else if (paint instanceof TexturePaint)
{
- TexturePaint tp = (TexturePaint) paint;
- BufferedImage img = tp.getImage();
+ TexturePaint tp = (TexturePaint) paint;
+ BufferedImage img = tp.getImage();
- // map the image to the anchor rectangle
- int width = (int) tp.getAnchorRect().getWidth();
- int height = (int) tp.getAnchorRect().getHeight();
+ // map the image to the anchor rectangle
+ int width = (int) tp.getAnchorRect().getWidth();
+ int height = (int) tp.getAnchorRect().getHeight();
- double scaleX = width / (double) img.getWidth();
- double scaleY = height / (double) img.getHeight();
+ double scaleX = width / (double) img.getWidth();
+ double scaleY = height / (double) img.getHeight();
- AffineTransform at = new AffineTransform(scaleX, 0, 0, scaleY, 0, 0);
- AffineTransformOp op = new AffineTransformOp(at, getRenderingHints());
- BufferedImage texture = op.filter(img, null);
- int[] pixels = texture.getRGB(0, 0, width, height, null, 0, width);
- setPaintPixels(nativePointer, pixels, width, height, width, true, 0, 0);
+ AffineTransform at = new AffineTransform(scaleX, 0, 0, scaleY, 0, 0);
+ AffineTransformOp op = new AffineTransformOp(at, getRenderingHints());
+ BufferedImage texture = op.filter(img, null);
+ int[] pixels = texture.getRGB(0, 0, width, height, null, 0, width);
+ setPaintPixels(nativePointer, pixels, width, height, width, true, 0, 0);
customPaint = false;
}
+
else if (paint instanceof GradientPaint)
{
- GradientPaint gp = (GradientPaint) paint;
- Point2D p1 = gp.getPoint1();
- Point2D p2 = gp.getPoint2();
- Color c1 = gp.getColor1();
- Color c2 = gp.getColor2();
- setGradient(nativePointer, p1.getX(), p1.getY(), p2.getX(), p2.getY(),
+ GradientPaint gp = (GradientPaint) paint;
+ Point2D p1 = gp.getPoint1();
+ Point2D p2 = gp.getPoint2();
+ Color c1 = gp.getColor1();
+ Color c2 = gp.getColor2();
+ setGradient(nativePointer, p1.getX(), p1.getY(), p2.getX(), p2.getY(),
c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha(),
c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha(),
gp.isCyclic());
@@ -703,15 +721,11 @@ public abstract class CairoGraphics2D extends Graphics2D
int userHeight = bounds.height;
// Find bounds in device space
- Point2D origin = transform.transform(new Point2D.Double(userX, userY),
- null);
- Point2D extreme = transform.transform(new Point2D.Double(userWidth + userX,
- userHeight + userY),
- null);
- int deviceX = (int)origin.getX();
- int deviceY = (int)origin.getY();
- int deviceWidth = (int)Math.ceil(extreme.getX() - origin.getX());
- int deviceHeight = (int)Math.ceil(extreme.getY() - origin.getY());
+ Rectangle2D bounds2D = getTransformedBounds(bounds, transform);
+ int deviceX = (int)bounds2D.getX();
+ int deviceY = (int)bounds2D.getY();
+ int deviceWidth = (int)Math.ceil(bounds2D.getWidth());
+ int deviceHeight = (int)Math.ceil(bounds2D.getHeight());
// Get raster of the paint background
PaintContext pc = paint.createContext(CairoSurface.cairoColorModel,
@@ -792,21 +806,22 @@ public abstract class CairoGraphics2D extends Graphics2D
stroke = st;
if (stroke instanceof BasicStroke)
{
- BasicStroke bs = (BasicStroke) stroke;
- cairoSetLine(nativePointer, bs.getLineWidth(), bs.getEndCap(),
- bs.getLineJoin(), bs.getMiterLimit());
-
- float[] dashes = bs.getDashArray();
- if (dashes != null)
- {
- double[] double_dashes = new double[dashes.length];
- for (int i = 0; i < dashes.length; i++)
- double_dashes[i] = dashes[i];
- cairoSetDash(nativePointer, double_dashes, double_dashes.length,
- (double) bs.getDashPhase());
- }
- else
- cairoSetDash(nativePointer, new double[0], 0, 0.0);
+ BasicStroke bs = (BasicStroke) stroke;
+ cairoSetLine(nativePointer, bs.getLineWidth(), bs.getEndCap(),
+ bs.getLineJoin(), bs.getMiterLimit());
+
+ float[] dashes = bs.getDashArray();
+ if (dashes != null)
+ {
+ double[] double_dashes = new double[dashes.length];
+ for (int i = 0; i < dashes.length; i++)
+ double_dashes[i] = dashes[i];
+
+ cairoSetDash(nativePointer, double_dashes, double_dashes.length,
+ (double) bs.getDashPhase());
+ }
+ else
+ cairoSetDash(nativePointer, new double[0], 0, 0.0);
}
}
@@ -864,6 +879,7 @@ public abstract class CairoGraphics2D extends Graphics2D
{
if (fg == null)
fg = Color.BLACK;
+
cairoSetRGBAColor(nativePointer, fg.getRed() / 255.0,
fg.getGreen() / 255.0,fg.getBlue() / 255.0,
fg.getAlpha() / 255.0);
@@ -916,18 +932,7 @@ public abstract class CairoGraphics2D extends Graphics2D
if (transform == null)
return uclip;
else
- {
- Point2D pos = transform.transform(new Point2D.Double(uclip.getX(),
- uclip.getY()),
- (Point2D) null);
- Point2D extent = transform.deltaTransform(new Point2D.Double(uclip
- .getWidth(),
- uclip
- .getHeight()),
- (Point2D) null);
- return new Rectangle2D.Double(pos.getX(), pos.getY(), extent.getX(),
- extent.getY());
- }
+ return getTransformedBounds(clip.getBounds2D(), transform);
}
public void setClip(int x, int y, int width, int height)
@@ -946,8 +951,8 @@ public abstract class CairoGraphics2D extends Graphics2D
// initial clip properly.
if( firstClip )
{
- originalClip = s;
- firstClip = false;
+ originalClip = s;
+ firstClip = false;
}
clip = s;
@@ -1007,7 +1012,7 @@ public abstract class CairoGraphics2D extends Graphics2D
if (comp instanceof AlphaComposite)
{
- AlphaComposite a = (AlphaComposite) comp;
+ AlphaComposite a = (AlphaComposite) comp;
cairoSetOperator(nativePointer, a.getRule());
}
@@ -1066,7 +1071,9 @@ public abstract class CairoGraphics2D extends Graphics2D
Rectangle r = findStrokedBounds(s);
setCustomPaint(r);
}
-
+
+ setAntialias(!hints.get(RenderingHints.KEY_ANTIALIASING)
+ .equals(RenderingHints.VALUE_ANTIALIAS_OFF));
createPath(s, true);
cairoStroke(nativePointer);
}
@@ -1077,7 +1084,9 @@ public abstract class CairoGraphics2D extends Graphics2D
if (customPaint)
setCustomPaint(s.getBounds());
-
+
+ setAntialias(!hints.get(RenderingHints.KEY_ANTIALIASING)
+ .equals(RenderingHints.VALUE_ANTIALIAS_OFF));
double alpha = 1.0;
if (comp instanceof AlphaComposite)
alpha = ((AlphaComposite) comp).getAlpha();
@@ -1263,13 +1272,15 @@ public abstract class CairoGraphics2D extends Graphics2D
public void copyArea(int ox, int oy, int owidth, int oheight,
int odx, int ody)
{
+ // FIXME: does this handle a rotation transform properly?
+ // (the width/height might not be correct)
Point2D pos = transform.transform(new Point2D.Double(ox, oy),
- (Point2D) null);
+ (Point2D) null);
Point2D dim = transform.transform(new Point2D.Double(ox + owidth,
- oy + oheight),
- (Point2D) null);
+ oy + oheight),
+ (Point2D) null);
Point2D p2 = transform.transform(new Point2D.Double(ox + odx, oy + ody),
- (Point2D) null);
+ (Point2D) null);
int x = (int)pos.getX();
int y = (int)pos.getY();
int width = (int)(dim.getX() - pos.getX());
@@ -1291,14 +1302,14 @@ public abstract class CairoGraphics2D extends Graphics2D
// Clip edges if necessary
if( x + dx < r.getX() ) // left
{
- width = x + dx + width;
- x = (int)r.getX() - dx;
+ width = x + dx + width;
+ x = (int)r.getX() - dx;
}
if( y + dy < r.getY() ) // top
{
- height = y + dy + height;
- y = (int)r.getY() - dy;
+ height = y + dy + height;
+ y = (int)r.getY() - dy;
}
if( x + dx + width >= r.getWidth() ) // right
@@ -1325,10 +1336,10 @@ public abstract class CairoGraphics2D extends Graphics2D
return hints.get(hintKey);
}
- public void setRenderingHints(Map hints)
+ public void setRenderingHints(Map<?,?> hints)
{
this.hints = new RenderingHints(getDefaultHints());
- this.hints.add(new RenderingHints(hints));
+ this.hints.putAll(hints);
shiftDrawCalls = hints.containsValue(RenderingHints.VALUE_STROKE_NORMALIZE)
|| hints.containsValue(RenderingHints.VALUE_STROKE_DEFAULT);
@@ -1342,7 +1353,7 @@ public abstract class CairoGraphics2D extends Graphics2D
public void addRenderingHints(Map hints)
{
- this.hints.add(new RenderingHints(hints));
+ this.hints.putAll(hints);
}
public RenderingHints getRenderingHints()
@@ -1373,6 +1384,24 @@ public abstract class CairoGraphics2D extends Graphics2D
// Do bilinear interpolation as default
return INTERPOLATION_BILINEAR;
}
+
+ /**
+ * Set antialias if needed. If the ignoreAA flag is set, this method will
+ * return without doing anything.
+ *
+ * @param needAA RenderingHints.VALUE_ANTIALIAS_ON or RenderingHints.VALUE_ANTIALIAS_OFF
+ */
+ private void setAntialias(boolean needAA)
+ {
+ if (ignoreAA)
+ return;
+
+ if (needAA != antialias)
+ {
+ antialias = !antialias;
+ cairoSetAntialias(nativePointer, antialias);
+ }
+ }
///////////////////////// IMAGE. METHODS ///////////////////////////////////
@@ -1396,12 +1425,12 @@ public abstract class CairoGraphics2D extends Graphics2D
try
{
- invertedXform = xform.createInverse();
+ invertedXform = xform.createInverse();
}
catch (NoninvertibleTransformException e)
{
- throw new ImagingOpException("Unable to invert transform "
- + xform.toString());
+ throw new ImagingOpException("Unable to invert transform "
+ + xform.toString());
}
// Unrecognized image - convert to a BufferedImage
@@ -1411,10 +1440,10 @@ public abstract class CairoGraphics2D extends Graphics2D
img = AsyncImage.realImage(img, obs);
if( !(img instanceof BufferedImage) )
{
- ImageProducer source = img.getSource();
- if (source == null)
- return false;
- img = Toolkit.getDefaultToolkit().createImage(source);
+ ImageProducer source = img.getSource();
+ if (source == null)
+ return false;
+ img = Toolkit.getDefaultToolkit().createImage(source);
}
BufferedImage b = (BufferedImage) img;
@@ -1427,7 +1456,7 @@ public abstract class CairoGraphics2D extends Graphics2D
// use the cached CairoSurface that BIG is drawing onto
if( BufferedImageGraphics.bufferedImages.get( b ) != null )
- raster = (Raster)BufferedImageGraphics.bufferedImages.get( b );
+ raster = BufferedImageGraphics.bufferedImages.get( b );
else
raster = b.getRaster();
@@ -1437,12 +1466,12 @@ public abstract class CairoGraphics2D extends Graphics2D
if (comp instanceof AlphaComposite)
alpha = ((AlphaComposite) comp).getAlpha();
- if(raster instanceof CairoSurface)
+ if(raster instanceof CairoSurface
+ && ((CairoSurface)raster).sharedBuffer == true)
{
- ((CairoSurface)raster).drawSurface(nativePointer, i2u, alpha,
- getInterpolation());
+ drawCairoSurface((CairoSurface)raster, xform, alpha, getInterpolation());
updateColor();
- return true;
+ return true;
}
if( bgcolor != null )
@@ -1450,24 +1479,31 @@ public abstract class CairoGraphics2D extends Graphics2D
Color oldColor = bg;
setBackground(bgcolor);
- double[] origin = new double[] {0,0};
- double[] dimensions = new double[] {width, height};
- xform.transform(origin, 0, origin, 0, 1);
- xform.deltaTransform(dimensions, 0, dimensions, 0, 1);
- clearRect((int)origin[0], (int)origin[1],
- (int)dimensions[0], (int)dimensions[1]);
+ Rectangle2D bounds = new Rectangle2D.Double(0, 0, width, height);
+ bounds = getTransformedBounds(bounds, xform);
+
+ clearRect((int)bounds.getX(), (int)bounds.getY(),
+ (int)bounds.getWidth(), (int)bounds.getHeight());
setBackground(oldColor);
}
int[] pixels = b.getRGB(0, 0, width, height, null, 0, width);
-
// FIXME: The above method returns data in the standard ARGB colorspace,
// meaning data should NOT be alpha pre-multiplied; however Cairo expects
// data to be premultiplied.
+
+ cairoSave(nativePointer);
+ Rectangle2D bounds = new Rectangle2D.Double(0, 0, width, height);
+ bounds = getTransformedBounds(bounds, xform);
+ cairoRectangle(nativePointer, bounds.getX(), bounds.getY(),
+ bounds.getWidth(), bounds.getHeight());
+ cairoClip(nativePointer);
drawPixels(nativePointer, pixels, width, height, width, i2u, alpha,
getInterpolation());
+
+ cairoRestore(nativePointer);
// Cairo seems to lose the current color which must be restored.
updateColor();
@@ -1578,6 +1614,66 @@ public abstract class CairoGraphics2D extends Graphics2D
{
return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null, observer);
}
+
+ /**
+ * Optimized method for drawing a CairoSurface onto this graphics context.
+ *
+ * @param surface The surface to draw.
+ * @param tx The transformation matrix (cannot be null).
+ * @param alpha The alpha value to paint with ( 0 <= alpha <= 1).
+ * @param interpolation The interpolation type.
+ */
+ protected void drawCairoSurface(CairoSurface surface, AffineTransform tx,
+ double alpha, int interpolation)
+ {
+ // Find offset required if this surface is a sub-raster, and append offset
+ // to transformation.
+ if (surface.getSampleModelTranslateX() != 0
+ || surface.getSampleModelTranslateY() != 0)
+ {
+ Point2D origin = new Point2D.Double(0, 0);
+ Point2D offset = new Point2D.Double(surface.getSampleModelTranslateX(),
+ surface.getSampleModelTranslateY());
+
+ tx.transform(origin, origin);
+ tx.transform(offset, offset);
+
+ tx.translate(offset.getX() - origin.getX(),
+ offset.getY() - origin.getY());
+ }
+
+ // Find dimensions of this surface relative to the root parent surface
+ Rectangle bounds = new Rectangle(-surface.getSampleModelTranslateX(),
+ -surface.getSampleModelTranslateY(),
+ surface.width, surface.height);
+
+ // Clip to the translated image
+ // We use direct cairo methods to avoid the overhead of maintaining a
+ // java copy of the clip, since we will be reverting it immediately
+ // after drawing
+ Shape newBounds = tx.createTransformedShape(bounds);
+ cairoSave(nativePointer);
+ walkPath(newBounds.getPathIterator(null), false);
+ cairoClip(nativePointer);
+
+ // Draw the surface
+ try
+ {
+ double[] i2u = new double[6];
+ tx.createInverse().getMatrix(i2u);
+ surface.nativeDrawSurface(surface.surfacePointer, nativePointer, i2u,
+ alpha, interpolation);
+ }
+ catch (NoninvertibleTransformException ex)
+ {
+ // This should never happen(?), so we don't need to do anything here.
+ ;
+ }
+
+ // Restore clip
+ cairoRestore(nativePointer);
+ }
+
///////////////////////// TEXT METHODS ////////////////////////////////////
@@ -1592,7 +1688,15 @@ public abstract class CairoGraphics2D extends Graphics2D
tl = new TextLayout( str, getFont(), getFontRenderContext() );
fontPeer.textLayoutCache.put(str, tl);
}
+
+ // Set antialias to text_antialiasing, and set the ignoreAA flag so that
+ // the setting doesn't get overridden in a draw() or fill() call.
+ setAntialias(!hints.get(RenderingHints.KEY_TEXT_ANTIALIASING)
+ .equals(RenderingHints.VALUE_TEXT_ANTIALIAS_OFF));
+ ignoreAA = true;
+
tl.draw(this, x, y);
+ ignoreAA = false;
}
public void drawString(String str, int x, int y)
@@ -1617,19 +1721,25 @@ public abstract class CairoGraphics2D extends Graphics2D
if (comp instanceof AlphaComposite)
alpha = ((AlphaComposite) comp).getAlpha();
+
+ setAntialias(!hints.get(RenderingHints.KEY_TEXT_ANTIALIASING)
+ .equals(RenderingHints.VALUE_TEXT_ANTIALIAS_OFF));
+ ignoreAA = true;
+
if (gv instanceof FreetypeGlyphVector && alpha == 1.0)
{
int n = gv.getNumGlyphs ();
int[] codes = gv.getGlyphCodes (0, n, null);
+ long[] fontset = ((FreetypeGlyphVector)gv).getGlyphFonts (0, n, null);
float[] positions = gv.getGlyphPositions (0, n, null);
setFont (gv.getFont ());
GdkFontPeer fontPeer = (GdkFontPeer) font.getPeer();
- synchronized (fontPeer)
- {
- cairoDrawGlyphVector(nativePointer, fontPeer,
- x, y, n, codes, positions);
- }
+ synchronized (fontPeer)
+ {
+ cairoDrawGlyphVector(nativePointer, fontPeer,
+ x, y, n, codes, positions, fontset);
+ }
}
else
{
@@ -1637,6 +1747,8 @@ public abstract class CairoGraphics2D extends Graphics2D
fill(gv.getOutline());
translate(-x, -y);
}
+
+ ignoreAA = false;
}
public void drawString(AttributedCharacterIterator ci, float x, float y)
@@ -1702,9 +1814,9 @@ public abstract class CairoGraphics2D extends Graphics2D
{
if( onStroke )
{
- Shape stroked = stroke.createStrokedShape( s );
- return stroked.intersects( (double)rect.x, (double)rect.y,
- (double)rect.width, (double)rect.height );
+ Shape stroked = stroke.createStrokedShape( s );
+ return stroked.intersects( (double)rect.x, (double)rect.y,
+ (double)rect.width, (double)rect.height );
}
return s.intersects( (double)rect.x, (double)rect.y,
(double)rect.width, (double)rect.height );
@@ -1747,34 +1859,34 @@ public abstract class CairoGraphics2D extends Graphics2D
imageToUser.getMatrix(i2u);
else
{
- i2u[0] = 1;
- i2u[1] = 0;
- i2u[2] = 0;
- i2u[3] = 1;
- i2u[4] = 0;
- i2u[5] = 0;
+ i2u[0] = 1;
+ i2u[1] = 0;
+ i2u[2] = 0;
+ i2u[3] = 1;
+ i2u[4] = 0;
+ i2u[5] = 0;
}
int[] pixels = findSimpleIntegerArray(cm, r);
if (pixels == null)
{
- // FIXME: I don't think this code will work correctly with a non-RGB
- // MultiPixelPackedSampleModel. Although this entire method should
- // probably be rewritten to better utilize Cairo's different supported
- // data formats.
- if (sm instanceof MultiPixelPackedSampleModel)
- {
- pixels = r.getPixels(0, 0, r.getWidth(), r.getHeight(), pixels);
- for (int i = 0; i < pixels.length; i++)
- pixels[i] = cm.getRGB(pixels[i]);
- }
- else
- {
- pixels = new int[r.getWidth() * r.getHeight()];
- for (int i = 0; i < pixels.length; i++)
- pixels[i] = cm.getRGB(db.getElem(i));
- }
+ // FIXME: I don't think this code will work correctly with a non-RGB
+ // MultiPixelPackedSampleModel. Although this entire method should
+ // probably be rewritten to better utilize Cairo's different supported
+ // data formats.
+ if (sm instanceof MultiPixelPackedSampleModel)
+ {
+ pixels = r.getPixels(0, 0, r.getWidth(), r.getHeight(), pixels);
+ for (int i = 0; i < pixels.length; i++)
+ pixels[i] = cm.getRGB(pixels[i]);
+ }
+ else
+ {
+ pixels = new int[r.getWidth() * r.getHeight()];
+ for (int i = 0; i < pixels.length; i++)
+ pixels[i] = cm.getRGB(db.getElem(i));
+ }
}
// Change all transparent pixels in the image to the specified bgcolor,
@@ -1782,20 +1894,21 @@ public abstract class CairoGraphics2D extends Graphics2D
// correctly.
if (cm.hasAlpha())
{
- if (bgcolor != null && cm.hasAlpha())
- for (int i = 0; i < pixels.length; i++)
- {
- if (cm.getAlpha(pixels[i]) == 0)
- pixels[i] = bgcolor.getRGB();
- }
+ if (bgcolor != null && cm.hasAlpha())
+ for (int i = 0; i < pixels.length; i++)
+ {
+ if (cm.getAlpha(pixels[i]) == 0)
+ pixels[i] = bgcolor.getRGB();
+ }
}
else
for (int i = 0; i < pixels.length; i++)
- pixels[i] |= 0xFF000000;
+ pixels[i] |= 0xFF000000;
double alpha = 1.0;
if (comp instanceof AlphaComposite)
alpha = ((AlphaComposite) comp).getAlpha();
+
drawPixels(nativePointer, pixels, r.getWidth(), r.getHeight(),
r.getWidth(), i2u, alpha, getInterpolation());
@@ -1815,7 +1928,7 @@ public abstract class CairoGraphics2D extends Graphics2D
double shift = 0.5;
if (!transform.isIdentity())
shift /= transform.getScaleX();
- return Math.round(coord) + shift;
+ return (coord + shift);
}
else
return coord;
@@ -1831,7 +1944,7 @@ public abstract class CairoGraphics2D extends Graphics2D
double shift = 0.5;
if (!transform.isIdentity())
shift /= transform.getScaleY();
- return Math.round(coord) + shift;
+ return (coord + shift);
}
else
return coord;
@@ -1849,53 +1962,54 @@ public abstract class CairoGraphics2D extends Graphics2D
cairoSetFillRule(nativePointer, p.getWindingRule());
for (; ! p.isDone(); p.next())
{
- int seg = p.currentSegment(coords);
- switch (seg)
- {
- case PathIterator.SEG_MOVETO:
- x = shiftX(coords[0], doShift);
- y = shiftY(coords[1], doShift);
- cairoMoveTo(nativePointer, x, y);
- break;
- case PathIterator.SEG_LINETO:
- x = shiftX(coords[0], doShift);
- y = shiftY(coords[1], doShift);
- cairoLineTo(nativePointer, x, y);
- break;
- case PathIterator.SEG_QUADTO:
- // splitting a quadratic bezier into a cubic:
- // see: http://pfaedit.sourceforge.net/bezier.html
- double x1 = x + (2.0 / 3.0) * (shiftX(coords[0], doShift) - x);
- double y1 = y + (2.0 / 3.0) * (shiftY(coords[1], doShift) - y);
-
- double x2 = x1 + (1.0 / 3.0) * (shiftX(coords[2], doShift) - x);
- double y2 = y1 + (1.0 / 3.0) * (shiftY(coords[3], doShift) - y);
-
- x = shiftX(coords[2], doShift);
- y = shiftY(coords[3], doShift);
- cairoCurveTo(nativePointer, x1, y1, x2, y2, x, y);
- break;
- case PathIterator.SEG_CUBICTO:
- x = shiftX(coords[4], doShift);
- y = shiftY(coords[5], doShift);
- cairoCurveTo(nativePointer, shiftX(coords[0], doShift),
- shiftY(coords[1], doShift),
- shiftX(coords[2], doShift),
- shiftY(coords[3], doShift), x, y);
- break;
- case PathIterator.SEG_CLOSE:
- cairoClosePath(nativePointer);
- break;
- }
+ int seg = p.currentSegment(coords);
+ switch (seg)
+ {
+ case PathIterator.SEG_MOVETO:
+ x = shiftX(coords[0], doShift);
+ y = shiftY(coords[1], doShift);
+ cairoMoveTo(nativePointer, x, y);
+ break;
+ case PathIterator.SEG_LINETO:
+ x = shiftX(coords[0], doShift);
+ y = shiftY(coords[1], doShift);
+ cairoLineTo(nativePointer, x, y);
+ break;
+ case PathIterator.SEG_QUADTO:
+ // splitting a quadratic bezier into a cubic:
+ // see: http://pfaedit.sourceforge.net/bezier.html
+ double x1 = x + (2.0 / 3.0) * (shiftX(coords[0], doShift) - x);
+ double y1 = y + (2.0 / 3.0) * (shiftY(coords[1], doShift) - y);
+
+ double x2 = x1 + (1.0 / 3.0) * (shiftX(coords[2], doShift) - x);
+ double y2 = y1 + (1.0 / 3.0) * (shiftY(coords[3], doShift) - y);
+
+ x = shiftX(coords[2], doShift);
+ y = shiftY(coords[3], doShift);
+ cairoCurveTo(nativePointer, x1, y1, x2, y2, x, y);
+ break;
+ case PathIterator.SEG_CUBICTO:
+ x = shiftX(coords[4], doShift);
+ y = shiftY(coords[5], doShift);
+ cairoCurveTo(nativePointer, shiftX(coords[0], doShift),
+ shiftY(coords[1], doShift),
+ shiftX(coords[2], doShift),
+ shiftY(coords[3], doShift), x, y);
+ break;
+ case PathIterator.SEG_CLOSE:
+ cairoClosePath(nativePointer);
+ break;
+ }
}
}
/**
* Used by setRenderingHints()
*/
- private Map getDefaultHints()
+ private Map<RenderingHints.Key, Object> getDefaultHints()
{
- HashMap defaultHints = new HashMap();
+ HashMap<RenderingHints.Key, Object> defaultHints =
+ new HashMap<RenderingHints.Key, Object>();
defaultHints.put(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
@@ -1972,11 +2086,27 @@ public abstract class CairoGraphics2D extends Graphics2D
if (clip == null)
return;
- if (! (clip instanceof GeneralPath))
- clip = new GeneralPath(clip);
-
- GeneralPath p = (GeneralPath) clip;
- p.transform(t);
+ // If the clip is a rectangle, and the transformation preserves the shape
+ // (translate/stretch only), then keep the clip as a rectangle
+ double[] matrix = new double[4];
+ t.getMatrix(matrix);
+ if (clip instanceof Rectangle2D && matrix[1] == 0 && matrix[2] == 0)
+ {
+ Rectangle2D rect = (Rectangle2D)clip;
+ double[] origin = new double[] {rect.getX(), rect.getY()};
+ double[] dimensions = new double[] {rect.getWidth(), rect.getHeight()};
+ t.transform(origin, 0, origin, 0, 1);
+ t.deltaTransform(dimensions, 0, dimensions, 0, 1);
+ rect.setRect(origin[0], origin[1], dimensions[0], dimensions[1]);
+ }
+ else
+ {
+ if (! (clip instanceof GeneralPath))
+ clip = new GeneralPath(clip);
+
+ GeneralPath p = (GeneralPath) clip;
+ p.transform(t);
+ }
}
private static Rectangle computeIntersection(int x, int y, int w, int h,
@@ -1999,4 +2129,39 @@ public abstract class CairoGraphics2D extends Graphics2D
return rect;
}
+
+ static Rectangle2D getTransformedBounds(Rectangle2D bounds, AffineTransform tx)
+ {
+ double x1 = bounds.getX();
+ double x2 = bounds.getX() + bounds.getWidth();
+ double x3 = x1;
+ double x4 = x2;
+ double y1 = bounds.getY();
+ double y2 = y1;
+ double y3 = bounds.getY() + bounds.getHeight();
+ double y4 = y3;
+
+ double[] points = new double[] {x1, y1, x2, y2, x3, y3, x4, y4};
+ tx.transform(points, 0, points, 0, 4);
+
+ double minX = points[0];
+ double maxX = minX;
+ double minY = points[1];
+ double maxY = minY;
+ for (int i = 0; i < 8; i++)
+ {
+ if (points[i] < minX)
+ minX = points[i];
+ if (points[i] > maxX)
+ maxX = points[i];
+ i++;
+
+ if (points[i] < minY)
+ minY = points[i];
+ if (points[i] > maxY)
+ maxY = points[i];
+ }
+
+ return new Rectangle2D.Double(minX, minY, (maxX - minX), (maxY - minY));
+ }
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurface.java b/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurface.java
index 5b63e62e7ed..b45a79fd6e7 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurface.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurface.java
@@ -1,5 +1,5 @@
/* CairoSurface.java
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2007 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -42,15 +42,22 @@ import gnu.java.awt.Buffers;
import java.awt.Graphics2D;
import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Shape;
import java.awt.color.ColorSpace;
+import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferInt;
import java.awt.image.DirectColorModel;
+import java.awt.image.Raster;
+import java.awt.image.RasterFormatException;
import java.awt.image.SampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.WritableRaster;
import java.nio.ByteOrder;
+import java.util.Arrays;
import java.util.Hashtable;
/**
@@ -68,9 +75,9 @@ public class CairoSurface extends WritableRaster
long surfacePointer;
/**
- * The native pointer to the image's data buffer
+ * Whether the data buffer is shared between java and cairo.
*/
- long bufferPointer;
+ boolean sharedBuffer;
// FIXME: use only the cairoCM_pre colormodel
// since that's what Cairo really uses (is there a way to do this cheaply?
@@ -98,22 +105,12 @@ public class CairoSurface extends WritableRaster
* @param width, height - the image size
* @param stride - the buffer row stride. (in ints)
*/
- private native void create(int width, int height, int stride);
+ private native void create(int width, int height, int stride, int[] buf);
/**
* Destroys the cairo surface and frees the buffer.
*/
- private native void destroy(long surfacePointer, long bufferPointer);
-
- /**
- * Gets buffer elements
- */
- private native int nativeGetElem(long bufferPointer, int i);
-
- /**
- * Sets buffer elements.
- */
- private native void nativeSetElem(long bufferPointer, int i, int val);
+ private native void destroy(long surfacePointer, int[] buf);
/**
* Draws this image to a given CairoGraphics context,
@@ -123,33 +120,30 @@ public class CairoSurface extends WritableRaster
double[] i2u, double alpha,
int interpolation);
- public void drawSurface(long contextPointer, double[] i2u, double alpha,
- int interpolation)
- {
- nativeDrawSurface(surfacePointer, contextPointer, i2u, alpha, interpolation);
- }
-
/**
- * getPixels -return the pixels as a java array.
+ * Synchronizes the image's data buffers, copying any changes made in the
+ * Java array into the native array.
+ *
+ * This method should only be called if (sharedBuffers == false).
*/
- native int[] nativeGetPixels(long bufferPointer, int size);
-
- public int[] getPixels(int size)
- {
- return nativeGetPixels(bufferPointer, size);
- }
-
+ native void syncNativeToJava(long surfacePointer, int[] buffer);
+
/**
- * getPixels -return the pixels as a java array.
+ * Synchronizes the image's data buffers, copying any changes made in the
+ * native array into the Java array.
+ *
+ * This method should only be called if (sharedBuffers == false).
*/
- native void nativeSetPixels(long bufferPointer, int[] pixels);
-
- public void setPixels(int[] pixels)
- {
- nativeSetPixels(bufferPointer, pixels);
- }
-
- native long getFlippedBuffer(long bufferPointer, int size);
+ native void syncJavaToNative(long surfacePointer, int[] buffer);
+
+ /**
+ * Return the buffer, with the sample values of each pixel reversed
+ * (ie, in ABGR instead of ARGB).
+ *
+ * @return A pointer to a flipped buffer. The memory is allocated in native
+ * code, and must be explicitly freed when it is no longer needed.
+ */
+ native long getFlippedBuffer(long surfacePointer);
/**
* Create a cairo_surface_t with specified width and height.
@@ -158,20 +152,38 @@ public class CairoSurface extends WritableRaster
*/
public CairoSurface(int width, int height)
{
- super(createCairoSampleModel(width, height),
- null, new Point(0, 0));
+ this(0, 0, width, height);
+ }
+
+ public CairoSurface(int x, int y, int width, int height)
+ {
+ super(createCairoSampleModel(width, height), null, new Point(x, y));
if(width <= 0 || height <= 0)
throw new IllegalArgumentException("Image must be at least 1x1 pixels.");
this.width = width;
this.height = height;
- create(width, height, width);
+ dataBuffer = new DataBufferInt(width * height);
+ create(width, height, width, getData());
- if(surfacePointer == 0 || bufferPointer == 0)
+ if(surfacePointer == 0)
throw new Error("Could not allocate bitmap.");
-
- dataBuffer = new CairoDataBuffer();
+ }
+
+ /**
+ * Create a Cairo Surface that is a subimage of another Cairo Surface
+ */
+ public CairoSurface(SampleModel sm, CairoSurface parent, Rectangle bounds,
+ Point origin)
+ {
+ super(sm, parent.dataBuffer, bounds, origin, parent);
+
+ this.width = super.width;
+ this.height = super.height;
+ this.surfacePointer = parent.surfacePointer;
+ this.sharedBuffer = parent.sharedBuffer;
+ this.dataBuffer = parent.dataBuffer;
}
/**
@@ -188,39 +200,39 @@ public class CairoSurface extends WritableRaster
// Swap ordering from GdkPixbuf to Cairo
if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
{
- for (int i = 0; i < data.length; i++ )
- {
- // On a big endian system we get a RRGGBBAA data array.
- int alpha = data[i] & 0xFF;
- if( alpha == 0 ) // I do not know why we need this, but it works.
- data[i] = 0;
- else
- {
- // Cairo needs a ARGB32 native array.
- data[i] = (data[i] >>> 8) | (alpha << 24);
- }
- }
+ for (int i = 0; i < data.length; i++ )
+ {
+ // On a big endian system we get a RRGGBBAA data array.
+ int alpha = data[i] & 0xFF;
+ if( alpha == 0 ) // I do not know why we need this, but it works.
+ data[i] = 0;
+ else
+ {
+ // Cairo needs a ARGB32 native array.
+ data[i] = (data[i] >>> 8) | (alpha << 24);
+ }
+ }
}
else
{
- for (int i = 0; i < data.length; i++ )
- {
- // On a little endian system we get a AABBGGRR data array.
- int alpha = data[i] & 0xFF000000;
- if( alpha == 0 ) // I do not know why we need this, but it works.
- data[i] = 0;
- else
- {
- int b = (data[i] & 0xFF0000) >> 16;
- int g = (data[i] & 0xFF00);
- int r = (data[i] & 0xFF) << 16;
- // Cairo needs a ARGB32 native array.
- data[i] = alpha | r | g | b;
- }
- }
+ for (int i = 0; i < data.length; i++ )
+ {
+ // On a little endian system we get a AABBGGRR data array.
+ int alpha = data[i] & 0xFF000000;
+ if( alpha == 0 ) // I do not know why we need this, but it works.
+ data[i] = 0;
+ else
+ {
+ int b = (data[i] & 0xFF0000) >> 16;
+ int g = (data[i] & 0xFF00);
+ int r = (data[i] & 0xFF) << 16;
+ // Cairo needs a ARGB32 native array.
+ data[i] = alpha | r | g | b;
+ }
+ }
}
- setPixels( data );
+ System.arraycopy(data, 0, getData(), 0, data.length);
}
/**
@@ -228,8 +240,8 @@ public class CairoSurface extends WritableRaster
*/
public void dispose()
{
- if(surfacePointer != 0)
- destroy(surfacePointer, bufferPointer);
+ if(surfacePointer != 0 && parent == null)
+ destroy(surfacePointer, getData());
}
/**
@@ -245,8 +257,17 @@ public class CairoSurface extends WritableRaster
*/
public GtkImage getGtkImage()
{
- return new GtkImage( width, height,
- getFlippedBuffer(bufferPointer, width * height ));
+ return new GtkImage(width, height, getFlippedBuffer(surfacePointer));
+ }
+
+ /**
+ * Convenience method to quickly grab the data array backing this Raster.
+ *
+ * @return The array behind the databuffer.
+ */
+ public int[] getData()
+ {
+ return ((DataBufferInt)dataBuffer).getData();
}
/**
@@ -276,34 +297,6 @@ public class CairoSurface extends WritableRaster
new Hashtable());
}
- private class CairoDataBuffer extends DataBuffer
- {
- public CairoDataBuffer()
- {
- super(DataBuffer.TYPE_INT, width * height);
- }
-
- /**
- * DataBuffer.getElem implementation
- */
- public int getElem(int bank, int i)
- {
- if(bank != 0 || i < 0 || i >= width * height)
- throw new IndexOutOfBoundsException(i+" size: "+width * height);
- return nativeGetElem(bufferPointer, i);
- }
-
- /**
- * DataBuffer.setElem implementation
- */
- public void setElem(int bank, int i, int val)
- {
- if(bank != 0 || i < 0 || i >= width*height)
- throw new IndexOutOfBoundsException(i+" size: "+width * height);
- nativeSetElem(bufferPointer, i, val);
- }
- }
-
/**
* Return a Graphics2D drawing to the CairoSurface.
*/
@@ -325,16 +318,25 @@ public class CairoSurface extends WritableRaster
}
/**
- * Copy an area of the surface. Expects parameters must be within bounds.
- * Count on a segfault otherwise.
+ * Copy a portion of this surface to another area on the surface. The given
+ * parameters must be within bounds - count on a segfault otherwise.
+ *
+ * @param x The x coordinate of the area to be copied from.
+ * @param y The y coordinate of the area to be copied from.
+ * @param width The width of the area to be copied.
+ * @param height The height of the area to be copied.
+ * @param dx The destination x coordinate.
+ * @param dy The destination y coordinate.
+ * @param stride The scanline stride.
*/
- native void copyAreaNative2(long bufferPointer, int x, int y, int width,
- int height, int dx, int dy, int stride);
public void copyAreaNative(int x, int y, int width,
int height, int dx, int dy, int stride)
{
- copyAreaNative2(bufferPointer, x, y, width, height, dx, dy, stride);
+ copyAreaNative2(surfacePointer, x, y, width, height, dx, dy, stride);
}
+ native void copyAreaNative2(long surfacePointer,
+ int x, int y, int width, int height,
+ int dx, int dy, int stride);
/**
* Creates a SampleModel that matches Cairo's native format
@@ -345,4 +347,83 @@ public class CairoSurface extends WritableRaster
new int[]{0x00FF0000, 0x0000FF00,
0x000000FF, 0xFF000000});
}
+
+ /**
+ * Returns whether this ColorModel is compatible with Cairo's native types.
+ *
+ * @param cm The color model to check.
+ * @return Whether it is compatible.
+ */
+ public static boolean isCompatibleColorModel(ColorModel cm)
+ {
+ return (cm.equals(cairoCM_pre) || cm.equals(cairoCM_opaque) ||
+ cm.equals(cairoColorModel));
+ }
+
+ /**
+ * Returns whether this SampleModel is compatible with Cairo's native types.
+ *
+ * @param sm The sample model to check.
+ * @return Whether it is compatible.
+ */
+ public static boolean isCompatibleSampleModel(SampleModel sm)
+ {
+ return (sm instanceof SinglePixelPackedSampleModel
+ && sm.getDataType() == DataBuffer.TYPE_INT
+ && Arrays.equals(((SinglePixelPackedSampleModel)sm).getBitMasks(),
+ new int[]{0x00FF0000, 0x0000FF00,
+ 0x000000FF, 0xFF000000}));
+ }
+
+ ///// Methods interhited from Raster and WritableRaster /////
+ public Raster createChild(int parentX, int parentY, int width, int height,
+ int childMinX, int childMinY, int[] bandList)
+ {
+ return createWritableChild(parentX, parentY, width, height,
+ childMinX, childMinY, bandList);
+ }
+
+ public WritableRaster createCompatibleWritableRaster()
+ {
+ return new CairoSurface(width, height);
+ }
+
+ public WritableRaster createCompatibleWritableRaster (int x, int y,
+ int w, int h)
+ {
+ return new CairoSurface(x, y, w, h);
+ }
+
+ public Raster createTranslatedChild(int childMinX, int childMinY)
+ {
+ return createWritableTranslatedChild(childMinX, childMinY);
+ }
+
+ public WritableRaster createWritableChild(int parentX, int parentY,
+ int w, int h, int childMinX,
+ int childMinY, int[] bandList)
+ {
+ if (parentX < minX || parentX + w > minX + width
+ || parentY < minY || parentY + h > minY + height)
+ throw new RasterFormatException("Child raster extends beyond parent");
+
+ SampleModel sm = (bandList == null) ?
+ sampleModel :
+ sampleModel.createSubsetSampleModel(bandList);
+
+ return new CairoSurface(sm, this,
+ new Rectangle(childMinX, childMinY, w, h),
+ new Point(sampleModelTranslateX + childMinX - parentX,
+ sampleModelTranslateY + childMinY - parentY));
+ }
+
+ public WritableRaster createWritableTranslatedChild(int x, int y)
+ {
+ int tcx = sampleModelTranslateX - minX + x;
+ int tcy = sampleModelTranslateY - minY + y;
+
+ return new CairoSurface(sampleModel, this,
+ new Rectangle(x, y, width, height),
+ new Point(tcx, tcy));
+ }
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java b/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java
index 36743b9c2da..35b015f3200 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java
@@ -40,6 +40,7 @@ package gnu.java.awt.peer.gtk;
import java.awt.AlphaComposite;
import java.awt.Color;
+import java.awt.Composite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
@@ -50,7 +51,6 @@ import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
-import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
@@ -116,6 +116,18 @@ public class CairoSurfaceGraphics extends CairoGraphics2D
*/
public void draw(Shape s)
{
+ if (!surface.sharedBuffer)
+ surface.syncJavaToNative(surface.surfacePointer, surface.getData());
+
+ // Find total bounds of shape
+ Rectangle r = findStrokedBounds(s);
+ if (shiftDrawCalls)
+ {
+ r.width++;
+ r.height++;
+ }
+
+ // Do the drawing
if (comp == null || comp instanceof AlphaComposite)
super.draw(s);
@@ -126,14 +138,21 @@ public class CairoSurfaceGraphics extends CairoGraphics2D
Graphics2D g2d = (Graphics2D)buffer.getGraphics();
g2d.setStroke(this.getStroke());
g2d.setColor(this.getColor());
+ g2d.setTransform(transform);
g2d.draw(s);
- drawComposite(s.getBounds2D(), null);
+ drawComposite(r.getBounds2D(), null);
}
+
+ if (!surface.sharedBuffer)
+ surface.syncNativeToJava(surface.surfacePointer, surface.getData());
}
public void fill(Shape s)
{
+ if (!surface.sharedBuffer)
+ surface.syncJavaToNative(surface.surfacePointer, surface.getData());
+
if (comp == null || comp instanceof AlphaComposite)
super.fill(s);
@@ -144,14 +163,21 @@ public class CairoSurfaceGraphics extends CairoGraphics2D
Graphics2D g2d = (Graphics2D)buffer.getGraphics();
g2d.setPaint(this.getPaint());
g2d.setColor(this.getColor());
+ g2d.setTransform(transform);
g2d.fill(s);
drawComposite(s.getBounds2D(), null);
}
+
+ if (!surface.sharedBuffer)
+ surface.syncNativeToJava(surface.surfacePointer, surface.getData());
}
public void drawRenderedImage(RenderedImage image, AffineTransform xform)
{
+ if (!surface.sharedBuffer)
+ surface.syncJavaToNative(surface.surfacePointer, surface.getData());
+
if (comp == null || comp instanceof AlphaComposite)
super.drawRenderedImage(image, xform);
@@ -161,18 +187,25 @@ public class CairoSurfaceGraphics extends CairoGraphics2D
Graphics2D g2d = (Graphics2D)buffer.getGraphics();
g2d.setRenderingHints(this.getRenderingHints());
+ g2d.setTransform(transform);
g2d.drawRenderedImage(image, xform);
drawComposite(buffer.getRaster().getBounds(), null);
}
-
+
+ if (!surface.sharedBuffer)
+ surface.syncNativeToJava(surface.surfacePointer, surface.getData());
}
protected boolean drawImage(Image img, AffineTransform xform,
Color bgcolor, ImageObserver obs)
{
+ if (!surface.sharedBuffer)
+ surface.syncJavaToNative(surface.surfacePointer, surface.getData());
+
+ boolean ret;
if (comp == null || comp instanceof AlphaComposite)
- return super.drawImage(img, xform, bgcolor, obs);
+ ret = super.drawImage(img, xform, bgcolor, obs);
else
{
@@ -187,14 +220,10 @@ public class CairoSurfaceGraphics extends CairoGraphics2D
BufferedImage bImg = (BufferedImage) img;
// Find translated bounds
- Point2D origin = new Point2D.Double(bImg.getMinX(), bImg.getMinY());
- Point2D pt = new Point2D.Double(bImg.getWidth() + bImg.getMinX(),
- bImg.getHeight() + bImg.getMinY());
+ Rectangle2D bounds = new Rectangle(bImg.getMinX(), bImg.getMinY(),
+ bImg.getWidth(), bImg.getHeight());
if (xform != null)
- {
- origin = xform.transform(origin, origin);
- pt = xform.transform(pt, pt);
- }
+ bounds = getTransformedBounds(bounds, xform);
// Create buffer and draw image
createBuffer();
@@ -204,15 +233,20 @@ public class CairoSurfaceGraphics extends CairoGraphics2D
g2d.drawImage(img, xform, obs);
// Perform compositing
- return drawComposite(new Rectangle2D.Double(origin.getX(),
- origin.getY(),
- pt.getX(), pt.getY()),
- obs);
+ ret = drawComposite(bounds, obs);
}
+
+ if (!surface.sharedBuffer)
+ surface.syncNativeToJava(surface.surfacePointer, surface.getData());
+
+ return ret;
}
public void drawGlyphVector(GlyphVector gv, float x, float y)
{
+ if (!surface.sharedBuffer)
+ surface.syncJavaToNative(surface.surfacePointer, surface.getData());
+
if (comp == null || comp instanceof AlphaComposite)
super.drawGlyphVector(gv, x, y);
@@ -230,51 +264,64 @@ public class CairoSurfaceGraphics extends CairoGraphics2D
bounds.getWidth(), bounds.getHeight());
drawComposite(bounds, null);
}
+
+ if (!surface.sharedBuffer)
+ surface.syncNativeToJava(surface.surfacePointer, surface.getData());
}
private boolean drawComposite(Rectangle2D bounds, ImageObserver observer)
{
- // Clip source to visible areas that need updating
- Rectangle2D clip = this.getClipBounds();
- Rectangle2D.intersect(bounds, clip, bounds);
- clip = new Rectangle(buffer.getMinX(), buffer.getMinY(),
- buffer.getWidth(), buffer.getHeight());
- Rectangle2D.intersect(bounds, clip, bounds);
+ // Find bounds in device space
+ bounds = getTransformedBounds(bounds, transform);
+
+ // Clip bounds by the stored clip, and by the internal buffer
+ Rectangle2D devClip = this.getClipInDevSpace();
+ Rectangle2D.intersect(bounds, devClip, bounds);
+ devClip = new Rectangle(buffer.getMinX(), buffer.getMinY(),
+ buffer.getWidth(), buffer.getHeight());
+ Rectangle2D.intersect(bounds, devClip, bounds);
+
+ // Round bounds as needed, but be careful in our rounding
+ // (otherwise it may leave unpainted stripes)
+ double x = bounds.getX();
+ double y = bounds.getY();
+ double maxX = x + bounds.getWidth();
+ double maxY = y + bounds.getHeight();
+ x = Math.round(x);
+ y = Math.round(y);
+ bounds.setRect(x, y, Math.round(maxX - x), Math.round(maxY - y));
+ // Find subimage of internal buffer for updating
BufferedImage buffer2 = buffer;
if (!bounds.equals(buffer2.getRaster().getBounds()))
buffer2 = buffer2.getSubimage((int)bounds.getX(), (int)bounds.getY(),
(int)bounds.getWidth(),
(int)bounds.getHeight());
-
- // Get destination clip to bounds
- double[] points = new double[] {bounds.getX(), bounds.getY(),
- bounds.getMaxX(), bounds.getMaxY()};
- transform.transform(points, 0, points, 0, 2);
-
- Rectangle2D deviceBounds = new Rectangle2D.Double(points[0], points[1],
- points[2] - points[0],
- points[3] - points[1]);
-
- Rectangle2D.intersect(deviceBounds, this.getClipInDevSpace(), deviceBounds);
-
+
+ // Find subimage of main image for updating
BufferedImage current = CairoSurface.getBufferedImage(surface);
- current = current.getSubimage((int)deviceBounds.getX(),
- (int)deviceBounds.getY(),
- (int)deviceBounds.getWidth(),
- (int)deviceBounds.getHeight());
+ current = current.getSubimage((int)bounds.getX(), (int)bounds.getY(),
+ (int)bounds.getWidth(),
+ (int)bounds.getHeight());
// Perform actual composite operation
compCtx.compose(buffer2.getRaster(), current.getRaster(),
buffer2.getRaster());
+ // Set cairo's composite to direct SRC, since we've already done our own
+ // compositing
+ Composite oldcomp = comp;
+ setComposite(AlphaComposite.Src);
+
// This MUST call directly into the "action" method in CairoGraphics2D,
// not one of the wrappers, to ensure that the composite isn't processed
// more than once!
boolean rv = super.drawImage(buffer2,
AffineTransform.getTranslateInstance(bounds.getX(),
bounds.getY()),
- new Color(0,0,0,0), null);
+ null, null);
+ setComposite(oldcomp);
+ updateColor();
return rv;
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java b/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java
index 8adf275ad44..e54320697d8 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java
@@ -52,7 +52,6 @@ import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
-import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
@@ -78,7 +77,7 @@ public class ComponentGraphics extends CairoGraphics2D
protected long cairo_t;
private BufferedImage buffer, componentBuffer;
- private static ThreadLocal hasLock = new ThreadLocal();
+ private static ThreadLocal<Integer> hasLock = new ThreadLocal<Integer>();
private static Integer ONE = Integer.valueOf(1);
ComponentGraphics()
@@ -122,11 +121,11 @@ public class ComponentGraphics extends CairoGraphics2D
*/
private void lock()
{
- Integer i = (Integer) hasLock.get();
+ Integer i = hasLock.get();
if (i == null)
{
- start_gdk_drawing();
- hasLock.set(ONE);
+ start_gdk_drawing();
+ hasLock.set(ONE);
}
else
hasLock.set(Integer.valueOf(i.intValue() + 1));
@@ -137,14 +136,16 @@ public class ComponentGraphics extends CairoGraphics2D
*/
private void unlock()
{
- Integer i = (Integer) hasLock.get();
+ Integer i = hasLock.get();
if (i == null)
throw new IllegalStateException();
if (i == ONE)
{
- hasLock.set(null);
- end_gdk_drawing();
+ hasLock.set(null);
+ end_gdk_drawing();
}
+ else if (i.intValue() == 2)
+ hasLock.set(ONE);
else
hasLock.set(Integer.valueOf(i.intValue() - 1));
}
@@ -176,11 +177,11 @@ public class ComponentGraphics extends CairoGraphics2D
private static native Pointer nativeGrab(GtkComponentPeer component);
private native void copyAreaNative(GtkComponentPeer component, int x, int y,
- int width, int height, int dx, int dy);
+ int width, int height, int dx, int dy);
private native void drawVolatile(GtkComponentPeer component,
- long vimg, int x, int y,
- int width, int height, int cx, int cy,
+ long vimg, int x, int y,
+ int width, int height, int cx, int cy,
int cw, int ch);
/**
@@ -232,16 +233,16 @@ public class ComponentGraphics extends CairoGraphics2D
{
if (comp == null || comp instanceof AlphaComposite)
super.draw(s);
-
+
else
{
createBuffer();
-
+
Graphics2D g2d = (Graphics2D)buffer.getGraphics();
g2d.setStroke(this.getStroke());
g2d.setColor(this.getColor());
g2d.draw(s);
-
+
drawComposite(s.getBounds2D(), null);
}
}
@@ -250,16 +251,16 @@ public class ComponentGraphics extends CairoGraphics2D
{
if (comp == null || comp instanceof AlphaComposite)
super.fill(s);
-
+
else
{
createBuffer();
-
+
Graphics2D g2d = (Graphics2D)buffer.getGraphics();
g2d.setPaint(this.getPaint());
g2d.setColor(this.getColor());
g2d.fill(s);
-
+
drawComposite(s.getBounds2D(), null);
}
}
@@ -268,7 +269,7 @@ public class ComponentGraphics extends CairoGraphics2D
{
if (comp == null || comp instanceof AlphaComposite)
super.drawRenderedImage(image, xform);
-
+
else
{
createBuffer();
@@ -276,7 +277,7 @@ public class ComponentGraphics extends CairoGraphics2D
Graphics2D g2d = (Graphics2D)buffer.getGraphics();
g2d.setRenderingHints(this.getRenderingHints());
g2d.drawRenderedImage(image, xform);
-
+
drawComposite(buffer.getRaster().getBounds(), null);
}
}
@@ -287,7 +288,7 @@ public class ComponentGraphics extends CairoGraphics2D
boolean rv;
if (comp == null || comp instanceof AlphaComposite)
rv = super.drawImage(img, xform, bgcolor, obs);
-
+
else
{
// Get buffered image of source
@@ -299,7 +300,7 @@ public class ComponentGraphics extends CairoGraphics2D
img = Toolkit.getDefaultToolkit().createImage(source);
}
BufferedImage bImg = (BufferedImage) img;
-
+
// Find translated bounds
Point2D origin = new Point2D.Double(bImg.getMinX(), bImg.getMinY());
Point2D pt = new Point2D.Double(bImg.getWidth() + bImg.getMinX(),
@@ -309,18 +310,18 @@ public class ComponentGraphics extends CairoGraphics2D
origin = xform.transform(origin, origin);
pt = xform.transform(pt, pt);
}
-
+
// Create buffer and draw image
createBuffer();
-
+
Graphics2D g2d = (Graphics2D)buffer.getGraphics();
g2d.setRenderingHints(this.getRenderingHints());
g2d.drawImage(img, xform, obs);
// Perform compositing
rv = drawComposite(new Rectangle2D.Double(origin.getX(),
- origin.getY(),
- pt.getX(), pt.getY()),
+ origin.getY(),
+ pt.getX(), pt.getY()),
obs);
}
return rv;
@@ -330,7 +331,7 @@ public class ComponentGraphics extends CairoGraphics2D
{
if (comp == null || comp instanceof AlphaComposite)
super.drawGlyphVector(gv, x, y);
-
+
else
{
createBuffer();
@@ -339,7 +340,7 @@ public class ComponentGraphics extends CairoGraphics2D
g2d.setPaint(this.getPaint());
g2d.setStroke(this.getStroke());
g2d.drawGlyphVector(gv, x, y);
-
+
Rectangle2D bounds = gv.getLogicalBounds();
bounds = new Rectangle2D.Double(x + bounds.getX(), y + bounds.getY(),
bounds.getWidth(), bounds.getHeight());
@@ -373,8 +374,8 @@ public class ComponentGraphics extends CairoGraphics2D
(int) r.getHeight());
return true;
}
- else
- return super.drawImage(vimg.getSnapshot(), x, y, observer);
+ else
+ return super.drawImage(vimg.getSnapshot(), x, y, observer);
}
BufferedImage bimg;
@@ -382,7 +383,7 @@ public class ComponentGraphics extends CairoGraphics2D
bimg = (BufferedImage) img;
else
{
- ImageProducer source = img.getSource();
+ ImageProducer source = img.getSource();
if (source == null)
return false;
bimg = (BufferedImage) Toolkit.getDefaultToolkit().createImage(source);
@@ -418,9 +419,9 @@ public class ComponentGraphics extends CairoGraphics2D
(int) r.getHeight());
return true;
}
- else
- return super.drawImage(vimg.getSnapshot(), x, y,
- width, height, observer);
+ else
+ return super.drawImage(vimg.getSnapshot(), x, y,
+ width, height, observer);
}
BufferedImage bimg;
@@ -429,7 +430,7 @@ public class ComponentGraphics extends CairoGraphics2D
bimg = (BufferedImage) img;
else
{
- ImageProducer source = img.getSource();
+ ImageProducer source = img.getSource();
if (source == null)
return false;
bimg = (BufferedImage) Toolkit.getDefaultToolkit().createImage(source);
@@ -458,8 +459,8 @@ public class ComponentGraphics extends CairoGraphics2D
transform.transform(points, 0, points, 0, 2);
Rectangle2D deviceBounds = new Rectangle2D.Double(points[0], points[1],
- points[2] - points[0],
- points[3] - points[1]);
+ points[2] - points[0],
+ points[3] - points[1]);
Rectangle2D.intersect(deviceBounds, this.getClipInDevSpace(), deviceBounds);
@@ -519,8 +520,8 @@ public class ComponentGraphics extends CairoGraphics2D
new Point(0,0));
componentBuffer = new BufferedImage(GtkVolatileImage.gdkColorModel, rst,
- GtkVolatileImage.gdkColorModel.isAlphaPremultiplied(),
- new Hashtable());
+ GtkVolatileImage.gdkColorModel.isAlphaPremultiplied(),
+ new Hashtable());
}
}
@@ -723,7 +724,7 @@ public class ComponentGraphics extends CairoGraphics2D
unlock();
}
}
-
+
@Override
protected void cairoRectangle(long pointer, double x, double y,
double width, double height)
@@ -908,4 +909,33 @@ public class ComponentGraphics extends CairoGraphics2D
unlock();
}
}
+
+ @Override
+ protected void cairoSetAntialias(long pointer, boolean aa)
+ {
+ try
+ {
+ lock();
+ super.cairoSetAntialias(pointer, aa);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void drawCairoSurface(CairoSurface surface, AffineTransform tx,
+ double alpha, int interpolation)
+ {
+ try
+ {
+ lock();
+ super.drawCairoSurface(surface, tx, alpha, interpolation);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java b/libjava/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
index 131a964488f..280f3e6fbcd 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
@@ -79,6 +79,11 @@ public class FreetypeGlyphVector extends GlyphVector
* The glyph codes
*/
private int[] glyphCodes;
+
+ /**
+ * The set of fonts used in this glyph vector.
+ */
+ private long[] fontSet = null;
/**
* Glyph transforms. (de facto only the translation is used)
@@ -86,6 +91,19 @@ public class FreetypeGlyphVector extends GlyphVector
private AffineTransform[] glyphTransforms;
private GlyphMetrics[] metricsCache;
+
+ private native void dispose(long[] fonts);
+
+ /**
+ * Returns a pointer to the native PangoFcFont object.
+ *
+ * The object will be referenced with g_object_ref n times before being
+ * returned, and must be unreferenced a corresponding number of times.
+ *
+ * @param n Number of times to reference the object.
+ * @return Pointer to the native default font.
+ */
+ private native long getNativeFontPointer(int n);
/**
* Create a glyphvector from a given (Freetype) font and a String.
@@ -112,11 +130,11 @@ public class FreetypeGlyphVector extends GlyphVector
getGlyphs();
if( flags == Font.LAYOUT_RIGHT_TO_LEFT )
{
- // reverse the glyph ordering.
- int[] temp = new int[ nGlyphs ];
- for(int i = 0; i < nGlyphs; i++)
- temp[ i ] = glyphCodes[ nGlyphs - i - 1];
- glyphCodes = temp;
+ // reverse the glyph ordering.
+ int[] temp = new int[ nGlyphs ];
+ for(int i = 0; i < nGlyphs; i++)
+ temp[i] = glyphCodes[nGlyphs - i - 1];
+ glyphCodes = temp;
}
performDefaultLayout();
}
@@ -135,6 +153,13 @@ public class FreetypeGlyphVector extends GlyphVector
glyphCodes = new int[ codes.length ];
System.arraycopy(codes, 0, glyphCodes, 0, codes.length);
nGlyphs = glyphCodes.length;
+
+ if (fontSet == null)
+ {
+ fontSet = new long[nGlyphs];
+ Arrays.fill(fontSet, getNativeFontPointer(nGlyphs));
+ }
+
performDefaultLayout();
}
@@ -152,11 +177,12 @@ public class FreetypeGlyphVector extends GlyphVector
if( gv.metricsCache != null )
{
- metricsCache = new GlyphMetrics[ nGlyphs ];
- System.arraycopy(gv.metricsCache, 0, metricsCache, 0, nGlyphs);
+ metricsCache = new GlyphMetrics[ nGlyphs ];
+ System.arraycopy(gv.metricsCache, 0, metricsCache, 0, nGlyphs);
}
glyphCodes = new int[ nGlyphs ];
+ fontSet = new long[nGlyphs];
glyphPositions = new float[(nGlyphs + 1) * 2];
glyphTransforms = new AffineTransform[ nGlyphs ];
for(int i = 0; i < nGlyphs; i++ )
@@ -166,6 +192,13 @@ public class FreetypeGlyphVector extends GlyphVector
}
System.arraycopy(gv.glyphPositions, 0, glyphPositions, 0,
glyphPositions.length);
+ System.arraycopy(gv.glyphCodes, 0, glyphCodes, 0, nGlyphs);
+ System.arraycopy(gv.fontSet, 0, fontSet, 0, nGlyphs);
+ }
+
+ public void finalize()
+ {
+ dispose(fontSet);
}
/**
@@ -175,16 +208,17 @@ public class FreetypeGlyphVector extends GlyphVector
{
nGlyphs = s.codePointCount( 0, s.length() );
glyphCodes = new int[ nGlyphs ];
+ fontSet = new long[ nGlyphs ];
int[] codePoints = new int[ nGlyphs ];
int stringIndex = 0;
for(int i = 0; i < nGlyphs; i++)
{
- codePoints[i] = s.codePointAt( stringIndex );
+ codePoints[i] = s.codePointAt( stringIndex );
// UTF32 surrogate handling
- if( codePoints[i] != (int)s.charAt( stringIndex ) )
- stringIndex ++;
- stringIndex ++;
+ if( codePoints[i] != (int)s.charAt( stringIndex ) )
+ stringIndex ++;
+ stringIndex ++;
if (Character.isISOControl(codePoints[i]))
{
@@ -194,22 +228,22 @@ public class FreetypeGlyphVector extends GlyphVector
}
}
- glyphCodes = getGlyphs( codePoints );
+ getGlyphs( codePoints, glyphCodes, fontSet );
}
/**
* Returns the glyph code within the font for a given character
*/
- public native int[] getGlyphs(int[] codepoints);
+ public native void getGlyphs(int[] codepoints, int[] glyphs, long[] fonts);
/**
* Returns the kerning of a glyph pair
*/
- private native Point2D getKerning(int leftGlyph, int rightGlyph);
+ private native Point2D getKerning(int leftGlyph, int rightGlyph, long font);
- private native double[] getMetricsNative( int glyphCode );
+ private native double[] getMetricsNative(int glyphCode, long font);
- private native GeneralPath getGlyphOutlineNative(int glyphIndex);
+ private native GeneralPath getGlyphOutlineNative(int glyphIndex, long font);
public Object clone()
@@ -267,10 +301,12 @@ public class FreetypeGlyphVector extends GlyphVector
x += gm.getAdvanceX();
y += gm.getAdvanceY();
-
- if (i != nGlyphs-1)
+
+ // Get the kerning only if it's not the last glyph, and the two glyphs are
+ // using the same font
+ if (i != nGlyphs-1 && fontSet[i] == fontSet[i+1])
{
- Point2D p = getKerning(glyphCodes[i], glyphCodes[i + 1]);
+ Point2D p = getKerning(glyphCodes[i], glyphCodes[i + 1], fontSet[i]);
x += p.getX();
y += p.getY();
}
@@ -291,7 +327,7 @@ public class FreetypeGlyphVector extends GlyphVector
* Returns multiple glyphcodes.
*/
public int[] getGlyphCodes(int beginGlyphIndex, int numEntries,
- int[] codeReturn)
+ int[] codeReturn)
{
int[] rval;
@@ -305,6 +341,26 @@ public class FreetypeGlyphVector extends GlyphVector
return rval;
}
+ /**
+ * Returns pointers to the fonts used in this glyph vector.
+ *
+ * The array index matches that of the glyph vector itself.
+ */
+ protected long[] getGlyphFonts(int beginGlyphIndex, int numEntries,
+ long[] codeReturn)
+ {
+ long[] rval;
+
+ if( codeReturn == null || codeReturn.length < numEntries)
+ rval = new long[ numEntries ];
+ else
+ rval = codeReturn;
+
+ System.arraycopy(fontSet, beginGlyphIndex, rval, 0, numEntries);
+
+ return rval;
+ }
+
public Shape getGlyphLogicalBounds(int glyphIndex)
{
GlyphMetrics gm = getGlyphMetrics( glyphIndex );
@@ -335,26 +391,24 @@ public class FreetypeGlyphVector extends GlyphVector
for(int i = 0; i < nGlyphs; i++)
{
- GlyphMetrics gm = (GlyphMetrics)
- peer.getGlyphMetrics( glyphCodes[ i ] );
- if( gm == null )
- {
- double[] val = getMetricsNative( glyphCodes[ i ] );
- if( val == null )
- gm = null;
- else
- {
- gm = new GlyphMetrics( true,
- (float)val[1],
- (float)val[2],
- new Rectangle2D.Double
- ( val[3], val[4],
- val[5], val[6] ),
- GlyphMetrics.STANDARD );
- peer.putGlyphMetrics( glyphCodes[ i ], gm );
- }
- }
- metricsCache[ i ] = gm;
+ GlyphMetrics gm = (GlyphMetrics)peer.getGlyphMetrics(glyphCodes[i]);
+ if( gm == null )
+ {
+ double[] val = getMetricsNative(glyphCodes[i], fontSet[i]);
+ if( val == null )
+ gm = null;
+ else
+ {
+ gm = new GlyphMetrics(true,
+ (float)val[1],
+ (float)val[2],
+ new Rectangle2D.Double(val[3], val[4],
+ val[5], val[6] ),
+ GlyphMetrics.STANDARD );
+ peer.putGlyphMetrics( glyphCodes[ i ], gm );
+ }
+ }
+ metricsCache[ i ] = gm;
}
}
@@ -371,13 +425,21 @@ public class FreetypeGlyphVector extends GlyphVector
/**
* Returns the outline of a single glyph.
+ *
+ * Despite what the Sun API says, this method returns the glyph relative to
+ * the origin of the *entire string*, not each individual glyph.
*/
public Shape getGlyphOutline(int glyphIndex)
{
- GeneralPath gp = getGlyphOutlineNative( glyphCodes[ glyphIndex ] );
- if (glyphTransforms[glyphIndex] != null)
- gp.transform( glyphTransforms[glyphIndex]);
+ GeneralPath gp = getGlyphOutlineNative(glyphCodes[glyphIndex],
+ fontSet[glyphIndex]);
+ AffineTransform tx = AffineTransform.getTranslateInstance(glyphPositions[glyphIndex*2],
+ glyphPositions[glyphIndex*2+1]);
+ if (glyphTransforms[glyphIndex] != null)
+ tx.concatenate( glyphTransforms[glyphIndex]);
+
+ gp.transform(tx);
return gp;
}
@@ -432,7 +494,6 @@ public class FreetypeGlyphVector extends GlyphVector
return logicalBounds;
Rectangle2D rect = (Rectangle2D)getGlyphLogicalBounds( 0 );
- AffineTransform tx = new AffineTransform();
for( int i = 1; i < nGlyphs; i++ )
{
Rectangle2D r2 = (Rectangle2D)getGlyphLogicalBounds( i );
@@ -458,14 +519,8 @@ public class FreetypeGlyphVector extends GlyphVector
public Shape getOutline()
{
GeneralPath path = new GeneralPath();
- AffineTransform tx = new AffineTransform();
for( int i = 0; i < getNumGlyphs(); i++ )
- {
- Shape outline = getGlyphOutline(i);
- tx.setToTranslation(glyphPositions[i*2], glyphPositions[i*2 +1]);
- outline = tx.createTransformedShape(outline);
- path.append(outline, false);
- }
+ path.append(getGlyphOutline(i), false);
return path;
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GThreadMutex.java b/libjava/classpath/gnu/java/awt/peer/gtk/GThreadMutex.java
deleted file mode 100644
index e73df9e5509..00000000000
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GThreadMutex.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/* GThreadMutex.java -- Implements a mutex object for glib's gthread
- abstraction, for use with GNU Classpath's --portable-native-sync option.
- This is used in gthread-jni.c
-
- Copyright (C) 2004 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;
-
-/** Implements a mutex object for glib's gthread
- abstraction, for use with GNU Classpath's --portable-native-sync option.
- This is used in gthread-jni.c.
-
- We use this object to implement the POSIX semantics for Mutexes. They are
- needed are needed for the function vector that is passed to glib's
- g_thread subpackage's initialization function.
-
- The GThreadMutex object itself serves as the Real Lock; if code has
- entered the monitor for this GThreadMutex object (in Java language, if
- it's synchronized on this object) then it holds the lock that this object
- represents.
-
- @author Steven Augart
- May, 2004
-
-
-*/
-
-class GThreadMutex
-{
- /** Might "lock" be locked? Is anyone waiting
- to get that lock? How long is the queue?
-
- If zero, nobody holds a lock on this GThreadMutex object, and nobody is
- trying to get one. Before someone attempts to acquire a lock on this
- object, they must increment potentialLockers. After they release their
- lock on this object, they must decrement potentialLockers.
-
- Access to this field is guarded by synchronizing on the object
- <code>lockForPotentialLockers</code>.
-
- After construction, we only access this field via JNI.
- */
- volatile int potentialLockers;
-
- /** An object to synchronize to if you want to examine or modify the
- <code>potentialLockers</code> field. Only hold this lock for brief
- moments, just long enough to check or set the value of
- <code>lockForPotentialLockers</code>.
-
- We use this representation so that g_thread_mutex_trylock() will work
- with the POSIX semantics. This is the only case in which you ever hold a
- lock on <code>lockForPotentialLockers</code> while trying to get another
- lock -- if you are the mutex_trylock() implementation, and you have just
- checked that <code>potentialLockers</code> has the value zero. In that
- case, mutex_trylock() holds the lock on lockForPotentialLockers so that
- another thread calling mutex_trylock() or mutex_lock() won't increment
- potentialLockers after we've checked it and before we've gained the lock
- on the POSIX mutex. Of course, in that case the operation of gaining
- the POSIX lock itself will succeed immediately, and once it has
- succeeded, trylock releases lockForPotentialLockers right away,
- incremented to 1 (one).
-
- After construction, we only access this field via JNI.
- */
- Object lockForPotentialLockers;
-
- GThreadMutex()
- {
- potentialLockers = 0;
- lockForPotentialLockers = new Object();
- }
-}
-// Local Variables:
-// c-file-style: "gnu"
-// End:
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java b/libjava/classpath/gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java
deleted file mode 100644
index 9a1b8e3a30a..00000000000
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java
+++ /dev/null
@@ -1,303 +0,0 @@
-/* GThreadNativeMethodRunner.java -- Implements pthread_create(), under
- glib's gthread abstraction, for use with GNU Classpath's
- --portable-native-sync option.
- This is used by gthread-jni.c
-
- Copyright (C) 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 java.lang.ref.WeakReference;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-/** Implements pthread_create(), under glib's gthread abstraction, for use
- with GNU Classpath's --portable-native-sync option. This is used in
- gthread-jni.c
-
- Also implements a registry for threads, mapping Thread objects to small
- integers. The registry uses weak references for threads that aren't
- joinable, so that they will be garbage collected.
-
- There are a number of possible alternative implementations.
-
-
- The rest of this comment consists of an answer to a question that was
- raised on the commit-classpath mailing list:
-
- Mark Wielaard wrote:
-
- > Can't we assume that jobject and gpointer are both (void *) so we don't
- > need the int <-> Thread (global jobject ref) mapping?
- > Maybe there are platforms where jobject and gpointer aren't the same,
- > but I guess that is pretty unlikely.
-
-
- I agree with you on the pointer size issues. A gpointer is a void *, so
- it's certainly guaranteed to be at least as large as any other
- pointer. And a jobject is implicitly an opaque pointer (in Jikes RVM, we
- use small integers, but we coerce them into the representation of a
- pointer).
-
- The int <==> Thread mapping addresses a different issue. I realize that I
- did not document this properly (two and a half lines in thread_create),
- and the point is subtle (at least to me; took me a while to figure out).
-
- The int => Thread mapping always returns jobjects that are local
- references, not global ones. This is because Thread objects need to be
- able to go away and be garbage collected after the thread they refer to
- has died.
-
- If we keep a global object reference to a thread, then when do we delete
- that global object reference? We have an answer in the case of GThread
- objects that were explicitly created with the joinable attribute. It is
- safe for us to maintain a global reference to any joinable thread, since
- the joinable thread must linger (even if only in a zombie state)
- until it's explicitly joined via a g_thread_join() call. The global ref
- could be cleaned up at that point too.
-
- However, in the case of GThreads that were created non-joinable by
- g_thread_create(), and in the case of Java threads that were created
- within pure Java code (not via g_thread_create()), we don't want them to
- linger forever, and there is no way to tell when the last reference
- to such threads needs to expire. In the case of this application -- AWT
- with GTK peers -- it would probably be safe anyway, since there are not
- very many threads we create, but I was going for correctness even in the
- case of long-running programs that might set up and tear down AWT
- interfaces many times.
-
- So, I duplicated the POSIX thread-ID semantics. The thread ID of a
- non-joinable thread remains valid as long as that thread is still alive.
- Once that thread dies, the old thread ID may be reused at any moment. And
- that's why the array indexed by thread ID numbers is an array of weak
- references.
-
- That's also why the int => Thread jobject mapping function always returns
- local references, since global references would lock the Thread in memory
- forever.
-
- I would dearly love there to be a cleaner solution. I dislike the
- repeated dips from C code into Java that are necessary to look up thread
- ID numbers. If anyone can think of one, I'm all ears.
-*/
-
-class GThreadNativeMethodRunner
- extends Thread
-{
- /** The C function pointer that was passed to g_thread_create().
- Specifically, this the numeric address of an object of
- C type "void *(*funcPtr)(void *funcArg)".
- */
- private final long funcPtr;
-
- /** The argument for the function "funcPtr(funcArg)". */
- private final long funcArg;
-
- GThreadNativeMethodRunner(long funcPtr, long funcArg, boolean joinable)
- {
- this.funcPtr = funcPtr;
- this.funcArg = funcArg;
-
- if (joinable)
- registerSelfJoinable();
- }
-
- public void run()
- {
- nativeRun(funcPtr, funcArg);
- }
-
- private native void nativeRun(long funcPtr, long funcArg);
-
- /** THREADS is an array of threads, indexed by thread ID codes. Not sure
- whether this is the "best" approach but it does make it O(1) to look up a
- thread by its ID.
-
- Zero is a valid thread ID code. Any negative number is invalid.
-
- Possible future fixes (TODO?)
-
- - The THREADS array will only grow. probably not a problem.
- But we could keep count when nulling entries and shrink when we have
- lots of nulls at the end. Probably not worth it. --mjw
-
- - Could make this a set of Object; see the comment on "joinable" below.
-
- The initial size of 17 is just a starting point. Any number will do,
- including zero.
- */
- private static WeakReference[] threads = new WeakReference[17];
-
- /** Used by threadToThreadID, below. Returns the registration number of
- the newly-registered thread.
- */
- private static synchronized int registerThread(Thread t)
- {
- int i;
-
- for (i = 0; i < threads.length; ++i)
- {
- WeakReference ref = threads[i];
- if (ref == null)
- break; // found an empty spot.
- }
-
- if (i == threads.length)
- {
- /* expand the array */
- WeakReference[] bigger = new WeakReference[threads.length * 2];
- System.arraycopy(threads, 0, bigger, 0, threads.length);
- threads = bigger;
- }
-
- threads[i] = new WeakReference(t);
-
- return i;
- }
-
- /** Look up the Thread ID # for a Thread. Assign a Thread ID # if none
- exists. This is a general routine for handling all threads, including
- the VM's main thread, if appropriate.
-
-
- Runs in O(n/2) time.
-
- We can't just issue a threadID upon thread creation. If we were to do
- that, not all threads would have a threadID, because not all threads
- are launched by GThreadNativeMethodRunner.
- */
- static synchronized int threadToThreadID(Thread t)
- {
- for (int i = 0; i < threads.length; ++i )
- {
- if (threads[i] == null)
- continue;
- Thread referent = (Thread) threads[i].get();
- if (referent == null)
- {
- threads[i] = null; // Purge the dead WeakReference.
- continue;
- }
- if (referent.equals(t))
- return i;
- } // for()
-
- /* No match found. */
- return registerThread(t);
- }
-
- /** @param threadID Must be a non-negative integer.
-
- Used to return null if the thread number was out of range or if
- the thread was unregistered. Now we throw an exception.
-
- Possible Alternative Interface: We could go back to returning null in
- some sort of check-free mode, so code that calls this function must
- be prepared to get null.
- */
- static Thread threadIDToThread(int threadID)
- throws IllegalArgumentException
- {
- if (threadID < 0)
- throw new IllegalArgumentException("Received a negative threadID, "
- + threadID);
- if (threadID >= threads.length)
- throw new IllegalArgumentException("Received a threadID (" + threadID
- + ") higher than was"
- + " ever issued");
-
- /* Note: if the user is using a stale reference, things will just
- break. We might end up getting a different thread than the one
- expected.
-
- TODO: Add an error-checking mode where the user's problems with threads
- are announced. For instance, if the user asks for the thread
- associated with a threadID that was never issued, we could print a
- warning or even abort.
-
- TODO: Consider optionally disabling all of the error-checking we
- already have; it probably slows down the implementation. We could
- just return NULL. This is just the reverse of the above TODO item.
- */
-
- WeakReference threadRef = threads[threadID];
-
- if (threadRef == null)
- throw new IllegalArgumentException("Asked to look up a stale or unissued"
- + "threadID (" + threadID + ")" );
-
-
- Thread referent = (Thread) threadRef.get();
- if (referent == null)
- throw new IllegalArgumentException ("Asked to look up a stale threadID ("
- + threadID + ")");
- return referent;
- }
-
- /** Joinable threads need a hard reference, so that they won't go away when
- they die. That is because their thread IDs need to stay valid until the
- thread is joined via thread_join(threadID). Joinable threads have to be
- explicitly joined before they are allowed to go away completely.
-
- Possible Alternative Implementation: Eliminate the Joinable set. When
- calling getThreadIDFromThread() you know whether or not the thread
- is joinable. So just store the Thread itself in the threads array?
- Make that array an Object array and check with instanceof. This
- looks cleaner and more robust to me and it saves a native -> Java
- call. But instanceof might be expensive. --mjw
- */
- private static final Set joinable =
- Collections.synchronizedSet(new HashSet());
-
- /** Only called from the constructor. */
- private void registerSelfJoinable()
- {
- joinable.add(this);
- }
-
- /** This method is only called from JNI, and only after we have succeeded in
- a thread_join() operation. */
- static void deRegisterJoinable(Thread thread)
- {
- joinable.remove(thread);
- }
-}
-
-// Local Variables:
-// c-file-style: "gnu"
-// End:
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java
index 5f5126ac590..c3c94d8a935 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java
@@ -67,7 +67,7 @@ public class GdkFontPeer extends ClasspathFontPeer
* The size of the cache has been chosen so that relativly large GUIs with
* text documents are still efficient.
*/
- HashMap textLayoutCache = new GtkToolkit.LRUCache(500);
+ HashMap<String,TextLayout> textLayoutCache = new GtkToolkit.LRUCache<String,TextLayout>(500);
private class GdkFontMetrics extends FontMetrics
{
@@ -79,7 +79,7 @@ public class GdkFontPeer extends ClasspathFontPeer
public int stringWidth (String str)
{
- TextLayout tl = (TextLayout) textLayoutCache.get(str);
+ TextLayout tl = textLayoutCache.get(str);
if (tl == null)
{
tl = new TextLayout(str, font, DEFAULT_CTX);
@@ -140,7 +140,7 @@ public class GdkFontPeer extends ClasspathFontPeer
/**
* Cache GlyphMetrics objects.
*/
- private HashMap metricsCache;
+ private HashMap<Integer,GlyphMetrics> metricsCache;
private static final int FONT_METRICS_ASCENT = 0;
private static final int FONT_METRICS_MAX_ASCENT = 1;
@@ -235,7 +235,7 @@ public class GdkFontPeer extends ClasspathFontPeer
super(name, style, size);
initState ();
setFont (this.familyName, this.style, (int)this.size);
- metricsCache = new HashMap();
+ metricsCache = new HashMap<Integer,GlyphMetrics>();
setupMetrics();
}
@@ -244,7 +244,7 @@ public class GdkFontPeer extends ClasspathFontPeer
super(name, attributes);
initState ();
setFont (this.familyName, this.style, (int)this.size);
- metricsCache = new HashMap();
+ metricsCache = new HashMap<Integer,GlyphMetrics>();
setupMetrics();
}
@@ -261,9 +261,9 @@ public class GdkFontPeer extends ClasspathFontPeer
return font;
else
{
- ClasspathToolkit toolkit;
- toolkit = (ClasspathToolkit) Toolkit.getDefaultToolkit();
- return toolkit.getFont(font.getName(), font.getAttributes());
+ ClasspathToolkit toolkit;
+ toolkit = (ClasspathToolkit) Toolkit.getDefaultToolkit();
+ return toolkit.getFont(font.getName(), font.getAttributes());
}
}
@@ -294,9 +294,9 @@ public class GdkFontPeer extends ClasspathFontPeer
name = getName(NameDecoder.NAME_SUBFAMILY, locale);
if (name == null)
{
- name = getName(NameDecoder.NAME_SUBFAMILY, Locale.ENGLISH);
- if ("Regular".equals(name))
- name = null;
+ name = getName(NameDecoder.NAME_SUBFAMILY, Locale.ENGLISH);
+ if ("Regular".equals(name))
+ name = null;
}
return name;
@@ -340,12 +340,12 @@ public class GdkFontPeer extends ClasspathFontPeer
{
if (nameTable == null)
{
- byte[] data = getTrueTypeTable((byte)'n', (byte) 'a',
- (byte) 'm', (byte) 'e');
- if( data == null )
- return null;
+ byte[] data = getTrueTypeTable((byte)'n', (byte) 'a',
+ (byte) 'm', (byte) 'e');
+ if( data == null )
+ return null;
- nameTable = ByteBuffer.wrap( data );
+ nameTable = ByteBuffer.wrap( data );
}
return NameDecoder.getName(nameTable, name, locale);
@@ -492,8 +492,8 @@ public class GdkFontPeer extends ClasspathFontPeer
char[] chars, int start, int limit,
int flags)
{
- return new FreetypeGlyphVector( font, chars, start, limit - start,
- frc, flags);
+ return new FreetypeGlyphVector(font, chars, start, limit - start,
+ frc, flags);
}
public LineMetrics getLineMetrics (Font font, String str,
@@ -515,13 +515,13 @@ public class GdkFontPeer extends ClasspathFontPeer
*/
GlyphMetrics getGlyphMetrics( int glyphCode )
{
- return (GlyphMetrics)metricsCache.get( new Integer( glyphCode ) );
+ return metricsCache.get(new Integer(glyphCode));
}
/**
* Put a GlyphMetrics object in the cache.
*/
- void putGlyphMetrics( int glyphCode, Object metrics )
+ void putGlyphMetrics( int glyphCode, GlyphMetrics metrics )
{
metricsCache.put( new Integer( glyphCode ), metrics );
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java
index db725b697df..bd6daa2d1e5 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java
@@ -38,16 +38,21 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
+import gnu.java.awt.ClasspathGraphicsEnvironment;
+
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
import java.awt.image.Raster;
+import java.awt.image.SampleModel;
+import java.awt.image.WritableRaster;
import java.util.Locale;
-public class GdkGraphicsEnvironment extends GraphicsEnvironment
+public class GdkGraphicsEnvironment extends ClasspathGraphicsEnvironment
{
private final int native_state = GtkGenericPeer.getUniqueInteger ();
@@ -139,4 +144,13 @@ public class GdkGraphicsEnvironment extends GraphicsEnvironment
* Used by GtkMouseInfoPeer.
*/
native int[] getMouseCoordinates();
+
+ public WritableRaster createRaster(ColorModel cm, SampleModel sm)
+ {
+ if (CairoSurface.isCompatibleSampleModel(sm)
+ && CairoSurface.isCompatibleColorModel(cm))
+ return new CairoSurface(sm.getWidth(), sm.getHeight());
+ else
+ return null;
+ }
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java
index 6d0a52b91be..6f6ea560db7 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java
@@ -184,22 +184,22 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
int len = 0;
synchronized(pixbufLock)
{
- initState();
+ initState();
}
needsClose = true;
// Note: We don't want the pixbufLock while reading from the InputStream.
while ((len = is.read (bytes)) != -1)
{
- synchronized(pixbufLock)
- {
- pumpBytes (bytes, len);
- }
+ synchronized(pixbufLock)
+ {
+ pumpBytes (bytes, len);
+ }
}
synchronized(pixbufLock)
{
- pumpDone();
+ pumpDone();
}
needsClose = false;
@@ -217,7 +217,7 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
{
synchronized(pixbufLock)
{
- finish(needsClose);
+ finish(needsClose);
}
}
@@ -226,8 +226,8 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
{
public String name;
public boolean writable = false;
- public ArrayList mimeTypes = new ArrayList();
- public ArrayList extensions = new ArrayList();
+ public ArrayList<String> mimeTypes = new ArrayList<String>();
+ public ArrayList<String> extensions = new ArrayList<String>();
public ImageFormatSpec(String name, boolean writable)
{
@@ -246,7 +246,7 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
}
}
- static ArrayList imageFormatSpecs;
+ static ArrayList<ImageFormatSpec> imageFormatSpecs;
public static ImageFormatSpec registerFormat(String name, boolean writable)
{
@@ -254,7 +254,7 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
synchronized(GdkPixbufDecoder.class)
{
if (imageFormatSpecs == null)
- imageFormatSpecs = new ArrayList();
+ imageFormatSpecs = new ArrayList<ImageFormatSpec>();
imageFormatSpecs.add(ifs);
}
return ifs;
@@ -262,13 +262,13 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
static String[] getFormatNames(boolean writable)
{
- ArrayList names = new ArrayList();
+ ArrayList<String> names = new ArrayList<String>();
synchronized (imageFormatSpecs)
{
- Iterator i = imageFormatSpecs.iterator();
+ Iterator<ImageFormatSpec> i = imageFormatSpecs.iterator();
while (i.hasNext())
{
- ImageFormatSpec ifs = (ImageFormatSpec) i.next();
+ ImageFormatSpec ifs = i.next();
if (writable && !ifs.writable)
continue;
names.add(ifs.name);
@@ -279,62 +279,50 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
* This generally means "all the extensions people might use".
*/
- Iterator j = ifs.extensions.iterator();
+ Iterator<String> j = ifs.extensions.iterator();
while (j.hasNext())
- names.add((String) j.next());
+ names.add(j.next());
}
}
- Object[] objs = names.toArray();
- String[] strings = new String[objs.length];
- for (int i = 0; i < objs.length; ++i)
- strings[i] = (String) objs[i];
- return strings;
+ return names.toArray(new String[names.size()]);
}
static String[] getFormatExtensions(boolean writable)
{
- ArrayList extensions = new ArrayList();
+ ArrayList<String> extensions = new ArrayList<String>();
synchronized (imageFormatSpecs)
{
- Iterator i = imageFormatSpecs.iterator();
+ Iterator<ImageFormatSpec> i = imageFormatSpecs.iterator();
while (i.hasNext())
{
- ImageFormatSpec ifs = (ImageFormatSpec) i.next();
+ ImageFormatSpec ifs = i.next();
if (writable && !ifs.writable)
continue;
- Iterator j = ifs.extensions.iterator();
+ Iterator<String> j = ifs.extensions.iterator();
while (j.hasNext())
- extensions.add((String) j.next());
+ extensions.add(j.next());
}
}
- Object[] objs = extensions.toArray();
- String[] strings = new String[objs.length];
- for (int i = 0; i < objs.length; ++i)
- strings[i] = (String) objs[i];
- return strings;
+ return extensions.toArray(new String[extensions.size()]);
}
static String[] getFormatMimeTypes(boolean writable)
{
- ArrayList mimeTypes = new ArrayList();
+ ArrayList<String> mimeTypes = new ArrayList<String>();
synchronized (imageFormatSpecs)
{
- Iterator i = imageFormatSpecs.iterator();
+ Iterator<ImageFormatSpec> i = imageFormatSpecs.iterator();
while (i.hasNext())
{
- ImageFormatSpec ifs = (ImageFormatSpec) i.next();
+ ImageFormatSpec ifs = i.next();
if (writable && !ifs.writable)
continue;
- Iterator j = ifs.mimeTypes.iterator();
+ Iterator<String> j = ifs.mimeTypes.iterator();
while (j.hasNext())
- mimeTypes.add((String) j.next());
+ mimeTypes.add(j.next());
}
}
- Object[] objs = mimeTypes.toArray();
- String[] strings = new String[objs.length];
- for (int i = 0; i < objs.length; ++i)
- strings[i] = (String) objs[i];
- return strings;
+ return mimeTypes.toArray(new String[mimeTypes.size()]);
}
@@ -348,10 +336,10 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
String str = (String) ext;
- Iterator i = imageFormatSpecs.iterator();
+ Iterator<ImageFormatSpec> i = imageFormatSpecs.iterator();
while (i.hasNext())
{
- ImageFormatSpec ifs = (ImageFormatSpec) i.next();
+ ImageFormatSpec ifs = i.next();
if (needWritable && !ifs.writable)
continue;
@@ -359,10 +347,10 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
if (ifs.name.equals(str))
return str;
- Iterator j = ifs.extensions.iterator();
+ Iterator<String> j = ifs.extensions.iterator();
while (j.hasNext())
{
- String extension = (String)j.next();
+ String extension = j.next();
if (extension.equals(str))
return ifs.name;
}
@@ -370,7 +358,7 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
j = ifs.mimeTypes.iterator();
while (j.hasNext())
{
- String mimeType = (String)j.next();
+ String mimeType = j.next();
if (mimeType.equals(str))
return ifs.name;
}
@@ -510,10 +498,10 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
if (pixels == null)
{
- BufferedImage img;
- if(model != null && model.hasAlpha())
- img = CairoSurface.getBufferedImage(width, height);
- img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+ BufferedImage img;
+ if(model != null && model.hasAlpha())
+ img = CairoSurface.getBufferedImage(width, height);
+ img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
int[] pix = new int[4];
for (int y = 0; y < height; ++y)
for (int x = 0; x < width; ++x)
@@ -527,10 +515,10 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
workerThread.start();
processImageStarted(1);
synchronized(pixbufLock)
- {
- streamImage(pixels, this.ext, width, height, model.hasAlpha(),
- this);
- }
+ {
+ streamImage(pixels, this.ext, width, height, model.hasAlpha(),
+ this);
+ }
synchronized(data)
{
data.add(DATADONE);
@@ -539,18 +527,18 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
while (workerThread.isAlive())
{
- try
- {
- workerThread.join();
- }
- catch (InterruptedException ioe)
- {
- // Ignored.
- }
+ try
+ {
+ workerThread.join();
+ }
+ catch (InterruptedException ioe)
+ {
+ // Ignored.
+ }
}
if (exception != null)
- throw exception;
+ throw exception;
processImageComplete();
}
@@ -566,7 +554,7 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
* Needs to be synchronized for access.
* The special object DATADONE is added when all data has been delivered.
*/
- private ArrayList data = new ArrayList();
+ private ArrayList<Object> data = new ArrayList<Object>();
/**
* Holds any IOException thrown by the run method that needs
@@ -643,7 +631,8 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
this.ext = findFormatName(ext, false);
}
- public GdkPixbufReader(GdkPixbufReaderSpi ownerSpi, Object ext, GdkPixbufDecoder d)
+ public GdkPixbufReader(GdkPixbufReaderSpi ownerSpi, Object ext,
+ GdkPixbufDecoder d)
{
this(ownerSpi, ext);
dec = d;
@@ -680,10 +669,12 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
if (bufferedImage == null)
{
- if(model != null && model.hasAlpha())
- bufferedImage = new BufferedImage (width, height, BufferedImage.TYPE_INT_ARGB);
- else
- bufferedImage = new BufferedImage (width, height, BufferedImage.TYPE_INT_RGB);
+ if(model != null && model.hasAlpha())
+ bufferedImage = new BufferedImage (width, height,
+ BufferedImage.TYPE_INT_ARGB);
+ else
+ bufferedImage = new BufferedImage (width, height,
+ BufferedImage.TYPE_INT_RGB);
}
int pixels2[];
@@ -735,11 +726,11 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
return null;
}
- public Iterator getImageTypes(int imageIndex)
+ public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex)
throws IOException
{
BufferedImage img = getBufferedImage();
- Vector vec = new Vector();
+ Vector<ImageTypeSpecifier> vec = new Vector<ImageTypeSpecifier>();
vec.add(new ImageTypeSpecifier(img));
return vec.iterator();
}
@@ -767,8 +758,8 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
else if (get instanceof DataInput)
dec = new GdkPixbufDecoder((DataInput) get);
else
- throw new IllegalArgumentException("input object not supported: "
- + get);
+ throw new IllegalArgumentException("input object not supported: "
+ + get);
}
public BufferedImage read(int imageIndex, ImageReadParam param)
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java
index 62116a3226c..a69c6f0659e 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java
@@ -188,7 +188,7 @@ class GdkScreenGraphicsDevice extends GraphicsDevice
displayModes = nativeGetDisplayModes(env);
}
- ArrayList list = new ArrayList();
+ ArrayList<DisplayMode> list = new ArrayList<DisplayMode>();
for(int i=0;i<displayModes.length;i++)
for(int j=0;j<displayModes[i].rates.length;j++)
list.add(new DisplayMode(displayModes[i].width,
@@ -196,7 +196,7 @@ class GdkScreenGraphicsDevice extends GraphicsDevice
DisplayMode.BIT_DEPTH_MULTI,
displayModes[i].rates[j]));
- return (DisplayMode[]) list.toArray(new DisplayMode[list.size()]);
+ return list.toArray(new DisplayMode[list.size()]);
}
native X11DisplayMode[] nativeGetDisplayModes(GdkGraphicsEnvironment env);
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java
index 90d16c57282..4a41d0696c3 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java
@@ -57,7 +57,8 @@ public class GtkCheckboxPeer extends GtkComponentPeer
private boolean currentState;
// A map from CheckboxGroup to GSList* GTK option group pointer.
- private static WeakHashMap groupMap = new WeakHashMap();
+ private static WeakHashMap<CheckboxGroup,Long> groupMap
+ = new WeakHashMap<CheckboxGroup,Long>();
public native void createCheckButton ();
public native void createRadioButton (long groupPointer);
@@ -98,7 +99,7 @@ public class GtkCheckboxPeer extends GtkComponentPeer
Long groupPointer = null;
synchronized (groupMap)
{
- groupPointer = (Long) groupMap.get(current_group);
+ groupPointer = groupMap.get(current_group);
}
if (groupPointer == null)
@@ -133,8 +134,8 @@ public class GtkCheckboxPeer extends GtkComponentPeer
{
if (currentState != state)
{
- currentState = state;
- gtkToggleButtonSetActive(state);
+ currentState = state;
+ gtkToggleButtonSetActive(state);
}
}
@@ -158,7 +159,7 @@ public class GtkCheckboxPeer extends GtkComponentPeer
Long groupPointer = null;
synchronized (groupMap)
{
- groupPointer = (Long) groupMap.get(current_group);
+ groupPointer = groupMap.get(current_group);
}
if (groupPointer == null)
@@ -203,7 +204,7 @@ public class GtkCheckboxPeer extends GtkComponentPeer
Long groupPointer = null;
synchronized (groupMap)
{
- groupPointer = (Long) groupMap.get(current_group);
+ groupPointer = groupMap.get(current_group);
}
if (groupPointer == null)
@@ -230,9 +231,9 @@ public class GtkCheckboxPeer extends GtkComponentPeer
// Only fire event is state actually changed.
if (currentState != state)
{
- currentState = state;
- super.postItemEvent(awtComponent,
- state ? ItemEvent.SELECTED : ItemEvent.DESELECTED);
+ currentState = state;
+ super.postItemEvent(awtComponent,
+ state ? ItemEvent.SELECTED : ItemEvent.DESELECTED);
}
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkChoicePeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkChoicePeer.java
index d866cefd33c..ff061d35c74 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkChoicePeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkChoicePeer.java
@@ -55,12 +55,12 @@ public class GtkChoicePeer extends GtkComponentPeer
int count = c.getItemCount ();
if (count > 0)
{
- for (int i = 0; i < count; i++)
- add( c.getItem(i), i );
+ for (int i = 0; i < count; i++)
+ add(c.getItem(i), i);
- selected = c.getSelectedIndex();
- if( selected >= 0 )
- select( selected );
+ selected = c.getSelectedIndex();
+ if (selected >= 0)
+ select( selected );
}
else
selected = -1;
@@ -121,9 +121,9 @@ public class GtkChoicePeer extends GtkComponentPeer
{
if( selected != index )
{
- selected = index;
- postItemEvent (((Choice) awtComponent).getItem( selected ),
- ItemEvent.SELECTED);
+ selected = index;
+ postItemEvent (((Choice) awtComponent).getItem( selected ),
+ ItemEvent.SELECTED);
}
}
@@ -133,11 +133,11 @@ public class GtkChoicePeer extends GtkComponentPeer
*/
public void handleEvent (AWTEvent event)
{
- super.handleEvent( event );
- if( event instanceof ItemEvent )
- if( ((ItemEvent)event).getItemSelectable() == awtComponent &&
- ((ItemEvent)event).getStateChange() == ItemEvent.SELECTED )
- ((Choice)awtComponent).select( selected );
+ super.handleEvent (event);
+ if (event instanceof ItemEvent)
+ if (((ItemEvent)event).getItemSelectable() == awtComponent
+ && ((ItemEvent)event).getStateChange() == ItemEvent.SELECTED)
+ ((Choice)awtComponent).select( selected );
}
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboard.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboard.java
index f520fe224b1..e41754641bb 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboard.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboard.java
@@ -71,9 +71,9 @@ public class GtkClipboard extends Clipboard
// cached by GtkSelection. True if
// gdk_display_supports_selection_notification.
static final boolean canCache = initNativeState(clipboard, selection,
- stringMimeType,
- imageMimeType,
- filesMimeType);
+ stringMimeType,
+ imageMimeType,
+ filesMimeType);
/**
* Creates the clipboard and sets the initial contents to the
@@ -140,8 +140,8 @@ public class GtkClipboard extends Clipboard
if (contents == null)
{
- advertiseContent(null, false, false, false);
- return;
+ advertiseContent(null, false, false, false);
+ return;
}
// We don't need to do anything for a GtkSelection facade.
@@ -153,46 +153,45 @@ public class GtkClipboard extends Clipboard
boolean files = false;
if (contents instanceof StringSelection
- || contents.isDataFlavorSupported(DataFlavor.stringFlavor)
- || contents.isDataFlavorSupported(DataFlavor.plainTextFlavor)
- || contents.isDataFlavorSupported(DataFlavor
- .getTextPlainUnicodeFlavor()))
+ || contents.isDataFlavorSupported(DataFlavor.stringFlavor)
+ || contents.isDataFlavorSupported(DataFlavor.plainTextFlavor)
+ || contents.isDataFlavorSupported(DataFlavor.getTextPlainUnicodeFlavor()))
text = true;
DataFlavor[] flavors = contents.getTransferDataFlavors();
String[] mimeTargets = new String[flavors.length];
for (int i = 0; i < flavors.length; i++)
{
- DataFlavor flavor = flavors[i];
- String mimeType = flavor.getMimeType();
- mimeTargets[i] = mimeType;
-
- if (! text)
- if ("text".equals(flavor.getPrimaryType())
- || flavor.isRepresentationClassReader())
- text = true;
-
- if (! images && flavors[i].equals(DataFlavor.imageFlavor))
- {
- try
- {
- Object o = contents.getTransferData(DataFlavor.imageFlavor);
- if (o instanceof Image)
- images = true;
- }
- catch (UnsupportedFlavorException ufe)
- {
- }
- catch (IOException ioe)
- {
- }
- catch (ClassCastException cce)
- {
- }
- }
-
- if (flavors[i].equals(DataFlavor.javaFileListFlavor))
- files = true;
+ DataFlavor flavor = flavors[i];
+ String mimeType = flavor.getMimeType();
+ mimeTargets[i] = mimeType;
+
+ if (! text)
+ if ("text".equals(flavor.getPrimaryType())
+ || flavor.isRepresentationClassReader())
+ text = true;
+
+ if (! images && flavors[i].equals(DataFlavor.imageFlavor))
+ {
+ try
+ {
+ Object o = contents.getTransferData(DataFlavor.imageFlavor);
+ if (o instanceof Image)
+ images = true;
+ }
+ catch (UnsupportedFlavorException ufe)
+ {
+ }
+ catch (IOException ioe)
+ {
+ }
+ catch (ClassCastException cce)
+ {
+ }
+ }
+
+ if (flavors[i].equals(DataFlavor.javaFileListFlavor))
+ files = true;
}
advertiseContent(mimeTargets, text, images, files);
@@ -207,9 +206,9 @@ public class GtkClipboard extends Clipboard
* selection has explicitly been erased.
*/
private native void advertiseContent(String[] targets,
- boolean text,
- boolean images,
- boolean files);
+ boolean text,
+ boolean images,
+ boolean files);
/**
* Called by the gtk+ clipboard when an application has requested
@@ -228,7 +227,7 @@ public class GtkClipboard extends Clipboard
try
{
return (String) contents.getTransferData(DataFlavor.stringFlavor);
- }
+ }
catch (UnsupportedFlavorException ufe)
{
}
@@ -244,20 +243,20 @@ public class GtkClipboard extends Clipboard
// turn the result into a string.
try
{
- DataFlavor plainText = DataFlavor.getTextPlainUnicodeFlavor();
- Reader r = plainText.getReaderForText(contents);
- if (r != null)
- {
- StringBuffer sb = new StringBuffer();
- char[] cs = new char[1024];
- int l = r.read(cs);
- while (l != -1)
- {
- sb.append(cs, 0, l);
- l = r.read(cs);
- }
- return sb.toString();
- }
+ DataFlavor plainText = DataFlavor.getTextPlainUnicodeFlavor();
+ Reader r = plainText.getReaderForText(contents);
+ if (r != null)
+ {
+ StringBuffer sb = new StringBuffer();
+ char[] cs = new char[1024];
+ int l = r.read(cs);
+ while (l != -1)
+ {
+ sb.append(cs, 0, l);
+ l = r.read(cs);
+ }
+ return sb.toString();
+ }
}
catch (IllegalArgumentException iae)
{
@@ -288,11 +287,11 @@ public class GtkClipboard extends Clipboard
try
{
- Object o = contents.getTransferData(DataFlavor.imageFlavor);
- if( o instanceof GtkImage )
- return (GtkImage) o;
- else
- return new GtkImage(((Image)o).getSource());
+ Object o = contents.getTransferData(DataFlavor.imageFlavor);
+ if( o instanceof GtkImage )
+ return (GtkImage) o;
+ else
+ return new GtkImage(((Image)o).getSource());
}
catch (UnsupportedFlavorException ufe)
{
@@ -321,14 +320,13 @@ public class GtkClipboard extends Clipboard
try
{
- List list = (List) contents.getTransferData
- (DataFlavor.javaFileListFlavor);
- String[] uris = new String[list.size()];
- int u = 0;
- Iterator it = list.iterator();
- while (it.hasNext())
- uris[u++] = ((File) it.next()).toURI().toString();
- return uris;
+ List list = (List) contents.getTransferData(DataFlavor.javaFileListFlavor);
+ String[] uris = new String[list.size()];
+ int u = 0;
+ Iterator it = list.iterator();
+ while (it.hasNext())
+ uris[u++] = ((File) it.next()).toURI().toString();
+ return uris;
}
catch (UnsupportedFlavorException ufe)
{
@@ -365,34 +363,34 @@ public class GtkClipboard extends Clipboard
// the other provideXXX() methods.
try
{
- DataFlavor flavor = new DataFlavor(target);
- Object o = contents.getTransferData(flavor);
-
- if (o instanceof byte[])
- return (byte[]) o;
-
- if (o instanceof InputStream)
- {
- InputStream is = (InputStream) o;
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- byte[] bs = new byte[1024];
- int l = is.read(bs);
- while (l != -1)
- {
- baos.write(bs, 0, l);
- l = is.read(bs);
- }
- return baos.toByteArray();
- }
-
- if (o instanceof Serializable)
- {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(baos);
- oos.writeObject(o);
- oos.close();
- return baos.toByteArray();
- }
+ DataFlavor flavor = new DataFlavor(target);
+ Object o = contents.getTransferData(flavor);
+
+ if (o instanceof byte[])
+ return (byte[]) o;
+
+ if (o instanceof InputStream)
+ {
+ InputStream is = (InputStream) o;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] bs = new byte[1024];
+ int l = is.read(bs);
+ while (l != -1)
+ {
+ baos.write(bs, 0, l);
+ l = is.read(bs);
+ }
+ return baos.toByteArray();
+ }
+
+ if (o instanceof Serializable)
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(o);
+ oos.close();
+ return baos.toByteArray();
+ }
}
catch (ClassNotFoundException cnfe)
{
@@ -416,8 +414,8 @@ public class GtkClipboard extends Clipboard
* Clipboard can be cached (gdk_display_supports_selection_notification).
*/
private static native boolean initNativeState(GtkClipboard clipboard,
- GtkClipboard selection,
- String stringTarget,
- String imageTarget,
- String filesTarget);
+ GtkClipboard selection,
+ String stringTarget,
+ String imageTarget,
+ String filesTarget);
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboardNotifier.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboardNotifier.java
index 61df796dc00..8e593455774 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboardNotifier.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboardNotifier.java
@@ -74,11 +74,11 @@ class GtkClipboardNotifier extends Thread
{
synchronized (notifier)
{
- if (clipboard == GtkClipboard.clipboard)
- announceClipboardChange = true;
- else
- announcePrimaryChange = true;
- notifier.notifyAll();
+ if (clipboard == GtkClipboard.clipboard)
+ announceClipboardChange = true;
+ else
+ announcePrimaryChange = true;
+ notifier.notifyAll();
}
}
@@ -87,44 +87,43 @@ class GtkClipboardNotifier extends Thread
GtkClipboard clipboard;
while (true)
{
- synchronized (this)
- {
- while (! announceClipboardChange && ! announcePrimaryChange)
- {
- try
- {
- this.wait();
- }
- catch (InterruptedException ie)
- {
- // ignore
- }
- }
-
- 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(clipboard), null);
- }
- catch (Throwable t)
- {
- // should never happen, but might if we have some faulty
- // listener.
- t.printStackTrace();
- }
+ synchronized (this)
+ {
+ while (! announceClipboardChange && ! announcePrimaryChange)
+ {
+ try
+ {
+ this.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignore
+ }
+ }
+
+ 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(clipboard), null);
+ }
+ catch (Throwable t)
+ {
+ // should never happen, but might if we have some faulty listener.
+ t.printStackTrace();
+ }
}
}
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java
index b1ef09d6e1b..a7ae8e17f2b 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java
@@ -109,7 +109,7 @@ public class GtkComponentPeer extends GtkGenericPeer
native void gtkWidgetGetLocationOnScreen (int[] point);
native void gtkWidgetSetCursor (int type, GtkImage image, int x, int y);
native void gtkWidgetSetCursorUnlocked (int type, GtkImage image,
- int x, int y);
+ 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);
@@ -206,7 +206,7 @@ public class GtkComponentPeer extends GtkGenericPeer
}
public int checkImage (Image image, int width, int height,
- ImageObserver observer)
+ ImageObserver observer)
{
return getToolkit().checkImage(image, width, height, observer);
}
@@ -402,7 +402,7 @@ public class GtkComponentPeer extends GtkGenericPeer
}
public boolean prepareImage (Image image, int width, int height,
- ImageObserver observer)
+ ImageObserver observer)
{
return getToolkit().prepareImage(image, width, height, observer);
}
@@ -539,17 +539,17 @@ public class GtkComponentPeer extends GtkGenericPeer
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;
+ GtkCursor gtkCursor = (GtkCursor) cursor;
+ image = gtkCursor.getGtkImage();
+ Point hotspot = gtkCursor.getHotspot();
+ x = hotspot.x;
+ y = hotspot.y;
}
else
{
- image = null;
- x = 0;
- y = 0;
+ image = null;
+ x = 0;
+ y = 0;
}
if (Thread.currentThread() == GtkMainThread.mainThread)
@@ -597,7 +597,7 @@ public class GtkComponentPeer extends GtkGenericPeer
if (b && ! (awtComponent instanceof Window))
{
Rectangle bounds = awtComponent.getBounds();
- b = (bounds.width > 0) && (bounds.height > 0);
+ b = (bounds.width > 0) && (bounds.height > 0);
}
if (Thread.currentThread() == GtkMainThread.mainThread)
@@ -617,23 +617,23 @@ public class GtkComponentPeer extends GtkGenericPeer
}
protected void postMouseEvent(int id, long when, int mods, int x, int y,
- int clickCount, boolean popupTrigger)
+ int clickCount, boolean popupTrigger)
{
q().postEvent(new MouseEvent(awtComponent, id, when, mods, x, y,
- clickCount, popupTrigger));
+ 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)
+ 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));
+ x, y, clickCount, popupTrigger,
+ type, amount, rotation));
}
protected void postExposeEvent (int x, int y, int width, int height)
@@ -659,12 +659,12 @@ public class GtkComponentPeer extends GtkGenericPeer
&& keyCode != KeyEvent.VK_ALT))
{
synchronized(q)
- {
- q.postEvent(keyEvent);
- keyEvent = new KeyEvent(awtComponent, KeyEvent.KEY_TYPED, when,
- mods, KeyEvent.VK_UNDEFINED, keyChar,
- keyLocation);
- q.postEvent(keyEvent);
+ {
+ q.postEvent(keyEvent);
+ keyEvent = new KeyEvent(awtComponent, KeyEvent.KEY_TYPED, when,
+ mods, KeyEvent.VK_UNDEFINED, keyChar,
+ keyLocation);
+ q.postEvent(keyEvent);
}
}
else
@@ -685,8 +685,8 @@ public class GtkComponentPeer extends GtkGenericPeer
protected void postItemEvent (Object item, int stateChange)
{
q().postEvent (new ItemEvent ((ItemSelectable)awtComponent,
- ItemEvent.ITEM_STATE_CHANGED,
- item, stateChange));
+ ItemEvent.ITEM_STATE_CHANGED,
+ item, stateChange));
}
protected void postTextEvent ()
@@ -828,8 +828,8 @@ public class GtkComponentPeer extends GtkGenericPeer
// buffer and one front buffer.
if (numBuffers == 2)
backBuffer = new GtkVolatileImage(this, awtComponent.getWidth(),
- awtComponent.getHeight(),
- caps.getBackBufferCapabilities());
+ awtComponent.getHeight(),
+ caps.getBackBufferCapabilities());
else
throw new AWTException("GtkComponentPeer.createBuffers:"
+ " multi-buffering not supported");
@@ -846,18 +846,18 @@ public class GtkComponentPeer extends GtkGenericPeer
public void flip (BufferCapabilities.FlipContents contents)
{
getGraphics().drawImage(backBuffer,
- awtComponent.getWidth(),
- awtComponent.getHeight(),
- null);
+ awtComponent.getWidth(),
+ awtComponent.getHeight(),
+ null);
// create new back buffer and clear it to the background color.
if (contents == BufferCapabilities.FlipContents.BACKGROUND)
{
backBuffer = createVolatileImage(awtComponent.getWidth(),
- awtComponent.getHeight());
+ awtComponent.getHeight());
backBuffer.getGraphics().clearRect(0, 0,
- awtComponent.getWidth(),
- awtComponent.getHeight());
+ awtComponent.getWidth(),
+ awtComponent.getHeight());
}
// FIXME: support BufferCapabilities.FlipContents.PRIOR
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java
index 8650578f70e..7d5ef91de13 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java
@@ -40,7 +40,6 @@ 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;
@@ -160,7 +159,8 @@ public class GtkFileDialogPeer extends GtkDialogPeer implements FileDialogPeer
in turn call the filter's accept() method and give back the return
value. */
// called back by native side: filename_filter_cb
- boolean filenameFilterCallback (String fullname) {
+ boolean filenameFilterCallback (String fullname)
+ {
String filename = fullname.substring(fullname.lastIndexOf(FS) + 1);
String dirname = fullname.substring(0, fullname.lastIndexOf(FS));
File dir = new File(dirname);
@@ -205,19 +205,19 @@ public class GtkFileDialogPeer extends GtkDialogPeer implements FileDialogPeer
if (sepIndex < 0)
{
/* This should never happen on Unix (all paths start with '/') */
- currentFile = fileName;
+ currentFile = fileName;
}
else
{
if (fileName.length() > (sepIndex + 1))
- {
- String fn = fileName.substring (sepIndex + 1);
- currentFile = fn;
- }
- else
- {
+ {
+ String fn = fileName.substring (sepIndex + 1);
+ currentFile = fn;
+ }
+ else
+ {
currentFile = null;
- }
+ }
String dn = fileName.substring (0, sepIndex + 1);
currentDirectory = dn;
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java
index d113e92f5b4..b35be522746 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java
@@ -1,5 +1,5 @@
/* GtkFramePeer.java -- Implements FramePeer with GTK
- Copyright (C) 1999, 2002, 2004, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2002, 2004, 2006, 2007 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -176,13 +176,17 @@ public class GtkFramePeer extends GtkWindowPeer
public void setIconImage (Image image)
{
- if (image != null)
- {
- if (image instanceof GtkImage)
- nativeSetIconImage((GtkImage) image);
- else
- nativeSetIconImage(new GtkImage(image.getSource()));
- }
+ if (image != null)
+ {
+ GtkImage gtkImage;
+ if (image instanceof GtkImage)
+ gtkImage = (GtkImage) image;
+ else
+ gtkImage = new GtkImage(image.getSource());
+
+ if (gtkImage.isLoaded && ! gtkImage.errorLoading)
+ nativeSetIconImage(gtkImage);
+ }
}
protected void postConfigureEvent (int x, int y, int width, int height)
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java
index 0fd98bbd7b4..719669eae0d 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java
@@ -71,7 +71,7 @@ public class GtkImage extends Image
/**
* Properties.
*/
- Hashtable props;
+ Hashtable<?,?> props;
/**
* Loaded or not flag, for asynchronous compatibility.
@@ -87,7 +87,7 @@ public class GtkImage extends Image
/**
* Observer queue.
*/
- Vector observers;
+ Vector<ImageObserver> observers;
/**
* Error flag for loading.
@@ -103,10 +103,10 @@ public class GtkImage extends Image
* The 32-bit AABBGGRR format the GDK uses.
*/
static ColorModel nativeModel = new DirectColorModel(32,
- 0x000000FF,
- 0x0000FF00,
- 0x00FF0000,
- 0xFF000000);
+ 0x000000FF,
+ 0x0000FF00,
+ 0x00FF0000,
+ 0xFF000000);
/**
* The singleton GtkImage that is returned on errors by GtkToolkit.
@@ -178,7 +178,7 @@ public class GtkImage extends Image
public GtkImage (ImageProducer producer)
{
isLoaded = false;
- observers = new Vector();
+ observers = new Vector<ImageObserver>();
source = producer;
errorLoading = false;
source.startProduction(new GtkImageConsumer(this, source));
@@ -194,7 +194,7 @@ public class GtkImage extends Image
{
isLoaded = true;
observers = null;
- props = new Hashtable();
+ props = new Hashtable<String,Object>();
errorLoading = false;
}
@@ -208,26 +208,26 @@ public class GtkImage extends Image
File f = new File(filename);
try
{
- String path = f.getCanonicalPath();
- synchronized(pixbufLock)
- {
- if (loadPixbuf(f.getCanonicalPath()) != true)
- throw new IllegalArgumentException("Couldn't load image: "
- + filename);
- }
+ String path = f.getCanonicalPath();
+ synchronized(pixbufLock)
+ {
+ if (loadPixbuf(f.getCanonicalPath()) != true)
+ throw new IllegalArgumentException("Couldn't load image: "
+ + filename);
+ }
}
catch(IOException e)
{
- IllegalArgumentException iae;
- iae = new IllegalArgumentException("Couldn't load image: "
- + filename);
- iae.initCause(e);
- throw iae;
+ IllegalArgumentException iae;
+ iae = new IllegalArgumentException("Couldn't load image: "
+ + filename);
+ iae.initCause(e);
+ throw iae;
}
isLoaded = true;
observers = null;
- props = new Hashtable();
+ props = new Hashtable<String,Object>();
}
/**
@@ -240,13 +240,13 @@ public class GtkImage extends Image
{
synchronized(pixbufLock)
{
- if (loadImageFromData (data) != true)
- throw new IllegalArgumentException ("Couldn't load image.");
+ if (loadImageFromData (data) != true)
+ throw new IllegalArgumentException ("Couldn't load image.");
}
isLoaded = true;
observers = null;
- props = new Hashtable();
+ props = new Hashtable<String,Object>();
errorLoading = false;
}
@@ -256,7 +256,7 @@ public class GtkImage extends Image
public GtkImage (URL url)
{
isLoaded = false;
- observers = new Vector();
+ observers = new Vector<ImageObserver>();
errorLoading = false;
if( url == null)
return;
@@ -269,23 +269,23 @@ public class GtkImage extends Image
int n = 0;
while ((n = bis.read(buf)) != -1)
- baos.write(buf, 0, n);
+ baos.write(buf, 0, n);
bis.close();
}
catch(IOException e)
{
- throw new IllegalArgumentException ("Couldn't load image.");
+ throw new IllegalArgumentException ("Couldn't load image.");
}
byte[] array = baos.toByteArray();
synchronized(pixbufLock)
{
- if (loadImageFromData(array) != true)
- throw new IllegalArgumentException ("Couldn't load image.");
+ if (loadImageFromData(array) != true)
+ throw new IllegalArgumentException ("Couldn't load image.");
}
isLoaded = true;
observers = null;
- props = new Hashtable();
+ props = new Hashtable<String,Object>();
}
/**
@@ -295,14 +295,14 @@ public class GtkImage extends Image
{
this.width = width;
this.height = height;
- props = new Hashtable();
+ props = new Hashtable<String,Object>();
isLoaded = true;
observers = null;
// Use the GDK scaling method.
synchronized(pixbufLock)
{
- createScaledPixbuf(src, hints);
+ createScaledPixbuf(src, hints);
}
}
@@ -315,11 +315,11 @@ public class GtkImage extends Image
this.pixbuf = pixbuf;
synchronized(pixbufLock)
{
- createFromPixbuf();
+ createFromPixbuf();
}
isLoaded = true;
observers = null;
- props = new Hashtable();
+ props = new Hashtable<String,Object>();
}
/**
@@ -331,7 +331,7 @@ public class GtkImage extends Image
{
this.width = width;
this.height = height;
- props = new Hashtable();
+ props = new Hashtable<String,Object>();
isLoaded = true;
observers = null;
initFromBuffer( bufferPointer );
@@ -346,8 +346,8 @@ public class GtkImage extends Image
{
if (errorImage == null)
{
- errorImage = new GtkImage();
- errorImage.errorLoading = true;
+ errorImage = new GtkImage();
+ errorImage.errorLoading = true;
}
return errorImage;
}
@@ -362,25 +362,25 @@ public class GtkImage extends Image
* Callback from the image consumer.
*/
public void setImage(int width, int height,
- int[] pixels, Hashtable properties)
+ int[] pixels, Hashtable<?,?> properties)
{
this.width = width;
this.height = height;
- props = (properties != null) ? properties : new Hashtable();
+ props = (properties != null) ? properties : new Hashtable<String,Object>();
if (width <= 0 || height <= 0 || pixels == null)
{
- errorLoading = true;
- return;
+ errorLoading = true;
+ return;
}
- isLoaded = true;
- deliver();
synchronized(pixbufLock)
{
- createPixbuf();
- setPixels(pixels);
+ createPixbuf();
+ setPixels(pixels);
}
+ isLoaded = true;
+ deliver();
}
// java.awt.Image methods ////////////////////////////////////////////////
@@ -427,7 +427,7 @@ public class GtkImage extends Image
return null;
}
return new MemoryImageSource(width, height, nativeModel, pixels,
- 0, width);
+ 0, width);
}
/**
@@ -436,19 +436,19 @@ public class GtkImage extends Image
public Graphics getGraphics ()
{
throw new IllegalAccessError("This method only works for off-screen"
- +" Images.");
+ +" Images.");
}
/**
* Returns a scaled instance of this pixbuf.
*/
public Image getScaledInstance(int width,
- int height,
- int hints)
+ int height,
+ int hints)
{
if (width <= 0 || height <= 0)
- throw new IllegalArgumentException("Width and height of scaled bitmap"+
- "must be >= 0");
+ throw new IllegalArgumentException("Width and height of scaled bitmap"
+ + "must be >= 0");
return new GtkImage(this, width, height, hints);
}
@@ -465,13 +465,13 @@ public class GtkImage extends Image
{
if (isLoaded && source != null)
{
- observers = new Vector();
- isLoaded = false;
- synchronized(pixbufLock)
+ observers = new Vector<ImageObserver>();
+ isLoaded = false;
+ synchronized(pixbufLock)
{
freePixbuf();
}
- source.startProduction(new GtkImageConsumer(this, source));
+ source.startProduction(new GtkImageConsumer(this, source));
}
}
@@ -479,10 +479,10 @@ public class GtkImage extends Image
{
if (isLoaded)
{
- synchronized(pixbufLock)
- {
- freePixbuf();
- }
+ synchronized(pixbufLock)
+ {
+ freePixbuf();
+ }
}
}
@@ -493,10 +493,10 @@ public class GtkImage extends Image
{
if (addObserver(observer))
{
- if (errorLoading == true)
- return ImageObserver.ERROR;
- else
- return 0;
+ if (errorLoading == true)
+ return ImageObserver.ERROR;
+ else
+ return 0;
}
return ImageObserver.ALLBITS | ImageObserver.WIDTH | ImageObserver.HEIGHT;
@@ -517,8 +517,8 @@ public class GtkImage extends Image
if (observers != null)
for(int i=0; i < observers.size(); i++)
- ((ImageObserver)observers.elementAt(i)).
- imageUpdate(this, flags, 0, 0, width, height);
+ ((ImageObserver)observers.elementAt(i)).imageUpdate(this, flags, 0, 0,
+ width, height);
observers = null;
}
@@ -531,10 +531,10 @@ public class GtkImage extends Image
{
if (!isLoaded)
{
- if(observer != null)
- if (!observers.contains (observer))
- observers.addElement (observer);
- return true;
+ if(observer != null)
+ if (!observers.contains (observer))
+ observers.addElement (observer);
+ return true;
}
return false;
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkImageConsumer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkImageConsumer.java
index 53e97bb1a8a..44cfaf9266a 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkImageConsumer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkImageConsumer.java
@@ -55,7 +55,7 @@ public class GtkImageConsumer implements ImageConsumer
{
private GtkImage target;
private int width, height;
- private Hashtable properties;
+ private Hashtable<?,?> properties;
private int[] pixelCache = null;
private ImageProducer source;
@@ -97,55 +97,55 @@ public class GtkImageConsumer implements ImageConsumer
}
public synchronized void setPixels (int x, int y, int width, int height,
- ColorModel cm, byte[] pixels,
- int offset, int scansize)
+ ColorModel cm, byte[] pixels,
+ int offset, int scansize)
{
setPixels (x, y, width, height, cm, convertPixels (pixels), offset,
scansize);
}
public synchronized void setPixels (int x, int y, int width, int height,
- ColorModel cm, int[] pixels,
- int offset, int scansize)
+ ColorModel cm, int[] pixels,
+ int offset, int scansize)
{
if (pixelCache == null)
return; // Not sure this should ever happen.
if (cm.equals(GtkImage.nativeModel))
for (int i = 0; i < height; i++)
- System.arraycopy (pixels, offset + (i * scansize),
- pixelCache, (y + i) * this.width + x,
- width);
+ System.arraycopy (pixels, offset + (i * scansize),
+ pixelCache, (y + i) * this.width + x,
+ width);
else
{
- if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
- {
- for (int i = 0; i < height; i++)
- for (int j = 0; j < width; j++)
- {
- // get in RRGGBBAA and convert to AARRGGBB
- int pix = cm.getRGB(pixels[offset + (i * scansize) + x + j]);
- int a = ((pix & 0xFF000000) >> 24) & 0xFF;
- int rgb = (pix & 0x00FFFFFF) << 8;
- pix = rgb | a;
- pixelCache[(y + i) * this.width + x + j] = pix;
- }
- }
- else
- {
- for (int i = 0; i < height; i++)
- for (int j = 0; j < width; j++)
- {
- // get in AARRGGBB and convert to AABBGGRR
- int pix = cm.getRGB(pixels[offset + (i * scansize) + x + j]);
- byte b = (byte)(pix & 0xFF);
- byte r = (byte)(((pix & 0x00FF0000) >> 16) & 0xFF);
- pix &= 0xFF00FF00;
- pix |= ((b & 0xFF) << 16);
- pix |= (r & 0xFF);
- pixelCache[(y + i) * this.width + x + j] = pix;
- }
- }
+ if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
+ {
+ for (int i = 0; i < height; i++)
+ for (int j = 0; j < width; j++)
+ {
+ // get in RRGGBBAA and convert to AARRGGBB
+ int pix = cm.getRGB(pixels[offset + (i * scansize) + x + j]);
+ int a = ((pix & 0xFF000000) >> 24) & 0xFF;
+ int rgb = (pix & 0x00FFFFFF) << 8;
+ pix = rgb | a;
+ pixelCache[(y + i) * this.width + x + j] = pix;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < height; i++)
+ for (int j = 0; j < width; j++)
+ {
+ // get in AARRGGBB and convert to AABBGGRR
+ int pix = cm.getRGB(pixels[offset + (i * scansize) + x + j]);
+ byte b = (byte)(pix & 0xFF);
+ byte r = (byte)(((pix & 0x00FF0000) >> 16) & 0xFF);
+ pix &= 0xFF00FF00;
+ pix |= ((b & 0xFF) << 16);
+ pix |= (r & 0xFF);
+ pixelCache[(y + i) * this.width + x + j] = pix;
+ }
+ }
}
}
@@ -162,7 +162,7 @@ public class GtkImageConsumer implements ImageConsumer
return ret;
}
- public synchronized void setProperties (Hashtable props)
+ public synchronized void setProperties (Hashtable<?,?> props)
{
this.properties = props;
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java
index 02db90d72bd..76f8e5fe331 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java
@@ -90,11 +90,11 @@ public class GtkLabelPeer extends GtkComponentPeer
switch (alignment)
{
case Label.LEFT:
- return 0.0f;
+ return 0.0f;
case Label.CENTER:
- return 0.5f;
+ return 0.5f;
case Label.RIGHT:
- return 1.0f;
+ return 1.0f;
}
return 0.0f;
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkListPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkListPeer.java
index bd6ec0aef75..f943a75d171 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkListPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkListPeer.java
@@ -148,33 +148,33 @@ public class GtkListPeer extends GtkComponentPeer
{
// Only generate the ActionEvent on the second click of a
// multiple click.
- MouseEvent me = (MouseEvent) e;
- if (!me.isConsumed ()
- && (me.getModifiersEx () & MouseEvent.BUTTON1_DOWN_MASK) != 0
- && me.getClickCount() == 2)
- {
+ MouseEvent me = (MouseEvent) e;
+ if (!me.isConsumed ()
+ && (me.getModifiersEx () & MouseEvent.BUTTON1_DOWN_MASK) != 0
+ && me.getClickCount() == 2)
+ {
String selectedItem = ((List) awtComponent).getSelectedItem ();
// Double-click only generates an Action event if
// something is selected.
if (selectedItem != null)
- postActionEvent (((List) awtComponent).getSelectedItem (),
- me.getModifiersEx ());
- }
+ postActionEvent (((List) awtComponent).getSelectedItem (),
+ me.getModifiersEx ());
+ }
}
if (e.getID () == KeyEvent.KEY_PRESSED)
{
- KeyEvent ke = (KeyEvent) e;
- if (!ke.isConsumed () && ke.getKeyCode () == KeyEvent.VK_ENTER)
- {
+ KeyEvent ke = (KeyEvent) e;
+ if (!ke.isConsumed () && ke.getKeyCode () == KeyEvent.VK_ENTER)
+ {
String selectedItem = ((List) awtComponent).getSelectedItem ();
// Enter only generates an Action event if something is
// selected.
if (selectedItem != null)
- postActionEvent (selectedItem, ke.getModifiersEx ());
- }
+ postActionEvent (selectedItem, ke.getModifiersEx ());
+ }
}
super.handleEvent (e);
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMainThread.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMainThread.java
index a4e280fe45f..e40a04eed92 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMainThread.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMainThread.java
@@ -40,8 +40,6 @@ package gnu.java.awt.peer.gtk;
import gnu.java.awt.peer.NativeEventLoopRunningEvent;
-import java.awt.AWTEvent;
-
/**
* The Java thread representing the native GTK main loop, that is,
* GtkMainThread.mainThread, terminates when GtkToolkit.gtkMain()
@@ -172,9 +170,9 @@ public class GtkMainThread extends Thread
{
synchronized (nWindowsLock)
{
- if (numberOfWindows == 0)
- startMainThread();
- numberOfWindows++;
+ if (numberOfWindows == 0)
+ startMainThread();
+ numberOfWindows++;
}
}
@@ -182,9 +180,9 @@ public class GtkMainThread extends Thread
{
synchronized (nWindowsLock)
{
- numberOfWindows--;
- if (numberOfWindows == 0)
- endMainThread();
+ numberOfWindows--;
+ if (numberOfWindows == 0)
+ endMainThread();
}
}
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java
index 898f224f5e1..c3427b18f36 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java
@@ -76,15 +76,15 @@ public class GtkMenuBarPeer extends GtkMenuComponentPeer
{
if (hasHelpMenu)
{
- // Remove the (help) menu, which is after all the other items.
- delMenu(((MenuBar) awtWidget).getMenuCount());
- hasHelpMenu = false;
+ // Remove the (help) menu, which is after all the other items.
+ delMenu(((MenuBar) awtWidget).getMenuCount());
+ hasHelpMenu = false;
}
if (menu != null)
{
- addMenu(menu);
- hasHelpMenu = true;
+ addMenu(menu);
+ hasHelpMenu = true;
}
}
@@ -103,9 +103,9 @@ public class GtkMenuBarPeer extends GtkMenuComponentPeer
// Make sure the help menu is the last one.
if (hasHelpMenu)
{
- addHelpMenu(null);
- addMenu((GtkMenuPeer) m.getPeer());
- addHelpMenu(((MenuBar) awtWidget).getHelpMenu());
+ addHelpMenu(null);
+ addMenu((GtkMenuPeer) m.getPeer());
+ addHelpMenu(((MenuBar) awtWidget).getHelpMenu());
}
else
addMenu((GtkMenuPeer) m.getPeer());
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java
index 55b95a18d0f..1e37cefc144 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java
@@ -64,9 +64,9 @@ public abstract class GtkMenuComponentPeer extends GtkGenericPeer
if (f == null)
{
MenuContainer parent = mc.getParent ();
- // Submenus inherit the font of their containing Menu(Bar).
- if (parent instanceof MenuComponent)
- f = parent.getFont ();
+ // Submenus inherit the font of their containing Menu(Bar).
+ if (parent instanceof MenuComponent)
+ f = parent.getFont ();
}
setFont(f);
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java
index 1d581c1a15c..ff6bdca9fbe 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java
@@ -96,8 +96,8 @@ public class GtkMenuPeer extends GtkMenuItemPeer
MenuShortcut ms = item.getShortcut ();
if (ms != null)
{
- key = ms.getKey ();
- shiftModifier = ms.usesShiftModifier ();
+ key = ms.getKey ();
+ shiftModifier = ms.usesShiftModifier ();
}
addItem ((MenuItemPeer) item.getPeer (), key, shiftModifier);
@@ -110,8 +110,8 @@ public class GtkMenuPeer extends GtkMenuItemPeer
if (ms != null)
{
- key = ms.getKey ();
- shiftModifier = ms.usesShiftModifier ();
+ key = ms.getKey ();
+ shiftModifier = ms.usesShiftModifier ();
}
addItem (item, key, shiftModifier);
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java
index 02bf84d4e8e..7aea50991df 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java
@@ -53,9 +53,9 @@ public class GtkMouseInfoPeer implements MouseInfoPeer
public int fillPointWithCoords(Point p)
{
int[] coords = gde.getMouseCoordinates();
- p.x = coords[1];
- p.y = coords[2];
- return coords[0];
+ p.x = coords[1];
+ p.y = coords[2];
+ return coords[0];
}
public boolean isWindowUnderMouse(Window w)
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollPanePeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollPanePeer.java
index 69f8b494625..657a2760876 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollPanePeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollPanePeer.java
@@ -74,10 +74,8 @@ public class GtkScrollPanePeer extends GtkContainerPeer
// If the child is in this range, GTK adds both scrollbars, but
// the AWT doesn't. So set the peer's scroll policy to
// GTK_POLICY_NEVER.
- if ((width > dim[0] - getVScrollbarWidth ()
- && width <= dim[0])
- && (height > dim[1] - getHScrollbarHeight ()
- && height <= dim[1]))
+ if ((width > dim[0] - getVScrollbarWidth () && width <= dim[0])
+ && (height > dim[1] - getHScrollbarHeight () && height <= dim[1]))
setPolicy (ScrollPane.SCROLLBARS_NEVER);
else
setPolicy (((ScrollPane) awtComponent).getScrollbarDisplayPolicy ());
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java
index e4147d36c97..c29706f408f 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java
@@ -50,14 +50,14 @@ public class GtkScrollbarPeer extends GtkComponentPeer
Scrollbar sb = (Scrollbar) awtComponent;
create (sb.getOrientation (), sb.getValue (),
- sb.getMinimum (), sb.getMaximum (),
- sb.getUnitIncrement (), sb.getBlockIncrement (),
- sb.getVisibleAmount ());
+ sb.getMinimum (), sb.getMaximum (),
+ sb.getUnitIncrement (), sb.getBlockIncrement (),
+ sb.getVisibleAmount ());
}
native void create (int orientation, int value,
- int min, int max, int stepIncr, int pageIncr,
- int visibleAmount);
+ int min, int max, int stepIncr, int pageIncr,
+ int visibleAmount);
native void connectSignals ();
@@ -86,7 +86,7 @@ public class GtkScrollbarPeer extends GtkComponentPeer
{
Scrollbar bar = (Scrollbar) awtComponent;
q().postEvent(new AdjustmentEvent(bar,
- AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED,
- type, value, true));
+ AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED,
+ type, value, true));
}
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkSelection.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkSelection.java
index 6a92f86e8b0..967a2edb432 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkSelection.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkSelection.java
@@ -130,7 +130,7 @@ public class GtkSelection implements Transferable
* Set as response to a requestURIs() call. Only valid when
* urisDelivered is true
*/
- private List uris;
+ private List<File> uris;
/**
* Indicates a requestBytes(String) call was made and the
@@ -163,51 +163,51 @@ public class GtkSelection implements Transferable
DataFlavor[] result;
synchronized (requestLock)
{
- // Did we request already and cache the result?
- if (mimeTypesDelivered)
- result = (DataFlavor[]) dataFlavors.clone();
- else
- {
- // Wait till there are no pending requests.
- while (requestInProgress)
- {
- try
- {
- requestLock.wait();
- }
- catch (InterruptedException ie)
- {
- // ignored
- }
- }
-
- // If nobody else beat us and cached the result we try
- // ourselves to get it.
- if (! mimeTypesDelivered)
- {
- requestInProgress = true;
- requestMimeTypes(clipboard);
- while (! mimeTypesDelivered)
- {
- try
- {
- requestLock.wait();
- }
- catch (InterruptedException ie)
- {
- // ignored
- }
- }
- requestInProgress = false;
- }
- result = dataFlavors;
- if (! GtkClipboard.canCache)
- {
- dataFlavors = null;
- mimeTypesDelivered = false;
- }
- requestLock.notifyAll();
- }
+ // Did we request already and cache the result?
+ if (mimeTypesDelivered)
+ result = (DataFlavor[]) dataFlavors.clone();
+ else
+ {
+ // Wait till there are no pending requests.
+ while (requestInProgress)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+
+ // If nobody else beat us and cached the result we try
+ // ourselves to get it.
+ if (! mimeTypesDelivered)
+ {
+ requestInProgress = true;
+ requestMimeTypes(clipboard);
+ while (! mimeTypesDelivered)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+ requestInProgress = false;
+ }
+ result = dataFlavors;
+ if (! GtkClipboard.canCache)
+ {
+ dataFlavors = null;
+ mimeTypesDelivered = false;
+ }
+ requestLock.notifyAll();
+ }
}
return result;
}
@@ -220,53 +220,55 @@ public class GtkSelection implements Transferable
{
synchronized (requestLock)
{
- if (mimeTypes == null)
- dataFlavors = new DataFlavor[0];
- else
- {
- // Most likely the mimeTypes include text in which case we add an
- // extra element.
- ArrayList flavorsList = new ArrayList(mimeTypes.length + 1);
- for (int i = 0; i < mimeTypes.length; i++)
- {
- try
- {
- if (mimeTypes[i] == GtkClipboard.stringMimeType)
- {
- // XXX - Fix DataFlavor.getTextPlainUnicodeFlavor()
- // and also add it to the list.
- flavorsList.add(DataFlavor.stringFlavor);
- flavorsList.add(DataFlavor.plainTextFlavor);
- }
- else if (mimeTypes[i] == GtkClipboard.imageMimeType)
- flavorsList.add(DataFlavor.imageFlavor);
- else if (mimeTypes[i] == GtkClipboard.filesMimeType)
- flavorsList.add(DataFlavor.javaFileListFlavor);
- else
- {
- // We check the target to prevent duplicates
- // of the "magic" targets above.
- DataFlavor target = new DataFlavor(mimeTypes[i]);
- if (! flavorsList.contains(target))
- flavorsList.add(target);
- }
- }
- catch (ClassNotFoundException cnfe)
- {
- cnfe.printStackTrace();
- }
- catch (NullPointerException npe)
- {
- npe.printStackTrace();
- }
- }
+ if (mimeTypes == null)
+ dataFlavors = new DataFlavor[0];
+ else
+ {
+ // Most likely the mimeTypes include text in which case we add an
+ // extra element.
+ ArrayList<DataFlavor> flavorsList =
+ new ArrayList<DataFlavor>(mimeTypes.length + 1);
+
+ for (int i = 0; i < mimeTypes.length; i++)
+ {
+ try
+ {
+ if (mimeTypes[i] == GtkClipboard.stringMimeType)
+ {
+ // XXX - Fix DataFlavor.getTextPlainUnicodeFlavor()
+ // and also add it to the list.
+ flavorsList.add(DataFlavor.stringFlavor);
+ flavorsList.add(DataFlavor.plainTextFlavor);
+ }
+ else if (mimeTypes[i] == GtkClipboard.imageMimeType)
+ flavorsList.add(DataFlavor.imageFlavor);
+ else if (mimeTypes[i] == GtkClipboard.filesMimeType)
+ flavorsList.add(DataFlavor.javaFileListFlavor);
+ else
+ {
+ // We check the target to prevent duplicates
+ // of the "magic" targets above.
+ DataFlavor target = new DataFlavor(mimeTypes[i]);
+ if (! flavorsList.contains(target))
+ flavorsList.add(target);
+ }
+ }
+ catch (ClassNotFoundException cnfe)
+ {
+ cnfe.printStackTrace();
+ }
+ catch (NullPointerException npe)
+ {
+ npe.printStackTrace();
+ }
+ }
- dataFlavors = new DataFlavor[flavorsList.size()];
- flavorsList.toArray(dataFlavors);
- }
+ dataFlavors = new DataFlavor[flavorsList.size()];
+ flavorsList.toArray(dataFlavors);
+ }
- mimeTypesDelivered = true;
- requestLock.notifyAll();
+ mimeTypesDelivered = true;
+ requestLock.notifyAll();
}
}
@@ -279,7 +281,7 @@ public class GtkSelection implements Transferable
DataFlavor[] dfs = getTransferDataFlavors();
for (int i = 0; i < dfs.length; i++)
if (flavor.equals(dfs[i]))
- return true;
+ return true;
return false;
}
@@ -294,51 +296,51 @@ public class GtkSelection implements Transferable
String result;
synchronized (requestLock)
{
- // Did we request already and cache the result?
- if (textDelivered)
- result = text;
- else
- {
- // Wait till there are no pending requests.
- while (requestInProgress)
- {
- try
- {
- requestLock.wait();
- }
- catch (InterruptedException ie)
- {
- // ignored
- }
- }
-
- // If nobody else beat us we try ourselves to get and
- // caching the result.
- if (! textDelivered)
- {
- requestInProgress = true;
- requestText(clipboard);
- while (! textDelivered)
- {
- try
- {
- requestLock.wait();
- }
- catch (InterruptedException ie)
- {
- // ignored
- }
- }
- requestInProgress = false;
- }
- result = text;
- if (! GtkClipboard.canCache)
- {
- text = null;
- textDelivered = false;
- }
- requestLock.notifyAll();
- }
+ // Did we request already and cache the result?
+ if (textDelivered)
+ result = text;
+ else
+ {
+ // Wait till there are no pending requests.
+ while (requestInProgress)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+
+ // If nobody else beat us we try ourselves to get and
+ // caching the result.
+ if (! textDelivered)
+ {
+ requestInProgress = true;
+ requestText(clipboard);
+ while (! textDelivered)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+ requestInProgress = false;
+ }
+ result = text;
+ if (! GtkClipboard.canCache)
+ {
+ text = null;
+ textDelivered = false;
+ }
+ requestLock.notifyAll();
+ }
}
return result;
}
@@ -351,9 +353,9 @@ public class GtkSelection implements Transferable
{
synchronized (requestLock)
{
- this.text = text;
- textDelivered = true;
- requestLock.notifyAll();
+ this.text = text;
+ textDelivered = true;
+ requestLock.notifyAll();
}
}
@@ -367,54 +369,56 @@ public class GtkSelection implements Transferable
Image result;
synchronized (requestLock)
{
- // Did we request already and cache the result?
- if (imageDelivered)
- result = image;
- else
- {
- // Wait till there are no pending requests.
- while (requestInProgress)
- {
- try
- {
- requestLock.wait();
- }
- catch (InterruptedException ie)
- {
- // ignored
- }
- }
-
- // If nobody else beat us we try ourselves to get and
- // caching the result.
- if (! imageDelivered)
- {
- requestInProgress = true;
- requestImage(clipboard);
- while (! imageDelivered)
- {
- try
- {
- requestLock.wait();
- }
- catch (InterruptedException ie)
- {
- // ignored
- }
- }
- requestInProgress = false;
- }
- if (imagePointer != null)
- image = new GtkImage(imagePointer);
- imagePointer = null;
- result = image;
- if (! GtkClipboard.canCache)
- {
- image = null;
- imageDelivered = false;
- }
- requestLock.notifyAll();
- }
+ // Did we request already and cache the result?
+ if (imageDelivered)
+ result = image;
+ else
+ {
+ // Wait till there are no pending requests.
+ while (requestInProgress)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+
+ // If nobody else beat us we try ourselves to get and
+ // caching the result.
+ if (! imageDelivered)
+ {
+ requestInProgress = true;
+ requestImage(clipboard);
+ while (! imageDelivered)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+ requestInProgress = false;
+ }
+
+ if (imagePointer != null)
+ image = new GtkImage(imagePointer);
+
+ imagePointer = null;
+ result = image;
+ if (! GtkClipboard.canCache)
+ {
+ image = null;
+ imageDelivered = false;
+ }
+ requestLock.notifyAll();
+ }
}
return result;
}
@@ -430,9 +434,9 @@ public class GtkSelection implements Transferable
{
synchronized (requestLock)
{
- this.imagePointer = pointer;
- imageDelivered = true;
- requestLock.notifyAll();
+ this.imagePointer = pointer;
+ imageDelivered = true;
+ requestLock.notifyAll();
}
}
@@ -441,56 +445,56 @@ public class GtkSelection implements Transferable
* URIs/Files and if not requests them and waits till they are
* available.
*/
- private List getURIs()
+ private List<File> getURIs()
{
- List result;
+ List<File> result;
synchronized (requestLock)
{
- // Did we request already and cache the result?
- if (urisDelivered)
- result = uris;
- else
- {
- // Wait till there are no pending requests.
- while (requestInProgress)
- {
- try
- {
- requestLock.wait();
- }
- catch (InterruptedException ie)
- {
- // ignored
- }
- }
-
- // If nobody else beat us we try ourselves to get and
- // caching the result.
- if (! urisDelivered)
- {
- requestInProgress = true;
- requestURIs(clipboard);
- while (! urisDelivered)
- {
- try
- {
- requestLock.wait();
- }
- catch (InterruptedException ie)
- {
- // ignored
- }
- }
- requestInProgress = false;
- }
- result = uris;
- if (! GtkClipboard.canCache)
- {
- uris = null;
- urisDelivered = false;
- }
- requestLock.notifyAll();
- }
+ // Did we request already and cache the result?
+ if (urisDelivered)
+ result = uris;
+ else
+ {
+ // Wait till there are no pending requests.
+ while (requestInProgress)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+
+ // If nobody else beat us we try ourselves to get and
+ // caching the result.
+ if (! urisDelivered)
+ {
+ requestInProgress = true;
+ requestURIs(clipboard);
+ while (! urisDelivered)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+ requestInProgress = false;
+ }
+ result = uris;
+ if (! GtkClipboard.canCache)
+ {
+ uris = null;
+ urisDelivered = false;
+ }
+ requestLock.notifyAll();
+ }
}
return result;
}
@@ -503,26 +507,26 @@ public class GtkSelection implements Transferable
{
synchronized (requestLock)
{
- if (uris != null && uris.length != 0)
- {
- ArrayList list = new ArrayList(uris.length);
- for (int i = 0; i < uris.length; i++)
- {
- try
- {
- URI uri = new URI(uris[i]);
- if (uri.getScheme().equals("file"))
- list.add(new File(uri));
- }
- catch (URISyntaxException use)
- {
- }
- }
- this.uris = list;
- }
-
- urisDelivered = true;
- requestLock.notifyAll();
+ if (uris != null && uris.length != 0)
+ {
+ ArrayList<File> list = new ArrayList<File>(uris.length);
+ for (int i = 0; i < uris.length; i++)
+ {
+ try
+ {
+ URI uri = new URI(uris[i]);
+ if (uri.getScheme().equals("file"))
+ list.add(new File(uri));
+ }
+ catch (URISyntaxException use)
+ {
+ }
+ }
+ this.uris = list;
+ }
+
+ urisDelivered = true;
+ requestLock.notifyAll();
}
}
@@ -537,39 +541,39 @@ public class GtkSelection implements Transferable
byte[] result;
synchronized (requestLock)
{
- // Wait till there are no pending requests.
- while (requestInProgress)
- {
- try
- {
- requestLock.wait();
- }
- catch (InterruptedException ie)
- {
- // ignored
- }
- }
-
- // Request bytes and wait till they are available.
- requestInProgress = true;
- requestBytes(clipboard, target);
- while (! bytesDelivered)
- {
- try
- {
- requestLock.wait();
- }
- catch (InterruptedException ie)
- {
- // ignored
- }
- }
- result = bytes;
- bytes = null;
- bytesDelivered = false;
- requestInProgress = false;
+ // Wait till there are no pending requests.
+ while (requestInProgress)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+
+ // Request bytes and wait till they are available.
+ requestInProgress = true;
+ requestBytes(clipboard, target);
+ while (! bytesDelivered)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+ result = bytes;
+ bytes = null;
+ bytesDelivered = false;
+ requestInProgress = false;
- requestLock.notifyAll();
+ requestLock.notifyAll();
}
return result;
}
@@ -583,9 +587,9 @@ public class GtkSelection implements Transferable
{
synchronized (requestLock)
{
- this.bytes = bytes;
- bytesDelivered = true;
- requestLock.notifyAll();
+ this.bytes = bytes;
+ bytesDelivered = true;
+ requestLock.notifyAll();
}
}
@@ -596,30 +600,30 @@ public class GtkSelection implements Transferable
// try one more time through getBytes().
if (flavor.equals(DataFlavor.stringFlavor))
{
- String text = getText();
- if (text != null)
- return text;
+ String text = getText();
+ if (text != null)
+ return text;
}
if (flavor.equals(DataFlavor.plainTextFlavor))
{
- String text = getText();
- if (text != null)
- return new StringBufferInputStream(text);
+ String text = getText();
+ if (text != null)
+ return new StringBufferInputStream(text);
}
if (flavor.equals(DataFlavor.imageFlavor))
{
- Image image = getImage();
- if (image != null)
- return image;
+ Image image = getImage();
+ if (image != null)
+ return image;
}
if (flavor.equals(DataFlavor.javaFileListFlavor))
{
- List uris = getURIs();
- if (uris != null)
- return uris;
+ List<File> uris = getURIs();
+ if (uris != null)
+ return uris;
}
byte[] bytes = getBytes(flavor.getMimeType());
@@ -628,20 +632,20 @@ public class GtkSelection implements Transferable
if (flavor.isMimeTypeSerializedObject())
{
- try
- {
- ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
- ObjectInputStream ois = new ObjectInputStream(bais);
- return ois.readObject();
- }
- catch (IOException ioe)
- {
- ioe.printStackTrace();
- }
- catch (ClassNotFoundException cnfe)
- {
- cnfe.printStackTrace();
- }
+ try
+ {
+ ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(bais);
+ return ois.readObject();
+ }
+ catch (IOException ioe)
+ {
+ ioe.printStackTrace();
+ }
+ catch (ClassNotFoundException cnfe)
+ {
+ cnfe.printStackTrace();
+ }
}
if (flavor.isRepresentationClassInputStream())
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java
index 5d9be1aec63..0c7d3a860e8 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java
@@ -100,8 +100,8 @@ public class GtkTextAreaPeer extends GtkComponentPeer
// GtkComponent.create.
if (f == null)
{
- f = new Font ("Dialog", Font.PLAIN, 12);
- awtComponent.setFont (f);
+ f = new Font ("Dialog", Font.PLAIN, 12);
+ awtComponent.setFont (f);
}
FontMetrics fm = getFontMetrics (f);
@@ -154,11 +154,11 @@ public class GtkTextAreaPeer extends GtkComponentPeer
int width = 0;
if (ta.getScrollbarVisibility () == TextArea.SCROLLBARS_BOTH
- || ta.getScrollbarVisibility () == TextArea.SCROLLBARS_HORIZONTAL_ONLY)
+ || ta.getScrollbarVisibility () == TextArea.SCROLLBARS_HORIZONTAL_ONLY)
height = getHScrollbarHeight ();
if (ta.getScrollbarVisibility () == TextArea.SCROLLBARS_BOTH
- || ta.getScrollbarVisibility () == TextArea.SCROLLBARS_VERTICAL_ONLY)
+ || ta.getScrollbarVisibility () == TextArea.SCROLLBARS_VERTICAL_ONLY)
width = getVScrollbarWidth ();
Font f = awtComponent.getFont ();
@@ -183,11 +183,11 @@ public class GtkTextAreaPeer extends GtkComponentPeer
int width = 0;
if (ta.getScrollbarVisibility () == TextArea.SCROLLBARS_BOTH
- || ta.getScrollbarVisibility () == TextArea.SCROLLBARS_HORIZONTAL_ONLY)
+ || ta.getScrollbarVisibility () == TextArea.SCROLLBARS_HORIZONTAL_ONLY)
height = getHScrollbarHeight ();
if (ta.getScrollbarVisibility () == TextArea.SCROLLBARS_BOTH
- || ta.getScrollbarVisibility () == TextArea.SCROLLBARS_VERTICAL_ONLY)
+ || ta.getScrollbarVisibility () == TextArea.SCROLLBARS_VERTICAL_ONLY)
width = getVScrollbarWidth ();
Font f = awtComponent.getFont ();
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java
index 763304864e0..9e62c8e7975 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java
@@ -94,8 +94,8 @@ public class GtkTextFieldPeer extends GtkComponentPeer
// GtkComponent.create.
if (f == null)
{
- f = new Font ("Dialog", Font.PLAIN, 12);
- awtComponent.setFont (f);
+ f = new Font ("Dialog", Font.PLAIN, 12);
+ awtComponent.setFont (f);
}
FontMetrics fm = getFontMetrics (f);
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java
index f746a47479f..df18d39c9d2 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java
@@ -1,5 +1,5 @@
/* GtkToolkit.java -- Implements an AWT Toolkit using GTK for peers
- Copyright (C) 1998, 1999, 2002, 2003, 2004, 2005, 2006
+ Copyright (C) 1998, 1999, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,6 +39,7 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
+import gnu.java.awt.AWTUtilities;
import gnu.java.awt.EmbeddedWindow;
import gnu.java.awt.dnd.GtkMouseDragGestureRecognizer;
import gnu.java.awt.dnd.peer.gtk.GtkDragSourceContextPeer;
@@ -86,6 +87,7 @@ import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import java.awt.dnd.InvalidDnDOperationException;
import java.awt.dnd.peer.DragSourceContextPeer;
+import java.awt.font.TextAttribute;
import java.awt.im.InputMethodHighlight;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
@@ -104,8 +106,8 @@ import java.awt.peer.LabelPeer;
import java.awt.peer.ListPeer;
import java.awt.peer.MenuBarPeer;
import java.awt.peer.MenuItemPeer;
-import java.awt.peer.MouseInfoPeer;
import java.awt.peer.MenuPeer;
+import java.awt.peer.MouseInfoPeer;
import java.awt.peer.PanelPeer;
import java.awt.peer.PopupMenuPeer;
import java.awt.peer.RobotPeer;
@@ -132,9 +134,11 @@ import javax.imageio.spi.IIORegistry;
public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
{
+ static final Object GTK_LOCK;
+
private static EventQueue q;
- static native void gtkInit(int portableNativeSync);
+ static native void gtkInit(int portableNativeSync, Object lock);
static native void gtkMain();
@@ -154,8 +158,9 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
portableNativeSync = 1; // true
else
portableNativeSync = 0; // false
-
- gtkInit(portableNativeSync);
+
+ GTK_LOCK = new String("GTK LOCK");
+ gtkInit(portableNativeSync, GTK_LOCK);
}
public GtkToolkit ()
@@ -167,14 +172,14 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
private native void getScreenSizeDimensions(int[] xy);
public int checkImage (Image image, int width, int height,
- ImageObserver observer)
+ ImageObserver observer)
{
int status = ImageObserver.ALLBITS
| ImageObserver.WIDTH
| ImageObserver.HEIGHT;
if (image instanceof GtkImage)
- return ((GtkImage) image).checkImage (observer);
+ return ((GtkImage) image).checkImage (observer);
if (image instanceof AsyncImage)
return ((AsyncImage) image).checkImage(observer);
@@ -208,11 +213,11 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
Image image;
try
{
- image = CairoSurface.getBufferedImage( new GtkImage( filename ) );
+ image = CairoSurface.getBufferedImage( new GtkImage( filename ) );
}
catch (IllegalArgumentException iae)
{
- image = null;
+ image = null;
}
return imageOrError(image);
}
@@ -230,11 +235,11 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
Image image;
try
{
- image = CairoSurface.getBufferedImage( new GtkImage( producer ) );
+ image = CairoSurface.getBufferedImage( new GtkImage( producer ) );
}
catch (IllegalArgumentException iae)
{
- image = null;
+ image = null;
}
return imageOrError(image);
}
@@ -245,13 +250,13 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
Image image;
try
{
- byte[] data = new byte[ imagelength ];
- System.arraycopy(imagedata, imageoffset, data, 0, imagelength);
- image = CairoSurface.getBufferedImage( new GtkImage( data ) );
+ byte[] data = new byte[ imagelength ];
+ System.arraycopy(imagedata, imageoffset, data, 0, imagelength);
+ image = CairoSurface.getBufferedImage( new GtkImage( data ) );
}
catch (IllegalArgumentException iae)
{
- image = null;
+ image = null;
}
return imageOrError(image);
}
@@ -275,22 +280,22 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
{
/* Return the GDK-native ABGR format */
return new DirectColorModel(32,
- 0x000000FF,
- 0x0000FF00,
- 0x00FF0000,
- 0xFF000000);
+ 0x000000FF,
+ 0x0000FF00,
+ 0x00FF0000,
+ 0xFF000000);
}
public String[] getFontList ()
{
return (new String[] { "Dialog",
- "DialogInput",
- "Monospaced",
- "Serif",
- "SansSerif" });
+ "DialogInput",
+ "Monospaced",
+ "Serif",
+ "SansSerif" });
}
- static class LRUCache extends LinkedHashMap
+ static class LRUCache<K,V> extends LinkedHashMap<K,V>
{
int max_entries;
public LRUCache(int max)
@@ -304,8 +309,9 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
}
}
- private LRUCache fontCache = new LRUCache(50);
- private LRUCache imageCache = new LRUCache(50);
+ private LRUCache<Map,ClasspathFontPeer> fontCache =
+ new LRUCache<Map,ClasspathFontPeer>(50);
+ private LRUCache<Object,Image> imageCache = new LRUCache<Object,Image>(50);
public FontMetrics getFontMetrics (Font font)
{
@@ -315,7 +321,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
public Image getImage (String filename)
{
if (imageCache.containsKey(filename))
- return (Image) imageCache.get(filename);
+ return imageCache.get(filename);
else
{
Image im = createImage(filename);
@@ -327,7 +333,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
public Image getImage (URL url)
{
if (imageCache.containsKey(url))
- return (Image) imageCache.get(url);
+ return imageCache.get(url);
else
{
Image im = createImage(url);
@@ -378,12 +384,12 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
* assumes the image is already prepared for rendering.
*/
public boolean prepareImage (Image image, int width, int height,
- ImageObserver observer)
+ ImageObserver observer)
{
/* GtkImages are always prepared, as long as they're loaded. */
if (image instanceof GtkImage)
- return ((((GtkImage)image).checkImage (observer) &
- ImageObserver.ALLBITS) != 0);
+ return ((((GtkImage)image).checkImage (observer)
+ & ImageObserver.ALLBITS) != 0);
if (image instanceof AsyncImage)
{
@@ -411,11 +417,11 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
/* Make the Peer reflect the state of the Component */
if (! (c instanceof Window))
{
- cp.setCursor (c.getCursor ());
+ cp.setCursor (c.getCursor ());
- Rectangle bounds = c.getBounds ();
- cp.setBounds (bounds.x, bounds.y, bounds.width, bounds.height);
- cp.setVisible (c.isVisible ());
+ Rectangle bounds = c.getBounds ();
+ cp.setBounds (bounds.x, bounds.y, bounds.width, bounds.height);
+ cp.setVisible (c.isVisible ());
}
}
@@ -563,7 +569,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
*/
private FontPeer getFontPeer (String name, int style, int size)
{
- Map attrs = new HashMap ();
+ Map<TextAttribute,Object> attrs = new HashMap<TextAttribute,Object>();
ClasspathFontPeer.copyStyleToAttrs (style, attrs);
ClasspathFontPeer.copySizeToAttrs (size, attrs);
return getClasspathFontPeer (name, attrs);
@@ -575,16 +581,17 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
* model, hence "ClasspathFontPeer".
*/
- public ClasspathFontPeer getClasspathFontPeer (String name, Map attrs)
+ public ClasspathFontPeer getClasspathFontPeer (String name,
+ Map<?,?> attrs)
{
- Map keyMap = new HashMap (attrs);
+ Map<Object,Object> keyMap = new HashMap<Object,Object>(attrs);
// We don't know what kind of "name" the user requested (logical, face,
// family), and we don't actually *need* to know here. The worst case
// involves failure to consolidate fonts with the same backend in our
// cache. This is harmless.
keyMap.put ("GtkToolkit.RequestedFontName", name);
if (fontCache.containsKey (keyMap))
- return (ClasspathFontPeer) fontCache.get (keyMap);
+ return fontCache.get (keyMap);
else
{
ClasspathFontPeer newPeer = new GdkFontPeer (name, attrs);
@@ -619,11 +626,10 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
return new GtkDragSourceContextPeer(e);
}
- public DragGestureRecognizer createDragGestureRecognizer(Class recognizer,
- DragSource ds,
- Component comp,
- int actions,
- DragGestureListener l)
+ public <T extends DragGestureRecognizer> T
+ createDragGestureRecognizer(Class<T> recognizer, DragSource ds,
+ Component comp, int actions,
+ DragGestureListener l)
{
if (recognizer.getName().equals("java.awt.dnd.MouseDragGestureRecognizer")
&& ! GraphicsEnvironment.isHeadless())
@@ -631,7 +637,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
GtkMouseDragGestureRecognizer gestureRecognizer
= new GtkMouseDragGestureRecognizer(ds, comp, actions, l);
gestureRecognizer.registerListeners();
- return gestureRecognizer;
+ return recognizer.cast(gestureRecognizer);
}
else
{
@@ -639,7 +645,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
}
}
- public Map mapInputMethodHighlight(InputMethodHighlight highlight)
+ public Map<TextAttribute,?> mapInputMethodHighlight(InputMethodHighlight highlight)
{
throw new Error("not implemented");
}
@@ -668,6 +674,22 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
return new GdkRobotPeer (screen);
}
+ public boolean getLockingKeyState(int keyCode)
+ {
+ int state = getLockState(keyCode);
+
+ if (state != -1)
+ return state == 1;
+
+ if (AWTUtilities.isValidKey(keyCode))
+ throw new UnsupportedOperationException
+ ("cannot get locking state of key code " + keyCode);
+
+ throw new IllegalArgumentException("invalid key code " + keyCode);
+ }
+
+ protected native int getLockState(int keyCode);
+
public void registerImageIOSpis(IIORegistry reg)
{
GdkPixbufDecoder.registerSpis(reg);
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java
index 8d49719b1d3..1451dd93354 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java
@@ -172,19 +172,17 @@ public class GtkWindowPeer extends GtkContainerPeer
public void setBounds (int x, int y, int width, int height)
{
- if (x != getX()
- || y != getY()
- || width != getWidth()
- || height != getHeight())
+ if (x != getX() || y != getY() || width != getWidth()
+ || height != getHeight())
{
- this.x = x;
- this.y = y;
- this.width = width;
- this.height = height;
+ 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);
+ nativeSetBounds (x, y,
+ width - insets.left - insets.right,
+ height - insets.top - insets.bottom);
}
}
@@ -211,7 +209,7 @@ public class GtkWindowPeer extends GtkContainerPeer
width = awtComponent.getWidth();
height = awtComponent.getHeight();
setSize (width - insets.left - insets.right,
- height - insets.top - insets.bottom);
+ height - insets.top - insets.bottom);
gtkWindowSetResizable (resizable);
}
@@ -253,22 +251,20 @@ public class GtkWindowPeer extends GtkContainerPeer
awtComponent.dispatchEvent(ev);
}
- if (frame_width != getWidth()
- || frame_height != getHeight())
+ if (frame_width != getWidth() || frame_height != getHeight())
{
- this.width = frame_width;
- this.height = frame_height;
- q().postEvent(new ComponentEvent(awtComponent,
- ComponentEvent.COMPONENT_RESIZED));
+ this.width = frame_width;
+ this.height = frame_height;
+ q().postEvent(new ComponentEvent(awtComponent,
+ ComponentEvent.COMPONENT_RESIZED));
}
- if (frame_x != getX()
- || frame_y != getY())
+ if (frame_x != getX() || frame_y != getY())
{
- this.x = frame_x;
- this.y = frame_y;
- q().postEvent(new ComponentEvent(awtComponent,
- ComponentEvent.COMPONENT_MOVED));
+ this.x = frame_x;
+ this.y = frame_y;
+ q().postEvent(new ComponentEvent(awtComponent,
+ ComponentEvent.COMPONENT_MOVED));
}
}
@@ -287,8 +283,8 @@ public class GtkWindowPeer extends GtkContainerPeer
{
if (id == WindowEvent.WINDOW_STATE_CHANGED)
{
- if (windowState != newState)
- {
+ if (windowState != newState)
+ {
// Post old styleWindowEvent with WINDOW_ICONIFIED or
// WINDOW_DEICONIFIED if appropriate.
if ((windowState & Frame.ICONIFIED) != 0
@@ -302,10 +298,10 @@ public class GtkWindowPeer extends GtkContainerPeer
WindowEvent.WINDOW_ICONIFIED,
opposite, 0, 0));
// Post new-style WindowStateEvent.
- q().postEvent (new WindowEvent ((Window) awtComponent, id,
+ q().postEvent (new WindowEvent ((Window) awtComponent, id,
opposite, windowState, newState));
- windowState = newState;
- }
+ windowState = newState;
+ }
}
else
q().postEvent (new WindowEvent ((Window) awtComponent, id, opposite));
@@ -384,7 +380,7 @@ public class GtkWindowPeer extends GtkContainerPeer
}
protected void postMouseEvent(int id, long when, int mods, int x, int y,
- int clickCount, boolean popupTrigger)
+ 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
@@ -392,8 +388,8 @@ public class GtkWindowPeer extends GtkContainerPeer
// insets but GtkFramePeer and GtkDialogPeer insets will be
// non-zero.
super.postMouseEvent (id, when, mods,
- x + insets.left, y + insets.top,
- clickCount, popupTrigger);
+ x + insets.left, y + insets.top,
+ clickCount, popupTrigger);
}
// We override this to keep it in sync with our internal
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/VolatileImageGraphics.java b/libjava/classpath/gnu/java/awt/peer/gtk/VolatileImageGraphics.java
index 62dbb45d81a..88438862b34 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/VolatileImageGraphics.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/VolatileImageGraphics.java
@@ -207,11 +207,11 @@ public class VolatileImageGraphics extends ComponentGraphics
if (img instanceof GtkVolatileImage
&& (comp == null || comp instanceof AlphaComposite))
{
- owner.drawVolatile( ((GtkVolatileImage)img).nativePointer,
- x, y,
- ((GtkVolatileImage)img).width,
- ((GtkVolatileImage)img).height );
- return true;
+ owner.drawVolatile( ((GtkVolatileImage)img).nativePointer,
+ x, y,
+ ((GtkVolatileImage)img).width,
+ ((GtkVolatileImage)img).height );
+ return true;
}
return super.drawImage( img, x, y, observer );
}
@@ -222,9 +222,9 @@ public class VolatileImageGraphics extends ComponentGraphics
if ((img instanceof GtkVolatileImage)
&& (comp == null || comp instanceof AlphaComposite))
{
- owner.drawVolatile( ((GtkVolatileImage)img).nativePointer,
- x, y, width, height );
- return true;
+ owner.drawVolatile( ((GtkVolatileImage)img).nativePointer,
+ x, y, width, height );
+ return true;
}
return super.drawImage( img, x, y, width, height, observer );
}
@@ -254,8 +254,8 @@ public class VolatileImageGraphics extends ComponentGraphics
transform.transform(points, 0, points, 0, 2);
Rectangle2D deviceBounds = new Rectangle2D.Double(points[0], points[1],
- points[2] - points[0],
- points[3] - points[1]);
+ points[2] - points[0],
+ points[3] - points[1]);
Rectangle2D.intersect(deviceBounds, this.getClipInDevSpace(), deviceBounds);
current = current.getSubimage((int)deviceBounds.getX(),
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtToolkit.java b/libjava/classpath/gnu/java/awt/peer/qt/QtToolkit.java
index 5116769389e..9b53b278b26 100644
--- a/libjava/classpath/gnu/java/awt/peer/qt/QtToolkit.java
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtToolkit.java
@@ -1,5 +1,5 @@
/* QtToolkit.java --
- Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,6 +37,7 @@ exception statement from your version. */
package gnu.java.awt.peer.qt;
+import gnu.java.awt.ClasspathToolkit;
import gnu.java.awt.EmbeddedWindow;
import gnu.java.awt.peer.ClasspathFontPeer;
import gnu.java.awt.peer.EmbeddedWindowPeer;
@@ -50,56 +51,56 @@ import java.awt.Choice;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.EventQueue;
+import java.awt.FileDialog;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Frame;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Label;
import java.awt.List;
-import java.awt.MenuBar;
import java.awt.Menu;
+import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.Panel;
-import java.awt.TextArea;
-import java.awt.TextField;
-import java.awt.FileDialog;
-import java.awt.GraphicsDevice;
-import java.awt.GraphicsEnvironment;
import java.awt.PopupMenu;
import java.awt.PrintJob;
-import java.awt.Scrollbar;
import java.awt.ScrollPane;
+import java.awt.Scrollbar;
+import java.awt.TextArea;
+import java.awt.TextField;
import java.awt.Window;
import java.awt.datatransfer.Clipboard;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.peer.DragSourceContextPeer;
import java.awt.event.AWTEventListener;
+import java.awt.im.InputMethodHighlight;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
-import java.awt.im.InputMethodHighlight;
import java.awt.peer.ButtonPeer;
-import java.awt.peer.FontPeer;
-import java.awt.peer.PanelPeer;
import java.awt.peer.CanvasPeer;
-import java.awt.peer.FramePeer;
-import java.awt.peer.PopupMenuPeer;
import java.awt.peer.CheckboxMenuItemPeer;
-import java.awt.peer.LabelPeer;
-import java.awt.peer.RobotPeer;
import java.awt.peer.CheckboxPeer;
-import java.awt.peer.ScrollPanePeer;
import java.awt.peer.ChoicePeer;
+import java.awt.peer.DialogPeer;
+import java.awt.peer.FileDialogPeer;
+import java.awt.peer.FontPeer;
+import java.awt.peer.FramePeer;
+import java.awt.peer.LabelPeer;
import java.awt.peer.ListPeer;
-import java.awt.peer.ScrollbarPeer;
import java.awt.peer.MenuBarPeer;
-import java.awt.peer.TextAreaPeer;
-import java.awt.peer.DialogPeer;
import java.awt.peer.MenuItemPeer;
-import java.awt.peer.TextFieldPeer;
-import java.awt.peer.FileDialogPeer;
import java.awt.peer.MenuPeer;
+import java.awt.peer.PanelPeer;
+import java.awt.peer.PopupMenuPeer;
+import java.awt.peer.RobotPeer;
+import java.awt.peer.ScrollPanePeer;
+import java.awt.peer.ScrollbarPeer;
+import java.awt.peer.TextAreaPeer;
+import java.awt.peer.TextFieldPeer;
import java.awt.peer.WindowPeer;
import java.io.InputStream;
import java.net.URL;
@@ -107,8 +108,6 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
-import gnu.java.awt.ClasspathToolkit;
-
public class QtToolkit extends ClasspathToolkit
{
public static EventQueue eventQueue = null; // the native event queue
@@ -163,7 +162,9 @@ public class QtToolkit extends ClasspathToolkit
if( guiThread == null )
initToolkit();
- while (!guiThread.isRunning()); // make sure the GUI thread has started.
+ // make sure the GUI thread has started.
+ while (!guiThread.isRunning())
+ ;
if( graphicsEnv == null )
graphicsEnv = new QtGraphicsEnvironment( this );
diff --git a/libjava/classpath/gnu/java/awt/print/JavaPrinterGraphics.java b/libjava/classpath/gnu/java/awt/print/JavaPrinterGraphics.java
index 9a3db012583..b86eea50b20 100644
--- a/libjava/classpath/gnu/java/awt/print/JavaPrinterGraphics.java
+++ b/libjava/classpath/gnu/java/awt/print/JavaPrinterGraphics.java
@@ -135,7 +135,8 @@ public class JavaPrinterGraphics extends Graphics implements PrinterGraphics
{
int index = 0;
while(spoolPage(out, printable, pageFormat, index++) ==
- Printable.PAGE_EXISTS);
+ Printable.PAGE_EXISTS)
+ ;
}
out.println("%%Trailer");
out.println("%%EOF");
diff --git a/libjava/classpath/gnu/java/awt/print/PostScriptGraphics2D.java b/libjava/classpath/gnu/java/awt/print/PostScriptGraphics2D.java
index e4cc8199a54..4e052a1d3f4 100644
--- a/libjava/classpath/gnu/java/awt/print/PostScriptGraphics2D.java
+++ b/libjava/classpath/gnu/java/awt/print/PostScriptGraphics2D.java
@@ -191,7 +191,8 @@ class PostScriptGraphics2D extends Graphics2D
{
int index = 0;
while(spoolPage(out, printable, pageFormat, index++) ==
- Printable.PAGE_EXISTS);
+ Printable.PAGE_EXISTS)
+ ;
}
out.println("%%Trailer");
out.println("%%EOF");