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
This commit is contained in:
parent
af333b9a7f
commit
e1bea0c068
2951 changed files with 80982 additions and 68583 deletions
|
@ -172,7 +172,6 @@ public class gnuDynValue extends RecordAny implements DynValue,
|
|||
else
|
||||
return super.current_member_kind();
|
||||
}
|
||||
;
|
||||
|
||||
/** @inheritDoc */
|
||||
public String current_member_name() throws TypeMismatch, InvalidValue
|
||||
|
@ -182,7 +181,6 @@ public class gnuDynValue extends RecordAny implements DynValue,
|
|||
else
|
||||
return super.current_member_name();
|
||||
}
|
||||
;
|
||||
|
||||
/** @inheritDoc */
|
||||
public NameDynAnyPair[] get_members_as_dyn_any() throws InvalidValue
|
||||
|
@ -191,7 +189,6 @@ public class gnuDynValue extends RecordAny implements DynValue,
|
|||
throw new InvalidValue(ISNULL);
|
||||
return super.gnu_get_members_as_dyn_any();
|
||||
}
|
||||
;
|
||||
|
||||
/** @inheritDoc */
|
||||
public NameValuePair[] get_members() throws InvalidValue
|
||||
|
@ -201,7 +198,6 @@ public class gnuDynValue extends RecordAny implements DynValue,
|
|||
else
|
||||
return super.gnu_get_members();
|
||||
}
|
||||
;
|
||||
|
||||
/** @inheritDoc */
|
||||
public void set_members_as_dyn_any(NameDynAnyPair[] value)
|
||||
|
@ -210,7 +206,6 @@ public class gnuDynValue extends RecordAny implements DynValue,
|
|||
super.set_members_as_dyn_any(value);
|
||||
isNull = false;
|
||||
}
|
||||
;
|
||||
|
||||
/** @inheritDoc */
|
||||
public void set_members(NameValuePair[] value)
|
||||
|
@ -219,7 +214,6 @@ public class gnuDynValue extends RecordAny implements DynValue,
|
|||
super.set_members(value);
|
||||
isNull = false;
|
||||
}
|
||||
;
|
||||
|
||||
/** @inheritDoc */
|
||||
public boolean is_null()
|
||||
|
|
|
@ -1348,7 +1348,6 @@ public class gnuPOA
|
|||
{
|
||||
return name;
|
||||
}
|
||||
;
|
||||
|
||||
/**
|
||||
* Return the parent of this POA.
|
||||
|
|
126
libjava/classpath/gnu/classpath/Pair.java
Normal file
126
libjava/classpath/gnu/classpath/Pair.java
Normal file
|
@ -0,0 +1,126 @@
|
|||
/* Pair.java -- A heterogenous pair of objects.
|
||||
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.classpath;
|
||||
|
||||
/**
|
||||
* A container for a pair of heterogenous objects.
|
||||
*
|
||||
* @author Andrew John Hughes (gnu_andrew@member.fsf.org)
|
||||
*/
|
||||
public class Pair<A,B>
|
||||
{
|
||||
|
||||
/**
|
||||
* The left-hand side of the pair.
|
||||
*/
|
||||
private A left;
|
||||
|
||||
/**
|
||||
* The right-hand side of the pair.
|
||||
*/
|
||||
private B right;
|
||||
|
||||
/**
|
||||
* Constructs a new pair using the given left and
|
||||
* right values.
|
||||
*
|
||||
* @param left the left-hand side of the pair.
|
||||
* @param right the right-hand side of the pair.
|
||||
*/
|
||||
public Pair(A left, B right)
|
||||
{
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the left-hand side of the pair.
|
||||
*
|
||||
* @return the left-hand value.
|
||||
*/
|
||||
public A getLeft()
|
||||
{
|
||||
return left;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the right-hand side of the pair.
|
||||
*
|
||||
* @return the right-hand value.
|
||||
*/
|
||||
public B getRight()
|
||||
{
|
||||
return right;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the specified object is also a
|
||||
* pair with equivalent left and right values.
|
||||
*
|
||||
* @param obj the object to compare.
|
||||
* @return true if the two are equal.
|
||||
*/
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj instanceof Pair)
|
||||
{
|
||||
Pair<A,B> p = (Pair<A,B>) obj;
|
||||
A lp = p.getLeft();
|
||||
B rp = p.getRight();
|
||||
return (lp == null ? left == null : lp.equals(left)) &&
|
||||
(rp == null ? right == null : rp.equals(right));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hashcode for the pair, created by the
|
||||
* summation of the hashcodes of the left and right
|
||||
* hand values.
|
||||
*
|
||||
* @return a hashcode for the pair.
|
||||
*/
|
||||
public int hashCode()
|
||||
{
|
||||
return (left == null ? 0 : left.hashCode())
|
||||
+ (right == null ? 0 : right.hashCode());
|
||||
}
|
||||
|
||||
}
|
|
@ -49,6 +49,7 @@ import java.util.Collections;
|
|||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.ServiceConfigurationError;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.util.logging.Logger;
|
||||
|
@ -176,7 +177,6 @@ public final class ServiceFactory
|
|||
*/
|
||||
private static final Logger LOGGER = Logger.getLogger("gnu.classpath");
|
||||
|
||||
|
||||
/**
|
||||
* Declared private in order to prevent constructing instances of
|
||||
* this utility class.
|
||||
|
@ -224,6 +224,51 @@ public final class ServiceFactory
|
|||
*/
|
||||
public static Iterator lookupProviders(Class spi,
|
||||
ClassLoader loader)
|
||||
{
|
||||
return lookupProviders(spi, loader, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds service providers that are implementing the specified
|
||||
* Service Provider Interface.
|
||||
*
|
||||
* <p><b>On-demand loading:</b> Loading and initializing service
|
||||
* providers is delayed as much as possible. The rationale is that
|
||||
* typical clients will iterate through the set of installed service
|
||||
* providers until one is found that matches some criteria (like
|
||||
* supported formats, or quality of service). In such scenarios, it
|
||||
* might make sense to install only the frequently needed service
|
||||
* providers on the local machine. More exotic providers can be put
|
||||
* onto a server; the server will only be contacted when no suitable
|
||||
* service could be found locally.
|
||||
*
|
||||
* <p><b>Security considerations:</b> Any loaded service providers
|
||||
* are loaded through the specified ClassLoader, or the system
|
||||
* ClassLoader if <code>classLoader</code> is
|
||||
* <code>null</code>. When <code>lookupProviders</code> is called,
|
||||
* the current {@link AccessControlContext} gets recorded. This
|
||||
* captured security context will determine the permissions when
|
||||
* services get loaded via the <code>next()</code> method of the
|
||||
* returned <code>Iterator</code>.
|
||||
*
|
||||
* @param spi the service provider interface which must be
|
||||
* implemented by any loaded service providers.
|
||||
*
|
||||
* @param loader the class loader that will be used to load the
|
||||
* service providers, or <code>null</code> for the system class
|
||||
* loader. For using the context class loader, see {@link
|
||||
* #lookupProviders(Class)}.
|
||||
* @param error true if a {@link ServiceConfigurationError}
|
||||
* should be thrown when an error occurs, rather
|
||||
* than it merely being logged.
|
||||
* @return an iterator over instances of <code>spi</code>.
|
||||
*
|
||||
* @throws IllegalArgumentException if <code>spi</code> is
|
||||
* <code>null</code>.
|
||||
*/
|
||||
public static Iterator lookupProviders(Class spi,
|
||||
ClassLoader loader,
|
||||
boolean error)
|
||||
{
|
||||
String resourceName;
|
||||
Enumeration urls;
|
||||
|
@ -246,10 +291,14 @@ public final class ServiceFactory
|
|||
* does not return anything (no providers installed).
|
||||
*/
|
||||
log(Level.WARNING, "cannot access {0}", resourceName, ioex);
|
||||
return Collections.EMPTY_LIST.iterator();
|
||||
if (error)
|
||||
throw new ServiceConfigurationError("Failed to access + " +
|
||||
resourceName, ioex);
|
||||
else
|
||||
return Collections.EMPTY_LIST.iterator();
|
||||
}
|
||||
|
||||
return new ServiceIterator(spi, urls, loader,
|
||||
return new ServiceIterator(spi, urls, loader, error,
|
||||
AccessController.getContext());
|
||||
}
|
||||
|
||||
|
@ -342,6 +391,11 @@ public final class ServiceFactory
|
|||
*/
|
||||
private Object nextProvider;
|
||||
|
||||
/**
|
||||
* True if a {@link ServiceConfigurationError} should be thrown
|
||||
* when an error occurs, instead of it merely being logged.
|
||||
*/
|
||||
private boolean error;
|
||||
|
||||
/**
|
||||
* Constructs an Iterator that loads and initializes services on
|
||||
|
@ -359,16 +413,21 @@ public final class ServiceFactory
|
|||
* @param loader the ClassLoader that gets used for loading
|
||||
* service providers.
|
||||
*
|
||||
* @param error true if a {@link ServiceConfigurationError}
|
||||
* should be thrown when an error occurs, rather
|
||||
* than it merely being logged.
|
||||
*
|
||||
* @param securityContext the security context to use when loading
|
||||
* and initializing service providers.
|
||||
*/
|
||||
ServiceIterator(Class spi, Enumeration urls, ClassLoader loader,
|
||||
AccessControlContext securityContext)
|
||||
boolean error, AccessControlContext securityContext)
|
||||
{
|
||||
this.spi = spi;
|
||||
this.urls = urls;
|
||||
this.loader = loader;
|
||||
this.securityContext = securityContext;
|
||||
this.error = error;
|
||||
this.nextProvider = loadNextServiceProvider();
|
||||
}
|
||||
|
||||
|
@ -426,6 +485,9 @@ public final class ServiceFactory
|
|||
log(Level.WARNING, "IOException upon reading {0}", currentURL,
|
||||
readProblem);
|
||||
line = null;
|
||||
if (error)
|
||||
throw new ServiceConfigurationError("Error reading " +
|
||||
currentURL, readProblem);
|
||||
}
|
||||
|
||||
/* When we are at the end of one list of services,
|
||||
|
@ -477,6 +539,13 @@ public final class ServiceFactory
|
|||
log(Level.WARNING, msg,
|
||||
new Object[] { line, spi.getName(), currentURL },
|
||||
ex);
|
||||
if (error)
|
||||
throw new ServiceConfigurationError("Cannot load service "+
|
||||
"provider class " +
|
||||
line + " specified by "+
|
||||
"\"META-INF/services/"+
|
||||
spi.getName() + "\" in "+
|
||||
currentURL, ex);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -497,6 +566,9 @@ public final class ServiceFactory
|
|||
catch (Exception ex)
|
||||
{
|
||||
log(Level.WARNING, "cannot close {0}", currentURL, ex);
|
||||
if (error)
|
||||
throw new ServiceConfigurationError("Cannot close " +
|
||||
currentURL, ex);
|
||||
}
|
||||
reader = null;
|
||||
currentURL = null;
|
||||
|
@ -515,6 +587,9 @@ public final class ServiceFactory
|
|||
catch (Exception ex)
|
||||
{
|
||||
log(Level.WARNING, "cannot open {0}", currentURL, ex);
|
||||
if (error)
|
||||
throw new ServiceConfigurationError("Cannot open " +
|
||||
currentURL, ex);
|
||||
}
|
||||
}
|
||||
while (reader == null);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* VariableTable.java -- A class representing a Variable Table for a method
|
||||
Copyright (C) 2005 Free Software Foundation
|
||||
Copyright (C) 2005, 2007 Free Software Foundation
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* ArrayValue.java -- JDWP wrapper class for an Object value
|
||||
/* ObjectValue.java -- JDWP wrapper class for an Object value
|
||||
Copyright (C) 2007 Free Software Foundation
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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>“Univers Light”</i>.
|
||||
|
@ -221,7 +228,8 @@ public interface FontDelegate
|
|||
float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics);
|
||||
boolean fractionalMetrics,
|
||||
int type);
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
83
libjava/classpath/gnu/java/awt/font/autofit/AutoHinter.java
Normal file
83
libjava/classpath/gnu/java/awt/font/autofit/AutoHinter.java
Normal file
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
80
libjava/classpath/gnu/java/awt/font/autofit/Edge.java
Normal file
80
libjava/classpath/gnu/java/awt/font/autofit/Edge.java
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
{
|
||||
// TODO: Implement.
|
||||
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)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
void computeSegments(int dim)
|
||||
private void setWeakPoint(Point p)
|
||||
{
|
||||
// TODO: Implement.
|
||||
p.setFlags((byte) (p.getFlags() | Point.FLAG_WEAK_INTERPOLATION));
|
||||
}
|
||||
|
||||
void linkSegments(int dim)
|
||||
/**
|
||||
* Computes the inflection points for a glyph.
|
||||
*/
|
||||
private void computeInflectionPoints()
|
||||
{
|
||||
// TODO: Implement.
|
||||
// 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;
|
||||
}
|
||||
|
||||
public boolean doAlignStrongPoints()
|
||||
{
|
||||
return (flags & FontDelegate.FLAG_NO_HINT_STRONG_POINTS) == 0;
|
||||
}
|
||||
|
||||
public boolean doAlignWeakPoints()
|
||||
{
|
||||
return (flags & FontDelegate.FLAG_NO_HINT_WEAK_POINTS) == 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
59
libjava/classpath/gnu/java/awt/font/autofit/LatinBlue.java
Normal file
59
libjava/classpath/gnu/java/awt/font/autofit/LatinBlue.java
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -45,5 +45,9 @@ class ScriptMetrics
|
|||
{
|
||||
|
||||
Script script;
|
||||
Scaler scaler;
|
||||
HintScaler scaler;
|
||||
ScriptMetrics()
|
||||
{
|
||||
scaler = new HintScaler();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
255
libjava/classpath/gnu/java/awt/font/autofit/Utils.java
Normal file
255
libjava/classpath/gnu/java/awt/font/autofit/Utils.java
Normal file
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
63
libjava/classpath/gnu/java/awt/font/opentype/Hinter.java
Normal file
63
libjava/classpath/gnu/java/awt/font/opentype/Hinter.java
Normal file
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,7 +90,8 @@ public abstract class Scaler
|
|||
float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics);
|
||||
boolean fractionalMetrics,
|
||||
Hinter hinter, int type);
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
285
libjava/classpath/gnu/java/awt/font/opentype/truetype/Point.java
Normal file
285
libjava/classpath/gnu/java/awt/font/opentype/truetype/Point.java
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -153,6 +150,11 @@ public abstract class AbstractGraphics2D
|
|||
implements Cloneable
|
||||
{
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -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
|
||||
|
@ -176,6 +185,11 @@ public abstract class AbstractGraphics2D
|
|||
*/
|
||||
private Paint paint;
|
||||
|
||||
/**
|
||||
* The paint context during rendering.
|
||||
*/
|
||||
private PaintContext paintContext;
|
||||
|
||||
/**
|
||||
* The 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1704,141 +1710,6 @@ public abstract class AbstractGraphics2D
|
|||
throw new UnsupportedOperationException("Not implemented yet.");
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2266,80 +1940,6 @@ public abstract class AbstractGraphics2D
|
|||
p.transform(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return a list of PolyEdge that form the shape in device space
|
||||
*/
|
||||
private ArrayList getSegments(Shape s, AffineTransform t,
|
||||
Rectangle2D deviceBounds, boolean isClip)
|
||||
{
|
||||
// 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())
|
||||
{
|
||||
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();
|
||||
}
|
||||
deviceBounds.setRect(minX, minY, maxX - minX, maxY - minY);
|
||||
return segs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ShapeCache for the calling thread.
|
||||
*
|
||||
|
@ -2347,7 +1947,7 @@ public abstract class AbstractGraphics2D
|
|||
*/
|
||||
private ShapeCache getShapeCache()
|
||||
{
|
||||
ShapeCache sc = (ShapeCache) shapeCache.get();
|
||||
ShapeCache sc = shapeCache.get();
|
||||
if (sc == null)
|
||||
{
|
||||
sc = new ShapeCache();
|
||||
|
@ -2355,4 +1955,20 @@ public abstract class AbstractGraphics2D
|
|||
}
|
||||
return sc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scanline converter for this thread.
|
||||
*
|
||||
* @return the scanline converter for this thread
|
||||
*/
|
||||
private ScanlineConverter getScanlineConverter()
|
||||
{
|
||||
ScanlineConverter sc = scanlineConverters.get();
|
||||
if (sc == null)
|
||||
{
|
||||
sc = new ScanlineConverter();
|
||||
scanlineConverters.set(sc);
|
||||
}
|
||||
return sc;
|
||||
}
|
||||
}
|
||||
|
|
195
libjava/classpath/gnu/java/awt/java2d/ActiveEdges.java
Normal file
195
libjava/classpath/gnu/java/awt/java2d/ActiveEdges.java
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -38,37 +38,62 @@ 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.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
|
@ -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: "
|
||||
|
|
91
libjava/classpath/gnu/java/awt/java2d/Scanline.java
Normal file
91
libjava/classpath/gnu/java/awt/java2d/Scanline.java
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
404
libjava/classpath/gnu/java/awt/java2d/ScanlineConverter.java
Normal file
404
libjava/classpath/gnu/java/awt/java2d/ScanlineConverter.java
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
301
libjava/classpath/gnu/java/awt/peer/ClasspathDesktopPeer.java
Normal file
301
libjava/classpath/gnu/java/awt/peer/ClasspathDesktopPeer.java
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
153
libjava/classpath/gnu/java/awt/peer/GnomeDesktopPeer.java
Normal file
153
libjava/classpath/gnu/java/awt/peer/GnomeDesktopPeer.java
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
135
libjava/classpath/gnu/java/awt/peer/KDEDesktopPeer.java
Normal file
135
libjava/classpath/gnu/java/awt/peer/KDEDesktopPeer.java
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
@ -74,12 +74,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.
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
|
@ -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:
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
DataFlavor flavor = flavors[i];
|
||||
String mimeType = flavor.getMimeType();
|
||||
mimeTargets[i] = mimeType;
|
||||
|
||||
if (! text)
|
||||
if ("text".equals(flavor.getPrimaryType())
|
||||
|| flavor.isRepresentationClassReader())
|
||||
text = true;
|
||||
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 (! 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;
|
||||
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);
|
||||
DataFlavor flavor = new DataFlavor(target);
|
||||
Object o = contents.getTransferData(flavor);
|
||||
|
||||
if (o instanceof byte[])
|
||||
return (byte[]) o;
|
||||
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 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();
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 ());
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
// 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
|
||||
}
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
// 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
|
||||
}
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
// 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
|
||||
}
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
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();
|
||||
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
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
// 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())
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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.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.FontPeer;
|
||||
import java.awt.peer.FramePeer;
|
||||
import java.awt.peer.LabelPeer;
|
||||
import java.awt.peer.ListPeer;
|
||||
import java.awt.peer.MenuBarPeer;
|
||||
import java.awt.peer.MenuItemPeer;
|
||||
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 );
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -153,7 +153,7 @@ public class ScanEngine
|
|||
writer = new StAXWriter(os);
|
||||
root = new Root();
|
||||
|
||||
final ScannerState start = current = new GenericScannerState(root);;
|
||||
final ScannerState start = current = new GenericScannerState(root);
|
||||
ScannerState conf;
|
||||
|
||||
// Use the ReportingScannerState to debug serialization issues.
|
||||
|
|
|
@ -139,7 +139,9 @@ public class Base64InputStream extends FilterInputStream
|
|||
while (count < len)
|
||||
{
|
||||
int i;
|
||||
while (Character.isWhitespace((char) (i = in.read())));
|
||||
while (Character.isWhitespace((char) (i = in.read())))
|
||||
;
|
||||
|
||||
int pos = BASE_64.indexOf((char) i);
|
||||
if (pos >= 0)
|
||||
{
|
||||
|
@ -173,11 +175,13 @@ public class Base64InputStream extends FilterInputStream
|
|||
case 1:
|
||||
throw new IOException("malformed Base-64 input");
|
||||
case 2:
|
||||
while (Character.isWhitespace((char) (i = in.read())));
|
||||
while (Character.isWhitespace((char) (i = in.read())))
|
||||
;
|
||||
if (i != BASE_64_PAD)
|
||||
throw new IOException("malformed Base-64 input");
|
||||
case 3:
|
||||
while (Character.isWhitespace((char) (i = in.read())));
|
||||
while (Character.isWhitespace((char) (i = in.read())))
|
||||
;
|
||||
}
|
||||
eof = true;
|
||||
break;
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
# This property file contains dependencies of classes, methods, and
|
||||
# field on other methods or classes.
|
||||
#
|
||||
# Syntax:
|
||||
#
|
||||
# <used>: <needed 1> [... <needed N>]
|
||||
#
|
||||
# means that when <used> is included, <needed 1> (... <needed N>) must
|
||||
# be included as well.
|
||||
#
|
||||
# <needed X> and <used> are of the form
|
||||
#
|
||||
# <class.methodOrField(signature)>
|
||||
#
|
||||
# or just
|
||||
#
|
||||
# <class>
|
||||
#
|
||||
# Within dependencies, variables can be used. A variable is defined as
|
||||
# follows:
|
||||
#
|
||||
# {variable}: value1 value2 ... value<n>
|
||||
#
|
||||
# variables can be used on the right side of dependencies as follows:
|
||||
#
|
||||
# <used>: com.bla.blu.{variable}.Class.m()V
|
||||
#
|
||||
# The use of the variable will expand to <n> dependencies of the form
|
||||
#
|
||||
# <used>: com.bla.blu.value1.Class.m()V
|
||||
# <used>: com.bla.blu.value2.Class.m()V
|
||||
# ...
|
||||
# <used>: com.bla.blu.value<n>.Class.m()V
|
||||
#
|
||||
# Variables can be redefined when building a system to select the
|
||||
# required support for features like encodings, protocols, etc.
|
||||
#
|
||||
# Hints:
|
||||
#
|
||||
# - For methods and fields, the signature is mandatory. For
|
||||
# specification, please see the Java Virtual Machine Specification by
|
||||
# SUN. Unlike in the spec, field signatures (types) are in brackets.
|
||||
#
|
||||
# - Package names must be separated by '/' (and not '.'). E.g.,
|
||||
# java/lang/Class (this is necessary, because the '.' is used to
|
||||
# separate method or field names from classes)
|
||||
#
|
||||
# - In case <needed> refers to a class, only the class itself will be
|
||||
# included in the resulting binary, NOT necessarily all its methods
|
||||
# and fields. If you want to refer to all methods and fields, you can
|
||||
# write class.* as an abbreviation.
|
||||
#
|
||||
# - Abbreviations for packages are also possible: my/package/* means all
|
||||
# methods and fields of all classes in my/package.
|
||||
#
|
||||
# - A line with a trailing '\' continues in the next line.
|
||||
|
||||
|
||||
# All encodings supported are loaded via gnu/java/io/EncodingManager.findEncoderConstructor
|
||||
# or gnu/java/io/EncodingManager.findDecoderConstructor from class
|
||||
# gnu/java/io/decode/Decoder<encoding>.
|
||||
#
|
||||
# This introduces a dependency for all encodings. To allow an easy selection
|
||||
# and addition of encodings, the library variable {encodings} can be set to
|
||||
# the set of supported encodings.
|
||||
#
|
||||
{encodings}: 8859_1 8859_2 8859_3 8859_4 8859_5 UTF8
|
||||
|
||||
gnu/java/io/EncodingManager.findEncoderConstructor(Ljava/lang/String;Z)Ljava/lang/reflect/Constructor;: \
|
||||
gnu/java/io/decode/Decoder{encodings}.*
|
||||
|
||||
gnu/java/io/EncodingManager.findDecoderConstructor(Ljava/lang/String;Z)Ljava/lang/reflect/Constructor;: \
|
||||
gnu/java/io/encode/Encoder{encodings}.* \
|
||||
|
||||
# end of file
|
|
@ -37,6 +37,8 @@ exception statement from your version. */
|
|||
|
||||
package gnu.java.lang.management;
|
||||
|
||||
import gnu.javax.management.Translator;
|
||||
|
||||
import java.lang.management.ManagementPermission;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
@ -124,7 +126,7 @@ public class BeanImpl
|
|||
new OpenMBeanAttributeInfoSupport[oldA.length];
|
||||
for (int a = 0; a < oldA.length; ++a)
|
||||
{
|
||||
OpenMBeanParameterInfo param = translate(oldA[a].getType());
|
||||
OpenMBeanParameterInfo param = Translator.translate(oldA[a].getType());
|
||||
if (param.getMinValue() == null)
|
||||
{
|
||||
Object[] lv;
|
||||
|
@ -134,7 +136,8 @@ public class BeanImpl
|
|||
lv = param.getLegalValues().toArray();
|
||||
attribs[a] = new OpenMBeanAttributeInfoSupport(oldA[a].getName(),
|
||||
oldA[a].getDescription(),
|
||||
param.getOpenType(),
|
||||
((OpenType<Object>)
|
||||
param.getOpenType()),
|
||||
oldA[a].isReadable(),
|
||||
oldA[a].isWritable(),
|
||||
oldA[a].isIs(),
|
||||
|
@ -144,13 +147,16 @@ public class BeanImpl
|
|||
else
|
||||
attribs[a] = new OpenMBeanAttributeInfoSupport(oldA[a].getName(),
|
||||
oldA[a].getDescription(),
|
||||
param.getOpenType(),
|
||||
((OpenType<Object>)
|
||||
param.getOpenType()),
|
||||
oldA[a].isReadable(),
|
||||
oldA[a].isWritable(),
|
||||
oldA[a].isIs(),
|
||||
param.getDefaultValue(),
|
||||
param.getMinValue(),
|
||||
param.getMaxValue());
|
||||
((Comparable<Object>)
|
||||
param.getMinValue()),
|
||||
((Comparable<Object>)
|
||||
param.getMaxValue()));
|
||||
}
|
||||
MBeanConstructorInfo[] oldC = info.getConstructors();
|
||||
OpenMBeanConstructorInfo[] cons = new OpenMBeanConstructorInfoSupport[oldC.length];
|
||||
|
@ -166,7 +172,7 @@ public class BeanImpl
|
|||
new OpenMBeanOperationInfoSupport(oldO[a].getName(),
|
||||
oldO[a].getDescription(),
|
||||
translateSignature(oldO[a].getSignature()),
|
||||
translate(oldO[a].getReturnType()).getOpenType(),
|
||||
Translator.translate(oldO[a].getReturnType()).getOpenType(),
|
||||
oldO[a].getImpact());
|
||||
openInfo = new OpenMBeanInfoSupport(info.getClassName(), info.getDescription(),
|
||||
attribs, cons, ops, info.getNotifications());
|
||||
|
@ -201,32 +207,36 @@ public class BeanImpl
|
|||
return ((Enum) value).name();
|
||||
Class vClass = value.getClass();
|
||||
if (vClass.isArray())
|
||||
return value;
|
||||
vClass = vClass.getComponentType();
|
||||
String cName = vClass.getName();
|
||||
String[] allowedTypes = OpenType.ALLOWED_CLASSNAMES;
|
||||
for (int a = 0; a < allowedTypes.length; ++a)
|
||||
if (cName.equals(allowedTypes[a]))
|
||||
return value;
|
||||
if (value instanceof List)
|
||||
{
|
||||
List l = (List) value;
|
||||
Class e = null;
|
||||
TypeVariable[] vars = vClass.getTypeParameters();
|
||||
for (int a = 0; a < vars.length; ++a)
|
||||
if (vars[a].getName().equals("E"))
|
||||
e = (Class) vars[a].getGenericDeclaration();
|
||||
if (e == null)
|
||||
e = Object.class;
|
||||
Object[] array = (Object[]) Array.newInstance(e, l.size());
|
||||
return l.toArray(array);
|
||||
}
|
||||
OpenMBeanInfo info = (OpenMBeanInfo) getMBeanInfo();
|
||||
OpenMBeanAttributeInfo[] attribs =
|
||||
(OpenMBeanAttributeInfo[]) info.getAttributes();
|
||||
MBeanAttributeInfo[] attribs =
|
||||
(MBeanAttributeInfo[]) info.getAttributes();
|
||||
OpenType type = null;
|
||||
for (int a = 0; a < attribs.length; ++a)
|
||||
if (attribs[a].getName().equals("attribute"))
|
||||
type = attribs[a].getOpenType();
|
||||
if (attribs[a].getName().equals(attribute))
|
||||
type = ((OpenMBeanAttributeInfo) attribs[a]).getOpenType();
|
||||
if (value instanceof List)
|
||||
{
|
||||
try
|
||||
{
|
||||
Class e =
|
||||
Class.forName(((ArrayType) type).getElementOpenType().getClassName());
|
||||
List l = (List) value;
|
||||
Object[] array = (Object[]) Array.newInstance(e, l.size());
|
||||
return l.toArray(array);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
throw (InternalError) (new InternalError("The class of the list " +
|
||||
"element type could not " +
|
||||
"be created").initCause(e));
|
||||
}
|
||||
}
|
||||
if (value instanceof Map)
|
||||
{
|
||||
TabularType ttype = (TabularType) type;
|
||||
|
@ -319,19 +329,13 @@ public class BeanImpl
|
|||
return getCachedMBeanInfo();
|
||||
}
|
||||
|
||||
private OpenType getTypeFromClass(Class c)
|
||||
throws OpenDataException
|
||||
{
|
||||
return translate(c.getName()).getOpenType();
|
||||
}
|
||||
|
||||
private OpenMBeanParameterInfo[] translateSignature(MBeanParameterInfo[] oldS)
|
||||
throws OpenDataException
|
||||
{
|
||||
OpenMBeanParameterInfo[] sig = new OpenMBeanParameterInfoSupport[oldS.length];
|
||||
for (int a = 0; a < oldS.length; ++a)
|
||||
{
|
||||
OpenMBeanParameterInfo param = translate(oldS[a].getType());
|
||||
OpenMBeanParameterInfo param = Translator.translate(oldS[a].getType());
|
||||
if (param.getMinValue() == null)
|
||||
{
|
||||
Object[] lv;
|
||||
|
@ -341,179 +345,24 @@ public class BeanImpl
|
|||
lv = param.getLegalValues().toArray();
|
||||
sig[a] = new OpenMBeanParameterInfoSupport(oldS[a].getName(),
|
||||
oldS[a].getDescription(),
|
||||
param.getOpenType(),
|
||||
((OpenType<Object>)
|
||||
param.getOpenType()),
|
||||
param.getDefaultValue(),
|
||||
lv);
|
||||
}
|
||||
else
|
||||
sig[a] = new OpenMBeanParameterInfoSupport(oldS[a].getName(),
|
||||
oldS[a].getDescription(),
|
||||
param.getOpenType(),
|
||||
((OpenType<Object>)
|
||||
param.getOpenType()),
|
||||
param.getDefaultValue(),
|
||||
param.getMinValue(),
|
||||
param.getMaxValue());
|
||||
((Comparable<Object>)
|
||||
param.getMinValue()),
|
||||
((Comparable<Object>)
|
||||
param.getMaxValue()));
|
||||
}
|
||||
return sig;
|
||||
}
|
||||
|
||||
private OpenMBeanParameterInfo translate(String type)
|
||||
throws OpenDataException
|
||||
{
|
||||
if (type.equals("boolean") || type.equals(Boolean.class.getName()))
|
||||
return new OpenMBeanParameterInfoSupport("TransParam",
|
||||
"Translated parameter",
|
||||
SimpleType.BOOLEAN,
|
||||
null,
|
||||
new Object[] {
|
||||
Boolean.TRUE,
|
||||
Boolean.FALSE
|
||||
});
|
||||
if (type.equals("byte") || type.equals(Byte.class.getName()))
|
||||
return new OpenMBeanParameterInfoSupport("TransParam",
|
||||
"Translated parameter",
|
||||
SimpleType.BYTE,
|
||||
null,
|
||||
Byte.valueOf(Byte.MIN_VALUE),
|
||||
Byte.valueOf(Byte.MAX_VALUE));
|
||||
if (type.equals("char") || type.equals(Character.class.getName()))
|
||||
return new OpenMBeanParameterInfoSupport("TransParam",
|
||||
"Translated parameter",
|
||||
SimpleType.CHARACTER,
|
||||
null,
|
||||
Character.valueOf(Character.MIN_VALUE),
|
||||
Character.valueOf(Character.MAX_VALUE));
|
||||
if (type.equals("double") || type.equals(Double.class.getName()))
|
||||
return new OpenMBeanParameterInfoSupport("TransParam",
|
||||
"Translated parameter",
|
||||
SimpleType.DOUBLE,
|
||||
null,
|
||||
Double.valueOf(Double.MIN_VALUE),
|
||||
Double.valueOf(Double.MAX_VALUE));
|
||||
if (type.equals("float") || type.equals(Float.class.getName()))
|
||||
return new OpenMBeanParameterInfoSupport("TransParam",
|
||||
"Translated parameter",
|
||||
SimpleType.FLOAT,
|
||||
null,
|
||||
Float.valueOf(Float.MIN_VALUE),
|
||||
Float.valueOf(Float.MAX_VALUE));
|
||||
if (type.equals("int") || type.equals(Integer.class.getName()))
|
||||
return new OpenMBeanParameterInfoSupport("TransParam",
|
||||
"Translated parameter",
|
||||
SimpleType.INTEGER,
|
||||
null,
|
||||
Integer.valueOf(Integer.MIN_VALUE),
|
||||
Integer.valueOf(Integer.MAX_VALUE));
|
||||
if (type.equals("long") || type.equals(Long.class.getName()))
|
||||
return new OpenMBeanParameterInfoSupport("TransParam",
|
||||
"Translated parameter",
|
||||
SimpleType.LONG,
|
||||
null,
|
||||
Long.valueOf(Long.MIN_VALUE),
|
||||
Long.valueOf(Long.MAX_VALUE));
|
||||
if (type.equals("short") || type.equals(Short.class.getName()))
|
||||
return new OpenMBeanParameterInfoSupport("TransParam",
|
||||
"Translated parameter",
|
||||
SimpleType.SHORT,
|
||||
null,
|
||||
Short.valueOf(Short.MIN_VALUE),
|
||||
Short.valueOf(Short.MAX_VALUE));
|
||||
if (type.equals(String.class.getName()))
|
||||
return new OpenMBeanParameterInfoSupport("TransParam",
|
||||
"Translated parameter",
|
||||
SimpleType.STRING);
|
||||
if (type.equals("void"))
|
||||
return new OpenMBeanParameterInfoSupport("TransParam",
|
||||
"Translated parameter",
|
||||
SimpleType.VOID);
|
||||
if (type.startsWith("java.util.Map"))
|
||||
{
|
||||
int lparam = type.indexOf("<");
|
||||
int comma = type.indexOf(",", lparam);
|
||||
int rparam = type.indexOf(">", comma);
|
||||
String key = type.substring(lparam + 1, comma).trim();
|
||||
OpenType k = translate(key).getOpenType();
|
||||
OpenType v = translate(type.substring(comma + 1, rparam).trim()).getOpenType();
|
||||
CompositeType ctype = new CompositeType(Map.class.getName(), Map.class.getName(),
|
||||
new String[] { "key", "value" },
|
||||
new String[] { "Map key", "Map value"},
|
||||
new OpenType[] { k, v});
|
||||
TabularType ttype = new TabularType(key, key, ctype,
|
||||
new String[] { "key" });
|
||||
return new OpenMBeanParameterInfoSupport("TransParam",
|
||||
"Translated parameter",
|
||||
ttype);
|
||||
}
|
||||
if (type.startsWith("java.util.List"))
|
||||
{
|
||||
int lparam = type.indexOf("<");
|
||||
int rparam = type.indexOf(">");
|
||||
OpenType e = translate(type.substring(lparam + 1, rparam).trim()).getOpenType();
|
||||
return new OpenMBeanParameterInfoSupport("TransParam",
|
||||
"Translated parameter",
|
||||
new ArrayType(1, e)
|
||||
);
|
||||
}
|
||||
Class c;
|
||||
try
|
||||
{
|
||||
c = Class.forName(type);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
throw (InternalError)
|
||||
(new InternalError("The class for a type used in a management bean " +
|
||||
"could not be loaded.").initCause(e));
|
||||
}
|
||||
if (c.isEnum())
|
||||
{
|
||||
Object[] values = c.getEnumConstants();
|
||||
String[] names = new String[values.length];
|
||||
for (int a = 0; a < values.length; ++a)
|
||||
names[a] = values[a].toString();
|
||||
return new OpenMBeanParameterInfoSupport("TransParam",
|
||||
"Translated parameter",
|
||||
SimpleType.STRING,
|
||||
null,
|
||||
(Object[]) names);
|
||||
}
|
||||
try
|
||||
{
|
||||
c.getMethod("from", new Class[] { CompositeData.class });
|
||||
Method[] methods = c.getMethods();
|
||||
List names = new ArrayList();
|
||||
List types = new ArrayList();
|
||||
for (int a = 0; a < methods.length; ++a)
|
||||
{
|
||||
String name = methods[a].getName();
|
||||
if (name.startsWith("get"))
|
||||
{
|
||||
names.add(name.substring(3));
|
||||
types.add(getTypeFromClass(methods[a].getReturnType()));
|
||||
}
|
||||
}
|
||||
String[] fields = (String[]) names.toArray();
|
||||
CompositeType ctype = new CompositeType(c.getName(), c.getName(),
|
||||
fields, fields,
|
||||
(OpenType[]) types.toArray());
|
||||
return new OpenMBeanParameterInfoSupport("TransParam",
|
||||
"Translated parameter",
|
||||
ctype);
|
||||
}
|
||||
catch (NoSuchMethodException e)
|
||||
{
|
||||
/* Ignored; we expect this if this isn't a from(CompositeData) class */
|
||||
}
|
||||
if (c.isArray())
|
||||
{
|
||||
int depth;
|
||||
for (depth = 0; c.getName().charAt(depth) == '['; ++depth);
|
||||
OpenType ot = getTypeFromClass(c.getComponentType());
|
||||
return new OpenMBeanParameterInfoSupport("TransParam",
|
||||
"Translated parameter",
|
||||
new ArrayType(depth, ot)
|
||||
);
|
||||
}
|
||||
throw new InternalError("The type used does not have an open type translation.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -82,6 +82,11 @@ public final class OperatingSystemMXBeanImpl
|
|||
return System.getProperty("os.name");
|
||||
}
|
||||
|
||||
public double getSystemLoadAverage()
|
||||
{
|
||||
return VMOperatingSystemMXBeanImpl.getSystemLoadAverage();
|
||||
}
|
||||
|
||||
public String getVersion()
|
||||
{
|
||||
return System.getProperty("os.version");
|
||||
|
|
|
@ -83,7 +83,19 @@ public final class ThreadMXBeanImpl
|
|||
*/
|
||||
private static final String TIME_ENABLED =
|
||||
"gnu.java.lang.management.ThreadTimeInitallyEnabled";
|
||||
|
||||
|
||||
/**
|
||||
* Constant for monitor usage monitoring support.
|
||||
*/
|
||||
private static final String MONITOR_SUPPORT =
|
||||
"gnu.java.lang.management.MonitorUsageMonitoringSupport";
|
||||
|
||||
/**
|
||||
* Constant for ownable synchronizer usage monitoring support.
|
||||
*/
|
||||
private static final String SYNCHRONIZER_SUPPORT =
|
||||
"gnu.java.lang.management.OwnableSynchronizerUsageMonitoringSupport";
|
||||
|
||||
/**
|
||||
* Flag to indicate whether time monitoring is enabled or not.
|
||||
*/
|
||||
|
@ -112,6 +124,23 @@ public final class ThreadMXBeanImpl
|
|||
contentionEnabled = false;
|
||||
}
|
||||
|
||||
public ThreadInfo[] dumpAllThreads(boolean lockedMonitors,
|
||||
boolean lockedSynchronizers)
|
||||
{
|
||||
return getThreadInfo(getAllThreadIds(), lockedMonitors,
|
||||
lockedSynchronizers);
|
||||
}
|
||||
|
||||
public long[] findDeadlockedThreads()
|
||||
{
|
||||
checkMonitorPermissions();
|
||||
if (!isSynchronizerUsageSupported())
|
||||
throw new UnsupportedOperationException("Ownable synchronizer usage " +
|
||||
"monitoring is not provided " +
|
||||
"by this VM.");
|
||||
return VMThreadMXBeanImpl.findDeadlockedThreads();
|
||||
}
|
||||
|
||||
public long[] findMonitorDeadlockedThreads()
|
||||
{
|
||||
checkMonitorPermissions();
|
||||
|
@ -207,6 +236,27 @@ public final class ThreadMXBeanImpl
|
|||
return infos;
|
||||
}
|
||||
|
||||
public ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors,
|
||||
boolean lockedSynchronizers)
|
||||
{
|
||||
checkMonitorPermissions();
|
||||
if (lockedMonitors && !isObjectMonitorUsageSupported())
|
||||
throw new UnsupportedOperationException("Monitor usage monitoring is " +
|
||||
"not provided by this VM.");
|
||||
if (lockedSynchronizers && !isSynchronizerUsageSupported())
|
||||
throw new UnsupportedOperationException("Ownable synchronizer usage " +
|
||||
"monitoring is not provided " +
|
||||
"by this VM.");
|
||||
ThreadInfo[] infos = getThreadInfo(ids, Integer.MAX_VALUE);
|
||||
if (lockedMonitors)
|
||||
for (ThreadInfo info : infos)
|
||||
VMThreadMXBeanImpl.getMonitorInfo(info);
|
||||
if (lockedSynchronizers)
|
||||
for (ThreadInfo info : infos)
|
||||
VMThreadMXBeanImpl.getLockInfo(info);
|
||||
return infos;
|
||||
}
|
||||
|
||||
public long getThreadUserTime(long id)
|
||||
{
|
||||
if (!isThreadCpuTimeSupported())
|
||||
|
@ -231,6 +281,16 @@ public final class ThreadMXBeanImpl
|
|||
return SystemProperties.getProperty(CURRENT_THREAD_TIME_SUPPORT) != null;
|
||||
}
|
||||
|
||||
public boolean isObjectMonitorUsageSupported()
|
||||
{
|
||||
return SystemProperties.getProperty(MONITOR_SUPPORT) != null;
|
||||
}
|
||||
|
||||
public boolean isSynchronizerUsageSupported()
|
||||
{
|
||||
return SystemProperties.getProperty(SYNCHRONIZER_SUPPORT) != null;
|
||||
}
|
||||
|
||||
public boolean isThreadContentionMonitoringEnabled()
|
||||
{
|
||||
if (isThreadContentionMonitoringSupported())
|
||||
|
|
|
@ -55,105 +55,44 @@ import java.util.ResourceBundle;
|
|||
public class LocaleHelper
|
||||
{
|
||||
/**
|
||||
* This method is used by the localized name lookup methods to retrieve
|
||||
* the localized name of a particular piece of locale data.
|
||||
* If the display name can not be localized to the supplied
|
||||
* locale, it will fall back on other output in the following order:
|
||||
*
|
||||
* <ul>
|
||||
* <li>the localized name in the default locale</li>
|
||||
* <li>the localized name in English (optional)</li>
|
||||
* <li>the localized name in the root locale bundle (optional)</li>
|
||||
* <li>the localized input string</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* If the supplied key is merely the empty string, then the empty string is
|
||||
* returned.
|
||||
* This method is used by the localized name lookup methods to
|
||||
* retrieve the next locale to try. The next locale is derived
|
||||
* from the supplied locale by applying the first applicable
|
||||
* rule from the following:
|
||||
* </p>
|
||||
* <ol>
|
||||
* <li>If the variant contains a <code>'_'</code>, then
|
||||
* this and everything following it is trimmed.</li>
|
||||
* <li>If the variant is non-empty, it is converted to
|
||||
* an empty string.</li>
|
||||
* <li>If the country is non-empty, it is converted to
|
||||
* an empty string.</li>
|
||||
* <li>If the language is non-empty, it is converted to
|
||||
* an empty string (forming {@link java.util.Locale#ROOT})</li>
|
||||
* </ol>
|
||||
* <p>
|
||||
* The base fallback locale is {@link java.util.Locale#ROOT}.
|
||||
* </p>
|
||||
*
|
||||
* @param inLocale the locale to use for formatting the display string.
|
||||
* @param key the locale data used as a key to the localized lookup tables.
|
||||
* @param name the name of the hashtable containing the localized data.
|
||||
* @param checkEnglish true if the method should fall back on data
|
||||
* from the English locale.
|
||||
* @param checkRoot true if the method should fall back on data from the
|
||||
* unlocalized root locale.
|
||||
* @return a <code>String</code>, hopefully containing the localized
|
||||
* variant of the input data.
|
||||
* @throws NullPointerException if <code>inLocale</code> is null.
|
||||
* @param locale the locale for which a localized piece of
|
||||
* data could not be obtained.
|
||||
* @return the next fallback locale to try.
|
||||
*/
|
||||
public static String getLocalizedString(Locale inLocale, String key,
|
||||
String name, boolean checkEnglish,
|
||||
boolean checkRoot)
|
||||
public static Locale getFallbackLocale(Locale locale)
|
||||
{
|
||||
String localizedString;
|
||||
String property;
|
||||
|
||||
if (key.equals(""))
|
||||
return "";
|
||||
property = name + "." + key;
|
||||
/* Localize to inLocale */
|
||||
try
|
||||
{
|
||||
localizedString =
|
||||
ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
|
||||
inLocale).getString(property);
|
||||
}
|
||||
catch (MissingResourceException exception)
|
||||
{
|
||||
localizedString = null;
|
||||
}
|
||||
/* Localize to default locale */
|
||||
if (localizedString == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
ResourceBundle bundle;
|
||||
|
||||
bundle =
|
||||
ResourceBundle.getBundle("gnu.java.locale.LocaleInformation");
|
||||
localizedString = bundle.getString(property);
|
||||
}
|
||||
catch (MissingResourceException exception)
|
||||
{
|
||||
localizedString = null;
|
||||
}
|
||||
}
|
||||
/* Localize to English */
|
||||
if (localizedString == null && checkEnglish)
|
||||
{
|
||||
try
|
||||
{
|
||||
localizedString =
|
||||
ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
|
||||
Locale.ENGLISH).getString(property);
|
||||
}
|
||||
catch (MissingResourceException exception)
|
||||
{
|
||||
localizedString = null;
|
||||
}
|
||||
}
|
||||
/* Return unlocalized version */
|
||||
if (localizedString == null && checkRoot)
|
||||
{
|
||||
try
|
||||
{
|
||||
localizedString =
|
||||
ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
|
||||
new Locale("","","")
|
||||
).getString(property);
|
||||
}
|
||||
catch (MissingResourceException exception)
|
||||
{
|
||||
localizedString = null;
|
||||
}
|
||||
}
|
||||
/* Return original input string */
|
||||
if (localizedString == null)
|
||||
{
|
||||
localizedString = key;
|
||||
}
|
||||
return localizedString;
|
||||
String language = locale.getLanguage();
|
||||
String country = locale.getCountry();
|
||||
String variant = locale.getVariant();
|
||||
int uscore = variant.indexOf('_');
|
||||
if (uscore != -1)
|
||||
return new Locale(language, country,
|
||||
variant.substring(0, uscore));
|
||||
if (!variant.isEmpty())
|
||||
return new Locale(language, country, "");
|
||||
if (!country.isEmpty())
|
||||
return new Locale(language, "", "");
|
||||
return Locale.ROOT;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
207
libjava/classpath/gnu/java/math/Fixed.java
Normal file
207
libjava/classpath/gnu/java/math/Fixed.java
Normal file
|
@ -0,0 +1,207 @@
|
|||
/* Fixed.java -- Utility methods for fixed point arithmetics
|
||||
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.math;
|
||||
|
||||
/**
|
||||
* Utility methods for fixed point arithmetics.
|
||||
*/
|
||||
public final class Fixed
|
||||
{
|
||||
|
||||
/**
|
||||
* Private constructor to avoid instantiation.
|
||||
*/
|
||||
private Fixed()
|
||||
{
|
||||
// Forbidden constructor.
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides two fixed point values with <code>n</code> digits.
|
||||
*
|
||||
* @param n the number of digits
|
||||
* @param a the first operand as fixed point value
|
||||
* @param b the second operand as fixed point value
|
||||
*
|
||||
* @return <code>a / b</code> as fixed point value
|
||||
*/
|
||||
public static int div(int n, int a, int b)
|
||||
{
|
||||
return (int) ((((long) a) << n) / b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies two fixed point values with <code>n</code> digits.
|
||||
*
|
||||
* @param n the number of digits
|
||||
* @param a the first operand as fixed point value
|
||||
* @param b the second operand as fixed point value
|
||||
*
|
||||
* @return <code>a * b</code> as fixed point value
|
||||
*/
|
||||
public static int mul(int n, int a, int b)
|
||||
{
|
||||
return (int) ((((long) a) * b) >> n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ceiling value of a fixed point value <code>a</code> with
|
||||
* the <code>n</code> digits.
|
||||
*
|
||||
* @param n the number of digits
|
||||
* @param a the fixed point value
|
||||
*
|
||||
* @return <code>ceil(a)</code> as fixed point value
|
||||
*/
|
||||
public static int ceil(int n, int a)
|
||||
{
|
||||
return (a + (1 << n - 1)) & -(1 << n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the floor value of a fixed point value <code>a</code> with
|
||||
* <code>n</code> digits.
|
||||
*
|
||||
* @param n the number of digits
|
||||
* @param a the fixed point value
|
||||
*
|
||||
* @return <code>floor(a)</code> as fixed point value
|
||||
*/
|
||||
public static int floor(int n, int a)
|
||||
{
|
||||
return a & -(1 << n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the round value of a fixed point value <code>a</code> with
|
||||
* the <code>n</code> digits.
|
||||
*
|
||||
* @param n the number of digits
|
||||
* @param a the fixed point value
|
||||
*
|
||||
* @return <code>round(a)</code> as fixed point value
|
||||
*/
|
||||
public static int round(int n, int a)
|
||||
{
|
||||
return (a + (1 << (n - 1))) & -(1 << n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fixed point value <code>a</code> with <code>n</code> digits
|
||||
* as float.
|
||||
*
|
||||
* @param n the number of digits
|
||||
* @param a the fixed point value
|
||||
*
|
||||
* @return the float value of <code>a</code>
|
||||
*/
|
||||
public static float floatValue(int n, int a)
|
||||
{
|
||||
return ((float) a) / (1 << n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fixed point value <code>a</code> with <code>n</code> digits
|
||||
* as double.
|
||||
*
|
||||
* @param n the number of digits
|
||||
* @param a the fixed point value
|
||||
*
|
||||
* @return the double value of <code>a</code>
|
||||
*/
|
||||
public static double doubleValue(int n, int a)
|
||||
{
|
||||
return ((double) a) / (1 << n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fixed point value that corresponds to the specified float
|
||||
* value <code>a</code> with <code>n</code> digits.
|
||||
*
|
||||
* @param n the number of digits
|
||||
* @param a the float value
|
||||
*
|
||||
* @return the fixed point value
|
||||
*/
|
||||
public static int fixedValue(int n, float a)
|
||||
{
|
||||
return (int) (a * (1 << n));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fixed point value that corresponds to the specified double
|
||||
* value <code>a</code> with <code>n</code> digits.
|
||||
*
|
||||
* @param n the number of digits
|
||||
* @param a the double value
|
||||
*
|
||||
* @return the fixed point value
|
||||
*/
|
||||
public static int fixedValue(int n, double a)
|
||||
{
|
||||
return (int) (a * (1 << n));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the integer value of the specified fixed point value
|
||||
* <code>a</code>. This simply cuts of the digits (== floor(a)).
|
||||
*
|
||||
* @param n the number of digits
|
||||
* @param a the fixed point value
|
||||
*
|
||||
* @return the integer value
|
||||
*/
|
||||
public static int intValue(int n, int a)
|
||||
{
|
||||
return a >> n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a fixed point decimal as rounded integer value.
|
||||
*
|
||||
* @param n the number of digits
|
||||
* @param a the fixed point number
|
||||
*
|
||||
* @return the fixed point decimal as rounded integer value
|
||||
*/
|
||||
public static int roundIntValue(int n, int a)
|
||||
{
|
||||
return (a + (1 << (n - 1))) >> n;
|
||||
}
|
||||
}
|
|
@ -1,190 +0,0 @@
|
|||
/* BASE.java --
|
||||
Copyright (C) 2003, 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.net;
|
||||
|
||||
/**
|
||||
* Encodes and decodes text according to the BASE64 encoding.
|
||||
*
|
||||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public final class BASE64
|
||||
{
|
||||
private static final byte[] src = {
|
||||
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
|
||||
0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54,
|
||||
0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64,
|
||||
0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
|
||||
0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
|
||||
0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
0x38, 0x39, 0x2b, 0x2f
|
||||
};
|
||||
|
||||
private static final byte[] dst;
|
||||
static
|
||||
{
|
||||
dst = new byte[0x100];
|
||||
for (int i = 0x0; i < 0xff; i++)
|
||||
{
|
||||
dst[i] = -1;
|
||||
}
|
||||
for (int i = 0; i < src.length; i++)
|
||||
{
|
||||
dst[src[i]] = (byte) i;
|
||||
}
|
||||
}
|
||||
|
||||
private BASE64()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the specified byte array using the BASE64 algorithm.
|
||||
*
|
||||
* @param bs the source byte array
|
||||
*/
|
||||
public static byte[] encode(byte[] bs)
|
||||
{
|
||||
int si = 0, ti = 0; // source/target array indices
|
||||
byte[] bt = new byte[((bs.length + 2) * 4) / 3]; // target byte array
|
||||
for (; si < bs.length; si += 3)
|
||||
{
|
||||
int buflen = bs.length - si;
|
||||
if (buflen == 1)
|
||||
{
|
||||
byte b = bs[si];
|
||||
int i = 0;
|
||||
bt[ti++] = src[b >>> 2 & 0x3f];
|
||||
bt[ti++] = src[(b << 4 & 0x30) + (i >>> 4 & 0xf)];
|
||||
}
|
||||
else if (buflen == 2)
|
||||
{
|
||||
byte b1 = bs[si], b2 = bs[si + 1];
|
||||
int i = 0;
|
||||
bt[ti++] = src[b1 >>> 2 & 0x3f];
|
||||
bt[ti++] = src[(b1 << 4 & 0x30) + (b2 >>> 4 & 0xf)];
|
||||
bt[ti++] = src[(b2 << 2 & 0x3c) + (i >>> 6 & 0x3)];
|
||||
}
|
||||
else
|
||||
{
|
||||
byte b1 = bs[si], b2 = bs[si + 1], b3 = bs[si + 2];
|
||||
bt[ti++] = src[b1 >>> 2 & 0x3f];
|
||||
bt[ti++] = src[(b1 << 4 & 0x30) + (b2 >>> 4 & 0xf)];
|
||||
bt[ti++] = src[(b2 << 2 & 0x3c) + (b3 >>> 6 & 0x3)];
|
||||
bt[ti++] = src[b3 & 0x3f];
|
||||
}
|
||||
}
|
||||
if (ti < bt.length)
|
||||
{
|
||||
byte[] tmp = new byte[ti];
|
||||
System.arraycopy(bt, 0, tmp, 0, ti);
|
||||
bt = tmp;
|
||||
}
|
||||
/*while (ti < bt.length)
|
||||
{
|
||||
bt[ti++] = 0x3d;
|
||||
}*/
|
||||
return bt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the specified byte array using the BASE64 algorithm.
|
||||
*
|
||||
* @param bs the source byte array
|
||||
*/
|
||||
public static byte[] decode(byte[] bs)
|
||||
{
|
||||
int srclen = bs.length;
|
||||
while (srclen > 0 && bs[srclen - 1] == 0x3d)
|
||||
{
|
||||
srclen--; /* strip padding character */
|
||||
}
|
||||
byte[] buffer = new byte[srclen];
|
||||
int buflen = 0;
|
||||
int si = 0;
|
||||
int len = srclen - si;
|
||||
while (len > 0)
|
||||
{
|
||||
byte b0 = dst[bs[si++] & 0xff];
|
||||
byte b2 = dst[bs[si++] & 0xff];
|
||||
buffer[buflen++] = (byte) (b0 << 2 & 0xfc | b2 >>> 4 & 0x3);
|
||||
if (len > 2)
|
||||
{
|
||||
b0 = b2;
|
||||
b2 = dst[bs[si++] & 0xff];
|
||||
buffer[buflen++] = (byte) (b0 << 4 & 0xf0 | b2 >>> 2 & 0xf);
|
||||
if (len > 3)
|
||||
{
|
||||
b0 = b2;
|
||||
b2 = dst[bs[si++] & 0xff];
|
||||
buffer[buflen++] = (byte) (b0 << 6 & 0xc0 | b2 & 0x3f);
|
||||
}
|
||||
}
|
||||
len = srclen - si;
|
||||
}
|
||||
byte[] bt = new byte[buflen];
|
||||
System.arraycopy(buffer, 0, bt, 0, buflen);
|
||||
return bt;
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
boolean decode = false;
|
||||
for (int i = 0; i < args.length; i++)
|
||||
{
|
||||
if (args[i].equals("-d"))
|
||||
{
|
||||
decode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] in = args[i].getBytes("US-ASCII");
|
||||
byte[] out = decode ? decode(in) : encode(in);
|
||||
System.out.println(args[i] + " = " +
|
||||
new String(out, "US-ASCII"));
|
||||
}
|
||||
catch (java.io.UnsupportedEncodingException e)
|
||||
{
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -81,8 +81,8 @@ public class DefaultContentHandlerFactory implements ContentHandlerFactory
|
|||
"image/x-xpixmap"
|
||||
};
|
||||
|
||||
private static HashSet imageTypes
|
||||
= new HashSet(Arrays.asList(known_image_types));
|
||||
private static HashSet<String> imageTypes
|
||||
= new HashSet<String>(Arrays.asList(known_image_types));
|
||||
|
||||
public ContentHandler createContentHandler(String mimeType)
|
||||
{
|
||||
|
|
|
@ -48,9 +48,9 @@ import java.security.PrivilegedAction;
|
|||
* @author Chris Burdess (dog@gnu.org)
|
||||
*/
|
||||
public class GetLocalHostAction
|
||||
implements PrivilegedAction
|
||||
implements PrivilegedAction<InetAddress>
|
||||
{
|
||||
public Object run()
|
||||
public InetAddress run()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
|
@ -49,8 +49,8 @@ import java.util.Vector;
|
|||
*/
|
||||
public class HeaderFieldHelper
|
||||
{
|
||||
private Vector headerFieldKeys;
|
||||
private Vector headerFieldValues;
|
||||
private Vector<String> headerFieldKeys;
|
||||
private Vector<String> headerFieldValues;
|
||||
|
||||
public HeaderFieldHelper()
|
||||
{
|
||||
|
@ -59,8 +59,8 @@ public class HeaderFieldHelper
|
|||
|
||||
public HeaderFieldHelper (int size)
|
||||
{
|
||||
headerFieldKeys = new Vector (size);
|
||||
headerFieldValues = new Vector (size);
|
||||
headerFieldKeys = new Vector<String> (size);
|
||||
headerFieldValues = new Vector<String> (size);
|
||||
}
|
||||
|
||||
public void addHeaderField (String key, String value)
|
||||
|
@ -75,7 +75,7 @@ public class HeaderFieldHelper
|
|||
|
||||
try
|
||||
{
|
||||
key = (String) headerFieldKeys.elementAt (index);
|
||||
key = headerFieldKeys.elementAt (index);
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException e)
|
||||
{
|
||||
|
@ -90,7 +90,7 @@ public class HeaderFieldHelper
|
|||
|
||||
try
|
||||
{
|
||||
value = (String) headerFieldValues.elementAt (index);
|
||||
value = headerFieldValues.elementAt (index);
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException e)
|
||||
{
|
||||
|
@ -105,8 +105,7 @@ public class HeaderFieldHelper
|
|||
|
||||
try
|
||||
{
|
||||
value = (String) headerFieldValues.elementAt
|
||||
(headerFieldKeys.indexOf(key));
|
||||
value = headerFieldValues.elementAt(headerFieldKeys.indexOf(key));
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException e)
|
||||
{
|
||||
|
@ -115,9 +114,9 @@ public class HeaderFieldHelper
|
|||
return value;
|
||||
}
|
||||
|
||||
public Map getHeaderFields()
|
||||
public Map<String, String> getHeaderFields()
|
||||
{
|
||||
HashMap headers = new HashMap();
|
||||
HashMap<String, String> headers = new HashMap<String, String>();
|
||||
int max = headerFieldKeys.size();
|
||||
|
||||
for (int index = 0; index < max; index++)
|
||||
|
|
|
@ -43,6 +43,7 @@ import java.io.InputStreamReader;
|
|||
import java.net.URL;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
/**
|
||||
|
@ -70,7 +71,8 @@ public class IndexListParser
|
|||
double versionNumber;
|
||||
// Map each jar to the prefixes defined for the jar.
|
||||
// This is intentionally kept in insertion order.
|
||||
LinkedHashMap prefixes = new LinkedHashMap();
|
||||
LinkedHashMap<URL, Set<String>> prefixes
|
||||
= new LinkedHashMap<URL, Set<String>>();
|
||||
|
||||
/**
|
||||
* Parses the given jarfile's INDEX.LIST file if it exists.
|
||||
|
@ -107,7 +109,7 @@ public class IndexListParser
|
|||
while ((line = br.readLine()) != null)
|
||||
{
|
||||
URL jarURL = new URL(baseURL, line);
|
||||
HashSet values = new HashSet();
|
||||
HashSet<String> values = new HashSet<String>();
|
||||
|
||||
// Read the names in the section.
|
||||
while ((line = br.readLine()) != null)
|
||||
|
@ -174,7 +176,7 @@ public class IndexListParser
|
|||
*
|
||||
* @return an map of all the headers, or null if no INDEX.LIST was found
|
||||
*/
|
||||
public LinkedHashMap getHeaders()
|
||||
public LinkedHashMap<URL, Set<String>> getHeaders()
|
||||
{
|
||||
return prefixes;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public final class JarURLLoader extends URLLoader
|
|||
// Base jar: url for all resources loaded from jar.
|
||||
final URL baseJarURL;
|
||||
// The "Class-Path" attribute of this Jar's manifest.
|
||||
ArrayList classPath;
|
||||
ArrayList<URLLoader> classPath;
|
||||
// If not null, a mapping from INDEX.LIST for this jar only.
|
||||
// This is a set of all prefixes and top-level files that
|
||||
// ought to be available in this jar.
|
||||
|
@ -90,20 +90,20 @@ public final class JarURLLoader extends URLLoader
|
|||
|
||||
IndexListParser parser = new IndexListParser(jarfile, baseJarURL,
|
||||
baseURL);
|
||||
LinkedHashMap indexMap = parser.getHeaders();
|
||||
LinkedHashMap<URL, Set<String>> indexMap = parser.getHeaders();
|
||||
if (indexMap != null)
|
||||
{
|
||||
// Note that the index also computes
|
||||
// the resulting Class-Path -- there are jars out there
|
||||
// where the index lists some required jars which do
|
||||
// not appear in the Class-Path attribute in the manifest.
|
||||
this.classPath = new ArrayList();
|
||||
Iterator it = indexMap.entrySet().iterator();
|
||||
this.classPath = new ArrayList<URLLoader>();
|
||||
Iterator<Map.Entry<URL, Set<String>>> it = indexMap.entrySet().iterator();
|
||||
while (it.hasNext())
|
||||
{
|
||||
Map.Entry entry = (Map.Entry) it.next();
|
||||
URL subURL = (URL) entry.getKey();
|
||||
Set prefixes = (Set) entry.getValue();
|
||||
Map.Entry<URL, Set<String>> entry = it.next();
|
||||
URL subURL = entry.getKey();
|
||||
Set<String> prefixes = entry.getValue();
|
||||
if (subURL.equals(baseURL))
|
||||
this.indexSet = prefixes;
|
||||
else
|
||||
|
@ -127,7 +127,7 @@ public final class JarURLLoader extends URLLoader
|
|||
= attributes.getValue(Attributes.Name.CLASS_PATH))
|
||||
!= null))
|
||||
{
|
||||
this.classPath = new ArrayList();
|
||||
this.classPath = new ArrayList<URLLoader>();
|
||||
StringTokenizer st = new StringTokenizer(classPathString, " ");
|
||||
while (st.hasMoreElements ())
|
||||
{
|
||||
|
@ -144,7 +144,7 @@ public final class JarURLLoader extends URLLoader
|
|||
cache, factory,
|
||||
subURL, subURL);
|
||||
this.classPath.add(subLoader);
|
||||
ArrayList extra = subLoader.getClassPath();
|
||||
ArrayList<URLLoader> extra = subLoader.getClassPath();
|
||||
if (extra != null)
|
||||
this.classPath.addAll(extra);
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ public final class JarURLLoader extends URLLoader
|
|||
}
|
||||
}
|
||||
|
||||
public ArrayList getClassPath()
|
||||
public ArrayList<URLLoader> getClassPath()
|
||||
{
|
||||
return classPath;
|
||||
}
|
||||
|
|
|
@ -140,7 +140,7 @@ public abstract class URLLoader
|
|||
* Return a list of new URLLoader objects representing any
|
||||
* class path entries added by this container.
|
||||
*/
|
||||
public ArrayList getClassPath()
|
||||
public ArrayList<URLLoader> getClassPath()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue