Imported GNU Classpath 0.90
Imported GNU Classpath 0.90
* scripts/makemake.tcl: LocaleData.java moved to gnu/java/locale.
* sources.am: Regenerated.
* gcj/javaprims.h: Regenerated.
* Makefile.in: Regenerated.
* gcj/Makefile.in: Regenerated.
* include/Makefile.in: Regenerated.
* testsuite/Makefile.in: Regenerated.
* gnu/java/lang/VMInstrumentationImpl.java: New override.
* gnu/java/net/local/LocalSocketImpl.java: Likewise.
* gnu/classpath/jdwp/VMMethod.java: Likewise.
* gnu/classpath/jdwp/VMVirtualMachine.java: Update to latest
interface.
* java/lang/Thread.java: Add UncaughtExceptionHandler.
* java/lang/reflect/Method.java: Implements GenericDeclaration and
isSynthetic(),
* java/lang/reflect/Field.java: Likewise.
* java/lang/reflect/Constructor.java
* java/lang/Class.java: Implements Type, GenericDeclaration,
getSimpleName() and getEnclosing*() methods.
* java/lang/Class.h: Add new public methods.
* java/lang/Math.java: Add signum(), ulp() and log10().
* java/lang/natMath.cc (log10): New function.
* java/security/VMSecureRandom.java: New override.
* java/util/logging/Logger.java: Updated to latest classpath
version.
* java/util/logging/LogManager.java: New override.
From-SVN: r113887
This commit is contained in:
@@ -79,6 +79,7 @@ public class EncapsulationStream
|
||||
boolean use_big_endian)
|
||||
{
|
||||
super();
|
||||
setBigEndian(use_big_endian);
|
||||
buffer = new AligningOutput();
|
||||
setOutputStream(buffer);
|
||||
parent = _parent;
|
||||
|
||||
@@ -51,6 +51,7 @@ import org.omg.CORBA.MARSHAL;
|
||||
import org.omg.CORBA.portable.IDLEntity;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
@@ -273,20 +274,36 @@ public class MessageHeader
|
||||
* Read the header from the stream.
|
||||
*
|
||||
* @param istream a stream to read from.
|
||||
*
|
||||
* @throws MARSHAL if this is not a GIOP 1.0 header.
|
||||
*/
|
||||
public void read(java.io.InputStream istream)
|
||||
throws MARSHAL
|
||||
public void read(java.io.InputStream istream)
|
||||
throws MARSHAL, EOFException
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] xMagic = new byte[MAGIC.length];
|
||||
istream.read(xMagic);
|
||||
if (!Arrays.equals(xMagic, MAGIC))
|
||||
int r = istream.read(xMagic);
|
||||
int minor;
|
||||
if (! Arrays.equals(xMagic, MAGIC))
|
||||
{
|
||||
MARSHAL m = new MARSHAL("Not a GIOP message");
|
||||
m.minor = Minor.Giop;
|
||||
StringBuffer b = new StringBuffer();
|
||||
if (r == - 1)
|
||||
{
|
||||
b.append("Immediate EOF");
|
||||
minor = Minor.EOF;
|
||||
}
|
||||
else
|
||||
{
|
||||
minor = Minor.Giop;
|
||||
b.append(r + " bytes: ");
|
||||
for (int i = 0; i < xMagic.length; i++)
|
||||
{
|
||||
b.append(Integer.toHexString(xMagic[i] & 0xFF));
|
||||
b.append(' ');
|
||||
}
|
||||
}
|
||||
MARSHAL m = new MARSHAL("Not a GIOP message: " + b);
|
||||
m.minor = minor;
|
||||
throw m;
|
||||
}
|
||||
|
||||
@@ -354,7 +371,7 @@ public class MessageHeader
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
MARSHAL t = new MARSHAL();
|
||||
MARSHAL t = new MARSHAL(ex.getMessage());
|
||||
t.minor = Minor.Header;
|
||||
t.initCause(ex);
|
||||
throw t;
|
||||
|
||||
@@ -407,20 +407,7 @@ public class IorDelegate extends SimpleDelegate
|
||||
*/
|
||||
public void release(org.omg.CORBA.Object target)
|
||||
{
|
||||
String key = ior.Internet.host + ":" + ior.Internet.port;
|
||||
|
||||
Socket socket = SocketRepository.get_socket(key);
|
||||
try
|
||||
{
|
||||
if (socket != null)
|
||||
{
|
||||
socket.close();
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
// do nothing, then.
|
||||
}
|
||||
// Do nothing here.
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* NameParser.java --
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
@@ -425,7 +425,8 @@ public class NameParser
|
||||
else
|
||||
{
|
||||
Delegate delegate = ((ObjectImpl) object)._get_delegate();
|
||||
ns = new _NamingContextStub(delegate);
|
||||
ns = new _NamingContextStub();
|
||||
((_NamingContextStub) ns)._set_delegate(delegate);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -41,11 +41,13 @@ package gnu.CORBA;
|
||||
import gnu.CORBA.CDR.BufferedCdrOutput;
|
||||
import gnu.CORBA.typecodes.AliasTypeCode;
|
||||
import gnu.CORBA.typecodes.ArrayTypeCode;
|
||||
import gnu.CORBA.typecodes.PrimitiveTypeCode;
|
||||
import gnu.CORBA.typecodes.RecordTypeCode;
|
||||
import gnu.CORBA.typecodes.StringTypeCode;
|
||||
|
||||
import org.omg.CORBA.Any;
|
||||
import org.omg.CORBA.BAD_PARAM;
|
||||
import org.omg.CORBA.Context;
|
||||
import org.omg.CORBA.ContextList;
|
||||
import org.omg.CORBA.Environment;
|
||||
import org.omg.CORBA.ExceptionList;
|
||||
@@ -526,4 +528,57 @@ public class OrbRestricted extends org.omg.CORBA_2_3.ORB
|
||||
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a typecode, representing a tree-like structure.
|
||||
* This structure contains a member that is a sequence of the same type,
|
||||
* as the structure itself. You can imagine as if the folder definition
|
||||
* contains a variable-length array of the enclosed (nested) folder
|
||||
* definitions. In this way, it is possible to have a tree like
|
||||
* structure that can be transferred via CORBA CDR stream.
|
||||
*
|
||||
* @deprecated It is easier and clearler to use a combination of
|
||||
* create_recursive_tc and create_sequence_tc instead.
|
||||
*
|
||||
* @param bound the maximal expected number of the nested components
|
||||
* on each node; 0 if not limited.
|
||||
*
|
||||
* @param offset the position of the field in the returned structure
|
||||
* that contains the sequence of the structures of the same field.
|
||||
* The members before this field are intialised using parameterless
|
||||
* StructMember constructor.
|
||||
*
|
||||
* @return a typecode, defining a stucture, where a member at the
|
||||
* <code>offset</code> position defines an array of the identical
|
||||
* structures.
|
||||
*
|
||||
* @see #create_recursive_tc(String)
|
||||
* @see #create_sequence_tc(int, TypeCode)
|
||||
*/
|
||||
public TypeCode create_recursive_sequence_tc(int bound, int offset)
|
||||
{
|
||||
RecordTypeCode r = new RecordTypeCode(TCKind.tk_struct);
|
||||
for (int i = 0; i < offset; i++)
|
||||
r.add(new StructMember());
|
||||
|
||||
TypeCode recurs = new PrimitiveTypeCode(TCKind.tk_sequence);
|
||||
|
||||
r.add(new StructMember("", recurs, null));
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default context of this ORB. This is an initial root of all
|
||||
* contexts.
|
||||
*
|
||||
* The default method returns a new context with the empty name and
|
||||
* no parent context.
|
||||
*
|
||||
* @return the default context of this ORB.
|
||||
*/
|
||||
public Context get_default_context()
|
||||
{
|
||||
return new gnuContext("", null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -116,9 +116,6 @@ public class SocketRepository
|
||||
*/
|
||||
public static Socket get_socket(Object key)
|
||||
{
|
||||
if (true)
|
||||
return null;
|
||||
|
||||
synchronized (sockets)
|
||||
{
|
||||
Socket s = (Socket) sockets.get(key);
|
||||
|
||||
@@ -83,6 +83,7 @@ import org.omg.PortableInterceptor.ClientRequestInterceptorOperations;
|
||||
import org.omg.PortableInterceptor.ForwardRequest;
|
||||
import org.omg.PortableInterceptor.InvalidSlot;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
@@ -593,7 +594,7 @@ public class gnuRequest extends Request implements Cloneable
|
||||
{
|
||||
final gnuRequest cloned = Clone();
|
||||
cloned.oneWay = true;
|
||||
|
||||
|
||||
new Thread()
|
||||
{
|
||||
public void run()
|
||||
@@ -717,12 +718,11 @@ public class gnuRequest extends Request implements Cloneable
|
||||
* property ({@link #setIOR(IOR)} before calling this method.
|
||||
*
|
||||
* @throws BAD_INV_ORDER, minor code 0, if the IOR has not been previously set
|
||||
* or if the direct argument addition is mixed with the direct argument
|
||||
* writing into the output stream.
|
||||
*
|
||||
* or if the direct argument addition is mixed with the direct
|
||||
* argument writing into the output stream.
|
||||
* @return the server response in binary form.
|
||||
*/
|
||||
public synchronized RawReply submit()
|
||||
public synchronized RawReply submit()
|
||||
throws ForwardRequest
|
||||
{
|
||||
gnu.CORBA.GIOP.MessageHeader header = new gnu.CORBA.GIOP.MessageHeader();
|
||||
@@ -788,20 +788,21 @@ public class gnuRequest extends Request implements Cloneable
|
||||
|
||||
if (socket == null)
|
||||
{
|
||||
// The BindException may be thrown under very heavy parallel
|
||||
// The IOException may be thrown under very heavy parallel
|
||||
// load. For some time, just wait, exceptiong the socket to free.
|
||||
Open: for (int i = 0; i < PAUSE_STEPS; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (orb instanceof OrbFunctional)
|
||||
socket = ((OrbFunctional) orb).socketFactory.createClientSocket(
|
||||
ior.Internet.host, ior.Internet.port);
|
||||
socket = ((OrbFunctional) orb).socketFactory.
|
||||
createClientSocket(
|
||||
ior.Internet.host, ior.Internet.port);
|
||||
else
|
||||
socket = new Socket(ior.Internet.host, ior.Internet.port);
|
||||
break Open;
|
||||
}
|
||||
catch (BindException ex)
|
||||
catch (IOException ex)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -833,7 +834,7 @@ public class gnuRequest extends Request implements Cloneable
|
||||
request_part.buffer.writeTo(socketOutput);
|
||||
|
||||
socketOutput.flush();
|
||||
if (!socket.isClosed())
|
||||
if (!socket.isClosed() && !oneWay)
|
||||
{
|
||||
MessageHeader response_header = new MessageHeader();
|
||||
InputStream socketInput = socket.getInputStream();
|
||||
@@ -937,6 +938,10 @@ public class gnuRequest extends Request implements Cloneable
|
||||
throws SystemException, ForwardRequest
|
||||
{
|
||||
RawReply response = submit();
|
||||
|
||||
// If this is a one way message, do not care about the response.
|
||||
if (oneWay && response == EMPTY)
|
||||
return;
|
||||
|
||||
if (m_rph == null)
|
||||
m_rph = response.header.create_reply_header();
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/* NotImplementedException.java -- Marker for stub methods
|
||||
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;
|
||||
|
||||
/**
|
||||
* This class is used as a marker to indicate that a given method
|
||||
* is merely a stub, requiring implementation. For historical
|
||||
* reasons, GNU Classpath includes a number of stub methods. We
|
||||
* don't wish to remove them, but we do want to make them easily
|
||||
* discoverable. JAPI will notice methods declared as throwing
|
||||
* this exception and mark them appropriately.
|
||||
*/
|
||||
public class NotImplementedException
|
||||
extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = 5112972057211125814L;
|
||||
|
||||
/**
|
||||
* This class is not instantiable. It should only be used
|
||||
* in a method 'throws' clause -- not actually ever thrown.
|
||||
*/
|
||||
private NotImplementedException()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -111,6 +111,13 @@ public class SystemProperties
|
||||
defaultProperties.put("java.io.tmpdir",
|
||||
defaultProperties.get("java.tmpdir"));
|
||||
|
||||
// FIXME: we need a better way to handle this.
|
||||
// For instance, having a single VM class for each OS might help.
|
||||
if (defaultProperties.get("gnu.classpath.mime.types.file") == null
|
||||
&& "Linux".equals(defaultProperties.get("os.name")))
|
||||
defaultProperties.put("gnu.classpath.mime.types.file",
|
||||
"/etc/mime.types");
|
||||
|
||||
VMSystemProperties.postInit(defaultProperties);
|
||||
|
||||
// Note that we use clone here and not new. Some programs assume
|
||||
@@ -149,4 +156,17 @@ public class SystemProperties
|
||||
|
||||
SystemProperties.properties = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the supplied system property and its current value.
|
||||
* If the specified property does not exist, nothing happens.
|
||||
*
|
||||
* @throws NullPointerException if the property name is null.
|
||||
* @return the value of the removed property, or null if no
|
||||
* such property exists.
|
||||
*/
|
||||
public static String remove(String name)
|
||||
{
|
||||
return (String) properties.remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Component.java -- a component log level.
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is a part of GNU Classpath.
|
||||
|
||||
@@ -74,7 +74,7 @@ public final class Component extends Level
|
||||
* Signifies that everything should be logged. This should be used to
|
||||
* enable or disable levels only; logging code should not use it.
|
||||
*/
|
||||
public static final Component EVERYTHING = new Component ("*", 0, 7);
|
||||
public static final Component EVERYTHING = new Component ("*", 0, 11);
|
||||
|
||||
/**
|
||||
* Signifies that all SSL related messages should be logged. This should
|
||||
@@ -115,6 +115,11 @@ public final class Component extends Level
|
||||
* java.policy files.
|
||||
*/
|
||||
public static final Component POLICY = new Component ("POLICY", 7);
|
||||
|
||||
/**
|
||||
* Trace ipp implementation.
|
||||
*/
|
||||
public static final Component IPP = new Component ("IPP", 10);
|
||||
|
||||
private final int startIndex;
|
||||
private final int endIndex;
|
||||
|
||||
@@ -43,7 +43,6 @@ import gnu.classpath.jdwp.event.Event;
|
||||
import gnu.classpath.jdwp.event.EventManager;
|
||||
import gnu.classpath.jdwp.event.EventRequest;
|
||||
import gnu.classpath.jdwp.exception.JdwpException;
|
||||
import gnu.classpath.jdwp.id.ThreadId;
|
||||
import gnu.classpath.jdwp.processor.PacketProcessor;
|
||||
import gnu.classpath.jdwp.transport.ITransport;
|
||||
import gnu.classpath.jdwp.transport.JdwpConnection;
|
||||
@@ -81,9 +80,6 @@ public class Jdwp
|
||||
// (-Xrunjdwp:..suspend=<boolean>)
|
||||
private static final String _PROPERTY_SUSPEND = "suspend";
|
||||
|
||||
// User's main application thread
|
||||
private Thread _mainThread;
|
||||
|
||||
// Connection to debugger
|
||||
private JdwpConnection _connection;
|
||||
|
||||
@@ -112,6 +108,16 @@ public class Jdwp
|
||||
return _instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the thread group used by JDWP threads
|
||||
*
|
||||
* @return the thread group
|
||||
*/
|
||||
public ThreadGroup getJdwpThreadGroup()
|
||||
{
|
||||
return _group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the virtual machine suspend on startup?
|
||||
*/
|
||||
@@ -132,11 +138,9 @@ public class Jdwp
|
||||
* Configures the back-end
|
||||
*
|
||||
* @param configArgs a string of configury options
|
||||
* @param mainThread the main application thread
|
||||
*/
|
||||
public void configure (String configArgs, Thread mainThread)
|
||||
public void configure (String configArgs)
|
||||
{
|
||||
_mainThread = mainThread;
|
||||
_processConfigury (configArgs);
|
||||
}
|
||||
|
||||
@@ -272,17 +276,6 @@ public class Jdwp
|
||||
try
|
||||
{
|
||||
_doInitialization ();
|
||||
|
||||
_mainThread.start ();
|
||||
|
||||
_mainThread.join ();
|
||||
}
|
||||
catch (InterruptedException ie)
|
||||
{
|
||||
/* Shutting down. If we're in server mode, we should
|
||||
prepare for a new connection. Otherwise, we should
|
||||
simply exit. */
|
||||
// FIXME
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/* BreakpointEvent.java -- An event specifying that the interpreter
|
||||
has hit a breakpoint
|
||||
Copyright (C) 2006 Free Software Foundation
|
||||
|
||||
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
|
||||
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.jdwp.event;
|
||||
|
||||
import gnu.classpath.jdwp.JdwpConstants;
|
||||
import gnu.classpath.jdwp.VMIdManager;
|
||||
import gnu.classpath.jdwp.id.ThreadId;
|
||||
import gnu.classpath.jdwp.util.Location;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* "Notification of a breakpoint in the target VM. The breakpoint event is
|
||||
* generated before the code at its location is executed."
|
||||
*
|
||||
* @author Keith Seitz (keiths@redhat.com)
|
||||
*/
|
||||
public class BreakpointEvent
|
||||
extends Event
|
||||
{
|
||||
// The thread in which this event occurred
|
||||
private Thread _thread;
|
||||
|
||||
// Location where breakpoint occurred
|
||||
private Location _location;
|
||||
|
||||
/**
|
||||
* Constructs a new BreakpointEvent
|
||||
*
|
||||
* @param thread thread in which event occurred
|
||||
* @param loc location where breakpoint occurred
|
||||
*/
|
||||
public BreakpointEvent(Thread thread, Location loc)
|
||||
{
|
||||
super(JdwpConstants.EventKind.BREAKPOINT);
|
||||
_thread = thread;
|
||||
_location = loc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a specific filtering parameter for this event.
|
||||
* Valid types are thread and location.
|
||||
*
|
||||
* @param type the type of parameter desired
|
||||
* @returns the desired parameter or null
|
||||
*/
|
||||
public Object getParameter(Class type)
|
||||
{
|
||||
if (type == ThreadId.class)
|
||||
return _thread;
|
||||
else if (type == Location.class)
|
||||
return _location;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the event to the given stream
|
||||
*
|
||||
* @param outStream the output stream to write the event to
|
||||
*/
|
||||
protected void _writeData (DataOutputStream outStream)
|
||||
throws IOException
|
||||
{
|
||||
VMIdManager idm = VMIdManager.getDefault();
|
||||
ThreadId tid = (ThreadId) idm.getObjectId(_thread);
|
||||
|
||||
tid.write(outStream);
|
||||
_location.write(outStream);
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,7 @@ import java.util.Iterator;
|
||||
* 2) Filter event notifications from the VM
|
||||
*
|
||||
* If an event request arrives from the debugger, the back-end will
|
||||
* call {@link #reqestEvent}, which will first check for a valid event.
|
||||
* call {@link #requestEvent}, which will first check for a valid event.
|
||||
* If it is valid, <code>EventManager</code> will record the request
|
||||
* internally and register the event with the virtual machine, which may
|
||||
* choose to handle the request itself (as is likely the case with
|
||||
|
||||
@@ -42,8 +42,6 @@ package gnu.classpath.jdwp.event;
|
||||
import gnu.classpath.jdwp.JdwpConstants;
|
||||
import gnu.classpath.jdwp.event.filters.*;
|
||||
import gnu.classpath.jdwp.exception.JdwpIllegalArgumentException;
|
||||
import gnu.classpath.jdwp.id.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
|
||||
@@ -49,7 +49,7 @@ import java.io.IOException;
|
||||
|
||||
/**
|
||||
* "Notification of a new running thread in the target VM. The new
|
||||
* thread can be the result of a call to {@link java.lang.Thread.start} or
|
||||
* thread can be the result of a call to {@link java.lang.Thread#start} or
|
||||
* the result of attaching a new thread to the VM though JNI. The
|
||||
* notification is generated by the new thread some time before its
|
||||
* execution starts. Because of this timing, it is possible to receive
|
||||
@@ -70,9 +70,9 @@ public class ThreadStartEvent
|
||||
private Thread _thread;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>ThreadStartEvent</code>
|
||||
* Constructs a new ThreadStartEvent object
|
||||
*
|
||||
* @param tid the thread ID in which event occurred
|
||||
* @param thread the thread ID in which event occurred
|
||||
*/
|
||||
public ThreadStartEvent (Thread thread) {
|
||||
super (JdwpConstants.EventKind.THREAD_END);
|
||||
|
||||
@@ -53,9 +53,7 @@ public class VmDeathEvent
|
||||
extends Event
|
||||
{
|
||||
/**
|
||||
* Constructs a <code>VmDeathEvent</code> object
|
||||
*
|
||||
* @param thread the initial thread
|
||||
* Constructs a new VmDeathEvent object
|
||||
*/
|
||||
public VmDeathEvent ()
|
||||
{
|
||||
|
||||
@@ -41,7 +41,6 @@ package gnu.classpath.jdwp.event.filters;
|
||||
|
||||
import gnu.classpath.jdwp.event.Event;
|
||||
import gnu.classpath.jdwp.exception.InvalidStringException;
|
||||
import gnu.classpath.jdwp.exception.InvalidClassException;
|
||||
import gnu.classpath.jdwp.id.ReferenceTypeId;
|
||||
|
||||
/**
|
||||
|
||||
@@ -61,7 +61,7 @@ public class ConditionalFilter
|
||||
* <p><b>NOTE:</b> This filter is marked "for the future",
|
||||
* i.e, there is no way to actually use this yet.
|
||||
*
|
||||
* @param cond the conditional expression
|
||||
* @param conditional the conditional expression
|
||||
* @throws NotImplementedException if used
|
||||
*/
|
||||
public ConditionalFilter (Object conditional)
|
||||
|
||||
@@ -59,11 +59,11 @@ public class ExceptionOnlyFilter
|
||||
private boolean _uncaught;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>ExceptionOnlyFilter</code>
|
||||
* Constructs a new ExceptionOnlyFilter
|
||||
*
|
||||
* @param refid
|
||||
* @param caught
|
||||
* @param uncaught
|
||||
* @param refId ID of the exception to report
|
||||
* @param caught Report caught exceptions
|
||||
* @param uncaught Report uncaught exceptions
|
||||
* @throws InvalidClassException if refid is invalid
|
||||
*/
|
||||
public ExceptionOnlyFilter (ReferenceTypeId refId, boolean caught,
|
||||
|
||||
@@ -64,7 +64,7 @@ public class FieldOnlyFilter
|
||||
* @param refId class for field
|
||||
* @param fid field
|
||||
* @throws InvalidClassException if class is invalid
|
||||
* @throws InvalidFieldExcpetion if field is invalid
|
||||
* @throws InvalidFieldException if field is invalid
|
||||
*/
|
||||
public FieldOnlyFilter (ReferenceTypeId refId, /*Field*/ReferenceTypeId fid)
|
||||
throws InvalidClassException, InvalidFieldException
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* LocationOnlyFilter.java -- filter on location
|
||||
Copyright (C) 2005 Free Software Foundation
|
||||
Copyright (C) 2005, 2006 Free Software Foundation
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
@@ -49,6 +49,13 @@ import gnu.classpath.jdwp.util.Location;
|
||||
* May be used with breakpoint, field access, field modification, step,
|
||||
* and exception event kinds.
|
||||
*
|
||||
* This "filter" is not really a filter. It is simply a way to communicate
|
||||
* location information for supported events in a generic way to ease
|
||||
* the burden of special casing several things in
|
||||
* EventReqeustCommandSet.executeSet.
|
||||
*
|
||||
* Consequently, this "filter" always matches any event.
|
||||
*
|
||||
* @author Keith Seitz (keiths@redhat.com)
|
||||
*/
|
||||
public class LocationOnlyFilter
|
||||
@@ -85,7 +92,7 @@ public class LocationOnlyFilter
|
||||
*/
|
||||
public boolean matches (Event event)
|
||||
{
|
||||
// FIXME
|
||||
throw new RuntimeException ("LocationOnlyFilter.matches not implemented");
|
||||
// This filter always matches. See comments in class javadoc.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,9 +44,9 @@ import gnu.classpath.jdwp.exception.InvalidThreadException;
|
||||
import gnu.classpath.jdwp.id.ThreadId;
|
||||
|
||||
/**
|
||||
* An event filter which restricts reported step events to those which
|
||||
* "An event filter which restricts reported step events to those which
|
||||
* satisfy depth and size constraints. This modifier can only be used with
|
||||
* step event kinds.
|
||||
* step event kinds."
|
||||
*
|
||||
* @author Keith Seitz (keiths@redhat.com)
|
||||
*/
|
||||
@@ -58,9 +58,11 @@ public class StepFilter
|
||||
private int _depth;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>StepFilter</code> with the given count.
|
||||
* Constructs a new StepFilter
|
||||
*
|
||||
* @param count the number of times the event will be ignored
|
||||
* @param tid ID of the thread in which to step
|
||||
* @param size size of each step
|
||||
* @param depth relative call stack limit
|
||||
* @throws InvalidThreadException if thread is invalid
|
||||
*/
|
||||
public StepFilter (ThreadId tid, int size, int depth)
|
||||
@@ -88,7 +90,7 @@ public class StepFilter
|
||||
* Returns the size of each step (insn, line)
|
||||
*
|
||||
* @return the step size
|
||||
* @see JdwpConstants.StepSize
|
||||
* @see gnu.classpath.jdwp.JdwpConstants.StepSize
|
||||
*/
|
||||
public int getSize ()
|
||||
{
|
||||
@@ -99,7 +101,7 @@ public class StepFilter
|
||||
* Returns the relative call stack limit (into, over, out)
|
||||
*
|
||||
* @return how to step
|
||||
* @see JdwpConstants.StepDepth
|
||||
* @see gnu.classpath.jdwp.JdwpConstants.StepDepth
|
||||
*/
|
||||
public int getDepth ()
|
||||
{
|
||||
|
||||
@@ -39,7 +39,6 @@ exception statement from your version. */
|
||||
|
||||
package gnu.classpath.jdwp.event.filters;
|
||||
|
||||
import gnu.classpath.jdwp.Jdwp;
|
||||
import gnu.classpath.jdwp.event.Event;
|
||||
import gnu.classpath.jdwp.exception.InvalidThreadException;
|
||||
import gnu.classpath.jdwp.id.ThreadId;
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/* NativeMethodException.java -- a native method exception
|
||||
Copyright (C) 2006 Free Software Foundation
|
||||
|
||||
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
|
||||
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.jdwp.exception;
|
||||
|
||||
import gnu.classpath.jdwp.JdwpConstants;
|
||||
|
||||
/**
|
||||
* An exception thrown when the debugger attempts to invoke
|
||||
* an unsupported command on a native method (like setting a breakpoint).
|
||||
*
|
||||
* @author Keith Seitz (keiths@redhat.com)
|
||||
*/
|
||||
public class NativeMethodException
|
||||
extends JdwpException
|
||||
{
|
||||
public NativeMethodException(long id)
|
||||
{
|
||||
super(JdwpConstants.Error.NATIVE_METHOD,
|
||||
"invalid method id (" + id + ")");
|
||||
}
|
||||
|
||||
public NativeMethodException(Throwable t)
|
||||
{
|
||||
super(JdwpConstants.Error.NATIVE_METHOD, t);
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public abstract class JdwpId
|
||||
/**
|
||||
* Tag of ID's type (see {@link gnu.classpath.jdwp.JdwpConstants.Tag})
|
||||
* for object-like IDs or the type tag (see {@link
|
||||
* gnu.classpath.JdwpConstants.TypeTag}) for reference type IDs.
|
||||
* gnu.classpath.jdwp.JdwpConstants.TypeTag}) for reference type IDs.
|
||||
*/
|
||||
private byte _tag;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* MethodCommandSet.java -- class to implement the Method Command Set
|
||||
Copyright (C) 2005 Free Software Foundation
|
||||
Copyright (C) 2005, 2006 Free Software Foundation
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
@@ -39,18 +39,16 @@ exception statement from your version. */
|
||||
package gnu.classpath.jdwp.processor;
|
||||
|
||||
import gnu.classpath.jdwp.JdwpConstants;
|
||||
import gnu.classpath.jdwp.VMVirtualMachine;
|
||||
import gnu.classpath.jdwp.VMMethod;
|
||||
import gnu.classpath.jdwp.exception.JdwpException;
|
||||
import gnu.classpath.jdwp.exception.JdwpInternalErrorException;
|
||||
import gnu.classpath.jdwp.exception.NotImplementedException;
|
||||
import gnu.classpath.jdwp.id.ObjectId;
|
||||
import gnu.classpath.jdwp.id.ReferenceTypeId;
|
||||
import gnu.classpath.jdwp.id.ClassReferenceTypeId;
|
||||
import gnu.classpath.jdwp.util.LineTable;
|
||||
import gnu.classpath.jdwp.util.VariableTable;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
@@ -101,26 +99,24 @@ public class MethodCommandSet
|
||||
private void executeLineTable(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
|
||||
ClassReferenceTypeId refId
|
||||
= (ClassReferenceTypeId) idMan.readReferenceTypeId(bb);
|
||||
Class clazz = refId.getType();
|
||||
|
||||
ObjectId oid = idMan.readObjectId(bb);
|
||||
Method method = (Method) oid.getObject();
|
||||
|
||||
LineTable lt = VMVirtualMachine.getLineTable(clazz, method);
|
||||
VMMethod method = VMMethod.readId(clazz, bb);
|
||||
LineTable lt = method.getLineTable();
|
||||
lt.write(os);
|
||||
}
|
||||
|
||||
private void executeVariableTable(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
|
||||
ClassReferenceTypeId refId
|
||||
= (ClassReferenceTypeId) idMan.readReferenceTypeId(bb);
|
||||
Class clazz = refId.getType();
|
||||
|
||||
ObjectId oid = idMan.readObjectId(bb);
|
||||
Method method = (Method) oid.getObject();
|
||||
|
||||
VariableTable vt = VMVirtualMachine.getVarTable(clazz, method);
|
||||
VMMethod method = VMMethod.readId(clazz, bb);
|
||||
VariableTable vt = method.getVariableTable();
|
||||
vt.write(os);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* ReferenceTypeCommandSet.java -- class to implement the ReferenceType
|
||||
Command Set
|
||||
Copyright (C) 2005 Free Software Foundation
|
||||
Copyright (C) 2005, 2006 Free Software Foundation
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
@@ -40,11 +40,13 @@ exception statement from your version. */
|
||||
package gnu.classpath.jdwp.processor;
|
||||
|
||||
import gnu.classpath.jdwp.JdwpConstants;
|
||||
import gnu.classpath.jdwp.VMMethod;
|
||||
import gnu.classpath.jdwp.VMVirtualMachine;
|
||||
import gnu.classpath.jdwp.exception.InvalidFieldException;
|
||||
import gnu.classpath.jdwp.exception.JdwpException;
|
||||
import gnu.classpath.jdwp.exception.JdwpInternalErrorException;
|
||||
import gnu.classpath.jdwp.exception.NotImplementedException;
|
||||
import gnu.classpath.jdwp.id.ClassReferenceTypeId;
|
||||
import gnu.classpath.jdwp.id.ObjectId;
|
||||
import gnu.classpath.jdwp.id.ReferenceTypeId;
|
||||
import gnu.classpath.jdwp.util.JdwpString;
|
||||
@@ -54,7 +56,6 @@ import gnu.classpath.jdwp.util.Value;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
@@ -181,17 +182,18 @@ public class ReferenceTypeCommandSet
|
||||
private void executeMethods(ByteBuffer bb, DataOutputStream os)
|
||||
throws JdwpException, IOException
|
||||
{
|
||||
ReferenceTypeId refId = idMan.readReferenceTypeId(bb);
|
||||
ClassReferenceTypeId refId
|
||||
= (ClassReferenceTypeId) idMan.readReferenceTypeId(bb);
|
||||
Class clazz = refId.getType();
|
||||
|
||||
Method[] methods = clazz.getMethods();
|
||||
os.writeInt(methods.length);
|
||||
VMMethod[] methods = VMVirtualMachine.getAllClassMethods(clazz);
|
||||
os.writeInt (methods.length);
|
||||
for (int i = 0; i < methods.length; i++)
|
||||
{
|
||||
Method method = methods[i];
|
||||
idMan.getObjectId(method).write(os);
|
||||
VMMethod method = methods[i];
|
||||
method.writeId(os);
|
||||
JdwpString.writeString(os, method.getName());
|
||||
JdwpString.writeString(os, Signature.computeMethodSignature(method));
|
||||
JdwpString.writeString(os, method.getSignature());
|
||||
os.writeInt(method.getModifiers());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,6 @@ package gnu.classpath.jdwp.processor;
|
||||
import gnu.classpath.jdwp.JdwpConstants;
|
||||
import gnu.classpath.jdwp.VMFrame;
|
||||
import gnu.classpath.jdwp.VMVirtualMachine;
|
||||
import gnu.classpath.jdwp.exception.InvalidObjectException;
|
||||
import gnu.classpath.jdwp.exception.JdwpException;
|
||||
import gnu.classpath.jdwp.exception.JdwpInternalErrorException;
|
||||
import gnu.classpath.jdwp.exception.NotImplementedException;
|
||||
|
||||
@@ -42,7 +42,6 @@ package gnu.classpath.jdwp.transport;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
|
||||
@@ -55,7 +55,7 @@ import java.io.IOException;
|
||||
* This class deal with everything except the command- and reply-specific
|
||||
* data, which get handled in {@link
|
||||
* gnu.classpath.jdwp.transport.JdwpCommandPacket} and {@link
|
||||
* gnu.classpath.jdwp.transprot.JdwpReplyPacket}.
|
||||
* gnu.classpath.jdwp.transport.JdwpReplyPacket}.
|
||||
*
|
||||
* @author Keith Seitz <keiths@redhat.com>
|
||||
*/
|
||||
@@ -183,7 +183,6 @@ public abstract class JdwpPacket
|
||||
* <code>null</code>.
|
||||
*
|
||||
* @param bytes packet data from the wire
|
||||
* @param index index into <code>bytes</code> to start processing
|
||||
* @return number of bytes in <code>bytes</code> processed
|
||||
*/
|
||||
public static JdwpPacket fromBytes (byte[] bytes)
|
||||
|
||||
@@ -45,7 +45,7 @@ import java.io.IOException;
|
||||
/**
|
||||
* A class represents a JDWP reply packet.
|
||||
* This class adds an error code to the packet header information
|
||||
* in {@link gnu.classpath.transport.JdwpPacket} and adds additional
|
||||
* in {@link gnu.classpath.jdwp.transport.JdwpPacket} and adds additional
|
||||
* reply packet-specific processing.
|
||||
*
|
||||
* @author Keith Seitz <keiths@redhat.com>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* LineTable.java -- A class representing a Line Table for a method
|
||||
Copyright (C) 2005 Free Software Foundation
|
||||
Copyright (C) 2005, 2006 Free Software Foundation
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
@@ -54,25 +54,24 @@ public class LineTable
|
||||
private final long end;
|
||||
private final int[] lineNum;
|
||||
private final long[] lineCI;
|
||||
private final int lines;
|
||||
|
||||
/**
|
||||
* Construct a line table with the given parameters.
|
||||
*
|
||||
* @param start lowest code index for method, -1 if native
|
||||
* @param end highest code index for method, -1 if native
|
||||
* @param lines number of entries in line table
|
||||
* @param lineCI code indexes for entries in line tables (of length lines)
|
||||
* @param lineNum line numbers for in line tables (of length lines)
|
||||
* @param lineNum line numbers for in line tables
|
||||
* @param lineCI code indicies for entries in line tables
|
||||
*/
|
||||
public LineTable(long start, long end, int lines, long lineCI[],
|
||||
int lineNum[])
|
||||
public LineTable(long start, long end, int[] lineNum, long[] lineCI)
|
||||
{
|
||||
if (lineNum.length != lineCI.length)
|
||||
throw new AssertionError("code index and line numbers tables "
|
||||
+ "not same length");
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.lines = lines;
|
||||
this.lineCI = lineCI;
|
||||
this.lineNum = lineNum;
|
||||
this.lineCI = lineCI;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,8 +85,8 @@ public class LineTable
|
||||
{
|
||||
os.writeLong(start);
|
||||
os.writeLong(end);
|
||||
os.writeInt(lines);
|
||||
for (int i = 0; i < lines; i++)
|
||||
os.writeInt(lineNum.length);
|
||||
for (int i = 0; i < lineNum.length; i++)
|
||||
{
|
||||
os.writeLong(lineCI[i]);
|
||||
os.writeInt(lineNum[i]);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Location.java -- class to read/write JDWP locations
|
||||
Copyright (C) 2005 Free Software Foundation
|
||||
Copyright (C) 2005, 2006 Free Software Foundation
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
@@ -39,13 +39,12 @@ exception statement from your version. */
|
||||
package gnu.classpath.jdwp.util;
|
||||
|
||||
import gnu.classpath.jdwp.VMIdManager;
|
||||
import gnu.classpath.jdwp.VMMethod;
|
||||
import gnu.classpath.jdwp.exception.JdwpException;
|
||||
import gnu.classpath.jdwp.id.ClassReferenceTypeId;
|
||||
import gnu.classpath.jdwp.id.ObjectId;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
@@ -55,62 +54,81 @@ import java.nio.ByteBuffer;
|
||||
*/
|
||||
public class Location
|
||||
{
|
||||
|
||||
private ClassReferenceTypeId crti;
|
||||
|
||||
private int index;
|
||||
|
||||
private byte tag;
|
||||
|
||||
private ObjectId mid;
|
||||
private VMMethod method;
|
||||
private long index;
|
||||
|
||||
/**
|
||||
* Create a location with the given parameters.
|
||||
*
|
||||
* @param tag the type of construct the location is in
|
||||
* @param clazz the class the location is in
|
||||
* @param meth the Method
|
||||
* @param method the method
|
||||
* @param index location in the method
|
||||
* @throws JdwpException
|
||||
*/
|
||||
public Location(byte tag, Class clazz, Method meth, int index)
|
||||
throws JdwpException
|
||||
public Location(VMMethod method, long index)
|
||||
{
|
||||
this.tag = tag;
|
||||
this.crti =
|
||||
(ClassReferenceTypeId) VMIdManager.getDefault().getReferenceTypeId(clazz);
|
||||
this.mid = VMIdManager.getDefault().getObjectId(meth);
|
||||
this.method = method;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a location from the given bytebuffer, consists of a TAG (byte),
|
||||
* followed by a ReferenceTypeId, a MethodId and an index (int).
|
||||
* followed by a ReferenceTypeId, a MethodId and an index (long).
|
||||
*
|
||||
* @param bb this holds the location
|
||||
* @throws IOException
|
||||
* @throws JdwpException
|
||||
* @throws IOException when an error occurs reading from the buffer
|
||||
* @throws JdwpException for invalid class or method IDs
|
||||
*/
|
||||
public Location(ByteBuffer bb) throws IOException, JdwpException
|
||||
public Location(ByteBuffer bb)
|
||||
throws IOException, JdwpException
|
||||
{
|
||||
this.tag = bb.get();
|
||||
this.crti =
|
||||
byte tag = bb.get();
|
||||
ClassReferenceTypeId classId =
|
||||
(ClassReferenceTypeId) VMIdManager.getDefault().readReferenceTypeId(bb);
|
||||
this.mid = VMIdManager.getDefault().readObjectId(bb);
|
||||
this.index = bb.getInt();
|
||||
Class klass = classId.getType();
|
||||
method = VMMethod.readId(klass, bb);
|
||||
index = bb.getLong();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the given location to an output stream.
|
||||
*
|
||||
* @param os stream to write to
|
||||
* @throws IOException
|
||||
* @throws IOException when an error occurs writing to the stream
|
||||
*/
|
||||
public void write(DataOutputStream os) throws IOException
|
||||
public void write(DataOutputStream os)
|
||||
throws IOException
|
||||
{
|
||||
os.writeByte(tag);
|
||||
crti.write(os);
|
||||
mid.write(os);
|
||||
os.writeInt(index);
|
||||
VMIdManager idm = VMIdManager.getDefault();
|
||||
ClassReferenceTypeId crti = (ClassReferenceTypeId)
|
||||
idm.getReferenceTypeId(method.getDeclaringClass());
|
||||
|
||||
crti.writeTagged(os);
|
||||
method.writeId(os);
|
||||
os.writeLong(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the method of this location
|
||||
*
|
||||
* @return the method
|
||||
*/
|
||||
public VMMethod getMethod()
|
||||
{
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the code index of this location
|
||||
*
|
||||
* @return the code index
|
||||
*/
|
||||
public long getIndex ()
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
// convenient for debugging
|
||||
public String toString ()
|
||||
{
|
||||
return method.toString () + "." + index;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Value.java -- class to read/write JDWP tagged and untagged values
|
||||
Copyright (C) 2005 Free Software Foundation
|
||||
Copyright (C) 2005, 2006, Free Software Foundation
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
@@ -203,12 +203,12 @@ public class Value
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the an object of the given Class from the untagged value contained
|
||||
* Reads an object of the given Class from the untagged value contained
|
||||
* in the ByteBuffer.
|
||||
*
|
||||
* @param bb contains the Object
|
||||
* @param bb contains the Object
|
||||
* @param type corresponds to the TAG of value to be read
|
||||
* @return
|
||||
* @return the resultant object
|
||||
* @throws JdwpException
|
||||
* @throws IOException
|
||||
*/
|
||||
@@ -232,7 +232,7 @@ public class Value
|
||||
else if (type == short.class)
|
||||
return new Short(bb.getShort());
|
||||
else if (type == boolean.class)
|
||||
return (bb.get() == 0) ? new Boolean(false) : new Boolean(true);
|
||||
return Boolean.valueOf(bb.get() != 0);
|
||||
else if (type == void.class)
|
||||
return new byte[0];
|
||||
else
|
||||
|
||||
@@ -0,0 +1,313 @@
|
||||
/* FontDelegate.java -- Interface implemented by all font delegates.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.font;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.text.CharacterIterator;
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
/**
|
||||
* The interface that all font delegate objects implement,
|
||||
* irrespective of where they get their information from.
|
||||
*
|
||||
* <p><b>Thread Safety:</b> All classes that implement the
|
||||
* <code>FontDelegate</code> interface must allow calling these
|
||||
* methods from multiple concurrent threads. The delegates are
|
||||
* responsible for performing the necessary synchronization.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
public interface FontDelegate
|
||||
{
|
||||
/**
|
||||
* Returns the full name of this font face in the specified
|
||||
* locale, for example <i>“Univers Light”</i>.
|
||||
*
|
||||
* @param locale the locale for which to localize the name.
|
||||
*
|
||||
* @return the face name.
|
||||
*/
|
||||
public String getFullName(Locale locale);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the family to which this font face belongs,
|
||||
* for example <i>“Univers”</i>.
|
||||
*
|
||||
* @param locale the locale for which to localize the name.
|
||||
*
|
||||
* @return the family name.
|
||||
*/
|
||||
public String getFamilyName(Locale locale);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of this font face inside the family, for example
|
||||
* <i>“Light”</i>.
|
||||
*
|
||||
* @param locale the locale for which to localize the name.
|
||||
*
|
||||
* @return the name of the face inside its family.
|
||||
*/
|
||||
public String getSubFamilyName(Locale locale);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the PostScript name of this font face, for example
|
||||
* <i>“Helvetica-Bold”</i>.
|
||||
*
|
||||
* @return the PostScript name, or <code>null</code> if the font
|
||||
* does not provide a PostScript name.
|
||||
*/
|
||||
public String getPostScriptName();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of glyphs in this font face.
|
||||
*/
|
||||
public int getNumGlyphs();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the index of the glyph which gets displayed if the font
|
||||
* cannot map a Unicode code point to a glyph. Many fonts show this
|
||||
* glyph as an empty box.
|
||||
*/
|
||||
public int getMissingGlyphCode();
|
||||
|
||||
|
||||
/**
|
||||
* Creates a GlyphVector by mapping each character in a
|
||||
* CharacterIterator to the corresponding glyph.
|
||||
*
|
||||
* <p>The mapping takes only the font’s <code>cmap</code>
|
||||
* tables into consideration. No other operations (such as glyph
|
||||
* re-ordering, composition, or ligature substitution) are
|
||||
* performed. This means that the resulting GlyphVector will not be
|
||||
* correct for text in languages that have complex
|
||||
* character-to-glyph mappings, such as Arabic, Hebrew, Hindi, or
|
||||
* Thai.
|
||||
*
|
||||
* @param font the font object that the created GlyphVector
|
||||
* will return when it gets asked for its font. This argument is
|
||||
* needed because the public API works with java.awt.Font,
|
||||
* not with some private delegate like OpenTypeFont.
|
||||
*
|
||||
* @param frc the font rendering parameters that are used for
|
||||
* measuring glyphs. The exact placement of text slightly depends on
|
||||
* device-specific characteristics, for instance the device
|
||||
* resolution or anti-aliasing. For this reason, any measurements
|
||||
* will only be accurate if the passed
|
||||
* <code>FontRenderContext</code> correctly reflects the relevant
|
||||
* parameters. Hence, <code>frc</code> should be obtained from the
|
||||
* same <code>Graphics2D</code> that will be used for drawing, and
|
||||
* any rendering hints should be set to the desired values before
|
||||
* obtaining <code>frc</code>.
|
||||
*
|
||||
* @param ci a CharacterIterator for iterating over the
|
||||
* characters to be displayed.
|
||||
*/
|
||||
public GlyphVector createGlyphVector(Font font,
|
||||
FontRenderContext frc,
|
||||
CharacterIterator ci);
|
||||
|
||||
|
||||
/**
|
||||
* Determines the advance width and height for a glyph.
|
||||
*
|
||||
* @param glyphIndex the glyph whose advance width is to be
|
||||
* determined.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialias <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @param advance a point whose <code>x</code> and <code>y</code>
|
||||
* fields will hold the advance in each direction. It is well
|
||||
* possible that both values are non-zero, for example for rotated
|
||||
* text or for Urdu fonts.
|
||||
*/
|
||||
public void getAdvance(int glyphIndex,
|
||||
float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal,
|
||||
Point2D advance);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the shape of a glyph.
|
||||
*
|
||||
* @param glyphIndex the glyph whose advance width is to be
|
||||
* determined.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialias <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts, this
|
||||
* parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional
|
||||
* metrics, <code>false</code> for rounding the result to a pixel
|
||||
* boundary.
|
||||
*
|
||||
* @return the scaled and grid-fitted outline of the specified
|
||||
* glyph, or <code>null</code> for bitmap fonts.
|
||||
*/
|
||||
public GeneralPath getGlyphOutline(int glyphIndex,
|
||||
float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics);
|
||||
|
||||
|
||||
/**
|
||||
* Returns a name for the specified glyph. This is useful for
|
||||
* generating PostScript or PDF files that embed some glyphs of a
|
||||
* font.
|
||||
*
|
||||
* <p><b>Names are not unique:</b> Under some rare circumstances,
|
||||
* the same name can be returned for different glyphs. It is
|
||||
* therefore recommended that printer drivers check whether the same
|
||||
* name has already been returned for antoher glyph, and make the
|
||||
* name unique by adding the string ".alt" followed by the glyph
|
||||
* index.</p>
|
||||
*
|
||||
* <p>This situation would occur for an OpenType or TrueType font
|
||||
* that has a <code>post</code> table of format 3 and provides a
|
||||
* mapping from glyph IDs to Unicode sequences through a
|
||||
* <code>Zapf</code> table. If the same sequence of Unicode
|
||||
* codepoints leads to different glyphs (depending on contextual
|
||||
* position, for example, or on typographic sophistication level),
|
||||
* the same name would get synthesized for those glyphs.
|
||||
*
|
||||
* @param glyphIndex the glyph whose name the caller wants to
|
||||
* retrieve.
|
||||
*/
|
||||
public String getGlyphName(int glyphIndex);
|
||||
|
||||
|
||||
/**
|
||||
* Determines the distance between the base line and the highest
|
||||
* ascender.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialiased <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the ascent, which usually is a positive number.
|
||||
*/
|
||||
public float getAscent(float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialiased,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal);
|
||||
|
||||
|
||||
/**
|
||||
* Determines the distance between the base line and the lowest
|
||||
* descender.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialiased <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the descent, which usually is a nagative number.
|
||||
*/
|
||||
public float getDescent(float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialiased,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal);
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/* FontFactory.java -- Factory for font delegates.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.font;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import java.awt.FontFormatException;
|
||||
import gnu.java.awt.font.opentype.OpenTypeFontFactory;
|
||||
|
||||
|
||||
/**
|
||||
* A factory for creating font delegate objects.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
public final class FontFactory
|
||||
{
|
||||
/**
|
||||
* The constructor is private so nobody can construct an instance
|
||||
*/
|
||||
private FontFactory()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates FontDelegate objects for the fonts in the specified buffer.
|
||||
* The following font formats are currently recognized:
|
||||
* recognized font formats are:
|
||||
*
|
||||
* <p><ul>
|
||||
* <li>OpenType (*.otf);</li>
|
||||
* <li>TrueType (*.ttf);</li>
|
||||
* <li>TrueType Collections (*.ttc);</li>
|
||||
* <li>Apple MacOS X data-fork font (*.dfont).</li></ul>
|
||||
*
|
||||
* <p>Some formats may contain more than a single font, for example
|
||||
* *.ttc and *.dfont files. This is the reason why this function
|
||||
* returns an array.
|
||||
*
|
||||
* <p>The implementation reads data from the buffer only when
|
||||
* needed. Therefore, it greatly increases efficiency if
|
||||
* <code>buf</code> has been obtained through mapping a file into
|
||||
* the virtual address space.
|
||||
*
|
||||
* @throws FontFormatException if the font data is not in one of the
|
||||
* known formats.
|
||||
*/
|
||||
public static FontDelegate[] createFonts(ByteBuffer buf)
|
||||
throws FontFormatException
|
||||
{
|
||||
return OpenTypeFontFactory.createFonts(buf);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,596 @@
|
||||
/* GNUGlyphVector.java -- The GNU implementation of GlyphVector.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.java.awt.font;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphMetrics;
|
||||
import java.awt.font.GlyphJustificationInfo;
|
||||
import java.awt.font.GlyphVector;
|
||||
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
|
||||
/**
|
||||
* The GNU implementation of the abstract GlyphVector class, which
|
||||
* uses the services provided by a FontDelegate for its functionality.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
public class GNUGlyphVector
|
||||
extends GlyphVector
|
||||
{
|
||||
private FontDelegate fontDelegate;
|
||||
private Font font;
|
||||
private FontRenderContext renderContext;
|
||||
private int[] glyphs;
|
||||
private float fontSize;
|
||||
private AffineTransform transform;
|
||||
private boolean valid;
|
||||
|
||||
|
||||
/**
|
||||
* The position of each glyph. The horizontal position of the
|
||||
* <code>i</code>-th glyph is at <code>pos[i * 2]</code>, its
|
||||
* vertical position at <code>pos[i * 2 + 1]</code>. The total
|
||||
* advance width of the entire vector is stored at
|
||||
* <code>pos[numGlyphs]</code>, the total advance height at
|
||||
* <code>pos[numGlyphs + 1]</code>.
|
||||
*/
|
||||
private float[] pos;
|
||||
|
||||
|
||||
private AffineTransform[] transforms;
|
||||
private int layoutFlags;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new GNUGlyphVector.
|
||||
*
|
||||
* @param fontDelegate the FontDelegate that creates this vector.
|
||||
*
|
||||
* @param font the Font that this GlyphVector will return for {@link
|
||||
* #getFont()}. That object is also used to determine the point
|
||||
* size, which affects the affine transformation used by the font
|
||||
* scaler.
|
||||
*
|
||||
* @param renderContext an object with parameters for font
|
||||
* rendering, such as whether anti-aliasing is enabled.
|
||||
*
|
||||
* @param glyphs the glyphs in this vector.
|
||||
*/
|
||||
public GNUGlyphVector(FontDelegate fontDelegate,
|
||||
Font font,
|
||||
FontRenderContext renderContext,
|
||||
int[] glyphs)
|
||||
{
|
||||
this.fontDelegate = fontDelegate;
|
||||
this.font = font;
|
||||
this.renderContext = renderContext;
|
||||
this.glyphs = glyphs;
|
||||
|
||||
fontSize = font.getSize2D();
|
||||
transform = font.getTransform(); // returns a modifiable copy
|
||||
transform.concatenate(renderContext.getTransform());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the font of the glyphs in this GlyphVector.
|
||||
*/
|
||||
public Font getFont()
|
||||
{
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the FontRenderContext that is used to calculate the
|
||||
* extent and position of the glyphs.
|
||||
*/
|
||||
public FontRenderContext getFontRenderContext()
|
||||
{
|
||||
return renderContext;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves each glyph in the vector to its default position.
|
||||
*/
|
||||
public void performDefaultLayout()
|
||||
{
|
||||
float x, y, advanceWidth, advanceHeight;
|
||||
int i, p;
|
||||
AffineTransform tx;
|
||||
Point2D.Float advance = new Point2D.Float();
|
||||
|
||||
pos = new float[(glyphs.length + 1) * 2];
|
||||
x = y = 0.0f;
|
||||
p = 0;
|
||||
for (i = p = 0; i < glyphs.length; i++)
|
||||
{
|
||||
p += 2;
|
||||
|
||||
if ((transforms == null) || (tx = transforms[i]) == null)
|
||||
tx = this.transform;
|
||||
else
|
||||
{
|
||||
tx = new AffineTransform(tx);
|
||||
tx.concatenate(this.transform);
|
||||
}
|
||||
|
||||
fontDelegate.getAdvance(glyphs[i], fontSize, tx,
|
||||
renderContext.isAntiAliased(),
|
||||
renderContext.usesFractionalMetrics(),
|
||||
/* horizontal */ true,
|
||||
advance);
|
||||
pos[p] = x += advance.x;
|
||||
pos[p + 1] = y += advance.y;
|
||||
}
|
||||
valid = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the number of glyphs in this GlyphVector.
|
||||
*/
|
||||
public int getNumGlyphs()
|
||||
{
|
||||
return glyphs.length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the glyph number by index in this vector.
|
||||
* Glyph numbers are specific to each font, so two fonts
|
||||
* will likely assign different numbers to the same glyph.
|
||||
*
|
||||
* @param glyphIndex the index of the glyph whose glyph number is to
|
||||
* be retrieved.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if <code>glyphIndex</code>
|
||||
* is not in the range <code[0 .. getNumGlyphs() - 1]</code>.
|
||||
*/
|
||||
public int getGlyphCode(int glyphIndex)
|
||||
{
|
||||
/* The exception is thrown automatically if the index is out
|
||||
* of the valid bounds.
|
||||
*/
|
||||
return glyphs[glyphIndex];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a slice of this GlyphVector.
|
||||
*
|
||||
* @param firstGlyphIndex the index of the first glyph in the
|
||||
* returned slice.
|
||||
*
|
||||
* @param numEntries the size of the returned slice.
|
||||
*
|
||||
* @param outCodes a pre-allocated array for storing the slice,
|
||||
* or <code>null</code> to cause allocation of a new array.
|
||||
*
|
||||
* @return a slice of this GlyphVector. If <code>outCodes</code>
|
||||
* is <code>null</code>, the slice will be stored into a freshly
|
||||
* allocated array; otherwise, the result will be stored into
|
||||
* <code>outCodes</code>.
|
||||
*/
|
||||
public int[] getGlyphCodes(int firstGlyphIndex,
|
||||
int numEntries,
|
||||
int[] outCodes)
|
||||
{
|
||||
if (numEntries < 0)
|
||||
throw new IllegalArgumentException();
|
||||
if (outCodes == null)
|
||||
outCodes = new int[numEntries];
|
||||
System.arraycopy(glyphs, firstGlyphIndex, outCodes, 0, numEntries);
|
||||
return outCodes;
|
||||
}
|
||||
|
||||
|
||||
public Rectangle2D getLogicalBounds()
|
||||
{
|
||||
float ascent, descent;
|
||||
|
||||
validate();
|
||||
|
||||
return new Rectangle2D.Float(0, 0,
|
||||
pos[pos.length - 2],
|
||||
getAscent() - getDescent());
|
||||
}
|
||||
|
||||
|
||||
public Rectangle2D getVisualBounds()
|
||||
{
|
||||
validate();
|
||||
|
||||
// FIXME: Not yet implemented.
|
||||
return getLogicalBounds();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the shape of this GlyphVector.
|
||||
*/
|
||||
public Shape getOutline()
|
||||
{
|
||||
validate();
|
||||
return getOutline(0.0f, 0.0f);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the shape of this GlyphVector, translated to the
|
||||
* specified position.
|
||||
*
|
||||
* @param x the horizontal position for rendering this vector.
|
||||
* @param y the vertical position for rendering this vector.
|
||||
*/
|
||||
public Shape getOutline(float x, float y)
|
||||
{
|
||||
validate();
|
||||
|
||||
GeneralPath outline = new GeneralPath();
|
||||
int len = glyphs.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
GeneralPath p = new GeneralPath(getGlyphOutline(i));
|
||||
outline.append(p, false);
|
||||
}
|
||||
AffineTransform t = new AffineTransform();
|
||||
t.translate(x, y);
|
||||
outline.transform(t);
|
||||
return outline;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the shape of the specified glyph.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if <code>glyphIndex</code> is
|
||||
* not in the range <code[0 .. getNumGlyphs()]</code>.
|
||||
*/
|
||||
public Shape getGlyphOutline(int glyphIndex)
|
||||
{
|
||||
AffineTransform tx, glyphTx;
|
||||
GeneralPath path;
|
||||
|
||||
validate();
|
||||
|
||||
if ((transforms != null)
|
||||
&& ((glyphTx = transforms[glyphIndex]) != null))
|
||||
{
|
||||
tx = new AffineTransform(transform);
|
||||
tx.concatenate(glyphTx);
|
||||
}
|
||||
else
|
||||
tx = transform;
|
||||
|
||||
path = fontDelegate.getGlyphOutline(glyphs[glyphIndex], fontSize, tx,
|
||||
renderContext.isAntiAliased(),
|
||||
renderContext.usesFractionalMetrics());
|
||||
|
||||
tx = new AffineTransform();
|
||||
tx.translate(pos[glyphIndex * 2], pos[glyphIndex * 2 + 1]);
|
||||
path.transform(tx);
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the position of the specified glyph, or the
|
||||
* total advance width and height of the vector.
|
||||
*
|
||||
* @param glyphIndex the index of the glyph in question.
|
||||
* If this value equals <code>getNumGlyphs()</code>, the
|
||||
* position <i>after</i> the last glyph will be returned,
|
||||
* which is the total advance width and height of the vector.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if <code>glyphIndex</code> is
|
||||
* not in the range <code[0 .. getNumGlyphs()]</code>.
|
||||
*/
|
||||
public Point2D getGlyphPosition(int glyphIndex)
|
||||
{
|
||||
validate();
|
||||
return new Point2D.Float(pos[glyphIndex * 2],
|
||||
pos[glyphIndex * 2 + 1]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves the specified glyph to a new position, or changes the
|
||||
* advance width and height of the entire glyph vector.
|
||||
*
|
||||
* <p>Note that the position of an individual glyph may also
|
||||
* affected by its affine transformation.
|
||||
*
|
||||
* @param glyphIndex the index of the moved glyph. If
|
||||
* <code>glyphIndex</code> equals the total number of glyphs in this
|
||||
* vector, the advance width and height of the vector is changed.
|
||||
*
|
||||
* @param position the new position of the glyph.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if <code>glyphIndex</code> is
|
||||
* not in the range <code[0 .. getNumGlyphs()]</code>.
|
||||
*/
|
||||
public void setGlyphPosition(int glyphIndex, Point2D position)
|
||||
{
|
||||
validate();
|
||||
pos[glyphIndex * 2] = (float) position.getX();
|
||||
pos[glyphIndex * 2 + 1] = (float) position.getY();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the affine transformation that is applied to the
|
||||
* glyph at the specified index.
|
||||
*
|
||||
* @param glyphIndex the index of the glyph whose transformation
|
||||
* is to be retrieved.
|
||||
*
|
||||
* @return an affine transformation, or <code>null</code>
|
||||
* for the identity transformation.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if <code>glyphIndex</code> is
|
||||
* not in the range <code[0 .. getNumGlyphs() - 1]</code>.
|
||||
*/
|
||||
public AffineTransform getGlyphTransform(int glyphIndex)
|
||||
{
|
||||
if (transforms == null)
|
||||
return null;
|
||||
else
|
||||
return transforms[glyphIndex];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Applies an affine transformation to the glyph at the specified
|
||||
* index.
|
||||
*
|
||||
* @param glyphIndex the index of the glyph to which the
|
||||
* transformation is applied.
|
||||
*
|
||||
* @param transform the affine transformation for the glyph, or
|
||||
* <code>null</code> for an identity transformation.
|
||||
*/
|
||||
public void setGlyphTransform(int glyphIndex,
|
||||
AffineTransform transform)
|
||||
{
|
||||
if (transforms == null)
|
||||
transforms = new AffineTransform[glyphs.length];
|
||||
transforms[glyphIndex] = transform;
|
||||
|
||||
/* If the GlyphVector has only a transform for a single glyph, and
|
||||
* the caller clears its transform, the FLAG_HAS_TRANSFORMS bit
|
||||
* should be cleared in layoutFlags. However, this would require
|
||||
* that we keep track of the number of transformed glyphs, or that
|
||||
* we count them when a transform is cleared. This would
|
||||
* complicate the code quite a bit. Note that the only drawback of
|
||||
* wrongly setting FLAG_HAS_TRANSFORMS is that a slower code path
|
||||
* might be taken for rendering the vector. Right now, we never
|
||||
* really look at the flag, so it does not make any difference.
|
||||
*/
|
||||
if (transform != null)
|
||||
layoutFlags |= FLAG_HAS_TRANSFORMS;
|
||||
valid = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns flags that can be used for optimizing the rendering
|
||||
* of this GlyphVector.
|
||||
*
|
||||
* @return a bit mask with the applicable flags set.
|
||||
*
|
||||
* @since 1.4
|
||||
*
|
||||
* @see GlyphVector#FLAG_HAS_POSITION_ADJUSTMENTS
|
||||
* @see GlyphVector#FLAG_HAS_TRANSFORMS
|
||||
* @see GlyphVector#FLAG_RUN_RTL
|
||||
* @see GlyphVector#FLAG_COMPLEX_GLYPHS
|
||||
* @see GlyphVector#FLAG_MASK
|
||||
*/
|
||||
public int getLayoutFlags()
|
||||
{
|
||||
return layoutFlags;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the positions of a range of glyphs in this vector.
|
||||
*
|
||||
* @param firstGlyphIndex the index of the first glyph whose
|
||||
* position is retrieved.
|
||||
*
|
||||
* @param numGlyphs the number of glyphs whose positions
|
||||
* are retrieved.
|
||||
*
|
||||
* @param outPositions an array for storing the results
|
||||
* (the length must be at least twice <code>numGlyphs</code>),
|
||||
* or <code>null</code> for freshly allocating an array.
|
||||
*
|
||||
* @return an array with the glyph positions. The horizontal
|
||||
* position of the <code>i</code>-th glyph is at index <code>2 *
|
||||
* i</code>, the vertical position at index <code>2 * i + 1</code>.
|
||||
*
|
||||
* @throws IllegalArgumentException if <code>numGlyphs</code>
|
||||
* is less than zero.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if either
|
||||
* <code>firstGlyphIndex</code> or <code>(firstGlyphIndex +
|
||||
* numGlyphs)</code> is not in the range <code>[0 .. getNumGlyphs() -
|
||||
* 1]</code>.
|
||||
*/
|
||||
public float[] getGlyphPositions(int firstGlyphIndex,
|
||||
int numGlyphs,
|
||||
float[] outPositions)
|
||||
{
|
||||
if (numGlyphs < 0)
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
validate();
|
||||
if (outPositions == null)
|
||||
outPositions = new float[numGlyphs * 2];
|
||||
|
||||
System.arraycopy(/*src */ pos, /* srcStart */ firstGlyphIndex * 2,
|
||||
/* dest */ outPositions, /* destStart */ 0,
|
||||
/* length */ numGlyphs * 2);
|
||||
return outPositions;
|
||||
}
|
||||
|
||||
|
||||
private float getAscent()
|
||||
{
|
||||
return fontDelegate.getAscent(fontSize, transform,
|
||||
renderContext.isAntiAliased(),
|
||||
renderContext.usesFractionalMetrics(),
|
||||
/* horizontal */ true);
|
||||
}
|
||||
|
||||
|
||||
private float getDescent()
|
||||
{
|
||||
return fontDelegate.getDescent(fontSize, transform,
|
||||
renderContext.isAntiAliased(),
|
||||
renderContext.usesFractionalMetrics(),
|
||||
/* horizontal */ true);
|
||||
}
|
||||
|
||||
|
||||
public Shape getGlyphLogicalBounds(int glyphIndex)
|
||||
{
|
||||
float x, y, ascent;
|
||||
|
||||
validate();
|
||||
ascent = getAscent();
|
||||
x = pos[glyphIndex * 2];
|
||||
y = pos[glyphIndex * 2 + 1];
|
||||
|
||||
return new Rectangle2D.Float(x, y - ascent,
|
||||
pos[(glyphIndex + 1) * 2] - x,
|
||||
ascent - getDescent());
|
||||
}
|
||||
|
||||
|
||||
public Shape getGlyphVisualBounds(int glyphIndex)
|
||||
{
|
||||
return getGlyphOutline(glyphIndex).getBounds2D();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the metrics of the glyph at the specified index.
|
||||
*
|
||||
* @param glyphIndex the index of the glyph whose metrics is to be
|
||||
* retrieved.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if <code>glyphIndex</code> is
|
||||
* not in the range <code[0 .. getNumGlyphs() - 1]</code>.
|
||||
*/
|
||||
public GlyphMetrics getGlyphMetrics(int glyphIndex)
|
||||
{
|
||||
// FIXME: Not yet implemented.
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the justification information for the glyph at the
|
||||
* specified index.
|
||||
*
|
||||
* @param glyphIndex the index of the glyph whose justification
|
||||
* information is to be retrieved.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if <code>glyphIndex</code> is
|
||||
* not in the range <code[0 .. getNumGlyphs() - 1]</code>.
|
||||
*/
|
||||
public GlyphJustificationInfo getGlyphJustificationInfo(int glyphIndex)
|
||||
{
|
||||
// FIXME: Not yet implemented.
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines whether another GlyphVector is for the same font and
|
||||
* rendering context, uses the same glyphs and positions them to the
|
||||
* same location.
|
||||
*
|
||||
* @param other the GlyphVector to compare with.
|
||||
*
|
||||
* @return <code>true</code> if the two vectors are equal,
|
||||
* <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean equals(GlyphVector other)
|
||||
{
|
||||
GNUGlyphVector o;
|
||||
if (!(other instanceof GNUGlyphVector))
|
||||
return false;
|
||||
|
||||
o = (GNUGlyphVector) other;
|
||||
if ((this.font != o.font)
|
||||
|| (this.fontDelegate != o.fontDelegate)
|
||||
|| (this.renderContext != o.renderContext)
|
||||
|| (this.glyphs.length != o.glyphs.length))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < glyphs.length; i++)
|
||||
if (this.glyphs[i] != o.glyphs[i])
|
||||
return false;
|
||||
|
||||
validate();
|
||||
o.validate();
|
||||
for (int i = 0; i < pos.length; i++)
|
||||
if (this.pos[i] != o.pos[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void validate()
|
||||
{
|
||||
if (!valid)
|
||||
performDefaultLayout();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,235 @@
|
||||
/* MacResourceFork.java -- Parses MacOS resource forks.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.font.opentype;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
|
||||
/**
|
||||
* A class for accessing data that is stored in the resource fork of
|
||||
* Macintosh files. Writing resource forks is currently not supported.
|
||||
*
|
||||
* <p>The gnu.java.awt.font package uses this class for accessing
|
||||
* fonts in the MacOS X ".dfont" format, which is is a file in the
|
||||
* format of a Macintosh resource fork, but stored in the normal data
|
||||
* fork of the file.
|
||||
*
|
||||
* <p>The implementation has been designed to work efficiently with
|
||||
* the virtual memory subsystem. It is recommended to pass an
|
||||
* instance of {@link java.nio.MappedByteBuffer} to the constructor.
|
||||
*
|
||||
* <p>Thread Safety: All access is synchronized on the ByteBuffer
|
||||
* that is passed to the constructor.
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html"
|
||||
* >Apple’ developer documentation about the Resource File
|
||||
* Format</a>
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
final class MacResourceFork
|
||||
{
|
||||
int[] types;
|
||||
Resource[][] resources;
|
||||
ByteBuffer buf;
|
||||
|
||||
public MacResourceFork(ByteBuffer buf)
|
||||
{
|
||||
int typeListOffset;
|
||||
int refListOffset;
|
||||
int nameListOffset;
|
||||
int mapOffset, mapLen;
|
||||
int dataOffset, dataLen;
|
||||
int numTypes;
|
||||
|
||||
synchronized (buf)
|
||||
{
|
||||
buf = buf.duplicate();
|
||||
this.buf = buf;
|
||||
buf.position(0);
|
||||
dataOffset = buf.getInt();
|
||||
mapOffset = buf.getInt();
|
||||
dataLen = buf.getInt();
|
||||
mapLen = buf.getInt();
|
||||
buf.position(mapOffset + 24);
|
||||
refListOffset = mapOffset + buf.getChar();
|
||||
nameListOffset = mapOffset + buf.getChar();
|
||||
numTypes = buf.getChar() + 1;
|
||||
types = new int[numTypes];
|
||||
resources = new Resource[numTypes][];
|
||||
|
||||
/* Parse resource type list. */
|
||||
typeListOffset = buf.position();
|
||||
for (int i = 0; i < numTypes; i++)
|
||||
{
|
||||
buf.position(typeListOffset + 8 * i);
|
||||
int resType = buf.getInt();
|
||||
int numRes = buf.getChar() + 1;
|
||||
|
||||
types[i] = resType;
|
||||
resources[i] = new Resource[numRes];
|
||||
|
||||
buf.position(refListOffset + buf.getChar());
|
||||
for (int j = 0; j < numRes; j++)
|
||||
{
|
||||
short resID = buf.getShort();
|
||||
int resNameOffset = nameListOffset + buf.getChar();
|
||||
int resDataOffset = buf.getInt();
|
||||
byte resAttr = (byte) (resDataOffset >> 24);
|
||||
resDataOffset = dataOffset + (resDataOffset & 0x00ffffff);
|
||||
buf.getInt(); /* skip four reserved bytes */
|
||||
|
||||
Resource rsrc = new Resource(buf, resType, resID, resDataOffset,
|
||||
resNameOffset);
|
||||
resources[i][j] = rsrc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Resource[] getResources(int type)
|
||||
{
|
||||
synchronized (buf)
|
||||
{
|
||||
for (int i = 0; i < types.length; i++)
|
||||
{
|
||||
if (types[i] == type)
|
||||
return resources[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public Resource getResource(int type, short id)
|
||||
{
|
||||
Resource[] res;
|
||||
|
||||
synchronized (buf)
|
||||
{
|
||||
for (int i = 0; i < types.length; i++)
|
||||
{
|
||||
if (types[i] != type)
|
||||
continue;
|
||||
|
||||
res = resources[i];
|
||||
for (int j = 0; j < res.length; j++)
|
||||
if (res[j].getID() == id)
|
||||
return res[j];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A single resource that is contained in a resource fork.
|
||||
*/
|
||||
public static final class Resource
|
||||
{
|
||||
int type;
|
||||
short id;
|
||||
byte attribute;
|
||||
int nameOffset;
|
||||
int dataOffset;
|
||||
ByteBuffer buf;
|
||||
|
||||
private Resource(ByteBuffer buf,
|
||||
int type, short id, int dataOffset, int nameOffset)
|
||||
{
|
||||
this.buf = buf;
|
||||
this.type = type;
|
||||
this.id = id;
|
||||
this.dataOffset = dataOffset;
|
||||
this.nameOffset = nameOffset;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the type of this resource.
|
||||
*
|
||||
* @return an <code>int</code> encoding a four-byte type tag,
|
||||
* such as <code>0x464f4e54</code> for <code>'FONT'</code>.
|
||||
*/
|
||||
public int getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the ID of this resource.
|
||||
*/
|
||||
public short getID()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the content of the resource. Only one page of memory
|
||||
* is touched, irrespective of the actual size of the resource.
|
||||
*/
|
||||
public ByteBuffer getContent()
|
||||
{
|
||||
synchronized (buf)
|
||||
{
|
||||
buf.limit(buf.capacity());
|
||||
int len = buf.getInt(dataOffset);
|
||||
buf.position(dataOffset + 4).limit(dataOffset + 4 + len);
|
||||
return buf.slice();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the length of the resource in bytes.
|
||||
*/
|
||||
public int getLength()
|
||||
{
|
||||
synchronized (buf)
|
||||
{
|
||||
return buf.getInt(dataOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,686 @@
|
||||
/* NameDecoder.java -- Decodes names of OpenType and TrueType fonts.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.java.awt.font.opentype;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
/**
|
||||
* A utility class that helps with decoding the names of OpenType
|
||||
* and TrueType fonts.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
class NameDecoder
|
||||
{
|
||||
public static final int NAME_COPYRIGHT = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Specifies the name of the family to which a font belongs, for
|
||||
* example “Univers”.
|
||||
*/
|
||||
public static final int NAME_FAMILY = 1;
|
||||
|
||||
|
||||
/**
|
||||
* Specified the name of the font inside its family, for
|
||||
* example “Light”.
|
||||
*/
|
||||
public static final int NAME_SUBFAMILY = 2;
|
||||
|
||||
|
||||
public static final int NAME_UNIQUE = 3;
|
||||
|
||||
|
||||
/**
|
||||
* Specifies the full human-readable name of a font, for example
|
||||
* “Univers Light”
|
||||
*/
|
||||
public static final int NAME_FULL = 4;
|
||||
|
||||
|
||||
public static final int NAME_VERSION = 5;
|
||||
|
||||
|
||||
/**
|
||||
* Specifies the PostScript name of a font, for example
|
||||
* “Univers-Light”.
|
||||
*/
|
||||
public static final int NAME_POSTSCRIPT = 6;
|
||||
|
||||
|
||||
public static final int NAME_TRADEMARK = 7;
|
||||
public static final int NAME_MANUFACTURER = 8;
|
||||
public static final int NAME_DESIGNER = 9;
|
||||
public static final int NAME_DESCRIPTION = 10;
|
||||
public static final int NAME_VENDOR_URL = 11;
|
||||
public static final int NAME_DESIGNER_URL = 12;
|
||||
public static final int NAME_LICENSE = 13;
|
||||
public static final int NAME_LICENSE_URL = 14;
|
||||
public static final int NAME_PREFERRED_FAMILY = 16;
|
||||
public static final int NAME_PREFERRED_SUBFAMILY = 17;
|
||||
public static final int NAME_FULL_MACCOMPATIBLE = 18;
|
||||
public static final int NAME_SAMPLE_TEXT = 19;
|
||||
public static final int NAME_POSTSCRIPT_CID = 20;
|
||||
|
||||
|
||||
private static final int PLATFORM_MACINTOSH = 1;
|
||||
private static final int PLATFORM_MICROSOFT = 3;
|
||||
|
||||
|
||||
public static String getName(ByteBuffer nameTable,
|
||||
int name, Locale locale)
|
||||
{
|
||||
int numRecords;
|
||||
int macLanguage, msLanguage;
|
||||
int offset;
|
||||
int namePlatform, nameEncoding, nameLanguage, nameID, nameLen;
|
||||
int nameStart;
|
||||
String result;
|
||||
boolean match;
|
||||
|
||||
if (nameTable == null)
|
||||
return null;
|
||||
|
||||
nameTable.position(0);
|
||||
/* We understand only format 0 of the name table. */
|
||||
if (nameTable.getChar() != 0)
|
||||
return null;
|
||||
|
||||
macLanguage = getMacLanguageCode(locale);
|
||||
msLanguage = getMicrosoftLanguageCode(locale);
|
||||
numRecords = nameTable.getChar();
|
||||
offset = nameTable.getChar();
|
||||
|
||||
for (int i = 0; i < numRecords; i++)
|
||||
{
|
||||
namePlatform = nameTable.getChar();
|
||||
nameEncoding = nameTable.getChar();
|
||||
nameLanguage = nameTable.getChar();
|
||||
nameID = nameTable.getChar();
|
||||
nameLen = nameTable.getChar();
|
||||
nameStart = offset + nameTable.getChar();
|
||||
|
||||
|
||||
if (nameID != name)
|
||||
continue;
|
||||
|
||||
match = false;
|
||||
switch (namePlatform)
|
||||
{
|
||||
case PLATFORM_MACINTOSH:
|
||||
if ((nameLanguage == macLanguage) || (locale == null))
|
||||
match = true;
|
||||
else
|
||||
{
|
||||
switch (macLanguage)
|
||||
{
|
||||
case 49: /* Azerbaijani/Cyrillic */
|
||||
match = (nameLanguage == /* Azerbaijani/Arabic */ 50)
|
||||
|| (nameLanguage == /* Azerbaijani/Roman */ 150);
|
||||
break;
|
||||
|
||||
case 57: /* Mongolian/Mongolian */
|
||||
match = (nameLanguage == /* Mongolian/Cyrillic */ 58);
|
||||
break;
|
||||
|
||||
case 83: /* Malay/Roman */
|
||||
match = (nameLanguage == /* Malay/Arabic */ 84);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PLATFORM_MICROSOFT:
|
||||
if (((nameLanguage & 0xff) == msLanguage) || (locale == null))
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (match)
|
||||
{
|
||||
result = decodeName(namePlatform, nameEncoding, nameLanguage,
|
||||
nameTable, nameStart, nameLen);
|
||||
if (result != null)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The language codes used by the Macintosh operating system. MacOS
|
||||
* defines numeric language identifiers in the range [0 .. 95] and
|
||||
* [128 .. 150]. To map this numeric identifier into an ISO 639
|
||||
* language code, multiply it by two and take the substring at that
|
||||
* position.
|
||||
*
|
||||
* <p>ISO 639 has revised the code for some languages, namely
|
||||
* <code>he</code> for Hebrew (formerly <code>iw</code>),
|
||||
* <code>yi</code> (formerly <code>ji</code>), and <code>id</code>
|
||||
* for Indonesian (formerly <code>in</code>). In those cases, this
|
||||
* table intentionally contains the older, obsolete code. The
|
||||
* reason is that this is the code which
|
||||
* java.util.Locale.getLanguage() is specified to return. The
|
||||
* implementation of {@link #getMacLanguageCode} depends on this.
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://www.unicode.org/unicode/onlinedat/languages.html"
|
||||
* >Language Codes: ISO 639, Microsoft and Macintosh</a>
|
||||
*/
|
||||
private static final String macLanguageCodes
|
||||
// 0 1 2
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
|
||||
= "enfrdeitnlsvesdaptnoiwjaarfielismttrhrzhurhithkoltplhuetlv "
|
||||
|
||||
// 3 4 5
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
|
||||
+ "fofaruzhnlgdsqrocssksljisrmkbgukbeuzkkazazhykamokytgtkmnmnps"
|
||||
|
||||
// 6 7 8
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
|
||||
+ "kukssdbonesamrbnasgupaormlkntatesimykmloviintlmsmsamti sosw"
|
||||
|
||||
// 9 10 11
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
|
||||
+ "rwrn mgeo "
|
||||
|
||||
// 12 13 14
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
|
||||
+ " cyeucalaqugnayttugtsjwsuglafbriugdgvgatoelkl"
|
||||
|
||||
// 15
|
||||
// 0
|
||||
+ "az";
|
||||
|
||||
|
||||
/**
|
||||
* The primary language IDs used by the Microsoft operating systems.
|
||||
*
|
||||
* <p>ISO 639 has revised the code for some languages, namely
|
||||
* <code>he</code> for Hebrew (formerly <code>iw</code>),
|
||||
* <code>yi</code> (formerly <code>ji</code>), and <code>id</code>
|
||||
* for Indonesian (formerly <code>in</code>). In those cases, this
|
||||
* table intentionally contains the older, obsolete code. The
|
||||
* reason is that this is the code which
|
||||
* java.util.Locale.getLanguage() is specified to return. The
|
||||
* implementation of {@link #getMicrosoftLanguageCode} depends on
|
||||
* this.
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://www.unicode.org/unicode/onlinedat/languages.html"
|
||||
* >Language Codes: ISO 639, Microsoft and Macintosh</a>
|
||||
*/
|
||||
private static final String microsoftLanguageCodes
|
||||
// 0 1 2
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
|
||||
= " arbgcazhcsdadeelenesfifriwhuisitjakonlnoplptrmrorushsksqsv"
|
||||
|
||||
// 3 4 5
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
|
||||
+ "thtrurinukbesletlvlttgfavihyazeu mk ts xhzuafkafohimt "
|
||||
|
||||
// 6 7 8
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
|
||||
+ "gajimskkkyswtkuzttbnpaguortateknmlasmrsamnbocykmlomygl sd"
|
||||
|
||||
// 9 10 11
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
|
||||
+ " si iuam ksnefypstl ha yo omtign laso";
|
||||
|
||||
|
||||
/**
|
||||
* Maps a Java Locale into a MacOS language code.
|
||||
*
|
||||
* <p>For languages that are written in several script systems,
|
||||
* MacOS defines multiple language codes. Java Locales have a
|
||||
* variant which could be used for that purpose, but a small
|
||||
* test program revealed that with Sun's JDK 1.4.1_01, only two
|
||||
* of 134 available Locales have a variant tag (namely no_NO_NY
|
||||
* and th_TH_TH).</p>
|
||||
*
|
||||
* <p>The following cases are problematic:
|
||||
*
|
||||
* <ul> <li>Azerbaijani (az): The MacOS language code is 49 if
|
||||
* Azerbaijani is written in the Cyrillic script; 50 if written in
|
||||
* the Arabic script; 150 if written in the Roman script. This
|
||||
* method will always return 49 for the Azerbaijani locale.</li>
|
||||
*
|
||||
* <li>Mongolian (mn): The MacOS language code is 57 if Mongolian is
|
||||
* written in the Mongolian script; 58 if written in the Cyrillic
|
||||
* script. This method will always return 57 for the Mongolian
|
||||
* locale.</li>
|
||||
*
|
||||
* <li>Malay (ms): The MacOS language code is 83 if Malay is written
|
||||
* in the Roman script; 84 if written in the Arabic script. This
|
||||
* method will always return 83 for the Malay locale.</li> </ul>
|
||||
*
|
||||
* @return a MacOS language code, or -1 if there is no such code for
|
||||
* <code>loc</code>’s language.
|
||||
*/
|
||||
private static int getMacLanguageCode(Locale loc)
|
||||
{
|
||||
int code;
|
||||
|
||||
if (loc == null)
|
||||
return -1;
|
||||
|
||||
code = findLanguageCode(loc.getLanguage(), macLanguageCodes);
|
||||
switch (code)
|
||||
{
|
||||
case 19:
|
||||
/* Traditional Chinese (MacOS language #19) and and Simplified
|
||||
* Chinese (MacOS language #33) both have "zh" as their ISO 639
|
||||
* code.
|
||||
*/
|
||||
if (loc.equals(Locale.SIMPLIFIED_CHINESE))
|
||||
code = 33;
|
||||
break;
|
||||
|
||||
// Other special cases would be 49, 57 and 83, but we do not
|
||||
// know what do do about them. See the method documentation for
|
||||
// details.
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Maps a Java Locale into a Microsoft language code.
|
||||
*/
|
||||
private static int getMicrosoftLanguageCode(Locale locale)
|
||||
{
|
||||
String isoCode;
|
||||
int code;
|
||||
|
||||
if (locale == null)
|
||||
return -1;
|
||||
|
||||
isoCode = locale.getLanguage();
|
||||
code = findLanguageCode(isoCode, microsoftLanguageCodes);
|
||||
if (code == -1)
|
||||
{
|
||||
if (isoCode.equals("hr") || isoCode.equals("sr"))
|
||||
{
|
||||
/* Microsoft uses code 26 for "sh" (Serbo-Croatian),
|
||||
* "hr" (Croatian) and "sr" (Serbian). Our table contains
|
||||
* "sh".
|
||||
*/
|
||||
code = 26;
|
||||
}
|
||||
else if (isoCode.equals("gd"))
|
||||
{
|
||||
/* Microsoft uses code 60 for "gd" (Scottish Gaelic) and
|
||||
* "ga" (Irish Gaelic). Out table contains "ga".
|
||||
*/
|
||||
code = 60;
|
||||
}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
private static int findLanguageCode(String lang, String langCodes)
|
||||
{
|
||||
int index;
|
||||
if (lang == null)
|
||||
return -1;
|
||||
|
||||
if (lang.length() != 2)
|
||||
return -1;
|
||||
|
||||
index = 0;
|
||||
do
|
||||
{
|
||||
index = langCodes.indexOf(lang, index);
|
||||
|
||||
/* The index must be even to be considered a match. Otherwise, we
|
||||
* could match with the second letter of one language and the
|
||||
* first of antoher one.
|
||||
*/
|
||||
}
|
||||
while (!((index < 0) || ((index & 1) == 0)));
|
||||
if (index < 0)
|
||||
return -1;
|
||||
|
||||
index = index / 2;
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
private static String decodeName(int platform, int encoding, int language,
|
||||
ByteBuffer buffer, int offset, int len)
|
||||
{
|
||||
byte[] byteBuf;
|
||||
String charsetName;
|
||||
int oldPosition;
|
||||
|
||||
charsetName = getCharsetName(platform, language, encoding);
|
||||
if (charsetName == null)
|
||||
return null;
|
||||
|
||||
byteBuf = new byte[len];
|
||||
oldPosition = buffer.position();
|
||||
try
|
||||
{
|
||||
buffer.position(offset);
|
||||
buffer.get(byteBuf);
|
||||
try
|
||||
{
|
||||
return new String(byteBuf, charsetName);
|
||||
}
|
||||
catch (UnsupportedEncodingException uex)
|
||||
{
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
buffer.position(oldPosition);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Maps a MacOS language code into a Java Locale.
|
||||
*
|
||||
* @param macLanguageCode the MacOS language code for
|
||||
* the language whose Java locale is to be retrieved.
|
||||
*
|
||||
* @return an suitable Locale, or <code>null</code> if
|
||||
* the mapping cannot be performed.
|
||||
*/
|
||||
private static Locale getMacLocale(int macLanguageCode)
|
||||
{
|
||||
String isoCode;
|
||||
|
||||
switch (macLanguageCode)
|
||||
{
|
||||
case 0: return Locale.ENGLISH;
|
||||
case 1: return Locale.FRENCH;
|
||||
case 2: return Locale.GERMAN;
|
||||
case 3: return Locale.ITALIAN;
|
||||
case 11: return Locale.JAPANESE;
|
||||
case 23: return Locale.KOREAN;
|
||||
case 19: return Locale.TRADITIONAL_CHINESE;
|
||||
case 33: return Locale.SIMPLIFIED_CHINESE;
|
||||
}
|
||||
|
||||
if ((macLanguageCode < 0) || (macLanguageCode > 150))
|
||||
return null;
|
||||
|
||||
isoCode = macLanguageCodes.substring(macLanguageCode << 1,
|
||||
(macLanguageCode + 1) << 1);
|
||||
if (isoCode.charAt(0) == ' ')
|
||||
return null;
|
||||
|
||||
return new Locale(isoCode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Maps a Windows LCID into a Java Locale.
|
||||
*
|
||||
* @param lcid the Windows language ID whose Java locale
|
||||
* is to be retrieved.
|
||||
*
|
||||
* @return an suitable Locale, or <code>null</code> if
|
||||
* the mapping cannot be performed.
|
||||
*/
|
||||
private static Locale getWindowsLocale(int lcid)
|
||||
{
|
||||
/* FIXME: This is grossly incomplete. */
|
||||
switch (lcid)
|
||||
{
|
||||
case 0x0407: return Locale.GERMAN;
|
||||
case 0x0408: return new Locale("el", "GR");
|
||||
case 0x0409: return Locale.ENGLISH;
|
||||
case 0x040b: return new Locale("fi");
|
||||
case 0x040c: return Locale.FRENCH;
|
||||
case 0x0416: return new Locale("pt");
|
||||
case 0x0807: return new Locale("de", "CH");
|
||||
case 0x0809: return new Locale("en", "UK");
|
||||
case 0x080c: return new Locale("fr", "BE");
|
||||
case 0x0816: return new Locale("pt", "BR");
|
||||
case 0x0c07: return new Locale("de", "AT");
|
||||
case 0x0c09: return new Locale("en", "AU");
|
||||
case 0x0c0c: return new Locale("fr", "CA");
|
||||
case 0x1007: return new Locale("de", "LU");
|
||||
case 0x1009: return new Locale("en", "CA");
|
||||
case 0x100c: return new Locale("fr", "CH");
|
||||
case 0x1407: return new Locale("de", "LI");
|
||||
case 0x1409: return new Locale("en", "NZ");
|
||||
case 0x140c: return new Locale("fr", "LU");
|
||||
case 0x1809: return new Locale("en", "IE");
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Maps a Macintosh Script Manager code to the name of the
|
||||
* corresponding Java Charset.
|
||||
*
|
||||
* @param macScript a MacOS ScriptCode, for example
|
||||
* 6 for <code>smGreek</code>.
|
||||
*
|
||||
* @return a String that can be used to retrieve a Java
|
||||
* CharsetDecorder, for example <code>MacGreek</code>, or
|
||||
* <code>null</code> if <code>macScript</code> has an
|
||||
* unsupported value.
|
||||
*/
|
||||
private static String getMacCharsetName(int macScript)
|
||||
{
|
||||
switch (macScript)
|
||||
{
|
||||
case 0: return "MacRoman";
|
||||
case 1: return "MacJapanese";
|
||||
case 2: return "MacKorean";
|
||||
case 3: return "MacTradChinese";
|
||||
case 4: return "MacArabic";
|
||||
case 5: return "MacHebrew";
|
||||
case 6: return "MacGreek";
|
||||
case 7: return "MacCyrillic";
|
||||
case 8: return "MacRSymbol";
|
||||
case 9: return "MacDevanagari";
|
||||
case 10: return "MacGurmukhi";
|
||||
case 11: return "MacGujarati";
|
||||
case 12: return "MacOriya";
|
||||
case 13: return "MacBengali";
|
||||
case 14: return "MacTamil";
|
||||
case 15: return "MacTelugu";
|
||||
case 16: return "MacKannada";
|
||||
case 17: return "MacMalayalam";
|
||||
case 18: return "MacSinhalese";
|
||||
case 19: return "MacBurmese";
|
||||
case 20: return "MacKhmer";
|
||||
case 21: return "MacThai";
|
||||
case 22: return "MacLao";
|
||||
case 23: return "MacGeorgian";
|
||||
case 24: return "MacArmenian";
|
||||
case 25: return "MacSimpChinese";
|
||||
case 26: return "MacTibetan";
|
||||
case 27: return "MacMongolian";
|
||||
case 28: return "MacEthiopic";
|
||||
case 29: return "MacCentralEurope";
|
||||
case 30: return "MacVietnamese";
|
||||
case 31: return "MacExtArabic";
|
||||
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Maps a Microsoft locale ID (LCID) to the name of the
|
||||
* corresponding Java Charset.
|
||||
*
|
||||
* @param lcid the Microsoft locale ID.
|
||||
*
|
||||
* @return a String that can be used to retrieve a Java
|
||||
* CharsetDecorder, for example <code>windows-1252</code>, or
|
||||
* <code>null</code> if <code>lcid</code> has an unsupported value.
|
||||
*/
|
||||
private static String getMicrosoftCharsetName(int lcid)
|
||||
{
|
||||
int lang;
|
||||
char codePage = '?';
|
||||
|
||||
/* Extract the language code from the LCID. */
|
||||
lang = lcid & 0x3ff;
|
||||
|
||||
/* In the majority of cases, the language alone determines the
|
||||
* codepage.
|
||||
*/
|
||||
if (lang < 100)
|
||||
codePage = (" 612D022322225022EC2202201?002A462110777 68 ?2 1 "
|
||||
+ " 2 2 2112 ?1 1 2 2 ")
|
||||
.charAt(lang);
|
||||
|
||||
/* There are a few exceptions, however, where multiple code pages
|
||||
* are used for the same language. */
|
||||
if (codePage == '?')
|
||||
{
|
||||
switch (lcid)
|
||||
{
|
||||
case 0x041a: // Croatian --> Windows-1250 (Central Europe)
|
||||
case 0x081a: // Serbian (Latin) --> Windows-1250 (Central Europe)
|
||||
codePage = '0';
|
||||
break;
|
||||
|
||||
case 0x42c: // Azeri (Latin) --> Windows-1254 (Turkish)
|
||||
case 0x443: // Uzbek (Latin) --> Windows-1254 (Turkish)
|
||||
codePage = '4';
|
||||
break;
|
||||
|
||||
case 0x82c: // Azeri (Cyrillic) --> Windows-1251 (Cyrillic)
|
||||
case 0x843: // Uzbek (Cyrillic) --> Windows-1251 (Cyrillic)
|
||||
case 0xc1a: // Serbian (Cyrillic) --> Windows-1251 (Cyrillic)
|
||||
codePage = '1';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (codePage)
|
||||
{
|
||||
case '0': return "windows-1250"; // Central Europe
|
||||
case '1': return "windows-1251"; // Cyrillic
|
||||
case '2': return "windows-1252"; // Latin 1
|
||||
case '3': return "windows-1253"; // Greek
|
||||
case '4': return "windows-1254"; // Turkish
|
||||
case '5': return "windows-1255"; // Hebrew
|
||||
case '6': return "windows-1256"; // Arabic
|
||||
case '7': return "windows-1257"; // Baltic
|
||||
case '8': return "windows-1258"; // Vietnam
|
||||
case 'A': return "windows-874"; // Thai
|
||||
case 'B': return "windows-936"; // Simplified Chinese, GBK
|
||||
case 'C': return "windows-949"; // Korean
|
||||
case 'D': return "windows-950"; // Traditional Chinese, Big5
|
||||
case 'E': return "windows-932"; // Japanese Shift-JIS
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the Locale of an OpenType name.
|
||||
*
|
||||
* @param platform the OpenType platform ID.
|
||||
*
|
||||
* @param language the language tag of the OpenType name. If
|
||||
* <code>platform</code> is 1, this is the MacOS language code.
|
||||
*
|
||||
* @param encoding the encoding tag of the OpenType name. If
|
||||
* <code>platform</code> is 1, this is the MacOS script code.
|
||||
*/
|
||||
public static Locale getLocale(int platform, int language, int encoding)
|
||||
{
|
||||
switch (platform)
|
||||
{
|
||||
case 1: /* Apple Macintosh */
|
||||
return getMacLocale(language);
|
||||
|
||||
case 3: /* Microsoft Windows */
|
||||
return getWindowsLocale(language);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the name of the charset for an OpenType font name.
|
||||
*
|
||||
* @param platform the OpenType platform ID.
|
||||
*
|
||||
* @param language the language tag of the OpenType name. If
|
||||
* <code>platform</code> is 1, this is the MacOS language code.
|
||||
*
|
||||
* @param encoding the encoding tag of the OpenType name. If
|
||||
* <code>platform</code> is 1, this is the MacOS script code.
|
||||
*
|
||||
* @return a charset name such as <code>"MacRoman"</code>,
|
||||
* or <code>null</code> if the combination is not known.
|
||||
*/
|
||||
public static String getCharsetName(int platform, int language, int encoding)
|
||||
{
|
||||
switch (platform)
|
||||
{
|
||||
case 1: /* Apple Macintosh */
|
||||
return getMacCharsetName(encoding);
|
||||
|
||||
case 3: /* Microsoft Windows */
|
||||
return getMicrosoftCharsetName(language);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,825 @@
|
||||
/* OpenTypeFont.java -- Manages OpenType and TrueType fonts.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.java.awt.font.opentype;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.FontFormatException;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.font.OpenType;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.text.CharacterIterator;
|
||||
import java.util.Locale;
|
||||
|
||||
import gnu.java.awt.font.FontDelegate;
|
||||
import gnu.java.awt.font.GNUGlyphVector;
|
||||
import gnu.java.awt.font.opentype.truetype.TrueTypeScaler;
|
||||
|
||||
|
||||
/**
|
||||
* A font that takes its data from OpenType or TrueType font tables.
|
||||
*
|
||||
* <p>OpenType is an extension of the TrueType font format. In addition
|
||||
* to tables for names, kerning or layout, it also stores the shapes
|
||||
* of individual glyphs. Three formats are recognized for glyphs:
|
||||
* Quadratic splines (classic TrueType), cubic splines (PostScript),
|
||||
* and bitmaps.
|
||||
*
|
||||
* @see <a
|
||||
* href="http://partners.adobe.com/asn/tech/type/opentype/">Adobe’s
|
||||
* OpenType specification</a>
|
||||
*
|
||||
* @see <a
|
||||
* href="http://developer.apple.com/fonts/TTRefMan/">Apple’s</code>
|
||||
* TrueType specification</a>
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
public final class OpenTypeFont
|
||||
implements FontDelegate
|
||||
{
|
||||
static final int TAG_OTTO = 0x4f54544f; // 'OTTO'
|
||||
static final int TAG_SFNT = 0x73666e74; // 'sfnt'
|
||||
static final int TAG_TRUE = 0x74727565; // 'true'
|
||||
static final int TAG_TTCF = 0x74746366; // 'ttcf'
|
||||
static final int TAG_ZAPF = 0x5a617066; // 'Zapf'
|
||||
|
||||
|
||||
/**
|
||||
* A buffer containing the font data. Note that this may well be an
|
||||
* instance of the subclass MappedByteBuffer, in which case the
|
||||
* virtual memory subsystem can more efficiently handle requests for
|
||||
* font data. This is especially recommended for large font files
|
||||
* that contain many glyphs that are rarely accessed.
|
||||
*/
|
||||
ByteBuffer buf;
|
||||
|
||||
|
||||
/**
|
||||
* The number of glyphs in this font.
|
||||
*/
|
||||
final int numGlyphs;
|
||||
|
||||
int[] tableTag, tableStart, tableLength;
|
||||
|
||||
|
||||
/**
|
||||
* The version of the font in 16.16 fixed-point encoding, for
|
||||
* example 0x00010000 for version 1.0. There are also two special
|
||||
* version IDs used by fonts for Apple Macintosh, namely 'true'
|
||||
* (0x74727565) and 'typ1'. OpenType fonts sometimes have 'OTTO' as
|
||||
* their version.
|
||||
*/
|
||||
private int version;
|
||||
|
||||
|
||||
/**
|
||||
* The number of font units per em. For fonts with TrueType
|
||||
* outlines, this is usually a power of two (such as 2048). For
|
||||
* OpenType fonts with PostScript outlines, other values are
|
||||
* acceptable (such as 1000).
|
||||
*/
|
||||
private int unitsPerEm;
|
||||
|
||||
|
||||
/**
|
||||
* A factor to convert font units into ems. This value is <code>1 /
|
||||
* unitsPerEm</code>.
|
||||
*/
|
||||
private float emsPerUnit;
|
||||
|
||||
|
||||
/**
|
||||
* The scaler to which the actual scaling work is delegated.
|
||||
*/
|
||||
private Scaler scaler;
|
||||
|
||||
|
||||
/**
|
||||
* A delegate object for mapping Unicode UCS-4 codepoints to glyph
|
||||
* IDs.
|
||||
*/
|
||||
private CharGlyphMap cmap;
|
||||
|
||||
|
||||
/**
|
||||
* A delegate object for providing a name for each glyph.
|
||||
*/
|
||||
private GlyphNamer glyphNamer;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an OpenType or TrueType font.
|
||||
*
|
||||
* @param buf a buffer with the contents of the font file. It is
|
||||
* recommended to use a <code>MappedByteBuffer</code> for very
|
||||
* large font files.
|
||||
*
|
||||
* @param offsetTablePosition the position of the OpenType offset
|
||||
* table in the font file. The offset table of most OpenType and
|
||||
* TrueType fonts starts at position 0. However, so-called TrueType
|
||||
* Collections support multiple OpenType fonts in a single file,
|
||||
* which allows sharing some glyphs between fonts. If many glyphs
|
||||
* are shared (for example all the Kanji glyphs between multiple
|
||||
* Japanese fonts), the space savings can be considerable. In that
|
||||
* case, the offset table of each individual font would start at its
|
||||
* own position.
|
||||
*
|
||||
* @throws java.awt.FontFormatException if the font data is
|
||||
* not in OpenType or TrueType format.
|
||||
*/
|
||||
OpenTypeFont(ByteBuffer buf, int offsetTablePosition)
|
||||
throws FontFormatException
|
||||
{
|
||||
int numTables, searchRange, entrySelector, rangeShift;
|
||||
|
||||
//buf = buf.duplicate();
|
||||
this.buf = buf;
|
||||
buf.limit(buf.capacity());
|
||||
buf.position(offsetTablePosition);
|
||||
|
||||
/* Check that the font data is in a supported format. */
|
||||
version = buf.getInt();
|
||||
switch (version)
|
||||
{
|
||||
case 0x00010000: // Microsoft TrueType
|
||||
case OpenType.TAG_TYP1: // Adobe PostScript embeded in Apple SFNT ('typ1')
|
||||
case TAG_SFNT: // Apple TrueType
|
||||
case TAG_TRUE: // Apple TrueType
|
||||
case TAG_OTTO: // OpenType
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new FontFormatException("not in OpenType or TrueType format");
|
||||
}
|
||||
|
||||
numTables = buf.getShort();
|
||||
searchRange = buf.getShort();
|
||||
entrySelector = buf.getShort();
|
||||
rangeShift = buf.getShort();
|
||||
|
||||
tableTag = new int[numTables];
|
||||
tableStart = new int[numTables];
|
||||
tableLength = new int[numTables];
|
||||
int lastTag = 0;
|
||||
for (int i = 0; i < numTables; i++)
|
||||
{
|
||||
tableTag[i] = buf.getInt();
|
||||
if (lastTag >= tableTag[i])
|
||||
throw new FontFormatException("unordered OpenType table");
|
||||
|
||||
buf.getInt(); // ignore checksum
|
||||
tableStart[i] = buf.getInt();
|
||||
tableLength[i] = buf.getInt();
|
||||
|
||||
//System.out.println(tagToString(tableTag[i]) + ", " + tableLength[i]);
|
||||
}
|
||||
|
||||
ByteBuffer head = getFontTable(OpenType.TAG_HEAD);
|
||||
if ((head.getInt(0) != 0x00010000)
|
||||
|| (head.getInt(12) != 0x5f0f3cf5))
|
||||
throw new FontFormatException("unsupported head version");
|
||||
|
||||
unitsPerEm = head.getChar(18);
|
||||
emsPerUnit = 1.0f / (float) unitsPerEm;
|
||||
|
||||
|
||||
ByteBuffer maxp = getFontTable(OpenType.TAG_MAXP);
|
||||
int maxpVersion = maxp.getInt(0);
|
||||
switch (maxpVersion)
|
||||
{
|
||||
case 0x00005000: /* version 0.5, with wrong fractional part */
|
||||
numGlyphs = maxp.getChar(4);
|
||||
break;
|
||||
|
||||
case 0x00010000: /* version 1.0 */
|
||||
numGlyphs = maxp.getChar(4);
|
||||
scaler = new TrueTypeScaler(unitsPerEm,
|
||||
getFontTable(OpenType.TAG_HHEA),
|
||||
getFontTable(OpenType.TAG_HMTX),
|
||||
getFontTable(OpenType.TAG_VHEA),
|
||||
getFontTable(OpenType.TAG_VMTX),
|
||||
maxp,
|
||||
getFontTable(OpenType.TAG_CVT),
|
||||
getFontTable(OpenType.TAG_FPGM),
|
||||
/* loca format */ head.getShort(50),
|
||||
getFontTable(OpenType.TAG_LOCA),
|
||||
getFontTable(OpenType.TAG_GLYF),
|
||||
getFontTable(OpenType.TAG_PREP));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new FontFormatException("unsupported maxp version");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the index of a table into the offset table. The
|
||||
* result can be used to find the offset and length of a table, as
|
||||
* in <code>tableStart[getTableIndex(TAG_NAME)]</code>.
|
||||
*
|
||||
* @param tag the table identifier, for instance
|
||||
* <code>OpenType.TAG_NAME</code>.
|
||||
*
|
||||
* @return the index of that table into the offset table, or
|
||||
* -1 if the font does not contain the table specified by
|
||||
* <code>tag</code>.
|
||||
*/
|
||||
private int getTableIndex(int tag)
|
||||
{
|
||||
/* FIXME: Since the font specification requires tableTag[] to be
|
||||
* ordered, one should do binary search here.
|
||||
*/
|
||||
for (int i = 0; i < tableTag.length; i++)
|
||||
if (tableTag[i] == tag)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the family to which this font face belongs,
|
||||
* for example <i>“Univers”</i>.
|
||||
*
|
||||
* @param locale the locale for which to localize the name.
|
||||
*
|
||||
* @return the family name.
|
||||
*/
|
||||
public synchronized String getFamilyName(Locale locale)
|
||||
{
|
||||
String name;
|
||||
|
||||
if (locale == null)
|
||||
locale = Locale.getDefault();
|
||||
|
||||
name = getName(NameDecoder.NAME_FAMILY, locale);
|
||||
if (name == null)
|
||||
name = getName(NameDecoder.NAME_FAMILY, Locale.ENGLISH);
|
||||
if (name == null)
|
||||
name = getName(NameDecoder.NAME_FAMILY, /* any language */ null);
|
||||
if (name == null)
|
||||
name = getName(NameDecoder.NAME_FULL, locale);
|
||||
if (name == null)
|
||||
name = getName(NameDecoder.NAME_FULL, /* any language */ null);
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of this font face inside the family, for example
|
||||
* <i>“Light”</i>.
|
||||
*
|
||||
* @param locale the locale for which to localize the name.
|
||||
*
|
||||
* @return the name of the face inside its family.
|
||||
*/
|
||||
public synchronized String getSubFamilyName(Locale locale)
|
||||
{
|
||||
String name;
|
||||
|
||||
if (locale == null)
|
||||
locale = Locale.getDefault();
|
||||
|
||||
name = getName(NameDecoder.NAME_SUBFAMILY, locale);
|
||||
if (name == null)
|
||||
{
|
||||
name = getName(NameDecoder.NAME_SUBFAMILY, Locale.ENGLISH);
|
||||
if ("Regular".equals(name))
|
||||
name = null;
|
||||
}
|
||||
|
||||
if (name == null)
|
||||
{
|
||||
String lang = locale.getLanguage();
|
||||
if ("de".equals(lang))
|
||||
name = "Standard";
|
||||
else if ("fr".equals(lang))
|
||||
name = "Standard";
|
||||
else if ("it".equals(lang))
|
||||
name = "Normale";
|
||||
else if ("nl".equals(lang))
|
||||
name = "Normaal";
|
||||
else if ("fi".equals(lang))
|
||||
name = "Normaali";
|
||||
else if ("sv".equals(lang))
|
||||
name = "Normal";
|
||||
else
|
||||
name = "Regular";
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the full name of this font face, for example
|
||||
* <i>“Univers Light”</i>.
|
||||
*
|
||||
* @param locale the locale for which to localize the name.
|
||||
*
|
||||
* @return the face name.
|
||||
*/
|
||||
public synchronized String getFullName(Locale locale)
|
||||
{
|
||||
String name;
|
||||
|
||||
if (locale == null)
|
||||
locale = Locale.getDefault();
|
||||
|
||||
name = getName(NameDecoder.NAME_FULL, locale);
|
||||
if (name == null)
|
||||
name = getName(NameDecoder.NAME_FULL, Locale.ENGLISH);
|
||||
if (name == null)
|
||||
name = getName(NameDecoder.NAME_FULL, /* any language */ null);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the PostScript name of this font face, for example
|
||||
* <i>“Univers-Light”</i>.
|
||||
*
|
||||
* @return the PostScript name, or <code>null</code> if the font
|
||||
* does not provide a PostScript name.
|
||||
*/
|
||||
public synchronized String getPostScriptName()
|
||||
{
|
||||
return getName(NameDecoder.NAME_POSTSCRIPT, /* any language */ null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of glyphs in this font face.
|
||||
*/
|
||||
public int getNumGlyphs()
|
||||
{
|
||||
/* No synchronization is needed because the number of glyphs is
|
||||
* set in the constructor, and it cannot change during the
|
||||
* lifetime of the object.
|
||||
*/
|
||||
return numGlyphs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the index of the glyph which gets displayed if the font
|
||||
* cannot map a Unicode code point to a glyph. Many fonts show this
|
||||
* glyph as an empty box.
|
||||
*/
|
||||
public int getMissingGlyphCode()
|
||||
{
|
||||
/* No synchronization is needed because the result is constant. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The font’s name table, or <code>null</code> if this
|
||||
* table has not yet been accessed.
|
||||
*/
|
||||
private ByteBuffer nameTable;
|
||||
|
||||
|
||||
/**
|
||||
* Extracts a String from the font’s name table.
|
||||
*
|
||||
* @param name the numeric TrueType or OpenType name ID.
|
||||
*
|
||||
* @param locale the locale for which names shall be localized, or
|
||||
* <code>null</code> if the locale does mot matter because the name
|
||||
* is known to be language-independent (for example, because it is
|
||||
* the PostScript name).
|
||||
*/
|
||||
private String getName(int name, Locale locale)
|
||||
{
|
||||
if (nameTable == null)
|
||||
nameTable = getFontTable(OpenType.TAG_NAME);
|
||||
return NameDecoder.getName(nameTable, name, locale);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the version of the font.
|
||||
*
|
||||
* @see java.awt.font.OpenType#getVersion
|
||||
*
|
||||
* @return the version in 16.16 fixed-point encoding, for example
|
||||
* 0x00010000 for version 1.0.
|
||||
*/
|
||||
public int getVersion()
|
||||
{
|
||||
/* No synchronization is needed because the version is set in the
|
||||
* constructor, and it cannot change during the lifetime of the
|
||||
* object.
|
||||
*/
|
||||
return version;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a view buffer for an OpenType table. The caller can
|
||||
* access the returned buffer without needing to synchronize access
|
||||
* from multiple threads.
|
||||
*
|
||||
* @param tag the table identifier, for example
|
||||
* <code>OpenType.GLYF</code>.
|
||||
*
|
||||
* @return a slice of the underlying buffer containing the table, or
|
||||
* <code>null</code> if the font does not contain the requested
|
||||
* table.
|
||||
*/
|
||||
public synchronized ByteBuffer getFontTable(int tag)
|
||||
{
|
||||
int index, start, len;
|
||||
ByteBuffer result;
|
||||
|
||||
index = getTableIndex(tag);
|
||||
if (index < 0)
|
||||
return null;
|
||||
|
||||
start = tableStart[index];
|
||||
len = tableLength[index];
|
||||
buf.limit(start + len).position(start);
|
||||
result = buf.slice();
|
||||
result.limit(len);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the size of one of the tables in the font,
|
||||
* or -1 if the table does not exist.
|
||||
*/
|
||||
public int getFontTableSize(int tag)
|
||||
{
|
||||
int index = getTableIndex(tag);
|
||||
if (index == -1)
|
||||
return index;
|
||||
return tableLength[index];
|
||||
}
|
||||
|
||||
|
||||
private CharGlyphMap getCharGlyphMap()
|
||||
{
|
||||
if (cmap != null)
|
||||
return cmap;
|
||||
|
||||
synchronized (this)
|
||||
{
|
||||
if (cmap == null)
|
||||
{
|
||||
int index = getTableIndex(OpenType.TAG_CMAP);
|
||||
int start = tableStart[index];
|
||||
buf.limit(start + tableLength[index]).position(start);
|
||||
cmap = CharGlyphMap.forTable(buf);
|
||||
}
|
||||
return cmap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Looks up a glyph in the font’s <code>cmap</code> tables,
|
||||
* without performing any glyph substitution or reordering. Because
|
||||
* of this limitation, this method cannot be used for script systems
|
||||
* that need advanced glyph mapping, such as Arabic, Korean, or even
|
||||
* Latin with exotic accents.
|
||||
*
|
||||
* <p>It is safe to call this method from any thread.
|
||||
*
|
||||
* @param ucs4 the Unicode codepoint in the 32-bit Unicode character
|
||||
* set UCS-4. Because UTF-16 surrogates do not correspond to a single
|
||||
* glyph, it does not make sense to pass them here.
|
||||
*
|
||||
* @return the glyph index, or zero if the font does not contain
|
||||
* a glyph for the specified codepoint.
|
||||
*/
|
||||
public int getGlyph(int ucs4)
|
||||
{
|
||||
return getCharGlyphMap().getGlyph(ucs4);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a GlyphVector by mapping each character in a
|
||||
* CharacterIterator to the corresponding glyph.
|
||||
*
|
||||
* <p>The mapping takes only the font’s <code>cmap</code>
|
||||
* tables into consideration. No other operations (such as glyph
|
||||
* re-ordering, composition, or ligature substitution) are
|
||||
* performed. This means that the resulting GlyphVector will not be
|
||||
* correct for text in languages that have complex
|
||||
* character-to-glyph mappings, such as Arabic, Hebrew, Hindi, or
|
||||
* Thai.
|
||||
*
|
||||
* @param font the font object that the created GlyphVector
|
||||
* will return when it gets asked for its font. This argument is
|
||||
* needed because the public API works with java.awt.Font,
|
||||
* not with some private delegate like OpenTypeFont.
|
||||
*
|
||||
* @param frc the font rendering parameters that are used for
|
||||
* measuring glyphs. The exact placement of text slightly depends on
|
||||
* device-specific characteristics, for instance the device
|
||||
* resolution or anti-aliasing. For this reason, any measurements
|
||||
* will only be accurate if the passed
|
||||
* <code>FontRenderContext</code> correctly reflects the relevant
|
||||
* parameters. Hence, <code>frc</code> should be obtained from the
|
||||
* same <code>Graphics2D</code> that will be used for drawing, and
|
||||
* any rendering hints should be set to the desired values before
|
||||
* obtaining <code>frc</code>.
|
||||
*
|
||||
* @param ci a CharacterIterator for iterating over the
|
||||
* characters to be displayed.
|
||||
*/
|
||||
public synchronized GlyphVector createGlyphVector(Font font,
|
||||
FontRenderContext frc,
|
||||
CharacterIterator ci)
|
||||
{
|
||||
CharGlyphMap cmap;
|
||||
int numGlyphs;
|
||||
int[] glyphs;
|
||||
int glyph;
|
||||
int c;
|
||||
|
||||
cmap = getCharGlyphMap();
|
||||
numGlyphs = ci.getEndIndex() - ci.getBeginIndex();
|
||||
glyphs = new int[numGlyphs];
|
||||
glyph = 0;
|
||||
for (c = ci.first(); c != CharacterIterator.DONE; c = ci.next())
|
||||
{
|
||||
/* handle surrogate pairs */
|
||||
if (c >> 10 == 0x36) // U+D800 .. U+DBFF: High surrogate
|
||||
c = (((c & 0x3ff) << 10) | (ci.next() & 0x3ff)) + 0x10000;
|
||||
glyphs[glyph] = cmap.getGlyph(c);
|
||||
glyph += 1;
|
||||
}
|
||||
|
||||
/* If we had surrogates, the allocated array is too large.
|
||||
* Because this will occur very rarely, it seems acceptable to
|
||||
* re-allocate a shorter array and copy the contents around.
|
||||
*/
|
||||
if (glyph != numGlyphs)
|
||||
{
|
||||
int[] newGlyphs = new int[glyph];
|
||||
System.arraycopy(glyphs, 0, newGlyphs, 0, glyph);
|
||||
glyphs = newGlyphs;
|
||||
}
|
||||
|
||||
return new GNUGlyphVector(this, font, frc, glyphs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Determines the advance width for a glyph.
|
||||
*
|
||||
* @param glyphIndex the glyph whose advance width is to be
|
||||
* determined.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialias <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @param advance a point whose <code>x</code> and <code>y</code>
|
||||
* fields will hold the advance in each direction. It is possible
|
||||
* that both values are non-zero, for example if
|
||||
* <code>transform</code> is a rotation, or in the case of Urdu
|
||||
* fonts.
|
||||
*/
|
||||
public synchronized void getAdvance(int glyphIndex,
|
||||
float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal,
|
||||
Point2D advance)
|
||||
{
|
||||
/* Delegate the measurement to the scaler. The synchronization is
|
||||
* needed because the scaler is not synchronized.
|
||||
*/
|
||||
scaler.getAdvance(glyphIndex, pointSize, transform,
|
||||
antialias, fractionalMetrics, horizontal,
|
||||
advance);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the shape of a glyph.
|
||||
*
|
||||
* @param glyph the glyph whose advance width is to be determined
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialias <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts, this
|
||||
* parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional
|
||||
* metrics, <code>false</code> for rounding the result to a pixel
|
||||
* boundary.
|
||||
*
|
||||
* @return the scaled and grid-fitted outline of the specified
|
||||
* glyph, or <code>null</code> for bitmap fonts.
|
||||
*/
|
||||
public synchronized GeneralPath getGlyphOutline(int glyph,
|
||||
float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics)
|
||||
{
|
||||
/* The synchronization is needed because the scaler is not
|
||||
* synchronized.
|
||||
*/
|
||||
return scaler.getOutline(glyph, pointSize, transform,
|
||||
antialias, fractionalMetrics);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a name for the specified glyph. This is useful for
|
||||
* generating PostScript or PDF files that embed some glyphs of a
|
||||
* font.
|
||||
*
|
||||
* <p><b>Names are not unique:</b> Under some rare circumstances,
|
||||
* the same name can be returned for different glyphs. It is
|
||||
* therefore recommended that printer drivers check whether the same
|
||||
* name has already been returned for antoher glyph, and make the
|
||||
* name unique by adding the string ".alt" followed by the glyph
|
||||
* index.</p>
|
||||
*
|
||||
* <p>This situation would occur for an OpenType or TrueType font
|
||||
* that has a <code>post</code> table of format 3 and provides a
|
||||
* mapping from glyph IDs to Unicode sequences through a
|
||||
* <code>Zapf</code> table. If the same sequence of Unicode
|
||||
* codepoints leads to different glyphs (depending on contextual
|
||||
* position, for example, or on typographic sophistication level),
|
||||
* the same name would get synthesized for those glyphs.
|
||||
*
|
||||
* @param glyphIndex the glyph whose name the caller wants to
|
||||
* retrieve.
|
||||
*/
|
||||
public synchronized String getGlyphName(int glyphIndex)
|
||||
{
|
||||
if (glyphNamer == null)
|
||||
glyphNamer = GlyphNamer.forTables(numGlyphs,
|
||||
getFontTable(OpenType.TAG_POST),
|
||||
getFontTable(TAG_ZAPF));
|
||||
|
||||
return glyphNamer.getGlyphName(glyphIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the distance between the base line and the highest
|
||||
* ascender.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialiased <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the ascent, which usually is a positive number.
|
||||
*/
|
||||
public synchronized float getAscent(float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialiased,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal)
|
||||
{
|
||||
return scaler.getAscent(pointSize, transform,
|
||||
antialiased, fractionalMetrics,
|
||||
horizontal);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the distance between the base line and the lowest
|
||||
* descender.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialiased <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the descent, which usually is a nagative number.
|
||||
*/
|
||||
public synchronized float getDescent(float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialiased,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal)
|
||||
{
|
||||
return scaler.getDescent(pointSize, transform,
|
||||
antialiased, fractionalMetrics,
|
||||
horizontal);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts a four-byte tag identifier into a String that can be
|
||||
* displayed when debugging this class.
|
||||
*
|
||||
* @param tag the tag as an <code>int</code>.
|
||||
*
|
||||
* @return the tag in human-readable form, for example
|
||||
* <code>name</code> or <code>glyf</code>.
|
||||
*/
|
||||
static String tagToString(int tag)
|
||||
{
|
||||
char[] c = new char[4];
|
||||
c[0] = (char) ((tag >> 24) & 0xff);
|
||||
c[1] = (char) ((tag >> 16) & 0xff);
|
||||
c[2] = (char) ((tag >> 8) & 0xff);
|
||||
c[3] = (char) (tag & 0xff);
|
||||
return new String(c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/* OpenTypeFontFactory.java -- Creates OpenType and TrueType fonts.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.java.awt.font.opentype;
|
||||
|
||||
import gnu.java.awt.font.FontDelegate;
|
||||
import java.awt.FontFormatException;
|
||||
import java.awt.font.OpenType;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
|
||||
/**
|
||||
* A factory for creating fonts that are stored in an
|
||||
* <i>sfnt</i>-housed format, for example OpenType or TrueType.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
public final class OpenTypeFontFactory
|
||||
{
|
||||
/**
|
||||
* The constructor is private so nobody can construct an instance
|
||||
* of this class.
|
||||
*/
|
||||
private OpenTypeFontFactory()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates FontDelegate objects for the fonts in the specified
|
||||
* buffer. The following font formats are currently recognized:
|
||||
*
|
||||
* <p><ul>
|
||||
* <li>OpenType (*.otf);</li>
|
||||
* <li>TrueType (*.ttf);</li>
|
||||
* <li>TrueType Collections (*.ttc);</li>
|
||||
* <li>Apple MacOS X data-fork font (*.dfont).</li></ul>
|
||||
*
|
||||
* <p>Some formats may contain more than a single font, for example
|
||||
* *.ttc and *.dfont files. This is the reason why this function
|
||||
* returns an array.
|
||||
*
|
||||
* <p>The implementation reads data from the buffer only when
|
||||
* needed. Therefore, it greatly increases efficiency if
|
||||
* <code>buf</code> has been obtained through mapping a file into
|
||||
* the virtual address space.
|
||||
*
|
||||
* @throws FontFormatException if the font data is not in one of the
|
||||
* known formats.
|
||||
*/
|
||||
public static FontDelegate[] createFonts(ByteBuffer buf)
|
||||
throws FontFormatException
|
||||
{
|
||||
OpenTypeFont[] fonts;
|
||||
int version;
|
||||
|
||||
version = buf.getInt(0);
|
||||
switch (version)
|
||||
{
|
||||
case 0x00010000: // Microsoft Windows TrueType
|
||||
case OpenType.TAG_TYP1: // Apple MacOS PostScript ('typ1')
|
||||
case OpenTypeFont.TAG_SFNT: // Apple MacOS TrueType ('sfnt')
|
||||
case OpenTypeFont.TAG_TRUE: // Apple MacOS TrueType ('true')
|
||||
case OpenTypeFont.TAG_OTTO: // OpenType
|
||||
return new OpenTypeFont[] { new OpenTypeFont(buf, 0) };
|
||||
}
|
||||
|
||||
|
||||
/* TrueType Collection, see "TrueType Collections" in
|
||||
* http://partners.adobe.com/asn/tech/type/opentype/otff.html
|
||||
*/
|
||||
if (version == OpenTypeFont.TAG_TTCF)
|
||||
{
|
||||
// This code has never been tested.
|
||||
fonts = new OpenTypeFont[buf.getInt(8)];
|
||||
for (int i = 0; i < fonts.length; i++)
|
||||
fonts[i] = new OpenTypeFont(buf, buf.getInt(16 + 4 * i));
|
||||
return fonts;
|
||||
}
|
||||
|
||||
|
||||
/* The MacOS X .dfont format is a Macintosh resource fork in
|
||||
* a normal file, contaning one or several 'sfnt' resources.
|
||||
* Unfortunately, MacOS resource forks have no magic code
|
||||
* that could be used for identification. Instead, we just try
|
||||
* to extract at least one 'sfnt'.
|
||||
*/
|
||||
try
|
||||
{
|
||||
MacResourceFork fork = new MacResourceFork(buf);
|
||||
MacResourceFork.Resource[] rsrc;
|
||||
|
||||
rsrc = fork.getResources(OpenTypeFont.TAG_SFNT);
|
||||
fonts = new OpenTypeFont[rsrc.length];
|
||||
for (int i = 0; i < fonts.length; i++)
|
||||
fonts[i] = new OpenTypeFont(rsrc[i].getContent(), 0);
|
||||
|
||||
return fonts;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
|
||||
throw new FontFormatException("not in OpenType or TrueType format");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
/* Scaler.java -- Common superclass for font scalers.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.java.awt.font.opentype;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
|
||||
/**
|
||||
* An common superclass for all font scalers. The main task of font
|
||||
* scaler is to retrieve a scaled and hinted outline for a glyph.
|
||||
*
|
||||
* <p>To make text more legible, high-quality fonts contain
|
||||
* instructions (sometimes also called “hints”) for
|
||||
* moving the scaled control points towards the coordinate grid of the
|
||||
* display device.
|
||||
*
|
||||
* <p><b>Lack of Thread Safety:</b> Font scalers are intentionally
|
||||
* <i>not</i> safe to access from multiple concurrent
|
||||
* threads. Synchronization needs to be performed externally. Usually,
|
||||
* the font that uses this scaler already has obtained a lock before
|
||||
* calling the scaler.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
public abstract class Scaler
|
||||
{
|
||||
/**
|
||||
* Retrieves the scaled outline of a glyph, adjusting control points
|
||||
* to the raster grid if necessary.
|
||||
*
|
||||
* @param glyph the glyph number whose outline is retrieved.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialias whether or not the rasterizer will perform
|
||||
* anti-aliasing on the returned path.
|
||||
*
|
||||
* @param fractionalMetrics <code>false</code> for adjusting glyph
|
||||
* positions to the raster grid of device space.
|
||||
*
|
||||
* @return the scaled and grid-fitted outline of the specified
|
||||
* glyph, or <code>null</code> for bitmap fonts.
|
||||
*/
|
||||
public abstract GeneralPath getOutline(int glyph,
|
||||
float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics);
|
||||
|
||||
|
||||
/**
|
||||
* Determines the advance width and height for a glyph.
|
||||
*
|
||||
* @param glyphIndex the glyph whose advance width is to be
|
||||
* determined.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialias <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @param advance a point whose <code>x</code> and <code>y</code>
|
||||
* fields will hold the advance in each direction. It is well
|
||||
* possible that both values are non-zero, for example for rotated
|
||||
* text or for Urdu fonts.
|
||||
*/
|
||||
public abstract void getAdvance(int glyphIndex,
|
||||
float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal,
|
||||
Point2D advance);
|
||||
|
||||
|
||||
/**
|
||||
* Determines the distance between the base line and the highest
|
||||
* ascender.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialias <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the ascent, which usually is a positive number.
|
||||
*/
|
||||
public abstract float getAscent(float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal);
|
||||
|
||||
|
||||
/**
|
||||
* Determines the distance between the base line and the lowest
|
||||
* descender.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialiased <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the descent, which usually is a nagative number.
|
||||
*/
|
||||
public abstract float getDescent(float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialiased,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal);
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/* Fixed.java -- Fixed-point arithmetics for TrueType coordinates.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.font.opentype.truetype;
|
||||
|
||||
|
||||
/**
|
||||
* A utility class for fixed-point arithmetics, where numbers are
|
||||
* represented with 26 dot 6 digits. This representation is used by
|
||||
* TrueType coordinates.
|
||||
*
|
||||
* <p>A good compiler will inline calls of methods in this class.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
final class Fixed
|
||||
{
|
||||
public static final int ONE = 1<<6;
|
||||
|
||||
|
||||
/**
|
||||
* The constructor is private so nobody can use it.
|
||||
*/
|
||||
private Fixed()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Multiplies two fixed-point numbers.
|
||||
*/
|
||||
public static int mul(int a, int b)
|
||||
{
|
||||
return (int) ((((long) a) * b) >> 6);
|
||||
}
|
||||
|
||||
|
||||
public static int div(int a, int b)
|
||||
{
|
||||
return (int) ((((long) a) << 6) / b);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static int ceil(int a)
|
||||
{
|
||||
return (a + 63) & -64;
|
||||
}
|
||||
|
||||
|
||||
public static int floor(int a)
|
||||
{
|
||||
return a & -64;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the length of a fixed-point vector.
|
||||
*/
|
||||
public static int vectorLength(int x, int y)
|
||||
{
|
||||
int shift;
|
||||
float fx, fy;
|
||||
|
||||
if (x == 0)
|
||||
return Math.abs(y);
|
||||
else if (y == 0)
|
||||
return Math.abs(x);
|
||||
|
||||
/* Use the FPU. */
|
||||
fx = ((float) x) / 64.0f;
|
||||
fy = ((float) y) / 64.0f;
|
||||
return (int) (Math.sqrt(fx * fx + fy * fy) * 64.0);
|
||||
}
|
||||
|
||||
|
||||
public static int intValue(int f)
|
||||
{
|
||||
return f >> 6;
|
||||
}
|
||||
|
||||
|
||||
public static float floatValue(int f)
|
||||
{
|
||||
return ((float) f) / 64;
|
||||
}
|
||||
|
||||
|
||||
public static double doubleValue(int f)
|
||||
{
|
||||
return ((double) f) / 64;
|
||||
}
|
||||
|
||||
|
||||
public static int valueOf(float f)
|
||||
{
|
||||
return (int) (f * 64);
|
||||
}
|
||||
|
||||
|
||||
public static int valueOf(double d)
|
||||
{
|
||||
return (int) (d * 64);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Makes a string representation of a fixed-point number.
|
||||
*/
|
||||
public static String toString(int f)
|
||||
{
|
||||
return String.valueOf(floatValue(f));
|
||||
}
|
||||
|
||||
|
||||
public static String toString(int x, int y)
|
||||
{
|
||||
StringBuffer sbuf = new StringBuffer(40);
|
||||
sbuf.append('(');
|
||||
sbuf.append(((float) x) / 64);
|
||||
sbuf.append(", ");
|
||||
sbuf.append(((float) y) / 64);
|
||||
sbuf.append(')');
|
||||
return sbuf.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,437 @@
|
||||
/* GlyphLoader.java -- Helper for loading TrueType glyph outlines.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.font.opentype.truetype;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
|
||||
/**
|
||||
* A class for loading scaled and hinted glyph outlines.
|
||||
*
|
||||
* <p><b>Lack of Thread Safety:</b> Glyph loaders are intentionally
|
||||
* <i>not</i> safe to access from multiple concurrent
|
||||
* threads. Synchronization needs to be performed externally. Usually,
|
||||
* the font has already obtained a lock before calling the scaler,
|
||||
* which in turn calls the GlyphLoader. It would thus be wasteful to
|
||||
* acquire additional locks for the GlyphLoader.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
final class GlyphLoader
|
||||
{
|
||||
/**
|
||||
* A helper object for locating glyph data. GlyphLocator is an
|
||||
* abstract superclass, and there is a concretization for each glyph
|
||||
* location table ('loca') format.
|
||||
*/
|
||||
private final GlyphLocator glyphLocator;
|
||||
|
||||
|
||||
/**
|
||||
* A helper object for measuring the advance width and height of a
|
||||
* glyph.
|
||||
*/
|
||||
private final GlyphMeasurer glyphMeasurer;
|
||||
|
||||
|
||||
/**
|
||||
* The virtual machine for executing TrueType bytecodes.
|
||||
*/
|
||||
private final VirtualMachine vm;
|
||||
|
||||
|
||||
/**
|
||||
* The number of font units in one em. A typical value is 2048,
|
||||
* but this depends on the font.
|
||||
*/
|
||||
private final int unitsPerEm;
|
||||
|
||||
private final int[] contourEndPoints;
|
||||
private final byte[] pointFlags;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a GlyphLoader.
|
||||
*/
|
||||
GlyphLoader(GlyphLocator glyphLocator, VirtualMachine vm,
|
||||
int unitsPerEm, int maxContours, int maxPoints,
|
||||
GlyphMeasurer glyphMeasurer)
|
||||
{
|
||||
this.glyphLocator = glyphLocator;
|
||||
this.glyphMeasurer = glyphMeasurer;
|
||||
this.unitsPerEm = unitsPerEm;
|
||||
this.vm = vm;
|
||||
|
||||
contourEndPoints = new int[maxContours];
|
||||
pointFlags = new byte[maxPoints];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param glyphIndex the number of the glyph whose outlines are to be
|
||||
* retrieved.
|
||||
*/
|
||||
public void loadGlyph(int glyphIndex,
|
||||
double pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
Zone glyphZone)
|
||||
{
|
||||
glyphZone.setNumPoints(4);
|
||||
loadSubGlyph(glyphIndex, pointSize, transform, antialias, glyphZone,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
|
||||
private void loadSubGlyph(int glyphIndex,
|
||||
double pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
Zone glyphZone,
|
||||
int preTranslateX,
|
||||
int preTranslateY)
|
||||
{
|
||||
ByteBuffer glyph;
|
||||
int numContours;
|
||||
int xMin, yMin, xMax, yMax;
|
||||
byte flag;
|
||||
|
||||
glyph = glyphLocator.getGlyphData(glyphIndex);
|
||||
|
||||
if (glyph == null)
|
||||
{
|
||||
glyphZone.setNumPoints(4);
|
||||
setPhantomPoints(glyphIndex, 0, glyphZone);
|
||||
glyphZone.transform(pointSize, transform, unitsPerEm,
|
||||
preTranslateX, preTranslateY);
|
||||
return;
|
||||
}
|
||||
|
||||
numContours = glyph.getShort();
|
||||
xMin = glyph.getChar();
|
||||
yMin = glyph.getChar();
|
||||
xMax = glyph.getChar();
|
||||
yMax = glyph.getChar();
|
||||
|
||||
|
||||
if (numContours >= 0)
|
||||
loadSimpleGlyph(glyphIndex, pointSize, transform, antialias,
|
||||
numContours, glyph, glyphZone,
|
||||
preTranslateX, preTranslateY);
|
||||
else
|
||||
loadCompoundGlyph(glyphIndex, pointSize, transform, antialias,
|
||||
glyph, glyphZone,
|
||||
preTranslateX, preTranslateY);
|
||||
}
|
||||
|
||||
|
||||
private void loadSimpleGlyph(int glyphIndex,
|
||||
double pointSize, AffineTransform transform,
|
||||
boolean antialias,
|
||||
int numContours, ByteBuffer glyph,
|
||||
Zone glyphZone,
|
||||
int preTranslateX, int preTranslateY)
|
||||
{
|
||||
int numPoints;
|
||||
int posInstructions, numInstructions;
|
||||
boolean execInstructions;
|
||||
|
||||
execInstructions = vm.setup(pointSize, transform, antialias);
|
||||
|
||||
/* Load the contour end points and determine the number of
|
||||
* points.
|
||||
*/
|
||||
for (int i = 0; i < numContours; i++)
|
||||
contourEndPoints[i] = glyph.getChar();
|
||||
if (numContours > 0)
|
||||
numPoints = 1 + contourEndPoints[numContours - 1];
|
||||
else
|
||||
numPoints = 0;
|
||||
glyphZone.setNumPoints(numPoints + 4);
|
||||
|
||||
numInstructions = glyph.getChar();
|
||||
posInstructions = glyph.position();
|
||||
glyph.position(posInstructions + numInstructions);
|
||||
loadFlags(numPoints, glyph);
|
||||
loadCoordinates(numPoints, glyph, glyphZone);
|
||||
for (int i = 0; i < numContours; i++)
|
||||
glyphZone.setContourEnd(contourEndPoints[i], true);
|
||||
|
||||
setPhantomPoints(glyphIndex, numPoints, glyphZone);
|
||||
glyphZone.transform(pointSize, transform, unitsPerEm,
|
||||
preTranslateX, preTranslateY);
|
||||
|
||||
if (execInstructions)
|
||||
{
|
||||
// FIXME: Hint the glyph.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final short ARGS_ARE_WORDS = 1;
|
||||
private static final short ARGS_ARE_XY_VALUES = 2;
|
||||
private static final short ROUND_XY_TO_GRID = 4;
|
||||
private static final short WE_HAVE_A_SCALE = 8;
|
||||
private static final short MORE_COMPONENTS = 32;
|
||||
private static final short WE_HAVE_AN_X_AND_Y_SCALE = 64;
|
||||
private static final short WE_HAVE_A_TWO_BY_TWO = 128;
|
||||
private static final short WE_HAVE_INSTRUCTIONS = 256;
|
||||
private static final short USE_MY_METRICS = 512;
|
||||
private static final short OVERLAP_COMPOUND = 1024;
|
||||
private static final short SCALED_COMPONENT_OFFSET = 2048;
|
||||
private static final short UNSCALED_COMPONENT_OFFSET = 4096;
|
||||
|
||||
private void loadCompoundGlyph(int glyphIndex,
|
||||
double pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
ByteBuffer glyph,
|
||||
Zone glyphZone,
|
||||
int preTranslateX, int preTranslateY)
|
||||
{
|
||||
short flags;
|
||||
int subGlyphIndex;
|
||||
int metricsGlyphIndex;
|
||||
Zone subGlyphZone = new Zone(glyphZone.getCapacity());
|
||||
int arg1, arg2;
|
||||
double a, b, c, d, e, f;
|
||||
AffineTransform componentTransform = new AffineTransform();
|
||||
|
||||
/* By default, use the metrics of the compound glyph. The default
|
||||
* is overridden if some component glyph has the USE_MY_METRICS
|
||||
* flag set.
|
||||
*/
|
||||
metricsGlyphIndex = glyphIndex;
|
||||
|
||||
do
|
||||
{
|
||||
flags = glyph.getShort();
|
||||
subGlyphIndex = glyph.getChar();
|
||||
|
||||
if ((flags & USE_MY_METRICS) != 0)
|
||||
metricsGlyphIndex = subGlyphIndex;
|
||||
|
||||
if ((flags & ARGS_ARE_WORDS) != 0)
|
||||
{
|
||||
arg1 = glyph.getShort();
|
||||
arg2 = glyph.getShort();
|
||||
}
|
||||
else
|
||||
{
|
||||
arg1 = glyph.get();
|
||||
arg2 = glyph.get();
|
||||
}
|
||||
|
||||
if ((flags & WE_HAVE_A_SCALE) != 0)
|
||||
{
|
||||
a = d = getDouble214(glyph);
|
||||
b = c = 0.0;
|
||||
}
|
||||
else if ((flags & WE_HAVE_AN_X_AND_Y_SCALE) != 0)
|
||||
{
|
||||
a = getDouble214(glyph);
|
||||
d = getDouble214(glyph);
|
||||
b = c = 0.0;
|
||||
}
|
||||
else if ((flags & WE_HAVE_A_TWO_BY_TWO) != 0)
|
||||
{
|
||||
a = getDouble214(glyph);
|
||||
b = getDouble214(glyph);
|
||||
c = getDouble214(glyph);
|
||||
d = getDouble214(glyph);
|
||||
}
|
||||
else
|
||||
{
|
||||
a = d = 1.0;
|
||||
b = c = 0.0;
|
||||
}
|
||||
|
||||
double m = Math.max(Math.abs(a), Math.abs(b));
|
||||
double n = Math.max(Math.abs(c), Math.abs(d));
|
||||
|
||||
/* The Apple TrueType specification actually says that m is
|
||||
* multiplied by two if
|
||||
*
|
||||
* abs(abs(a) - abs(c)) <= 33/65536,
|
||||
*
|
||||
* but this is probably a typo. On 2003-07-23, Sascha Brawer
|
||||
* wrote an e-mail message to applefonts@apple.com, asking
|
||||
* whether this might possibly be an error in the specification.
|
||||
*/
|
||||
if (Math.abs(Math.abs(a) - Math.abs(b)) <= 33.0/65536.0)
|
||||
m = m * 2;
|
||||
|
||||
if (Math.abs(Math.abs(c) - Math.abs(d)) <= 33.0/65536.0)
|
||||
n = n * 2;
|
||||
|
||||
if ((flags & ARGS_ARE_XY_VALUES) != 0)
|
||||
{
|
||||
e = m * arg1;
|
||||
f = n * arg2;
|
||||
}
|
||||
else
|
||||
e = f = 0.0;
|
||||
|
||||
componentTransform.setTransform(a, b, c, d, 0.0, 0.0);
|
||||
|
||||
// System.out.println("componentTransform = " + componentTransform
|
||||
// + ", e=" + e + ", f=" + f);
|
||||
componentTransform.concatenate(transform);
|
||||
|
||||
int pos = glyph.position();
|
||||
int lim = glyph.limit();
|
||||
|
||||
loadSubGlyph(subGlyphIndex, pointSize, componentTransform,
|
||||
antialias, subGlyphZone,
|
||||
Math.round((float) e + preTranslateX),
|
||||
Math.round(-((float) f + preTranslateY)));
|
||||
glyphZone.combineWithSubGlyph(subGlyphZone, 4);
|
||||
glyph.limit(lim).position(pos);
|
||||
}
|
||||
while ((flags & MORE_COMPONENTS) != 0);
|
||||
|
||||
setPhantomPoints(metricsGlyphIndex, glyphZone.getSize() - 4, glyphZone);
|
||||
}
|
||||
|
||||
|
||||
private double getDouble214(ByteBuffer buf)
|
||||
{
|
||||
return ((double) buf.getShort()) / (1 << 14);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Loads the per-point flags of a glyph into the
|
||||
* <code>pointFlags</code> field.
|
||||
*/
|
||||
private void loadFlags(int numPoints, ByteBuffer glyph)
|
||||
{
|
||||
byte flag;
|
||||
int numRepetitions;
|
||||
|
||||
for (int i = 0; i < numPoints; i++)
|
||||
{
|
||||
pointFlags[i] = flag = glyph.get();
|
||||
if ((flag & 8) != 0)
|
||||
{
|
||||
numRepetitions = ((int) glyph.get()) & 0xff;
|
||||
while (numRepetitions > 0)
|
||||
{
|
||||
pointFlags[++i] = flag;
|
||||
--numRepetitions;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void loadCoordinates(int numPoints, ByteBuffer glyph,
|
||||
Zone glyphZone)
|
||||
{
|
||||
int x, y;
|
||||
byte flag;
|
||||
|
||||
x = 0;
|
||||
for (int i = 0; i < numPoints; i++)
|
||||
{
|
||||
flag = pointFlags[i];
|
||||
if ((flag & 2) == 0)
|
||||
{
|
||||
if ((flag & 16) == 0)
|
||||
x += glyph.getShort();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((flag & 16) != 0)
|
||||
x += (glyph.get() & 0xff);
|
||||
else
|
||||
x -= (glyph.get() & 0xff);
|
||||
}
|
||||
glyphZone.setOriginalX(i, x);
|
||||
glyphZone.setOnCurve(i, (flag & 1) == 1);
|
||||
}
|
||||
|
||||
y = 0;
|
||||
for (int i = 0; i < numPoints; i++)
|
||||
{
|
||||
flag = pointFlags[i];
|
||||
if ((flag & 4) == 0)
|
||||
{
|
||||
if ((flag & 32) == 0)
|
||||
y += glyph.getShort();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((flag & 32) != 0)
|
||||
y += (glyph.get() & 0xff);
|
||||
else
|
||||
y -= (glyph.get() & 0xff);
|
||||
}
|
||||
glyphZone.setOriginalY(i, -y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setPhantomPoints(int glyphIndex, int numPoints,
|
||||
Zone glyphZone)
|
||||
{
|
||||
/* Phantom point 0: Character origin. */
|
||||
glyphZone.setOriginalX(numPoints, 0);
|
||||
glyphZone.setOriginalY(numPoints, 0);
|
||||
|
||||
/* Phantom point 1: Horizontal advance point. */
|
||||
glyphZone.setOriginalX(numPoints + 1,
|
||||
glyphMeasurer.getAdvanceWidth(glyphIndex, true));
|
||||
glyphZone.setOriginalY(numPoints + 1,
|
||||
glyphMeasurer.getAdvanceHeight(glyphIndex, true));
|
||||
|
||||
/* Phantom point 2: Vertical origin. */
|
||||
int vertX = glyphMeasurer.getAscent(/* vertical */ false);
|
||||
int vertY = glyphMeasurer.getAscent(/* horizontal */ true);
|
||||
glyphZone.setOriginalX(numPoints + 2, vertX);
|
||||
glyphZone.setOriginalY(numPoints + 2, vertY);
|
||||
|
||||
/* Phantom point 3: Vertical advance point. */
|
||||
glyphZone.setOriginalX(numPoints + 3,
|
||||
vertX + glyphMeasurer.getAdvanceWidth(glyphIndex, false));
|
||||
glyphZone.setOriginalY(numPoints + 3,
|
||||
vertY + glyphMeasurer.getAdvanceHeight(glyphIndex, false));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
/* GlyphLocator.java -- Locates outlines of TrueType glyphs.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.java.awt.font.opentype.truetype;
|
||||
|
||||
import java.awt.FontFormatException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
|
||||
/**
|
||||
* Locates glyph outlines in a TrueType or OpenType <code>glyf</code>
|
||||
* table.
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://partners.adobe.com/asn/tech/type/opentype/loca.html"
|
||||
* >Adobe’s specification of the OpenType ‘loca’
|
||||
* table</a>
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
abstract class GlyphLocator
|
||||
{
|
||||
/**
|
||||
* The actual glyph data of the font, which is contained in the
|
||||
* 'glyf' table.
|
||||
*/
|
||||
protected ByteBuffer glyfTable;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new GlyphLocator for a <code>loca</code> table.
|
||||
*
|
||||
* @param format the format of the <code>loca</code> table. The
|
||||
* value must be 0 for two-byte offsets, or 1 for four-byte
|
||||
* offsets. TrueType and OpenType fonts indicate the format in the
|
||||
* <code>indexToLoc</code> field of the <a href=
|
||||
* "http://partners.adobe.com/asn/tech/type/opentype/head.html"
|
||||
* >font header</a>.
|
||||
*
|
||||
* @param loca the <code>loca</code> table of the font, which
|
||||
* contains the position of each glyph in the <code>glyf</code>
|
||||
* table.
|
||||
*
|
||||
* @param glyf the <code>glyf</code> table of the font, which
|
||||
* contains the outline data of each glyph.
|
||||
*
|
||||
* @throws FontFormatException if <code>format</code> is neither 0
|
||||
* nor 1.
|
||||
*/
|
||||
public static GlyphLocator forTable(int format, ByteBuffer loca,
|
||||
ByteBuffer glyf)
|
||||
throws FontFormatException
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case 0:
|
||||
return new GlyphLocator.TwoByte(loca, glyf);
|
||||
|
||||
case 1:
|
||||
return new GlyphLocator.FourByte(loca, glyf);
|
||||
|
||||
default:
|
||||
throw new FontFormatException("unsupported loca format");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Locates the outline data for a glyph.
|
||||
*
|
||||
* <p>For efficiency, the glyph locator does not create a new buffer
|
||||
* for each invocation. Instead, this method always returns the same
|
||||
* buffer object. Therefore, the data of a glyph must have been read
|
||||
* completely before another glyph of the same font gets requested
|
||||
* through this method.
|
||||
*
|
||||
* @param glyph the number of the glyph whose outlines are to be
|
||||
* retrieved.
|
||||
*
|
||||
* @return a buffer whose position is set to the first byte of glyph
|
||||
* data, and whose limit is set to disallow accessing any data that
|
||||
* does not belong to the glyph. If there is no outline data for the
|
||||
* requested glyph, as would be the case for the space glyph, the
|
||||
* result will be <code>null</code>.
|
||||
*/
|
||||
public abstract ByteBuffer getGlyphData(int glyph);
|
||||
|
||||
|
||||
/**
|
||||
* A GlyphLocator that locates glyphs using two-byte offsets,
|
||||
* interpreting <code>loca</code> tables of format 0.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
private final static class TwoByte
|
||||
extends GlyphLocator
|
||||
{
|
||||
final CharBuffer indexToLoc;
|
||||
|
||||
TwoByte(ByteBuffer loca, ByteBuffer glyf)
|
||||
{
|
||||
this.glyfTable = glyf;
|
||||
indexToLoc = loca.asCharBuffer();
|
||||
}
|
||||
|
||||
|
||||
public ByteBuffer getGlyphData(int glyph)
|
||||
{
|
||||
int offset, limit;
|
||||
offset = ((int) indexToLoc.get(glyph)) << 1;
|
||||
limit = ((int) indexToLoc.get(glyph + 1)) << 1;
|
||||
if (offset >= limit)
|
||||
return null;
|
||||
|
||||
glyfTable.limit(limit).position(offset);
|
||||
return glyfTable;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A GlyphLocator that locates glyphs using four-byte offsets,
|
||||
* interpreting <code>loca</code> tables of format 1.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
private final static class FourByte
|
||||
extends GlyphLocator
|
||||
{
|
||||
final IntBuffer indexToLoc;
|
||||
|
||||
FourByte(ByteBuffer loca, ByteBuffer glyf)
|
||||
{
|
||||
this.glyfTable = glyf;
|
||||
indexToLoc = loca.asIntBuffer();
|
||||
}
|
||||
|
||||
|
||||
public ByteBuffer getGlyphData(int glyph)
|
||||
{
|
||||
int offset, limit;
|
||||
offset = indexToLoc.get(glyph);
|
||||
limit = indexToLoc.get(glyph + 1);
|
||||
if (offset >= limit)
|
||||
return null;
|
||||
|
||||
glyfTable.limit(limit).position(offset);
|
||||
return glyfTable;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
/* GlyphMeasurer.java -- Helper for measuring TrueType glyphs.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.font.opentype.truetype;
|
||||
|
||||
import java.awt.FontFormatException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
|
||||
/**
|
||||
* A class for measuring TrueType and OpenType glyphs.
|
||||
*
|
||||
* <p><b>Lack of Thread Safety:</b> Glyph measurers are intentionally
|
||||
* <i>not</i> safe to access from multiple concurrent
|
||||
* threads. Synchronization needs to be performed externally. Usually,
|
||||
* the font has already obtained a lock before calling the scaler,
|
||||
* which in turn calls the GlyphMeasurer. It would thus be wasteful to
|
||||
* acquire additional locks for the GlyphMeasurer.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
final class GlyphMeasurer
|
||||
{
|
||||
/**
|
||||
* A view buffer that allows accessing the contents of the
|
||||
* font’s <code>hmtx</code> table as shorts.
|
||||
*/
|
||||
private final ShortBuffer horizontalGlyphMetrics;
|
||||
|
||||
|
||||
/**
|
||||
* A view buffer that allows accessing the contents of the
|
||||
* font’s <code>vmtx</code> table as shorts.
|
||||
*/
|
||||
private final ShortBuffer verticalGlyphMetrics;
|
||||
|
||||
|
||||
private final int numLongHorizontalMetricsEntries;
|
||||
private final int numLongVerticalMetricsEntries;
|
||||
|
||||
private final int horizontalAscent;
|
||||
private final int verticalAscent;
|
||||
|
||||
private final int horizontalDescent;
|
||||
private final int verticalDescent;
|
||||
|
||||
private final int horizontalLineGap;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a GlyphMeasurer from TrueType/OpenType font tables.
|
||||
*
|
||||
* @param hhea the <code>hhea</code> table, which contains
|
||||
* information about horizontal metrics that is common to all
|
||||
* glyphs.
|
||||
*
|
||||
* @param hmtx the <code>hmtx</code> table, which contains
|
||||
* glyph-specific information about horizontal metrics.
|
||||
*
|
||||
* @param vhea the <code>vhea</code> table, which contains
|
||||
* information about vertical metrics that is common to all
|
||||
* glyphs. If a font does not provide such a table, pass
|
||||
* <code>null</code>.
|
||||
*
|
||||
* @param vmtx the <code>vmtx</code> table, which contains
|
||||
* glyph-specific information about vertical metrics. If a font
|
||||
* does not provide such a table, pass <code>null</code>.
|
||||
*/
|
||||
GlyphMeasurer(ByteBuffer hhea, ByteBuffer hmtx,
|
||||
ByteBuffer vhea, ByteBuffer vmtx)
|
||||
throws FontFormatException
|
||||
{
|
||||
if ((hhea.getInt(0) != 0x00010000) || (hhea.getInt(30) != 0))
|
||||
throw new FontFormatException("unsupported hhea format");
|
||||
|
||||
horizontalAscent = hhea.getShort(4);
|
||||
horizontalDescent = hhea.getShort(6);
|
||||
horizontalLineGap = hhea.getShort(8);
|
||||
|
||||
numLongHorizontalMetricsEntries = hhea.getChar(34);
|
||||
horizontalGlyphMetrics = hmtx.asShortBuffer();
|
||||
|
||||
if (vhea != null)
|
||||
{
|
||||
verticalAscent = vhea.getShort(4);
|
||||
verticalDescent = vhea.getShort(6);
|
||||
numLongVerticalMetricsEntries = vhea.getChar(34);
|
||||
verticalGlyphMetrics = vmtx.asShortBuffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
verticalAscent = /* advanceWidthMax */ hhea.getChar(10) / 2;
|
||||
verticalDescent = -verticalAscent;
|
||||
numLongVerticalMetricsEntries = 0;
|
||||
verticalGlyphMetrics = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the distance from the baseline to the highest ascender.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the maximal ascent, in font units.
|
||||
*/
|
||||
public int getAscent(boolean horizontal)
|
||||
{
|
||||
return horizontal ? horizontalAscent : verticalAscent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the distance from the baseline to the lowest descender.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the maximal descent, in font units.
|
||||
*/
|
||||
public int getDescent(boolean horizontal)
|
||||
{
|
||||
return horizontal ? horizontalDescent : verticalDescent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the typographic line gap.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the line gap, in font units.
|
||||
*/
|
||||
public int getLineGap(boolean horizontal)
|
||||
{
|
||||
return horizontalLineGap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the advance width of a glyph, without considering
|
||||
* hinting.
|
||||
*
|
||||
* @param glyphIndex the index of the glyph whose advance width is
|
||||
* to be determined.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the advance width, in font units.
|
||||
*/
|
||||
public int getAdvanceWidth(int glyphIndex, boolean horizontal)
|
||||
{
|
||||
if (!horizontal)
|
||||
return 0;
|
||||
|
||||
glyphIndex = Math.min(glyphIndex,
|
||||
numLongHorizontalMetricsEntries - 1);
|
||||
return horizontalGlyphMetrics.get(glyphIndex << 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the advance width of a glyph, without considering
|
||||
* hinting.
|
||||
*
|
||||
* @param glyphIndex the index of the glyph whose advance width is
|
||||
* to be determined.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the advance width, in font units.
|
||||
*/
|
||||
public int getAdvanceHeight(int glyphIndex, boolean horizontal)
|
||||
{
|
||||
if (horizontal)
|
||||
return 0;
|
||||
|
||||
/* If a font does not provide vertical glyph metrics, advance
|
||||
* by the height of one horizontal line.
|
||||
*/
|
||||
if (verticalGlyphMetrics == null)
|
||||
return horizontalAscent - horizontalDescent + horizontalLineGap;
|
||||
|
||||
glyphIndex = Math.min(glyphIndex,
|
||||
numLongVerticalMetricsEntries - 1);
|
||||
return verticalGlyphMetrics.get(glyphIndex << 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,372 @@
|
||||
/* TrueTypeScaler.java -- Font scaler for TrueType outlines.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.java.awt.font.opentype.truetype;
|
||||
|
||||
import gnu.java.awt.font.opentype.Scaler;
|
||||
|
||||
import java.awt.FontFormatException;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
|
||||
/**
|
||||
* A scaler for fonts whose outlines are described in the TrueType
|
||||
* format.
|
||||
*
|
||||
* <p><b>Lack of Thread Safety:</b> Font scalers are intentionally
|
||||
* <i>not</i> safe to access from multiple concurrent threads.
|
||||
* Synchronization needs to be performed externally. Usually, the font
|
||||
* that uses this scaler already has obtained a lock before calling
|
||||
* the scaler.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
public final class TrueTypeScaler
|
||||
extends Scaler
|
||||
{
|
||||
/**
|
||||
* The TrueType or OpenType table that contains the glyph outlines.
|
||||
*/
|
||||
private ByteBuffer glyfTable;
|
||||
|
||||
|
||||
/**
|
||||
* A helper object for loading glyph outlines.
|
||||
*/
|
||||
private GlyphLoader glyphLoader;
|
||||
|
||||
|
||||
/**
|
||||
* A helper object for measuring the advance width and height of a
|
||||
* glyph.
|
||||
*/
|
||||
private final GlyphMeasurer glyphMeasurer;
|
||||
|
||||
private final Zone glyphZone;
|
||||
|
||||
|
||||
/**
|
||||
* The number of units per em. A typical value is 2048, but some
|
||||
* font use other numbers as well.
|
||||
*/
|
||||
private int unitsPerEm;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new TrueTypeScaler.
|
||||
*
|
||||
* @param unitsPerEm the number of font units per em. This value can
|
||||
* be retrieved from the font’s <code>head</code> table.
|
||||
*
|
||||
* @param maxp the <code>maxp</code> table of the font, which
|
||||
* contains various constants needed for setting up the virtual
|
||||
* machine that interprets TrueType bytecodes.
|
||||
*
|
||||
* @param controlValueTable the <code>cvt</code> table of the font,
|
||||
* which contains the initial values of the control value table.
|
||||
*
|
||||
* @param fpgm the <code>fpgm</code> table of the font, which
|
||||
* contains a font program that is executed exactly once. The
|
||||
* purpose of the font program is to define functions and to patch
|
||||
* the interpreter.
|
||||
*
|
||||
* @param locaFormat the format of the <code>loca</code> table. The
|
||||
* value must be 0 for two-byte offsets, or 1 for four-byte
|
||||
* offsets. TrueType and OpenType fonts indicate the format in the
|
||||
* <code>indexToLoc</code> field of the <a href=
|
||||
* "http://partners.adobe.com/asn/tech/type/opentype/head.html"
|
||||
* >font header</a>.
|
||||
*
|
||||
* @param loca the <code>loca</code> table of the font, which
|
||||
* contains for each glyph the offset of its outline data
|
||||
* in <code>glyf</code>.
|
||||
*
|
||||
* @param glyf the <code>glyf</code> table of the font, which
|
||||
* contains the outline data for all glyphs in the font.
|
||||
*
|
||||
* @param preProgram the <code>prep</code> table of the font, which
|
||||
* contains a program that is executed whenever the point size or
|
||||
* the device transform have changed. This program is called
|
||||
* pre-program because it gets executed before the instructions of
|
||||
* the individual glyphs. If the font does not contain a
|
||||
* pre-program, pass <code>null</code>.
|
||||
*
|
||||
* @throws FontFormatException if <code>format</code> is neither 0
|
||||
* nor 1.
|
||||
*/
|
||||
public TrueTypeScaler(int unitsPerEm,
|
||||
ByteBuffer hhea,
|
||||
ByteBuffer htmx,
|
||||
ByteBuffer vhea,
|
||||
ByteBuffer vtmx,
|
||||
ByteBuffer maxp,
|
||||
ByteBuffer controlValueTable,
|
||||
ByteBuffer fpgm,
|
||||
int locaFormat, ByteBuffer loca,
|
||||
ByteBuffer glyf,
|
||||
ByteBuffer preProgram)
|
||||
throws FontFormatException
|
||||
{
|
||||
int maxContours, maxPoints;
|
||||
VirtualMachine vm;
|
||||
|
||||
maxContours = Math.max(/* maxContours */ (int) maxp.getChar(8),
|
||||
/* maxCompositeContours */ (int) maxp.getChar(12))
|
||||
+ /* fix for some broken fonts */ 8;
|
||||
maxPoints = Math.max(/* maxPoints */ (int) maxp.getChar(6),
|
||||
/* maxCompositePoints */ (int) maxp.getChar(10))
|
||||
+ /* fix for some broken fonts */ 12;
|
||||
|
||||
|
||||
glyphZone = new Zone(maxPoints + /* four phantom points */ 4);
|
||||
this.glyfTable = glyf;
|
||||
vm = new VirtualMachine(unitsPerEm, maxp,
|
||||
controlValueTable, fpgm,
|
||||
preProgram);
|
||||
|
||||
GlyphLocator locator = GlyphLocator.forTable(locaFormat, loca, glyf);
|
||||
glyphMeasurer = new GlyphMeasurer(hhea, htmx, vhea, vtmx);
|
||||
glyphLoader = new GlyphLoader(locator, vm, unitsPerEm,
|
||||
maxContours, maxPoints,
|
||||
glyphMeasurer);
|
||||
|
||||
this.unitsPerEm = unitsPerEm;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the scaled outline of a glyph, adjusting control points
|
||||
* to the raster grid if necessary.
|
||||
*
|
||||
* @param glyphIndex the glyph number whose outline is retrieved.
|
||||
*
|
||||
* @param pointSize the point size for the glyph.
|
||||
*
|
||||
* @param deviceTransform an affine transformation for the device.
|
||||
*
|
||||
* @param antialias whether or not the rasterizer will perform
|
||||
* anti-aliasing on the returned path.
|
||||
*
|
||||
* @param fractionalMetrics <code>false</code> for adjusting glyph
|
||||
* positions to the raster grid of device space.
|
||||
*/
|
||||
public GeneralPath getOutline(int glyphIndex,
|
||||
float pointSize,
|
||||
AffineTransform deviceTransform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics)
|
||||
{
|
||||
glyphLoader.loadGlyph(glyphIndex, pointSize, deviceTransform,
|
||||
antialias, glyphZone);
|
||||
return glyphZone.getPath();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the advance width and height for a glyph.
|
||||
*
|
||||
* @param glyphIndex the glyph whose advance width and height is to
|
||||
* be determined.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialias <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @param advance a point whose <code>x</code> and <code>y</code>
|
||||
* fields will hold the advance in each direction. It is possible
|
||||
* that both values are non-zero, for example if
|
||||
* <code>transform</code> is a rotation, or in the case of Urdu
|
||||
* fonts.
|
||||
*/
|
||||
public void getAdvance(int glyphIndex,
|
||||
float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal,
|
||||
Point2D advance)
|
||||
{
|
||||
double x, y;
|
||||
double scaleFactor = (double) pointSize / unitsPerEm;
|
||||
|
||||
/* FIXME: Should grid-fit if needed. Also, use cache if present
|
||||
* in the font.
|
||||
*/
|
||||
advance.setLocation(
|
||||
scaleFactor * glyphMeasurer.getAdvanceWidth(glyphIndex, horizontal),
|
||||
scaleFactor * glyphMeasurer.getAdvanceHeight(glyphIndex, horizontal));
|
||||
|
||||
transform.transform(advance, advance);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Scales a value from font units to pixels, given the point size
|
||||
* and the transform.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional
|
||||
* metrics, <code>false</code> for rounding the result to a pixel
|
||||
* boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> if the <code>funits</code>
|
||||
* value is along the x axis, <code>false</code> if it is along the
|
||||
* y axis.
|
||||
*/
|
||||
private float scaleFromFUnits(int funits,
|
||||
float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal)
|
||||
{
|
||||
double s;
|
||||
|
||||
s = (double) pointSize / unitsPerEm;
|
||||
if (transform != null)
|
||||
s *= horizontal ? transform.getScaleY() : transform.getScaleX();
|
||||
s *= funits;
|
||||
if (!fractionalMetrics)
|
||||
s = Math.round(s);
|
||||
return (float) s;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the distance between the base line and the highest
|
||||
* ascender.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialias <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the ascent, which usually is a positive number.
|
||||
*/
|
||||
public float getAscent(float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialias,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal)
|
||||
{
|
||||
/* Note that the ascent is orthogonal to the direction of line
|
||||
* layout: If the line direction is horizontal, the measurement of
|
||||
* ascent is along the vertical axis, and vice versa.
|
||||
*/
|
||||
return scaleFromFUnits(glyphMeasurer.getAscent(horizontal),
|
||||
pointSize,
|
||||
transform,
|
||||
fractionalMetrics,
|
||||
/* reverse */ !horizontal);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the distance between the base line and the lowest
|
||||
* descender.
|
||||
*
|
||||
* @param pointSize the point size of the font.
|
||||
*
|
||||
* @param transform a transform that is applied in addition to
|
||||
* scaling to the specified point size. This is often used for
|
||||
* scaling according to the device resolution. Those who lack any
|
||||
* aesthetic sense may also use the transform to slant or stretch
|
||||
* glyphs.
|
||||
*
|
||||
* @param antialiased <code>true</code> for anti-aliased rendering,
|
||||
* <code>false</code> for normal rendering. For hinted fonts,
|
||||
* this parameter may indeed affect the result.
|
||||
*
|
||||
* @param fractionalMetrics <code>true</code> for fractional metrics,
|
||||
* <code>false</code> for rounding the result to a pixel boundary.
|
||||
*
|
||||
* @param horizontal <code>true</code> for horizontal line layout,
|
||||
* <code>false</code> for vertical line layout.
|
||||
*
|
||||
* @return the descent, which usually is a nagative number.
|
||||
*/
|
||||
public float getDescent(float pointSize,
|
||||
AffineTransform transform,
|
||||
boolean antialiased,
|
||||
boolean fractionalMetrics,
|
||||
boolean horizontal)
|
||||
{
|
||||
/* Note that the descent is orthogonal to the direction of line
|
||||
* layout: If the line direction is horizontal, the measurement of
|
||||
* descent is along the vertical axis, and vice versa.
|
||||
*/
|
||||
return scaleFromFUnits(glyphMeasurer.getDescent(horizontal),
|
||||
pointSize,
|
||||
transform,
|
||||
fractionalMetrics,
|
||||
/* reverse */ !horizontal);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,243 @@
|
||||
/* Zone.java -- A collection of points with some additional information.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.java.awt.font.opentype.truetype;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.PathIterator;
|
||||
|
||||
|
||||
/**
|
||||
* A collection of points with some additional information.
|
||||
*/
|
||||
final class Zone
|
||||
{
|
||||
private final int[] pos;
|
||||
private final int[] origPos;
|
||||
private final byte[] flags;
|
||||
private int numPoints;
|
||||
|
||||
private static final int FLAG_TOUCHED_X = 1;
|
||||
private static final int FLAG_TOUCHED_Y = 2;
|
||||
private static final int FLAG_ON_CURVE = 4;
|
||||
private static final int FLAG_CONTOUR_END = 8;
|
||||
|
||||
public Zone(int maxNumPoints)
|
||||
{
|
||||
origPos = new int[maxNumPoints * 2];
|
||||
pos = new int[maxNumPoints * 2];
|
||||
flags = new byte[maxNumPoints];
|
||||
}
|
||||
|
||||
|
||||
public int getCapacity()
|
||||
{
|
||||
return flags.length;
|
||||
}
|
||||
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return numPoints;
|
||||
}
|
||||
|
||||
|
||||
public int getX(int point)
|
||||
{
|
||||
return pos[2 * point];
|
||||
}
|
||||
|
||||
|
||||
public void setX(int point, int value, boolean touch)
|
||||
{
|
||||
pos[2 * point] = value;
|
||||
if (touch)
|
||||
flags[point] |= FLAG_TOUCHED_X;
|
||||
}
|
||||
|
||||
|
||||
public void setY(int point, int value, boolean touch)
|
||||
{
|
||||
pos[2 * point + 1] = value;
|
||||
if (touch)
|
||||
flags[point] |= FLAG_TOUCHED_Y;
|
||||
}
|
||||
|
||||
|
||||
public int getY(int point)
|
||||
{
|
||||
return pos[2 * point + 1];
|
||||
}
|
||||
|
||||
|
||||
public int getOriginalX(int point)
|
||||
{
|
||||
return origPos[2 * point];
|
||||
}
|
||||
|
||||
|
||||
public int getOriginalY(int point)
|
||||
{
|
||||
return origPos[2 * point + 1];
|
||||
}
|
||||
|
||||
|
||||
public void setOriginalX(int point, int x)
|
||||
{
|
||||
origPos[2 * point] = x;
|
||||
}
|
||||
|
||||
public void setOriginalY(int point, int y)
|
||||
{
|
||||
origPos[2 * point + 1] = y;
|
||||
}
|
||||
|
||||
public void setNumPoints(int numPoints)
|
||||
{
|
||||
this.numPoints = numPoints;
|
||||
for (int i = 0; i < numPoints; i++)
|
||||
flags[i] = 0;
|
||||
for (int i = 0; i < 2 * numPoints; i++)
|
||||
origPos[i] = pos[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
public boolean isOnCurve(int point)
|
||||
{
|
||||
return (flags[point] & FLAG_ON_CURVE) != 0;
|
||||
}
|
||||
|
||||
|
||||
public void setOnCurve(int point, boolean onCurve)
|
||||
{
|
||||
if (onCurve)
|
||||
flags[point] |= FLAG_ON_CURVE;
|
||||
else
|
||||
flags[point] &= ~FLAG_ON_CURVE;
|
||||
}
|
||||
|
||||
|
||||
public boolean isContourEnd(int point)
|
||||
{
|
||||
return (flags[point] & FLAG_CONTOUR_END) != 0;
|
||||
}
|
||||
|
||||
|
||||
public void setContourEnd(int point, boolean segEnd)
|
||||
{
|
||||
if (segEnd)
|
||||
flags[point] |= FLAG_CONTOUR_END;
|
||||
else
|
||||
flags[point] &= ~FLAG_CONTOUR_END;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void transform(double pointSize, AffineTransform deviceTransform,
|
||||
int unitsPerEm, int preTranslateX, int preTranslateY)
|
||||
{
|
||||
double scaleX, scaleY, shearX, shearY;
|
||||
double factor;
|
||||
|
||||
factor = pointSize / (double) unitsPerEm;
|
||||
scaleX = deviceTransform.getScaleX() * factor;
|
||||
scaleY = deviceTransform.getScaleY() * factor;
|
||||
shearX = deviceTransform.getShearX() * factor;
|
||||
shearY = deviceTransform.getShearY() * factor;
|
||||
|
||||
for (int i = 0; i < numPoints; i++)
|
||||
{
|
||||
int x = origPos[2 * i] + preTranslateX;
|
||||
int y = origPos[2 * i + 1] + preTranslateY;
|
||||
|
||||
origPos[2*i] = pos[2 * i] = Fixed.valueOf(scaleX * x + shearX * y);
|
||||
origPos[2*i+1] = pos[2 * i + 1] = Fixed.valueOf(shearY * x + scaleY * y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void combineWithSubGlyph(Zone zone, int numPhantomPoints)
|
||||
{
|
||||
int offset = this.numPoints - numPhantomPoints;
|
||||
int count = zone.numPoints;
|
||||
System.arraycopy(zone.origPos, 0, this.origPos, 2 * offset,
|
||||
count * 2);
|
||||
System.arraycopy(zone.pos, 0, this.pos, 2 * offset,
|
||||
count * 2);
|
||||
System.arraycopy(zone.flags, 0, this.flags, offset, count);
|
||||
this.numPoints += count - numPhantomPoints;
|
||||
}
|
||||
|
||||
|
||||
private void dump()
|
||||
{
|
||||
for (int i = 0; i < numPoints; i++)
|
||||
{
|
||||
System.out.print(" " + i + ": ");
|
||||
System.out.print(Fixed.toString(pos[i*2], pos[i*2+1]));
|
||||
System.out.print(' ');
|
||||
System.out.print(Fixed.toString(origPos[i*2], origPos[i*2+1]));
|
||||
System.out.print(' ');
|
||||
if (isOnCurve(i))
|
||||
System.out.print('.');
|
||||
else
|
||||
System.out.print('c');
|
||||
if (isContourEnd(i))
|
||||
System.out.print('E');
|
||||
System.out.println();
|
||||
if (isContourEnd(i))
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public PathIterator getPathIterator()
|
||||
{
|
||||
return new ZonePathIterator(this);
|
||||
}
|
||||
|
||||
|
||||
public GeneralPath getPath()
|
||||
{
|
||||
GeneralPath p = new GeneralPath(GeneralPath.WIND_NON_ZERO, numPoints);
|
||||
p.append(getPathIterator(), /* connect */ false);
|
||||
return p;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,391 @@
|
||||
/* ZonePathIterator.java -- A PathIterator over glyph zones.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package gnu.java.awt.font.opentype.truetype;
|
||||
|
||||
import java.awt.geom.PathIterator;
|
||||
|
||||
|
||||
/**
|
||||
* A PathIterator that enumerates the non-phantom points in a zone.
|
||||
*
|
||||
* <p><b>Lack of thread safety:</b> Instances of this class are
|
||||
* <i>not</i> safe to access from multiple concurrent threads.
|
||||
*
|
||||
* @see Zone
|
||||
*
|
||||
* @author Sascha Brawer (brawer@dandelis.ch)
|
||||
*/
|
||||
final class ZonePathIterator
|
||||
implements PathIterator
|
||||
{
|
||||
/**
|
||||
* If <code>state</code> has this value, <code>currentSegment</code>
|
||||
* will emit a <code>SEG_LINETO</code> or <code>SEG_QUADTO</code> segment
|
||||
* to the current point. For a discussion of subtleties of on-curve
|
||||
* and off-curve points, please refer to the documentation for
|
||||
* {@link #getSegment}.
|
||||
*/
|
||||
private static final int EMIT_SEGMENT = 0;
|
||||
|
||||
|
||||
/**
|
||||
* If <code>state</code> has this value, <code>currentSegment</code>
|
||||
* will emit a <code>SEG_CLOSE</code> in order to close the sub-path
|
||||
* for the current contour.
|
||||
*/
|
||||
private static final int EMIT_CLOSE = 1;
|
||||
|
||||
|
||||
/**
|
||||
* If <code>state</code> has this value, <code>currentSegment</code>
|
||||
* will emit a <code>SEG_MOVETO</code> segment to the first point in
|
||||
* the current contour. If the first point is off-curve, a suitable
|
||||
* on-curve point is calculated.
|
||||
*
|
||||
* @see #getStartSegment
|
||||
*/
|
||||
private static final int EMIT_MOVETO = 2;
|
||||
|
||||
|
||||
/**
|
||||
* The state of the iterator, which is one of
|
||||
* <code>EMIT_SEGMENT</code>, <code>EMIT_CLOSE</code>, or
|
||||
* <code>EMIT_MOVETO</code>.
|
||||
*/
|
||||
private int state;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The zone whose segments are enumerated by this iterator.
|
||||
*/
|
||||
private Zone zone;
|
||||
|
||||
|
||||
/**
|
||||
* The total number of points in the zone, not including the four
|
||||
* phantom points at its end.
|
||||
*/
|
||||
private int numPoints;
|
||||
|
||||
|
||||
/**
|
||||
* The number of the current point.
|
||||
*/
|
||||
private int curPoint;
|
||||
|
||||
|
||||
/**
|
||||
* The number of the first point in the current contour.
|
||||
*/
|
||||
private int contourStart;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a ZonePathIterator for the specified zone.
|
||||
*
|
||||
* @param zone the zone whose segments will be enumerated
|
||||
* by this iterator.
|
||||
*/
|
||||
ZonePathIterator(Zone zone)
|
||||
{
|
||||
this.zone = zone;
|
||||
numPoints = zone.getSize() - /* four phantom points */ 4;
|
||||
|
||||
// The first segment that needs to be emitted is a SEG_MOVETO.
|
||||
state = EMIT_MOVETO;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the winding rule. TrueType glyphs always use the non-zero
|
||||
* winding rule, so this method will always return {@link
|
||||
* PathIterator#WIND_NON_ZERO}.
|
||||
*/
|
||||
public int getWindingRule()
|
||||
{
|
||||
return PathIterator.WIND_NON_ZERO;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean isDone()
|
||||
{
|
||||
return (state != EMIT_CLOSE) && (curPoint >= numPoints);
|
||||
}
|
||||
|
||||
|
||||
public void next()
|
||||
{
|
||||
boolean onCurve;
|
||||
|
||||
/* If the current point is the end of a segment, and no SEG_CLOSE
|
||||
* has been emitted yet, this will be the next segment.
|
||||
*/
|
||||
if (zone.isContourEnd(curPoint) && (state != EMIT_CLOSE))
|
||||
{
|
||||
state = EMIT_CLOSE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the previously emitted segment was a SEG_CLOSE, we are now
|
||||
* at the beginning of a new contour.
|
||||
*/
|
||||
if (state == EMIT_CLOSE)
|
||||
{
|
||||
contourStart = ++curPoint;
|
||||
state = EMIT_MOVETO;
|
||||
return;
|
||||
}
|
||||
|
||||
onCurve = zone.isOnCurve(curPoint);
|
||||
|
||||
/* If the last segment was a moveto, and the current point
|
||||
* (which is the first point in the contour) is off-curve,
|
||||
* we need to emit a quadto segment for the first point.
|
||||
*/
|
||||
if ((state == EMIT_MOVETO) && !onCurve)
|
||||
{
|
||||
state = EMIT_SEGMENT;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
curPoint++;
|
||||
|
||||
/* If the last point has been off-curve, and the now current
|
||||
* point is on-curve, the last segment was a quadto that
|
||||
* had the now current point at its end. In this case, we can
|
||||
* skip a segment.
|
||||
*/
|
||||
if (!onCurve && zone.isOnCurve(curPoint))
|
||||
{
|
||||
/* But if the skipped point is the end of a contour, we must not
|
||||
* skip the SEG_CLOSE. An example where this matters is the 'o'
|
||||
* glyph in the Helvetica font face that comes with MacOS X
|
||||
* 10.1.5.
|
||||
*/
|
||||
if (zone.isContourEnd(curPoint))
|
||||
{
|
||||
state = EMIT_CLOSE;
|
||||
return;
|
||||
}
|
||||
|
||||
curPoint++;
|
||||
}
|
||||
|
||||
state = EMIT_SEGMENT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the successor of the current point in the current
|
||||
* contour. The successor of the last point in a contour is the
|
||||
* start of that contour.
|
||||
*
|
||||
* @return the number of the point that follows the current point in
|
||||
* the same contour.
|
||||
*/
|
||||
private int getSuccessor(int p)
|
||||
{
|
||||
if (zone.isContourEnd(p))
|
||||
return contourStart;
|
||||
else
|
||||
return p + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the current path segment using single-precision
|
||||
* coordinate values.
|
||||
*/
|
||||
public int currentSegment(float[] coords)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case EMIT_CLOSE:
|
||||
return PathIterator.SEG_CLOSE;
|
||||
|
||||
case EMIT_MOVETO:
|
||||
return getStartSegment(curPoint, coords);
|
||||
|
||||
default:
|
||||
return getSegment(curPoint, coords);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A helper array that is used by {@link
|
||||
* #currentSegment(double[])}.
|
||||
*/
|
||||
float[] floats;
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the current path segment using double-precision
|
||||
* coordinate values.
|
||||
*/
|
||||
public int currentSegment(double[] coords)
|
||||
{
|
||||
if (floats == null)
|
||||
floats = new float[6];
|
||||
int result;
|
||||
|
||||
result = currentSegment(floats);
|
||||
for (int i = 0; i < 6; i++)
|
||||
coords[i] = floats[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the segment for the specified point.
|
||||
*
|
||||
* <p><img src="doc-files/ZonePathIterator-1.png" width="426"
|
||||
* height="194" alt="An example curve" /></p>
|
||||
*
|
||||
* <p>If <code>cur</code> is an on-curve point, the returned segment
|
||||
* is a straight line to <code>cur</code>. In the illustration, this
|
||||
* would be the case for <code>cur = 4</code>.</p>
|
||||
*
|
||||
* <p>If <code>cur</code> is an off-curve point, and
|
||||
* <code>cur</code>’s successor <code>succ</code> is also
|
||||
* off-curve, the returned segment is a quadratic Bézier
|
||||
* spline whose control point is <code>cur</code>, and whose end
|
||||
* point is located at the middle of the line connecting
|
||||
* <code>cur</code> and <code>succ</code>. In the illustration,
|
||||
* this would be the case for <code>cur = 5</code>.</p>
|
||||
*
|
||||
* <p>If <code>cur</code> is an off-curve point, and
|
||||
* <code>cur</code>’s successor <code>succ</code> is
|
||||
* on-curve, the returned segment is a quadratic Bézier
|
||||
* spline whose control point is <code>cur</code>, and whose end
|
||||
* point is <code>succ</code>. In the illustration, this would
|
||||
* be the case for <code>cur = 6</code>.</p>
|
||||
*
|
||||
* @return either <code>PathIterator.SEG_LINETO</code> or
|
||||
* <code>PathIterator.SEG_QUADTO</code>.
|
||||
*/
|
||||
private int getSegment(int cur, float[] coords)
|
||||
{
|
||||
int curX, curY;
|
||||
int succ, succX, succY;
|
||||
|
||||
curX = zone.getX(cur);
|
||||
curY = zone.getY(cur);
|
||||
coords[0] = Fixed.floatValue(curX);
|
||||
coords[1] = Fixed.floatValue(curY);
|
||||
|
||||
if (zone.isOnCurve(cur))
|
||||
return PathIterator.SEG_LINETO;
|
||||
|
||||
succ = getSuccessor(cur);
|
||||
succX = zone.getX(succ);
|
||||
succY = zone.getY(succ);
|
||||
|
||||
if (zone.isOnCurve(succ))
|
||||
{
|
||||
coords[2] = Fixed.floatValue(succX);
|
||||
coords[3] = Fixed.floatValue(succY);
|
||||
}
|
||||
else
|
||||
{
|
||||
coords[2] = Fixed.floatValue((curX + succX) / 2);
|
||||
coords[3] = Fixed.floatValue((curY + succY) / 2);
|
||||
}
|
||||
return PathIterator.SEG_QUADTO;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the start segment for the contour which starts
|
||||
* at the specified point.
|
||||
*
|
||||
* <p>If the contour starts with an on-curve point, the returned
|
||||
* segment is a <code>SEG_MOVETO</code> to that point.</p>
|
||||
*
|
||||
* <p>If the contour starts with an off-curve point, and the contour
|
||||
* ends with an on-curve point, the returned segment is a
|
||||
* <code>SEG_MOVETO</code> to the end point.</p>
|
||||
*
|
||||
* <p>If the contour starts with an off-curve point, and the contour
|
||||
* also ends with an off-curve point, the returned segment is a
|
||||
* <code>SEG_MOVETO</code> to the location at the middle between the
|
||||
* start and end points of the contour.</p>
|
||||
*
|
||||
* @return <code>PathIterator.SEG_MOVETO</code>.
|
||||
*/
|
||||
private int getStartSegment(int contourStart, float[] coords)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
if (zone.isOnCurve(contourStart))
|
||||
{
|
||||
x = zone.getX(contourStart);
|
||||
y = zone.getY(contourStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Find the last point of the current contour. */
|
||||
int contourEnd = contourStart;
|
||||
while (!zone.isContourEnd(contourEnd))
|
||||
++contourEnd;
|
||||
|
||||
if (zone.isOnCurve(contourEnd))
|
||||
{
|
||||
/* An example is the 'o' glyph of the Helvetica which comes
|
||||
* with Apple MacOS X 10.1.5.
|
||||
*/
|
||||
x = zone.getX(contourEnd);
|
||||
y = zone.getY(contourEnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = (zone.getX(contourStart) + zone.getX(contourEnd)) / 2;
|
||||
y = (zone.getY(contourStart) + zone.getY(contourEnd)) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
coords[0] = Fixed.floatValue(x);
|
||||
coords[1] = Fixed.floatValue(y);
|
||||
return PathIterator.SEG_MOVETO;
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,316 @@
|
||||
/* AlphaCompositeContext.java -- CompositeContext impl for AlphaComposite
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.java2d;
|
||||
|
||||
import java.awt.AWTError;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.CompositeContext;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
|
||||
/**
|
||||
* A CompositeContext implementation for {@link AlphaComposite}.
|
||||
*
|
||||
* @author Roman Kennke (kennke@aicas.com)
|
||||
*/
|
||||
public class AlphaCompositeContext
|
||||
implements CompositeContext
|
||||
{
|
||||
|
||||
/**
|
||||
* The Composite object for which we perform compositing.
|
||||
*/
|
||||
private AlphaComposite composite;
|
||||
|
||||
/**
|
||||
* The source color model.
|
||||
*/
|
||||
private ColorModel srcColorModel;
|
||||
|
||||
/**
|
||||
* The destination color model.
|
||||
*/
|
||||
private ColorModel dstColorModel;
|
||||
|
||||
/**
|
||||
* The blending factor for the source.
|
||||
*/
|
||||
private float fs;
|
||||
|
||||
/**
|
||||
* The blending factor for the destination.
|
||||
*/
|
||||
private float fd;
|
||||
|
||||
/**
|
||||
* Creates a new AlphaCompositeContext.
|
||||
*
|
||||
* @param aComp the AlphaComposite object
|
||||
* @param srcCM the source color model
|
||||
* @param dstCM the destination color model
|
||||
*/
|
||||
public AlphaCompositeContext(AlphaComposite aComp, ColorModel srcCM,
|
||||
ColorModel dstCM)
|
||||
{
|
||||
composite = aComp;
|
||||
srcColorModel = srcCM;
|
||||
dstColorModel = dstCM;
|
||||
|
||||
|
||||
// Determine the blending factors according to the rule in the
|
||||
// AlphaComposite. For some rules the factors must be determined
|
||||
// dynamically because they depend on the actual pixel value.
|
||||
switch (composite.getRule())
|
||||
{
|
||||
case AlphaComposite.CLEAR:
|
||||
fs = 0.F;
|
||||
fd= 0.F;
|
||||
break;
|
||||
case AlphaComposite.DST:
|
||||
fs = 0.F;
|
||||
fd= 1.F;
|
||||
break;
|
||||
case AlphaComposite.DST_ATOP:
|
||||
fs = 1.F; // Determined later as 1 - alpha_dst;
|
||||
fd = 1.F; // Determined later as alpha_src;
|
||||
break;
|
||||
case AlphaComposite.DST_IN:
|
||||
fs = 0.F;
|
||||
fd = 0.F; // Determined later as alpha_src;
|
||||
break;
|
||||
case AlphaComposite.DST_OUT:
|
||||
fs = 0.F;
|
||||
fd = 0.F; // Determined later as 1 - alpha_src;
|
||||
break;
|
||||
case AlphaComposite.DST_OVER:
|
||||
fs = 1.F; // Determined later as 1 - alpha_dst.
|
||||
fd= 1.F;
|
||||
break;
|
||||
case AlphaComposite.SRC:
|
||||
fs = 1.F;
|
||||
fd= 0.F;
|
||||
break;
|
||||
case AlphaComposite.SRC_ATOP:
|
||||
fs = 1.F; // Determined later as alpha_dst;
|
||||
fd = 1.F; // Determined later as 1 - alpha_src;
|
||||
break;
|
||||
case AlphaComposite.SRC_IN:
|
||||
fs = 0.F; // Determined later as alpha_dst;
|
||||
fd = 0.F;
|
||||
break;
|
||||
case AlphaComposite.SRC_OUT:
|
||||
fs = 0.F; // Determined later as 1 - alpha_dst;
|
||||
fd = 0.F;
|
||||
break;
|
||||
case AlphaComposite.SRC_OVER:
|
||||
fs = 1.F;
|
||||
fd= 1.F; // Determined later as 1 - alpha_src.
|
||||
break;
|
||||
case AlphaComposite.XOR:
|
||||
fs = 1.F; // Determined later as 1 - alpha_dst.
|
||||
fd= 1.F; // Determined later as 1 - alpha_src.
|
||||
break;
|
||||
default:
|
||||
throw new AWTError("Illegal AlphaComposite rule");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases all resources held by this composite object.
|
||||
*/
|
||||
public void dispose()
|
||||
{
|
||||
// Nothing to do here yet.
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs compositing according to the rules specified in the
|
||||
* AlphaComposite from the constructor.
|
||||
*/
|
||||
public void compose(Raster src, Raster dstIn, WritableRaster dstOut)
|
||||
{
|
||||
|
||||
// TODO: This implementation is very general and highly inefficient. There
|
||||
// are two possible ways to optimize this:
|
||||
// 1. Special cased implementations for common ColorModels and transfer
|
||||
// types.
|
||||
// 2. Native implementation.
|
||||
|
||||
int x0 = src.getMinX();
|
||||
int y0 = src.getMinY();
|
||||
int width = src.getWidth();
|
||||
int height = src.getHeight();
|
||||
int x1 = x0 + width;
|
||||
int y1 = y0 + height;
|
||||
|
||||
Object srcPixel = null;
|
||||
Object dstPixel = null;
|
||||
|
||||
// Prepare the array that holds the color and alpha components of the
|
||||
// source pixels.
|
||||
float[] srcComponents;
|
||||
int srcComponentsLength = srcColorModel.getNumComponents();
|
||||
if (! srcColorModel.hasAlpha())
|
||||
srcComponentsLength += 1;
|
||||
srcComponents = new float[srcComponentsLength];
|
||||
|
||||
// Prepare the array that holds the color and alpha components of the
|
||||
// destination pixels.
|
||||
float[] dstComponents;
|
||||
int dstComponentsLength = dstColorModel.getNumComponents();
|
||||
if (! dstColorModel.hasAlpha())
|
||||
dstComponentsLength += 1;
|
||||
dstComponents = new float[dstComponentsLength];
|
||||
|
||||
if (srcComponentsLength != dstComponentsLength)
|
||||
throw new AWTError("The color models of the source and destination have"
|
||||
+ "incompatible number of color components");
|
||||
|
||||
int srcTransferType = srcColorModel.getTransferType();
|
||||
int dstTransferType = dstColorModel.getTransferType();
|
||||
|
||||
for (int y = y0; y < y1; y++)
|
||||
{
|
||||
for (int x = x0; x < x1; x++)
|
||||
{
|
||||
// Fetch source pixel.
|
||||
srcPixel = src.getDataElements(x, y, (int[]) srcPixel);
|
||||
// Fetch destination pixel.
|
||||
dstPixel = dstIn.getDataElements(x, y, dstPixel);
|
||||
// Get normalized components. This is the only type that is
|
||||
// guaranteed to be supported by all ColorModels.
|
||||
srcComponents =
|
||||
srcColorModel.getNormalizedComponents(srcPixel, srcComponents, 0);
|
||||
if (! srcColorModel.hasAlpha())
|
||||
srcComponents[srcComponentsLength - 1] = 1.0F;
|
||||
dstComponents =
|
||||
dstColorModel.getNormalizedComponents(dstPixel, dstComponents, 0);
|
||||
if (! dstColorModel.hasAlpha())
|
||||
dstComponents[dstComponentsLength - 1] = 1.0F;
|
||||
|
||||
// Prepare the input.
|
||||
float compositeAlpha = composite.getAlpha();
|
||||
srcComponents[srcComponentsLength - 1] *= compositeAlpha;
|
||||
if (srcColorModel.isAlphaPremultiplied())
|
||||
{
|
||||
for (int i = srcComponentsLength - 2; i >= 0; i--)
|
||||
srcComponents[i] *= compositeAlpha;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = srcComponentsLength - 1; i >= 0; i--)
|
||||
srcComponents[i] *= srcComponents[srcComponentsLength - 1];
|
||||
}
|
||||
if (! dstColorModel.isAlphaPremultiplied())
|
||||
{
|
||||
for (int i = dstComponentsLength - 2; i >= 0; i--)
|
||||
dstComponents[i] *= dstComponents[dstComponents.length - 1];
|
||||
}
|
||||
|
||||
// Determine the blending factors according to the rule in the
|
||||
// AlphaComposite. For some rules the factors must be determined
|
||||
// dynamically because they depend on the actual pixel value.
|
||||
float srcAlpha = srcComponents[srcComponentsLength - 1];
|
||||
float dstAlpha = dstComponents[dstComponentsLength - 1];
|
||||
switch (composite.getRule())
|
||||
{
|
||||
case AlphaComposite.DST_ATOP:
|
||||
fs = 1.F - dstAlpha;
|
||||
fd = srcAlpha;
|
||||
break;
|
||||
case AlphaComposite.DST_IN:
|
||||
fd = srcAlpha;
|
||||
break;
|
||||
case AlphaComposite.DST_OUT:
|
||||
fd = 1.F - srcAlpha;
|
||||
break;
|
||||
case AlphaComposite.DST_OVER:
|
||||
fs = 1.F - dstAlpha;
|
||||
break;
|
||||
case AlphaComposite.SRC_ATOP:
|
||||
fs = srcAlpha;
|
||||
fd = 1.F - srcAlpha;
|
||||
break;
|
||||
case AlphaComposite.SRC_IN:
|
||||
fs = dstAlpha;
|
||||
break;
|
||||
case AlphaComposite.SRC_OUT:
|
||||
fs = 1.F - dstAlpha;
|
||||
break;
|
||||
case AlphaComposite.SRC_OVER:
|
||||
fd= 1.F - srcAlpha;
|
||||
break;
|
||||
case AlphaComposite.XOR:
|
||||
fs = 1.F - dstAlpha;
|
||||
fd= 1.F - srcAlpha;
|
||||
break;
|
||||
default:
|
||||
// For the other cases the factors have already been determined
|
||||
// in the constructor.
|
||||
}
|
||||
|
||||
// Apply the blending equation to the pixels.
|
||||
for (int i = 0; i < srcComponentsLength; i++)
|
||||
{
|
||||
dstComponents[i] = srcComponents[i] * fs
|
||||
+ dstComponents[i] * fd;
|
||||
}
|
||||
|
||||
// Convert the result back when the destination is not
|
||||
// alpha-premultiplied.
|
||||
dstAlpha = dstComponents[dstComponentsLength - 1];
|
||||
if (!dstColorModel.isAlphaPremultiplied() && dstAlpha != 0.F)
|
||||
{
|
||||
for (int i = 0; i < dstComponentsLength - 1; i++)
|
||||
{
|
||||
dstComponents[i] = dstComponents[i] / dstAlpha;
|
||||
}
|
||||
}
|
||||
|
||||
// Store the result in the destination raster.
|
||||
dstPixel = dstColorModel.getDataElements(dstComponents, 0,
|
||||
dstPixel);
|
||||
dstOut.setDataElements(x, y, dstPixel);
|
||||
} // End X loop.
|
||||
} // End Y loop.
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/* CubicSegment.java -- Cubic segment used for BasicStroke
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.java2d;
|
||||
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
/**
|
||||
* Cubic Bezier curve segment
|
||||
*/
|
||||
public class CubicSegment extends Segment
|
||||
{
|
||||
public Point2D cp1; // control points
|
||||
public Point2D cp2; // control points
|
||||
|
||||
/**
|
||||
* Constructor - takes coordinates of the starting point,
|
||||
* first control point, second control point and end point,
|
||||
* respecively.
|
||||
*/
|
||||
public CubicSegment(double x1, double y1, double c1x, double c1y,
|
||||
double c2x, double c2y, double x2, double y2)
|
||||
{
|
||||
super();
|
||||
P1 = new Point2D.Double(x1, y1);
|
||||
P2 = new Point2D.Double(x2, y2);
|
||||
cp1 = new Point2D.Double(c1x, c1y);
|
||||
cp2 = new Point2D.Double(c2x, c2y);
|
||||
}
|
||||
|
||||
public CubicSegment(Point2D p1, Point2D cp1, Point2D cp2, Point2D p2)
|
||||
{
|
||||
super();
|
||||
P1 = p1;
|
||||
P2 = p2;
|
||||
this.cp1 = cp1;
|
||||
this.cp2 = cp2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones this segment
|
||||
*/
|
||||
public Object clone()
|
||||
{
|
||||
return new CubicSegment(P1.getX(), P1.getY(), cp1.getX(), cp1.getY(),
|
||||
cp2.getX(), cp2.getY(), P2.getX(), P2.getY());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "top" and "bottom" segments of this segment.
|
||||
* First array element is p0 + normal, second is p0 - normal.
|
||||
*/
|
||||
public Segment[] getDisplacedSegments(double radius)
|
||||
{
|
||||
this.radius = radius;
|
||||
double x0 = P1.getX();
|
||||
double y0 = P1.getY();
|
||||
double x1 = cp1.getX();
|
||||
double y1 = cp1.getY();
|
||||
double x2 = cp2.getX();
|
||||
double y2 = cp2.getY();
|
||||
double x3 = P2.getX();
|
||||
double y3 = P2.getY();
|
||||
double[] p1 = normal(x0, y0, x1, y1);
|
||||
double[] p2 = normal(x2, y2, x3, y3);
|
||||
|
||||
|
||||
// FIXME: Doesn't compile.
|
||||
// return new Segment[]{s1, s2};
|
||||
return new Segment[0];
|
||||
}
|
||||
|
||||
public void reverse()
|
||||
{
|
||||
Point2D temp = P1;
|
||||
P1 = P2;
|
||||
P2 = temp;
|
||||
temp = cp1;
|
||||
cp1 = cp2;
|
||||
cp2 = temp;
|
||||
}
|
||||
|
||||
public double[] first()
|
||||
{
|
||||
return new double[]{cp1.getX(), cp1.getY()};
|
||||
}
|
||||
|
||||
public double[] last()
|
||||
{
|
||||
return new double[]{cp2.getX(), cp2.getY()};
|
||||
}
|
||||
} // class CubicSegment
|
||||
@@ -0,0 +1,103 @@
|
||||
/* LineSegment.java -- Line segment used for BasicStroke
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.java2d;
|
||||
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
public class LineSegment extends Segment
|
||||
{
|
||||
public LineSegment(double x1, double y1, double x2, double y2)
|
||||
{
|
||||
super();
|
||||
P1 = new Point2D.Double(x1, y1);
|
||||
P2 = new Point2D.Double(x2, y2);
|
||||
}
|
||||
|
||||
public LineSegment(Point2D p1, Point2D p2)
|
||||
{
|
||||
super();
|
||||
P1 = (Point2D) p1.clone();
|
||||
P2 = (Point2D) p2.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones this segment
|
||||
*/
|
||||
public Object clone()
|
||||
{
|
||||
return new LineSegment(P1, P2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "top" and "bottom" segments of this segment.
|
||||
* First array element is p0 + normal, second is p0 - normal.
|
||||
*/
|
||||
public Segment[] getDisplacedSegments(double radius)
|
||||
{
|
||||
this.radius = radius;
|
||||
double x0 = P1.getX();
|
||||
double y0 = P1.getY();
|
||||
double x1 = P2.getX();
|
||||
double y1 = P2.getY();
|
||||
double[] p = normal(x0, y0, x1, y1);
|
||||
Segment s1 = (new LineSegment(x0 + p[0], y0 + p[1],
|
||||
x1 + p[0], y1 + p[1] ));
|
||||
Segment s2 = (new LineSegment(x0 - p[0], y0 - p[1],
|
||||
x1 - p[0], y1 - p[1] ));
|
||||
return new Segment[]{s1, s2};
|
||||
}
|
||||
|
||||
public void reverse()
|
||||
{
|
||||
Point2D p = P1;
|
||||
P1 = P2;
|
||||
P2 = p;
|
||||
}
|
||||
|
||||
public double[] first()
|
||||
{
|
||||
return new double[]{P2.getX(), P2.getY()};
|
||||
}
|
||||
|
||||
public double[] last()
|
||||
{
|
||||
return new double[]{P1.getX(), P1.getY()};
|
||||
}
|
||||
} // class LineSegment
|
||||
@@ -0,0 +1,117 @@
|
||||
/* PolyEdge.java -- An edge in a polygon, used for polygon filling
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.java2d;
|
||||
|
||||
/**
|
||||
* An edge in a polygon. This is used by the scanline conversion algorithm
|
||||
* implemented in {@link AbstractGraphics2D#rawFillShape}.
|
||||
*
|
||||
* @author Roman Kennke (kennke@aicas.com)
|
||||
*/
|
||||
public class PolyEdge
|
||||
implements Comparable
|
||||
{
|
||||
|
||||
/**
|
||||
* The start and end coordinates of the edge. y0 is always smaller or equal
|
||||
* than y1.
|
||||
*/
|
||||
public double x0, y0, x1, y1;
|
||||
|
||||
/**
|
||||
* The slope of the edge. This is dx / dy.
|
||||
*/
|
||||
double slope;
|
||||
|
||||
/**
|
||||
* The intersection of this edge with the current scanline.
|
||||
*/
|
||||
double xIntersection;
|
||||
|
||||
/**
|
||||
* Creates a new PolyEdge with the specified coordinates.
|
||||
*
|
||||
* @param x0 the starting point, x coordinate
|
||||
* @param y0 the starting point, y coordinate
|
||||
* @param x1 the end point, x coordinate
|
||||
* @param y1 the end point, y coordinate
|
||||
*/
|
||||
PolyEdge(double x0, double y0, double x1, double y1)
|
||||
{
|
||||
if (y0 < y1)
|
||||
{
|
||||
this.x0 = x0;
|
||||
this.y0 = y0;
|
||||
this.x1 = x1;
|
||||
this.y1 = y1;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.x0 = x1;
|
||||
this.y0 = y1;
|
||||
this.x1 = x0;
|
||||
this.y1 = y0;
|
||||
}
|
||||
slope = (this.x1 - this.x0) / (this.y1 - this.y0);
|
||||
if (this.y0 == this.y1) // Horizontal edge.
|
||||
xIntersection = Math.min(this.x0, this.x1);
|
||||
else
|
||||
xIntersection = this.x0 + slope * (Math.ceil(this.y0) - this.y0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts PolyEdges by the x coordinate from the minimum x value.
|
||||
*/
|
||||
public int compareTo(Object o)
|
||||
{
|
||||
PolyEdge other = (PolyEdge) o;
|
||||
int comp = 0;
|
||||
if (x0 < other.x0)
|
||||
comp = -1;
|
||||
else if (x0 > other.x0)
|
||||
comp = 1;
|
||||
return comp;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "Edge: " + x0 + ", " + y0 + ", " + x1 + ", " + y1 + ", slope: "
|
||||
+ slope + ", xIntersection: " + xIntersection;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/* PolyEdgeComparator.java -- Sorts PolyEdges by their current intersection
|
||||
points
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.java2d;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Sorts {@link PolyEdge}s by their current intersection points.
|
||||
*
|
||||
* @author Roman Kennke (kennke@aicas.com)
|
||||
*/
|
||||
public class PolyEdgeComparator
|
||||
implements Comparator
|
||||
{
|
||||
|
||||
/**
|
||||
* The current scanline.
|
||||
*/
|
||||
int y;
|
||||
|
||||
public int compare(Object o1, Object o2)
|
||||
{
|
||||
PolyEdge edge1 = (PolyEdge) o1;
|
||||
PolyEdge edge2 = (PolyEdge) o2;
|
||||
int comp = 0;
|
||||
if (edge1.xIntersection < edge2.xIntersection)
|
||||
comp = -1;
|
||||
else if (edge1.xIntersection > edge2.xIntersection)
|
||||
comp = 1;
|
||||
return comp;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
/* QuadSegment.java -- QuadCurve segment used for BasicStroke
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.java2d;
|
||||
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.QuadCurve2D;
|
||||
|
||||
/**
|
||||
* Quadratic Bezier curve segment
|
||||
*
|
||||
* Note: Most peers don't support quadratics directly, so it might make
|
||||
* sense to represent them as cubics internally and just be done with it.
|
||||
* I think we should be peer-agnostic, however, and stay faithful to the
|
||||
* input geometry types as far as possible.
|
||||
*/
|
||||
public class QuadSegment extends Segment
|
||||
{
|
||||
public Point2D cp; // control point
|
||||
|
||||
/**
|
||||
* Constructor, takes the coordinates of the start, control,
|
||||
* and end point, respectively.
|
||||
*/
|
||||
public QuadSegment(double x1, double y1, double cx, double cy, double x2,
|
||||
double y2)
|
||||
{
|
||||
super();
|
||||
P1 = new Point2D.Double(x1, y1);
|
||||
P2 = new Point2D.Double(x2, y2);
|
||||
cp = new Point2D.Double(cx, cy);
|
||||
}
|
||||
|
||||
public QuadSegment(Point2D p1, Point2D cp, Point2D p2)
|
||||
{
|
||||
super();
|
||||
P1 = p1;
|
||||
P2 = p2;
|
||||
this.cp = cp;
|
||||
}
|
||||
|
||||
public QuadSegment(QuadCurve2D curve)
|
||||
{
|
||||
super();
|
||||
P1 = curve.getP1();
|
||||
P2 = curve.getP2();
|
||||
this.cp = curve.getCtrlPt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones this segment
|
||||
*/
|
||||
public Object clone()
|
||||
{
|
||||
return new QuadSegment(P1.getX(), P1.getY(), cp.getX(), cp.getY(),
|
||||
P2.getX(), P2.getY());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "top" and "bottom" segments of a given segment.
|
||||
* First array element is p0 + normal, second is p0 - normal.
|
||||
*/
|
||||
public Segment[] getDisplacedSegments(double radius)
|
||||
{
|
||||
this.radius = radius;
|
||||
double x0 = P1.getX();
|
||||
double y0 = P1.getY();
|
||||
double x1 = cp.getX();
|
||||
double y1 = cp.getY();
|
||||
double x2 = P2.getX();
|
||||
double y2 = P2.getY();
|
||||
|
||||
QuadCurve2D left = new QuadCurve2D.Double();
|
||||
QuadCurve2D right = new QuadCurve2D.Double();
|
||||
QuadCurve2D orig = new QuadCurve2D.Double(x0, y0, x1, y1, x2, y2);
|
||||
orig.subdivide(left, right);
|
||||
|
||||
QuadSegment s1 = offsetSubdivided(left, true);
|
||||
QuadSegment s2 = offsetSubdivided(left, false);
|
||||
|
||||
s1.add( offsetSubdivided(right, true) );
|
||||
s2.add( offsetSubdivided(right, false) );
|
||||
|
||||
return new Segment[]{s1, s2};
|
||||
}
|
||||
|
||||
private QuadSegment offsetSubdivided(QuadCurve2D curve, boolean plus)
|
||||
{
|
||||
double[] n1 = normal(curve.getX1(), curve.getY1(),
|
||||
curve.getCtrlX(), curve.getCtrlY());
|
||||
double[] n2 = normal(curve.getCtrlX(), curve.getCtrlY(),
|
||||
curve.getX2(), curve.getY2());
|
||||
|
||||
Point2D cp;
|
||||
QuadSegment s;
|
||||
if( plus )
|
||||
{
|
||||
cp = lineIntersection(curve.getX1() + n1[0],
|
||||
curve.getY1() + n1[1],
|
||||
curve.getCtrlX() + n1[0],
|
||||
curve.getCtrlY() + n1[1],
|
||||
curve.getCtrlX() + n2[0],
|
||||
curve.getCtrlY() + n2[1],
|
||||
curve.getX2() + n2[0],
|
||||
curve.getY2() + n2[1], true);
|
||||
s = new QuadSegment(curve.getX1() + n1[0], curve.getY1() + n1[1],
|
||||
cp.getX(), cp.getY(),
|
||||
curve.getX2() + n2[0], curve.getY2() + n2[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
cp = lineIntersection(curve.getX1() - n1[0],
|
||||
curve.getY1() - n1[1],
|
||||
curve.getCtrlX() - n1[0],
|
||||
curve.getCtrlY() - n1[1],
|
||||
curve.getCtrlX() - n2[0],
|
||||
curve.getCtrlY() - n2[1],
|
||||
curve.getX2() - n2[0],
|
||||
curve.getY2() - n2[1], true);
|
||||
|
||||
s = new QuadSegment(curve.getX1() - n1[0], curve.getY1() - n1[1],
|
||||
cp.getX(), cp.getY(),
|
||||
curve.getX2() - n2[0], curve.getY2() - n2[1]);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private Point2D lineIntersection(double X1, double Y1,
|
||||
double X2, double Y2,
|
||||
double X3, double Y3,
|
||||
double X4, double Y4,
|
||||
boolean infinite)
|
||||
{
|
||||
double x1 = X1;
|
||||
double y1 = Y1;
|
||||
double rx = X2 - x1;
|
||||
double ry = Y2 - y1;
|
||||
|
||||
double x2 = X3;
|
||||
double y2 = Y3;
|
||||
double sx = X4 - x2;
|
||||
double sy = Y4 - y2;
|
||||
|
||||
double determinant = sx * ry - sy * rx;
|
||||
double nom = (sx * (y2 - y1) + sy * (x1 - x2));
|
||||
|
||||
// lines can be considered parallel.
|
||||
if (Math.abs(determinant) < 1E-6)
|
||||
return null;
|
||||
|
||||
nom = nom / determinant;
|
||||
|
||||
// check if lines are within the bounds
|
||||
if(!infinite && (nom > 1.0 || nom < 0.0))
|
||||
return null;
|
||||
|
||||
return new Point2D.Double(x1 + nom * rx, y1 + nom * ry);
|
||||
}
|
||||
|
||||
public void reverse()
|
||||
{
|
||||
Point2D p = P1;
|
||||
P1 = P2;
|
||||
P2 = p;
|
||||
}
|
||||
|
||||
public double[] first()
|
||||
{
|
||||
return new double[]{cp.getX(), cp.getY()};
|
||||
}
|
||||
|
||||
public double[] last()
|
||||
{
|
||||
return new double[]{cp.getX(), cp.getY()};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/* RasterGraphics.java -- A Graphics2D impl for Rasters
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.java2d;
|
||||
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.WritableRaster;
|
||||
|
||||
/**
|
||||
* A Graphics2D implementation that operates on Raster objects. This is
|
||||
* primarily used for BufferedImages, but can theoretically be used on
|
||||
* arbitrary WritableRasters.
|
||||
*
|
||||
* @author Roman Kennke (kennke@aicas.com)
|
||||
*/
|
||||
public class RasterGraphics
|
||||
extends AbstractGraphics2D
|
||||
{
|
||||
|
||||
/**
|
||||
* The raster on which we operate.
|
||||
*/
|
||||
private WritableRaster raster;
|
||||
|
||||
/**
|
||||
* The color model of this Graphics instance.
|
||||
*/
|
||||
private ColorModel colorModel;
|
||||
|
||||
public RasterGraphics(WritableRaster r, ColorModel cm)
|
||||
{
|
||||
raster = r;
|
||||
colorModel = cm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color model of this Graphics object.
|
||||
*
|
||||
* @return the color model of this Graphics object
|
||||
*/
|
||||
protected ColorModel getColorModel()
|
||||
{
|
||||
return colorModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a WritableRaster that is used by this class to perform the
|
||||
* rendering in. It is not necessary that the target surface immediately
|
||||
* reflects changes in the raster. Updates to the raster are notified via
|
||||
* {@link AbstractGraphics2D#updateRaster}.
|
||||
*
|
||||
* @return the destination raster
|
||||
*/
|
||||
protected WritableRaster getDestinationRaster()
|
||||
{
|
||||
return raster;
|
||||
}
|
||||
|
||||
public GraphicsConfiguration getDeviceConfiguration()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/* Segment.java -- Abstract segment used for BasicStroke
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.java2d;
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
public abstract class Segment implements Cloneable
|
||||
{
|
||||
// segment type, PathIterator segment types are used.
|
||||
public Point2D P1;
|
||||
public Point2D P2;
|
||||
public Segment next;
|
||||
public Segment last;
|
||||
protected double radius;
|
||||
|
||||
public Segment()
|
||||
{
|
||||
P1 = P2 = null;
|
||||
next = null;
|
||||
last = this;
|
||||
}
|
||||
|
||||
public void add(Segment newsegment)
|
||||
{
|
||||
last.next = newsegment;
|
||||
last = last.next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverses the orientation of the whole polygon
|
||||
*/
|
||||
public void reverseAll()
|
||||
{
|
||||
reverse();
|
||||
Segment v = next;
|
||||
Segment former = this;
|
||||
next = null;
|
||||
|
||||
while (v != null)
|
||||
{
|
||||
v.reverse();
|
||||
v.last = this;
|
||||
Segment oldnext = v.next;
|
||||
v.next = former;
|
||||
|
||||
former = v;
|
||||
v = oldnext; // move to the next in list
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "Segment:"+P1+", "+P2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the normal vector to the slope of the line.
|
||||
* Returns: 0.5*width*(norm of derivative of the (x0,y0)-(x1,y1) vector)
|
||||
*/
|
||||
protected double[] normal(double x0, double y0, double x1, double y1)
|
||||
{
|
||||
double dx = (x1 - x0);
|
||||
double dy = (y1 - y0);
|
||||
if( dy == 0 )
|
||||
{
|
||||
dy = radius * ((dx > 0)?1:-1);
|
||||
dx = 0;
|
||||
}
|
||||
else if( dx == 0 )
|
||||
{
|
||||
dx = radius * ((dy > 0)?-1:1);
|
||||
dy = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
double N = Math.sqrt(dx * dx + dy * dy);
|
||||
double odx = dx;
|
||||
dx = -radius * dy / N;
|
||||
dy = radius * odx / N;
|
||||
}
|
||||
return new double[]{ dx, dy };
|
||||
}
|
||||
|
||||
public abstract void reverse();
|
||||
|
||||
/**
|
||||
* Get the "top" and "bottom" segments of a segment.
|
||||
* First array element is p0 + normal, second is p0 - normal.
|
||||
*/
|
||||
public abstract Segment[] getDisplacedSegments(double radius);
|
||||
|
||||
public abstract double[] first();
|
||||
public abstract double[] last();
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/* GLightweightPeer.java --
|
||||
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
@@ -54,11 +54,14 @@ import java.awt.Insets;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.PaintEvent;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.awt.image.ImageProducer;
|
||||
import java.awt.image.VolatileImage;
|
||||
import java.awt.peer.ComponentPeer;
|
||||
import java.awt.peer.ContainerPeer;
|
||||
import java.awt.peer.LightweightPeer;
|
||||
|
||||
@@ -79,7 +82,7 @@ import java.awt.peer.LightweightPeer;
|
||||
* Lightweight components are painted directly onto their parent
|
||||
* containers through an Image object provided by the toolkit.
|
||||
*/
|
||||
public class GLightweightPeer
|
||||
public class GLightweightPeer
|
||||
implements LightweightPeer, ContainerPeer
|
||||
{
|
||||
private Component comp;
|
||||
@@ -247,7 +250,25 @@ public class GLightweightPeer
|
||||
|
||||
public void setBounds(int x, int y, int width, int height) {}
|
||||
|
||||
public void setCursor(Cursor cursor) {}
|
||||
/**
|
||||
* Sets the cursor on the heavy-weight parent peer.
|
||||
* Called by the MouseListener on mouse enter.
|
||||
*/
|
||||
public void setCursor(Cursor cursor)
|
||||
{
|
||||
Component p = comp.getParent();
|
||||
while (p != null && p.isLightweight())
|
||||
p = p.getParent();
|
||||
|
||||
if (p != null)
|
||||
{
|
||||
// Don't actually change the cursor of the component
|
||||
// otherwise other childs inherit this cursor.
|
||||
ComponentPeer peer = p.getPeer();
|
||||
if (peer != null)
|
||||
peer.setCursor(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {}
|
||||
|
||||
|
||||
@@ -110,14 +110,10 @@ public class GdkFontMetrics extends FontMetrics
|
||||
return stringWidth (new String (data, off, len));
|
||||
}
|
||||
|
||||
/*
|
||||
Sun's Motif implementation always returns 0 or 1 here (???), but
|
||||
going by the X11 man pages, it seems as though we should return
|
||||
font.ascent + font.descent.
|
||||
*/
|
||||
public int getLeading ()
|
||||
{
|
||||
return 1;
|
||||
// Sun always returns 0.
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getAscent ()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* GdkFontPeer.java -- Implements FontPeer with GTK+
|
||||
Copyright (C) 1999, 2004, 2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
@@ -43,6 +43,7 @@ import gnu.java.awt.peer.ClasspathFontPeer;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.font.LineMetrics;
|
||||
@@ -157,7 +158,7 @@ public class GdkFontPeer extends ClasspathFontPeer
|
||||
|
||||
public String getPostScriptName(Font font)
|
||||
{
|
||||
return null;
|
||||
return this.familyName;
|
||||
}
|
||||
|
||||
public boolean canDisplay (Font font, char c)
|
||||
@@ -301,7 +302,9 @@ public class GdkFontPeer extends ClasspathFontPeer
|
||||
|
||||
public FontMetrics getFontMetrics (Font font)
|
||||
{
|
||||
return new GdkFontMetrics (font);
|
||||
// Get the font metrics through GtkToolkit to take advantage of
|
||||
// the metrics cache.
|
||||
return Toolkit.getDefaultToolkit().getFontMetrics (font);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
|
||||
@@ -218,8 +219,10 @@ public class GdkGraphics extends Graphics
|
||||
public boolean drawImage (Image img, int x, int y,
|
||||
Color bgcolor, ImageObserver observer)
|
||||
{
|
||||
return drawImage(img, x, y, img.getWidth(null), img.getHeight(null),
|
||||
bgcolor, observer);
|
||||
if (img != null)
|
||||
return drawImage(img, x, y, img.getWidth(null), img.getHeight(null),
|
||||
bgcolor, observer);
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean drawImage (Image img, int x, int y, ImageObserver observer)
|
||||
@@ -227,16 +230,19 @@ public class GdkGraphics extends Graphics
|
||||
return drawImage (img, x, y, null, observer);
|
||||
}
|
||||
|
||||
public boolean drawImage (Image img, int x, int y, int width, int height,
|
||||
Color bgcolor, ImageObserver observer)
|
||||
public boolean drawImage(Image img, int x, int y, int width, int height,
|
||||
Color bgcolor, ImageObserver observer)
|
||||
{
|
||||
if (img instanceof GtkImage)
|
||||
return ((GtkImage)img).drawImage (this, x, y, width, height,
|
||||
bgcolor, observer);
|
||||
else
|
||||
return (new GtkImage(img.getSource())).drawImage (this, x, y,
|
||||
width, height,
|
||||
bgcolor, observer);
|
||||
if (img != null)
|
||||
{
|
||||
if (img instanceof GtkImage)
|
||||
return ((GtkImage) img).drawImage(this, x, y, width, height, bgcolor,
|
||||
observer);
|
||||
return (new GtkImage(img.getSource())).drawImage(this, x, y, width,
|
||||
height, bgcolor,
|
||||
observer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean drawImage (Image img, int x, int y, int width, int height,
|
||||
@@ -249,14 +255,16 @@ public class GdkGraphics extends Graphics
|
||||
int sx1, int sy1, int sx2, int sy2,
|
||||
Color bgcolor, ImageObserver observer)
|
||||
{
|
||||
if (img instanceof GtkImage)
|
||||
return ((GtkImage)img).drawImage(this, dx1, dy1, dx2, dy2,
|
||||
sx1, sy1, sx2, sy2, bgcolor, observer);
|
||||
else
|
||||
return (new GtkImage(img.getSource())).drawImage(this, dx1, dy1,
|
||||
dx2, dy2,
|
||||
sx1, sy1, sx2, sy2,
|
||||
bgcolor, observer);
|
||||
if (img != null)
|
||||
{
|
||||
if (img instanceof GtkImage)
|
||||
return ((GtkImage) img).drawImage(this, dx1, dy1, dx2, dy2, sx1, sy1,
|
||||
sx2, sy2, bgcolor, observer);
|
||||
return (new GtkImage(img.getSource())).drawImage(this, dx1, dy1, dx2,
|
||||
dy2, sx1, sy1, sx2,
|
||||
sy2, bgcolor, observer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean drawImage (Image img, int dx1, int dy1, int dx2, int dy2,
|
||||
@@ -373,7 +381,9 @@ public class GdkGraphics extends Graphics
|
||||
|
||||
public FontMetrics getFontMetrics (Font font)
|
||||
{
|
||||
return new GdkFontMetrics (font);
|
||||
// Get the font metrics through GtkToolkit to take advantage of
|
||||
// the metrics cache.
|
||||
return Toolkit.getDefaultToolkit().getFontMetrics (font);
|
||||
}
|
||||
|
||||
native void setClipRectangle (int x, int y, int width, int height);
|
||||
|
||||
@@ -1229,7 +1229,10 @@ public class GdkGraphics2D extends Graphics2D
|
||||
drawPixels(pixels, r.getWidth(), r.getHeight(), r.getWidth(), i2u);
|
||||
|
||||
updateBufferedImage();
|
||||
|
||||
|
||||
// Cairo seems loosing the current color.
|
||||
setColor(fg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* GdkPixbufDecoder.java -- Image data decoding object
|
||||
Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
@@ -82,6 +82,14 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
|
||||
initStaticState ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock that should be held for all gdkpixbuf operations. We don't use
|
||||
* the global gdk_threads_enter/leave functions since gdkpixbuf
|
||||
* operations can be done in parallel to drawing and manipulating gtk
|
||||
* widgets.
|
||||
*/
|
||||
static Object pixbufLock = new Object();
|
||||
|
||||
static native void initStaticState();
|
||||
private final int native_state = GtkGenericPeer.getUniqueInteger ();
|
||||
|
||||
@@ -92,6 +100,7 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
|
||||
Vector curr;
|
||||
|
||||
// interface to GdkPixbuf
|
||||
// These native functions should be called with the pixbufLock held.
|
||||
native void initState ();
|
||||
native void pumpBytes (byte[] bytes, int len) throws IOException;
|
||||
native void pumpDone () throws IOException;
|
||||
@@ -171,11 +180,26 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
|
||||
|
||||
byte bytes[] = new byte[4096];
|
||||
int len = 0;
|
||||
initState();
|
||||
synchronized(pixbufLock)
|
||||
{
|
||||
initState();
|
||||
}
|
||||
needsClose = true;
|
||||
|
||||
// Note: We don't want the pixbufLock while reading from the InputStream.
|
||||
while ((len = is.read (bytes)) != -1)
|
||||
pumpBytes (bytes, len);
|
||||
pumpDone();
|
||||
{
|
||||
synchronized(pixbufLock)
|
||||
{
|
||||
pumpBytes (bytes, len);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized(pixbufLock)
|
||||
{
|
||||
pumpDone();
|
||||
}
|
||||
|
||||
needsClose = false;
|
||||
|
||||
for (int i = 0; i < curr.size (); i++)
|
||||
@@ -189,7 +213,10 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
|
||||
|
||||
public void finalize()
|
||||
{
|
||||
finish(needsClose);
|
||||
synchronized(pixbufLock)
|
||||
{
|
||||
finish(needsClose);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -495,8 +522,11 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
|
||||
}
|
||||
|
||||
processImageStarted(1);
|
||||
streamImage(pixels, this.ext, width, height, model.hasAlpha(),
|
||||
(DataOutput) this.getOutput());
|
||||
synchronized(pixbufLock)
|
||||
{
|
||||
streamImage(pixels, this.ext, width, height, model.hasAlpha(),
|
||||
(DataOutput) this.getOutput());
|
||||
}
|
||||
processImageComplete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,61 +38,22 @@ exception statement from your version. */
|
||||
|
||||
package gnu.java.awt.peer.gtk;
|
||||
|
||||
import java.awt.AWTEvent;
|
||||
import java.awt.Canvas;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.event.PaintEvent;
|
||||
import java.awt.peer.CanvasPeer;
|
||||
|
||||
public class GtkCanvasPeer extends GtkComponentPeer implements CanvasPeer
|
||||
{
|
||||
native void create ();
|
||||
native void realize ();
|
||||
|
||||
public GtkCanvasPeer (Canvas c)
|
||||
{
|
||||
super (c);
|
||||
}
|
||||
|
||||
public Graphics getGraphics ()
|
||||
{
|
||||
if (GtkToolkit.useGraphics2D ())
|
||||
return new GdkGraphics2D (this);
|
||||
else
|
||||
return new GdkGraphics (this);
|
||||
}
|
||||
|
||||
public void handleEvent (AWTEvent event)
|
||||
{
|
||||
int id = event.getID();
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case PaintEvent.PAINT:
|
||||
case PaintEvent.UPDATE:
|
||||
{
|
||||
try
|
||||
{
|
||||
Graphics g = getGraphics ();
|
||||
g.setClip (((PaintEvent)event).getUpdateRect());
|
||||
|
||||
if (id == PaintEvent.PAINT)
|
||||
awtComponent.paint (g);
|
||||
else
|
||||
awtComponent.update (g);
|
||||
|
||||
g.dispose ();
|
||||
}
|
||||
catch (InternalError e)
|
||||
{
|
||||
System.err.println (e);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Preferred size for a drawing widget is always what the user requested */
|
||||
// Preferred size for a drawing widget is always what the user
|
||||
// requested.
|
||||
public Dimension getPreferredSize ()
|
||||
{
|
||||
return awtComponent.getSize ();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* GtkClipboard.java
|
||||
Copyright (C) 1999, 2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999, 2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
@@ -48,59 +48,85 @@ import java.util.Iterator;
|
||||
|
||||
public class GtkClipboard extends Clipboard
|
||||
{
|
||||
/**
|
||||
* The one and only gtk+ clipboard instance for the CLIPBOARD selection.
|
||||
*/
|
||||
final static GtkClipboard clipboard = new GtkClipboard("System Clipboard");
|
||||
|
||||
/**
|
||||
* The one and only gtk+ clipboard instance for the PRIMARY selection.
|
||||
*/
|
||||
final static GtkClipboard selection = new GtkClipboard("System Selection");
|
||||
|
||||
// Given to the native side so it can signal special targets that
|
||||
// can be converted to one of the special predefined DataFlavors.
|
||||
static final String stringMimeType;
|
||||
static final String imageMimeType;
|
||||
static final String filesMimeType;
|
||||
static final String stringMimeType
|
||||
= DataFlavor.stringFlavor.getMimeType();
|
||||
static final String imageMimeType
|
||||
= DataFlavor.imageFlavor.getMimeType();
|
||||
static final String filesMimeType
|
||||
= DataFlavor.javaFileListFlavor.getMimeType();
|
||||
|
||||
// Indicates whether the results of the clipboard selection can be
|
||||
// cached by GtkSelection. True if
|
||||
// gdk_display_supports_selection_notification.
|
||||
static final boolean canCache;
|
||||
|
||||
static
|
||||
{
|
||||
stringMimeType = DataFlavor.stringFlavor.getMimeType();
|
||||
imageMimeType = DataFlavor.imageFlavor.getMimeType();
|
||||
filesMimeType = DataFlavor.javaFileListFlavor.getMimeType();
|
||||
|
||||
canCache = initNativeState(stringMimeType, imageMimeType, filesMimeType);
|
||||
}
|
||||
|
||||
/**
|
||||
* The one and only gtk+ clipboard instance.
|
||||
*/
|
||||
private static GtkClipboard instance = new GtkClipboard();
|
||||
static final boolean canCache = initNativeState(clipboard, selection,
|
||||
stringMimeType,
|
||||
imageMimeType,
|
||||
filesMimeType);
|
||||
|
||||
/**
|
||||
* Creates the clipboard and sets the initial contents to the
|
||||
* current gtk+ selection.
|
||||
*/
|
||||
private GtkClipboard()
|
||||
private GtkClipboard(String name)
|
||||
{
|
||||
super("System Clipboard");
|
||||
setContents(new GtkSelection(), null);
|
||||
super(name);
|
||||
setContents(new GtkSelection(this), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the one and only GtkClipboard instance.
|
||||
* Returns the one and only GtkClipboard instance for the CLIPBOARD
|
||||
* selection.
|
||||
*/
|
||||
|
||||
static GtkClipboard getInstance()
|
||||
static GtkClipboard getClipboardInstance()
|
||||
{
|
||||
return instance;
|
||||
return clipboard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the one and only GtkClipboard instance for the PRIMARY
|
||||
* selection.
|
||||
*/
|
||||
static GtkClipboard getSelectionInstance()
|
||||
{
|
||||
return selection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the GtkSelection facade as new contents of the clipboard.
|
||||
* Called from gtk+ when another application grabs the clipboard and
|
||||
* we loose ownership.
|
||||
*
|
||||
* @param cleared If true this is a clear event (someone takes the
|
||||
* clipboard from us) otherwise it is an owner changed event.
|
||||
*/
|
||||
private static void setSystemContents()
|
||||
private synchronized void setSystemContents(boolean cleared)
|
||||
{
|
||||
GtkClipboardNotifier.announce();
|
||||
// We need to notify clipboard owner listeners when we were the
|
||||
// owner (the selection was explictly set) and someone takes the
|
||||
// clipboard away from us and asks us the clear any held storage,
|
||||
// or if we weren't the owner of the clipboard to begin with, but
|
||||
// the clipboard contents changed. We could refine this and check
|
||||
// whether the actual available formats did in fact change, but we
|
||||
// assume listeners will check for that anyway (and if possible we
|
||||
// ask to cache the available formats so even if multiple
|
||||
// listeners check after a notification the overhead should be
|
||||
// minimal).
|
||||
boolean owner = ! (contents instanceof GtkSelection);
|
||||
boolean needNotification = (cleared && owner) || (! cleared && ! owner);
|
||||
if (needNotification)
|
||||
GtkClipboardNotifier.announce(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,15 +172,12 @@ public class GtkClipboard extends Clipboard
|
||||
|| flavor.isRepresentationClassReader())
|
||||
text = true;
|
||||
|
||||
// XXX - We only support automatic image conversion for
|
||||
// GtkImages at the moment. So explicitly check that we have
|
||||
// one.
|
||||
if (! images && flavors[i].equals(DataFlavor.imageFlavor))
|
||||
{
|
||||
try
|
||||
{
|
||||
Object o = contents.getTransferData(DataFlavor.imageFlavor);
|
||||
if (o instanceof GtkImage)
|
||||
if (o instanceof Image)
|
||||
images = true;
|
||||
}
|
||||
catch (UnsupportedFlavorException ufe)
|
||||
@@ -265,7 +288,11 @@ public class GtkClipboard extends Clipboard
|
||||
|
||||
try
|
||||
{
|
||||
return (GtkImage) contents.getTransferData(DataFlavor.imageFlavor);
|
||||
Object o = contents.getTransferData(DataFlavor.imageFlavor);
|
||||
if( o instanceof GtkImage )
|
||||
return (GtkImage) o;
|
||||
else
|
||||
return new GtkImage(((Image)o).getSource());
|
||||
}
|
||||
catch (UnsupportedFlavorException ufe)
|
||||
{
|
||||
@@ -384,11 +411,13 @@ public class GtkClipboard extends Clipboard
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the gtk+ clipboard and caches any native side
|
||||
* Initializes the gtk+ clipboards and caches any native side
|
||||
* structures needed. Returns whether or not the contents of the
|
||||
* Clipboard can be cached (gdk_display_supports_selection_notification).
|
||||
*/
|
||||
private static native boolean initNativeState(String stringTarget,
|
||||
private static native boolean initNativeState(GtkClipboard clipboard,
|
||||
GtkClipboard selection,
|
||||
String stringTarget,
|
||||
String imageTarget,
|
||||
String filesTarget);
|
||||
}
|
||||
|
||||
@@ -39,11 +39,15 @@ exception statement from your version. */
|
||||
package gnu.java.awt.peer.gtk;
|
||||
|
||||
import java.awt.datatransfer.*;
|
||||
import java.util.*;
|
||||
|
||||
class GtkClipboardNotifier extends Thread
|
||||
{
|
||||
/** Whether or not to announce a GtkSelection change. */
|
||||
private static boolean announceChange;
|
||||
/** Whether to announce a new GtkSelection has been set for CLIPBOARD. */
|
||||
static private boolean announceClipboardChange;
|
||||
|
||||
/** Whether to announce a new GtkSelection has been set for PRIMARY. */
|
||||
static private boolean announcePrimaryChange;
|
||||
|
||||
/**
|
||||
* The one and only instance. All operations are synchronized on
|
||||
@@ -64,24 +68,30 @@ class GtkClipboardNotifier extends Thread
|
||||
|
||||
/**
|
||||
* Notifies that a new GtkSelection has to be announced.
|
||||
*
|
||||
* @param clipboard either the GtkClipboard.clipboard or the
|
||||
* GtkClipboard.selection.
|
||||
*/
|
||||
static void announce()
|
||||
static void announce(GtkClipboard clipboard)
|
||||
{
|
||||
synchronized (notifier)
|
||||
{
|
||||
announceChange = true;
|
||||
if (clipboard == GtkClipboard.clipboard)
|
||||
announceClipboardChange = true;
|
||||
else
|
||||
announcePrimaryChange = true;
|
||||
notifier.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
final GtkClipboard clipboard = GtkClipboard.getInstance();
|
||||
GtkClipboard clipboard;
|
||||
while (true)
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
while (!announceChange)
|
||||
while (! announceClipboardChange && ! announcePrimaryChange)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -92,14 +102,24 @@ class GtkClipboardNotifier extends Thread
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
announceChange = false;
|
||||
|
||||
if (announceClipboardChange)
|
||||
{
|
||||
clipboard = GtkClipboard.clipboard;
|
||||
announceClipboardChange = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
clipboard = GtkClipboard.selection;
|
||||
announcePrimaryChange = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Do the actual announcement without the lock held. We will
|
||||
// notice a new change after this notification has finished.
|
||||
try
|
||||
{
|
||||
clipboard.setContents(new GtkSelection(), null);
|
||||
clipboard.setContents(new GtkSelection(clipboard), null);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
|
||||
@@ -63,6 +63,7 @@ import java.awt.event.FocusEvent;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.event.PaintEvent;
|
||||
import java.awt.event.TextEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
@@ -86,8 +87,6 @@ public class GtkComponentPeer extends GtkGenericPeer
|
||||
|
||||
Insets insets;
|
||||
|
||||
boolean isInRepaint;
|
||||
|
||||
/* this isEnabled differs from Component.isEnabled, in that it
|
||||
knows if a parent is disabled. In that case Component.isEnabled
|
||||
may return true, but our isEnabled will always return false */
|
||||
@@ -100,8 +99,9 @@ public class GtkComponentPeer extends GtkGenericPeer
|
||||
native void gtkWidgetGetPreferredDimensions (int[] dim);
|
||||
native void gtkWindowGetLocationOnScreen (int[] point);
|
||||
native void gtkWidgetGetLocationOnScreen (int[] point);
|
||||
native void gtkWidgetSetCursor (int type);
|
||||
native void gtkWidgetSetCursorUnlocked (int type);
|
||||
native void gtkWidgetSetCursor (int type, GtkImage image, int x, int y);
|
||||
native void gtkWidgetSetCursorUnlocked (int type, GtkImage image,
|
||||
int x, int y);
|
||||
native void gtkWidgetSetBackground (int red, int green, int blue);
|
||||
native void gtkWidgetSetForeground (int red, int green, int blue);
|
||||
native void gtkWidgetSetSensitive (boolean sensitive);
|
||||
@@ -150,6 +150,9 @@ public class GtkComponentPeer extends GtkGenericPeer
|
||||
setNativeEventMask ();
|
||||
|
||||
realize ();
|
||||
|
||||
if (awtComponent.isCursorSet())
|
||||
setCursor ();
|
||||
}
|
||||
|
||||
void setParentAndBounds ()
|
||||
@@ -176,16 +179,6 @@ public class GtkComponentPeer extends GtkGenericPeer
|
||||
gtkWidgetSetParent (p);
|
||||
}
|
||||
|
||||
void beginNativeRepaint ()
|
||||
{
|
||||
isInRepaint = true;
|
||||
}
|
||||
|
||||
void endNativeRepaint ()
|
||||
{
|
||||
isInRepaint = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the bounds of this peer's AWT Component based on dimensions
|
||||
* returned by the native windowing system. Most Components impose
|
||||
@@ -250,6 +243,8 @@ public class GtkComponentPeer extends GtkGenericPeer
|
||||
return getToolkit().getFontMetrics(font);
|
||||
}
|
||||
|
||||
// getGraphics may be overridden by derived classes but it should
|
||||
// never return null.
|
||||
public Graphics getGraphics ()
|
||||
{
|
||||
if (GtkToolkit.useGraphics2D ())
|
||||
@@ -291,30 +286,10 @@ public class GtkComponentPeer extends GtkGenericPeer
|
||||
switch (id)
|
||||
{
|
||||
case PaintEvent.PAINT:
|
||||
paintComponent((PaintEvent) event);
|
||||
break;
|
||||
case PaintEvent.UPDATE:
|
||||
{
|
||||
try
|
||||
{
|
||||
Graphics g = getGraphics();
|
||||
|
||||
if (!awtComponent.isShowing() || awtComponent.getWidth() < 1
|
||||
|| awtComponent.getHeight() < 1 || g == null)
|
||||
break;
|
||||
|
||||
g.setClip(((PaintEvent) event).getUpdateRect());
|
||||
|
||||
if (id == PaintEvent.PAINT)
|
||||
awtComponent.paint(g);
|
||||
else
|
||||
awtComponent.update(g);
|
||||
|
||||
g.dispose();
|
||||
}
|
||||
catch (InternalError e)
|
||||
{
|
||||
System.err.println(e);
|
||||
}
|
||||
}
|
||||
updateComponent((PaintEvent) event);
|
||||
break;
|
||||
case KeyEvent.KEY_PRESSED:
|
||||
ke = (KeyEvent) event;
|
||||
@@ -328,7 +303,49 @@ public class GtkComponentPeer extends GtkGenericPeer
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This method and its overrides are the only methods in the peers
|
||||
// that should call awtComponent.paint.
|
||||
protected void paintComponent (PaintEvent event)
|
||||
{
|
||||
// Do not call Component.paint if the component is not showing or
|
||||
// if its bounds form a degenerate rectangle.
|
||||
if (!awtComponent.isShowing()
|
||||
|| (awtComponent.getWidth() < 1 || awtComponent.getHeight() < 1))
|
||||
return;
|
||||
|
||||
// Creating and disposing a GdkGraphics every time paint is called
|
||||
// seems expensive. However, the graphics state does not carry
|
||||
// over between calls to paint, and resetting the graphics object
|
||||
// may even be more costly than simply creating a new one.
|
||||
Graphics g = getGraphics();
|
||||
|
||||
g.setClip(event.getUpdateRect());
|
||||
|
||||
awtComponent.paint(g);
|
||||
|
||||
g.dispose();
|
||||
}
|
||||
|
||||
// This method and its overrides are the only methods in the peers
|
||||
// that should call awtComponent.update.
|
||||
protected void updateComponent (PaintEvent event)
|
||||
{
|
||||
// Do not call Component.update if the component is not showing or
|
||||
// if its bounds form a degenerate rectangle.
|
||||
if (!awtComponent.isShowing()
|
||||
|| (awtComponent.getWidth() < 1 || awtComponent.getHeight() < 1))
|
||||
return;
|
||||
|
||||
Graphics g = getGraphics();
|
||||
|
||||
g.setClip(event.getUpdateRect());
|
||||
|
||||
awtComponent.update(g);
|
||||
|
||||
g.dispose();
|
||||
}
|
||||
|
||||
public boolean isFocusTraversable ()
|
||||
{
|
||||
return true;
|
||||
@@ -369,7 +386,7 @@ public class GtkComponentPeer extends GtkGenericPeer
|
||||
|
||||
public void repaint (long tm, int x, int y, int width, int height)
|
||||
{
|
||||
if (x == 0 && y == 0 && width == 0 && height == 0)
|
||||
if (width < 1 || height < 1)
|
||||
return;
|
||||
|
||||
if (tm <= 0)
|
||||
@@ -490,10 +507,28 @@ public class GtkComponentPeer extends GtkGenericPeer
|
||||
|
||||
public void setCursor (Cursor cursor)
|
||||
{
|
||||
if (Thread.currentThread() == GtkToolkit.mainThread)
|
||||
gtkWidgetSetCursorUnlocked (cursor.getType ());
|
||||
int x, y;
|
||||
GtkImage image;
|
||||
int type = cursor.getType();
|
||||
if (cursor instanceof GtkCursor)
|
||||
{
|
||||
GtkCursor gtkCursor = (GtkCursor) cursor;
|
||||
image = gtkCursor.getGtkImage();
|
||||
Point hotspot = gtkCursor.getHotspot();
|
||||
x = hotspot.x;
|
||||
y = hotspot.y;
|
||||
}
|
||||
else
|
||||
gtkWidgetSetCursor (cursor.getType ());
|
||||
{
|
||||
image = null;
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if (Thread.currentThread() == GtkToolkit.mainThread)
|
||||
gtkWidgetSetCursorUnlocked(cursor.getType(), image, x, y);
|
||||
else
|
||||
gtkWidgetSetCursor(cursor.getType(), image, x, y);
|
||||
}
|
||||
|
||||
public void setEnabled (boolean b)
|
||||
@@ -532,7 +567,7 @@ public class GtkComponentPeer extends GtkGenericPeer
|
||||
public void setVisible (boolean b)
|
||||
{
|
||||
// Only really set visible when component is bigger than zero pixels.
|
||||
if (b)
|
||||
if (b && ! (awtComponent instanceof Window))
|
||||
{
|
||||
Rectangle bounds = awtComponent.getBounds();
|
||||
b = (bounds.width > 0) && (bounds.height > 0);
|
||||
@@ -561,10 +596,22 @@ public class GtkComponentPeer extends GtkGenericPeer
|
||||
clickCount, popupTrigger));
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for component_scroll_cb.
|
||||
*/
|
||||
protected void postMouseWheelEvent(int id, long when, int mods,
|
||||
int x, int y, int clickCount,
|
||||
boolean popupTrigger,
|
||||
int type, int amount, int rotation)
|
||||
{
|
||||
q().postEvent(new MouseWheelEvent(awtComponent, id, when, mods,
|
||||
x, y, clickCount, popupTrigger,
|
||||
type, amount, rotation));
|
||||
}
|
||||
|
||||
protected void postExposeEvent (int x, int y, int width, int height)
|
||||
{
|
||||
if (!isInRepaint)
|
||||
q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT,
|
||||
q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT,
|
||||
new Rectangle (x, y, width, height)));
|
||||
}
|
||||
|
||||
|
||||
@@ -99,11 +99,6 @@ public class GtkContainerPeer extends GtkComponentPeer
|
||||
}
|
||||
}
|
||||
|
||||
public Graphics getGraphics ()
|
||||
{
|
||||
return super.getGraphics();
|
||||
}
|
||||
|
||||
public void beginLayout () { }
|
||||
public void endLayout () { }
|
||||
public boolean isPaintPending () { return false; }
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/* GtkCursor.java -- Simple wrapper for custom cursor.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.peer.gtk;
|
||||
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Image;
|
||||
import java.awt.Point;
|
||||
|
||||
/**
|
||||
* Simple wrapper for custom Cursor.
|
||||
*/
|
||||
public class GtkCursor extends Cursor
|
||||
{
|
||||
private final GtkImage image;
|
||||
private final Point hotspot;
|
||||
|
||||
GtkCursor(Image image, Point hotspot, String name)
|
||||
{
|
||||
super(name);
|
||||
if (image instanceof GtkImage)
|
||||
this.image = (GtkImage) image;
|
||||
else
|
||||
this.image = new GtkImage(image.getSource());
|
||||
this.hotspot = hotspot;
|
||||
}
|
||||
|
||||
GtkImage getGtkImage()
|
||||
{
|
||||
return image;
|
||||
}
|
||||
|
||||
Point getHotspot()
|
||||
{
|
||||
return hotspot;
|
||||
}
|
||||
}
|
||||
@@ -51,34 +51,6 @@ public class GtkDialogPeer extends GtkWindowPeer
|
||||
{
|
||||
super (dialog);
|
||||
}
|
||||
|
||||
public Graphics getGraphics ()
|
||||
{
|
||||
Graphics g;
|
||||
if (GtkToolkit.useGraphics2D ())
|
||||
g = new GdkGraphics2D (this);
|
||||
else
|
||||
g = new GdkGraphics (this);
|
||||
g.translate (-insets.left, -insets.top);
|
||||
return g;
|
||||
}
|
||||
|
||||
protected void postMouseEvent(int id, long when, int mods, int x, int y,
|
||||
int clickCount, boolean popupTrigger)
|
||||
{
|
||||
super.postMouseEvent (id, when, mods,
|
||||
x + insets.left, y + insets.top,
|
||||
clickCount, popupTrigger);
|
||||
}
|
||||
|
||||
protected void postExposeEvent (int x, int y, int width, int height)
|
||||
{
|
||||
if (!isInRepaint)
|
||||
q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT,
|
||||
new Rectangle (x + insets.left,
|
||||
y + insets.top,
|
||||
width, height)));
|
||||
}
|
||||
|
||||
void create ()
|
||||
{
|
||||
|
||||
@@ -41,6 +41,7 @@ package gnu.java.awt.peer.gtk;
|
||||
import java.awt.Dialog;
|
||||
import java.awt.FileDialog;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.event.PaintEvent;
|
||||
import java.awt.peer.FileDialogPeer;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
@@ -166,10 +167,10 @@ public class GtkFileDialogPeer extends GtkDialogPeer implements FileDialogPeer
|
||||
return filter.accept(dir, filename);
|
||||
}
|
||||
|
||||
public Graphics getGraphics ()
|
||||
// Sun does not call FileDialog.update.
|
||||
protected void updateComponent (PaintEvent event)
|
||||
{
|
||||
// GtkFileDialog will repaint by itself
|
||||
return null;
|
||||
// Override GtkComponetPeer.updateComponent to do nothing.
|
||||
}
|
||||
|
||||
// called back by native side: handle_response_cb
|
||||
|
||||
@@ -1,225 +0,0 @@
|
||||
/* GtkFontPeer.java -- Implements FontPeer with GTK+
|
||||
Copyright (C) 1999, 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.awt.peer.gtk;
|
||||
|
||||
import gnu.java.awt.peer.ClasspathFontPeer;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.font.LineMetrics;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.text.CharacterIterator;
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class GtkFontPeer extends ClasspathFontPeer
|
||||
{
|
||||
private static ResourceBundle bundle;
|
||||
|
||||
static
|
||||
{
|
||||
try
|
||||
{
|
||||
bundle = ResourceBundle.getBundle ("gnu.java.awt.peer.gtk.font");
|
||||
}
|
||||
catch (Throwable ignored)
|
||||
{
|
||||
bundle = null;
|
||||
}
|
||||
}
|
||||
|
||||
private final String Xname;
|
||||
|
||||
public GtkFontPeer (String name, int style)
|
||||
{
|
||||
// All fonts get a default size of 12 if size is not specified.
|
||||
this(name, style, 12);
|
||||
}
|
||||
|
||||
public GtkFontPeer (String name, int style, int size)
|
||||
{
|
||||
super(name, style, size);
|
||||
|
||||
String Xname = null;
|
||||
if (bundle != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Xname = bundle.getString (name.toLowerCase () + "." + style);
|
||||
}
|
||||
catch (MissingResourceException mre)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
if (Xname == null)
|
||||
{
|
||||
String weight;
|
||||
String slant;
|
||||
String spacing;
|
||||
|
||||
if (style == Font.ITALIC || (style == (Font.BOLD+Font.ITALIC)))
|
||||
slant = "i";
|
||||
else
|
||||
slant = "r";
|
||||
if (style == Font.BOLD || (style == (Font.BOLD+Font.ITALIC)))
|
||||
weight = "bold";
|
||||
else
|
||||
weight = "medium";
|
||||
if (name.equals("Serif") || name.equals("SansSerif")
|
||||
|| name.equals("Helvetica") || name.equals("Times"))
|
||||
spacing = "p";
|
||||
else
|
||||
spacing = "c";
|
||||
|
||||
Xname = "-*-*-" + weight + "-" + slant + "-normal-*-*-" + size + "-*-*-" + spacing + "-*-*-*";
|
||||
}
|
||||
|
||||
this.Xname = Xname;
|
||||
}
|
||||
|
||||
public String getXLFD ()
|
||||
{
|
||||
return Xname;
|
||||
}
|
||||
|
||||
|
||||
/* remaining methods are for static compatibility with the newer
|
||||
ClasspathFontPeer superclass; none of these methods ever existed or
|
||||
worked on the older FontPeer interface, but we need to pretend to
|
||||
support them anyways. */
|
||||
|
||||
public boolean canDisplay (Font font, char c)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public int canDisplayUpTo (Font font, CharacterIterator i, int start, int limit)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String getSubFamilyName (Font font, Locale locale)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String getPostScriptName (Font font)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public int getNumGlyphs (Font font)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public int getMissingGlyphCode (Font font)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public byte getBaselineFor (Font font, char c)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String getGlyphName (Font font, int glyphIndex)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public GlyphVector createGlyphVector (Font font,
|
||||
FontRenderContext frc,
|
||||
CharacterIterator ci)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public GlyphVector createGlyphVector (Font font,
|
||||
FontRenderContext ctx,
|
||||
int[] glyphCodes)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public GlyphVector layoutGlyphVector (Font font,
|
||||
FontRenderContext frc,
|
||||
char[] chars, int start,
|
||||
int limit, int flags)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public FontMetrics getFontMetrics (Font font)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean hasUniformLineMetrics (Font font)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public LineMetrics getLineMetrics (Font font,
|
||||
CharacterIterator ci,
|
||||
int begin, int limit,
|
||||
FontRenderContext rc)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Rectangle2D getMaxCharBounds (Font font,
|
||||
FontRenderContext rc)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Rectangle2D getStringBounds (Font font,
|
||||
CharacterIterator ci,
|
||||
int begin, int limit,
|
||||
FontRenderContext frc)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/* GtkFramePeer.java -- Implements FramePeer with GTK
|
||||
Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999, 2002, 2004, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
@@ -122,25 +122,11 @@ public class GtkFramePeer extends GtkWindowPeer
|
||||
|
||||
public void setBounds (int x, int y, int width, int height)
|
||||
{
|
||||
// prevent window_configure_cb -> awtComponent.setSize ->
|
||||
// peer.setBounds -> nativeSetBounds self-deadlock on GDK lock.
|
||||
if (Thread.currentThread() == GtkToolkit.mainThread)
|
||||
{
|
||||
int menuBarWidth = width - insets.left - insets.right;
|
||||
if (menuBar != null && menuBarWidth > 0)
|
||||
setMenuBarWidthUnlocked (menuBar, menuBarWidth);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int menuBarWidth = width - insets.left - insets.right;
|
||||
if (menuBar != null && menuBarWidth > 0)
|
||||
setMenuBarWidth (menuBar, menuBarWidth);
|
||||
|
||||
nativeSetBounds (x, y,
|
||||
width - insets.left - insets.right,
|
||||
height - insets.top - insets.bottom
|
||||
+ menuBarHeight);
|
||||
super.setBounds(x, y, width, height + menuBarHeight);
|
||||
}
|
||||
|
||||
public void setResizable (boolean resizable)
|
||||
@@ -196,56 +182,21 @@ public class GtkFramePeer extends GtkWindowPeer
|
||||
}
|
||||
}
|
||||
|
||||
public Graphics getGraphics ()
|
||||
{
|
||||
Graphics g;
|
||||
if (GtkToolkit.useGraphics2D ())
|
||||
g = new GdkGraphics2D (this);
|
||||
else
|
||||
g = new GdkGraphics (this);
|
||||
g.translate (-insets.left, -insets.top);
|
||||
return g;
|
||||
}
|
||||
|
||||
protected void postConfigureEvent (int x, int y, int width, int height)
|
||||
{
|
||||
int frame_width = width + insets.left + insets.right;
|
||||
if (menuBar != null && width > 0)
|
||||
setMenuBarWidthUnlocked (menuBar, width);
|
||||
|
||||
// Since insets.top already includes the MenuBar's height, we need
|
||||
// to subtract the MenuBar's height from the top inset.
|
||||
int frame_height = height + insets.top + insets.bottom - menuBarHeight;
|
||||
int frame_height = height - menuBarHeight;
|
||||
|
||||
if (frame_width != awtComponent.getWidth()
|
||||
|| frame_height != awtComponent.getHeight())
|
||||
awtComponent.setSize(frame_width, frame_height);
|
||||
|
||||
int frame_x = x - insets.left;
|
||||
// Likewise, since insets.top includes the MenuBar height, we need
|
||||
// to add back the MenuBar height to the frame's y position. If
|
||||
// no MenuBar exists in this frame, the MenuBar height will be 0.
|
||||
int frame_y = y - insets.top + menuBarHeight;
|
||||
int frame_y = y + menuBarHeight;
|
||||
|
||||
if (frame_x != awtComponent.getX()
|
||||
|| frame_y != awtComponent.getY())
|
||||
{
|
||||
// awtComponent.setLocation(frame_x, frame_y);
|
||||
}
|
||||
}
|
||||
|
||||
protected void postMouseEvent(int id, long when, int mods, int x, int y,
|
||||
int clickCount, boolean popupTrigger)
|
||||
{
|
||||
super.postMouseEvent (id, when, mods,
|
||||
x + insets.left, y + insets.top,
|
||||
clickCount, popupTrigger);
|
||||
}
|
||||
|
||||
protected void postExposeEvent (int x, int y, int width, int height)
|
||||
{
|
||||
if (!isInRepaint)
|
||||
q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT,
|
||||
new Rectangle (x + insets.left,
|
||||
y + insets.top,
|
||||
width, height)));
|
||||
super.postConfigureEvent(x, frame_y, width, frame_height);
|
||||
}
|
||||
|
||||
public int getState ()
|
||||
|
||||
@@ -123,41 +123,50 @@ public class GtkImage extends Image
|
||||
|
||||
/**
|
||||
* Returns a copy of the pixel data as a java array.
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
*/
|
||||
private native int[] getPixels();
|
||||
|
||||
/**
|
||||
* Sets the pixel data from a java array.
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
*/
|
||||
private native void setPixels(int[] pixels);
|
||||
|
||||
/**
|
||||
* Loads an image using gdk-pixbuf from a file.
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
*/
|
||||
private native boolean loadPixbuf(String name);
|
||||
|
||||
/**
|
||||
* Loads an image using gdk-pixbuf from data.
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
*/
|
||||
private native boolean loadImageFromData(byte[] data);
|
||||
|
||||
/**
|
||||
* Allocates a Gtk Pixbuf or pixmap
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
*/
|
||||
private native void createPixmap();
|
||||
|
||||
/**
|
||||
* Frees the above.
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
*/
|
||||
private native void freePixmap();
|
||||
|
||||
/**
|
||||
* Sets the pixmap to scaled copy of src image. hints are rendering hints.
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
*/
|
||||
private native void createScaledPixmap(GtkImage src, int hints);
|
||||
|
||||
/**
|
||||
* Draws the image, optionally scaled and composited.
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
* Also acquires global gdk lock for drawing.
|
||||
*/
|
||||
private native void drawPixelsScaled (GdkGraphics gc,
|
||||
int bg_red, int bg_green, int bg_blue,
|
||||
@@ -166,6 +175,8 @@ public class GtkImage extends Image
|
||||
|
||||
/**
|
||||
* Draws the image, optionally scaled flipped and composited.
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
* Also acquires global gdk lock for drawing.
|
||||
*/
|
||||
private native void drawPixelsScaledFlipped (GdkGraphics gc,
|
||||
int bg_red, int bg_green,
|
||||
@@ -219,12 +230,21 @@ public class GtkImage extends Image
|
||||
File f = new File(filename);
|
||||
try
|
||||
{
|
||||
if (loadPixbuf(f.getCanonicalPath()) != true)
|
||||
throw new IllegalArgumentException("Couldn't load image: "+filename);
|
||||
String path = f.getCanonicalPath();
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
if (loadPixbuf(f.getCanonicalPath()) != true)
|
||||
throw new IllegalArgumentException("Couldn't load image: "
|
||||
+ filename);
|
||||
}
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
throw new IllegalArgumentException("Couldn't load image: "+filename);
|
||||
IllegalArgumentException iae;
|
||||
iae = new IllegalArgumentException("Couldn't load image: "
|
||||
+ filename);
|
||||
iae.initCause(e);
|
||||
throw iae;
|
||||
}
|
||||
|
||||
isLoaded = true;
|
||||
@@ -241,8 +261,11 @@ public class GtkImage extends Image
|
||||
*/
|
||||
public GtkImage (byte[] data)
|
||||
{
|
||||
if (loadImageFromData (data) != true)
|
||||
throw new IllegalArgumentException ("Couldn't load image.");
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
if (loadImageFromData (data) != true)
|
||||
throw new IllegalArgumentException ("Couldn't load image.");
|
||||
}
|
||||
|
||||
isLoaded = true;
|
||||
observers = null;
|
||||
@@ -277,8 +300,12 @@ public class GtkImage extends Image
|
||||
{
|
||||
throw new IllegalArgumentException ("Couldn't load image.");
|
||||
}
|
||||
if (loadImageFromData (baos.toByteArray()) != true)
|
||||
throw new IllegalArgumentException ("Couldn't load image.");
|
||||
byte[] array = baos.toByteArray();
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
if (loadImageFromData(array) != true)
|
||||
throw new IllegalArgumentException ("Couldn't load image.");
|
||||
}
|
||||
|
||||
isLoaded = true;
|
||||
observers = null;
|
||||
@@ -296,7 +323,10 @@ public class GtkImage extends Image
|
||||
isLoaded = true;
|
||||
observers = null;
|
||||
offScreen = true;
|
||||
createPixmap();
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
createPixmap();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -312,7 +342,10 @@ public class GtkImage extends Image
|
||||
offScreen = false;
|
||||
|
||||
// Use the GDK scaling method.
|
||||
createScaledPixmap(src, hints);
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
createScaledPixmap(src, hints);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -322,7 +355,10 @@ public class GtkImage extends Image
|
||||
GtkImage (Pointer pixbuf)
|
||||
{
|
||||
pixmap = pixbuf;
|
||||
createFromPixbuf();
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
createFromPixbuf();
|
||||
}
|
||||
isLoaded = true;
|
||||
observers = null;
|
||||
offScreen = false;
|
||||
@@ -349,6 +385,7 @@ public class GtkImage extends Image
|
||||
|
||||
/**
|
||||
* Native helper function for constructor that takes a pixbuf Pointer.
|
||||
* Should be called with the GdkPixbufDecoder.pixbufLock held.
|
||||
*/
|
||||
private native void createFromPixbuf();
|
||||
|
||||
@@ -370,8 +407,11 @@ public class GtkImage extends Image
|
||||
|
||||
isLoaded = true;
|
||||
deliver();
|
||||
createPixmap();
|
||||
setPixels(pixels);
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
createPixmap();
|
||||
setPixels(pixels);
|
||||
}
|
||||
}
|
||||
|
||||
// java.awt.Image methods ////////////////////////////////////////////////
|
||||
@@ -408,7 +448,13 @@ public class GtkImage extends Image
|
||||
{
|
||||
if (!isLoaded)
|
||||
return null;
|
||||
return new MemoryImageSource(width, height, nativeModel, getPixels(),
|
||||
|
||||
int[] pixels;
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
pixels = getPixels();
|
||||
}
|
||||
return new MemoryImageSource(width, height, nativeModel, pixels,
|
||||
0, width);
|
||||
}
|
||||
|
||||
@@ -454,7 +500,10 @@ public class GtkImage extends Image
|
||||
{
|
||||
observers = new Vector();
|
||||
isLoaded = false;
|
||||
freePixmap();
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
freePixmap();
|
||||
}
|
||||
source.startProduction(new GtkImageConsumer(this, source));
|
||||
}
|
||||
}
|
||||
@@ -462,7 +511,12 @@ public class GtkImage extends Image
|
||||
public void finalize()
|
||||
{
|
||||
if (isLoaded)
|
||||
freePixmap();
|
||||
{
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
freePixmap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -529,23 +583,29 @@ public class GtkImage extends Image
|
||||
srcHeight = height - srcY;
|
||||
}
|
||||
|
||||
if ( this.width <= 0 || this.height <= 0 )
|
||||
return true;
|
||||
|
||||
if ( srcWidth <= 0 || srcHeight <= 0 || dstWidth <= 0 || dstHeight <= 0)
|
||||
return true;
|
||||
|
||||
if(bgcolor != null)
|
||||
drawPixelsScaledFlipped (g, bgcolor.getRed (), bgcolor.getGreen (),
|
||||
bgcolor.getBlue (),
|
||||
flipX, flipY,
|
||||
srcX, srcY,
|
||||
srcWidth, srcHeight,
|
||||
dstX, dstY,
|
||||
dstWidth, dstHeight,
|
||||
true);
|
||||
else
|
||||
drawPixelsScaledFlipped (g, 0, 0, 0, flipX, flipY,
|
||||
srcX, srcY, srcWidth, srcHeight,
|
||||
dstX, dstY, dstWidth, dstHeight,
|
||||
false);
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
if(bgcolor != null)
|
||||
drawPixelsScaledFlipped (g, bgcolor.getRed (), bgcolor.getGreen (),
|
||||
bgcolor.getBlue (),
|
||||
flipX, flipY,
|
||||
srcX, srcY,
|
||||
srcWidth, srcHeight,
|
||||
dstX, dstY,
|
||||
dstWidth, dstHeight,
|
||||
true);
|
||||
else
|
||||
drawPixelsScaledFlipped (g, 0, 0, 0, flipX, flipY,
|
||||
srcX, srcY, srcWidth, srcHeight,
|
||||
dstX, dstY, dstWidth, dstHeight,
|
||||
false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -559,11 +619,17 @@ public class GtkImage extends Image
|
||||
if (addObserver(observer))
|
||||
return false;
|
||||
|
||||
if(bgcolor != null)
|
||||
drawPixelsScaled(g, bgcolor.getRed (), bgcolor.getGreen (),
|
||||
bgcolor.getBlue (), x, y, width, height, true);
|
||||
else
|
||||
drawPixelsScaled(g, 0, 0, 0, x, y, width, height, false);
|
||||
if ( this.width <= 0 || this.height <= 0 )
|
||||
return true;
|
||||
|
||||
synchronized(GdkPixbufDecoder.pixbufLock)
|
||||
{
|
||||
if(bgcolor != null)
|
||||
drawPixelsScaled(g, bgcolor.getRed (), bgcolor.getGreen (),
|
||||
bgcolor.getBlue (), x, y, width, height, true);
|
||||
else
|
||||
drawPixelsScaled(g, 0, 0, 0, x, y, width, height, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ package gnu.java.awt.peer.gtk;
|
||||
|
||||
import java.awt.AWTEvent;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.List;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
@@ -120,11 +121,12 @@ public class GtkListPeer extends GtkComponentPeer
|
||||
|
||||
public Dimension preferredSize (int rows)
|
||||
{
|
||||
int dims[] = new int[2];
|
||||
|
||||
int visibleRows = ((List) awtComponent).getRows();
|
||||
getSize (rows, visibleRows, dims);
|
||||
return new Dimension (dims[0], dims[1]);
|
||||
// getSize returns the minimum size of the list.
|
||||
// The width is too narrow for a typical list.
|
||||
List l = (List) awtComponent;
|
||||
Dimension d = getMinimumSize();
|
||||
FontMetrics fm = l.getFontMetrics(l.getFont());
|
||||
return new Dimension(d.width + fm.stringWidth("1234567890"), d.height);
|
||||
}
|
||||
|
||||
public void removeAll ()
|
||||
|
||||
@@ -39,9 +39,7 @@ exception statement from your version. */
|
||||
package gnu.java.awt.peer.gtk;
|
||||
|
||||
import java.awt.AWTEvent;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Panel;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.PaintEvent;
|
||||
import java.awt.peer.PanelPeer;
|
||||
@@ -59,35 +57,10 @@ public class GtkPanelPeer extends GtkContainerPeer
|
||||
public void handleEvent(AWTEvent event)
|
||||
{
|
||||
int id = event.getID();
|
||||
switch (id)
|
||||
{
|
||||
case MouseEvent.MOUSE_PRESSED:
|
||||
awtComponent.requestFocusInWindow();
|
||||
break;
|
||||
case PaintEvent.UPDATE:
|
||||
case PaintEvent.PAINT:
|
||||
{
|
||||
try
|
||||
{
|
||||
Graphics g = getGraphics();
|
||||
if (! awtComponent.isShowing() || awtComponent.getWidth() < 1
|
||||
|| awtComponent.getHeight() < 1 || g == null)
|
||||
return;
|
||||
|
||||
g.setClip(((PaintEvent) event).getUpdateRect());
|
||||
|
||||
// Do not want to clear anything before painting.);
|
||||
awtComponent.paint(g);
|
||||
|
||||
g.dispose();
|
||||
return;
|
||||
}
|
||||
catch (InternalError e)
|
||||
{
|
||||
System.err.println(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (id == MouseEvent.MOUSE_PRESSED)
|
||||
awtComponent.requestFocusInWindow();
|
||||
|
||||
super.handleEvent(event);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,9 +55,6 @@ import java.awt.Image;
|
||||
* that the available flavors might have changed. When requested it
|
||||
* (lazily) caches the targets, and (text, image, or files/uris)
|
||||
* clipboard contents.
|
||||
*
|
||||
* XXX - should only cache when
|
||||
* gdk_display_supports_selection_notification is true.
|
||||
*/
|
||||
public class GtkSelection implements Transferable
|
||||
{
|
||||
@@ -66,6 +63,11 @@ public class GtkSelection implements Transferable
|
||||
*/
|
||||
static private Object requestLock = new Object();
|
||||
|
||||
/**
|
||||
* Whether we belong to the Clipboard (true) or to the Primary selection.
|
||||
*/
|
||||
private final boolean clipboard;
|
||||
|
||||
/**
|
||||
* Whether a request for mimetypes, text, images, uris or byte[] is
|
||||
* currently in progress. Should only be tested or set with
|
||||
@@ -143,10 +145,13 @@ public class GtkSelection implements Transferable
|
||||
private byte[] bytes;
|
||||
|
||||
/**
|
||||
* Should only be created by the GtkClipboard class.
|
||||
* Should only be created by the GtkClipboard class. The clipboard
|
||||
* should be either GtkClipboard.clipboard or
|
||||
* GtkClipboard.selection.
|
||||
*/
|
||||
GtkSelection()
|
||||
GtkSelection(GtkClipboard clipboard)
|
||||
{
|
||||
this.clipboard = (clipboard == GtkClipboard.clipboard);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,7 +186,7 @@ public class GtkSelection implements Transferable
|
||||
if (! mimeTypesDelivered)
|
||||
{
|
||||
requestInProgress = true;
|
||||
requestMimeTypes();
|
||||
requestMimeTypes(clipboard);
|
||||
while (! mimeTypesDelivered)
|
||||
{
|
||||
try
|
||||
@@ -312,7 +317,7 @@ public class GtkSelection implements Transferable
|
||||
if (! textDelivered)
|
||||
{
|
||||
requestInProgress = true;
|
||||
requestText();
|
||||
requestText(clipboard);
|
||||
while (! textDelivered)
|
||||
{
|
||||
try
|
||||
@@ -385,7 +390,7 @@ public class GtkSelection implements Transferable
|
||||
if (! imageDelivered)
|
||||
{
|
||||
requestInProgress = true;
|
||||
requestImage();
|
||||
requestImage(clipboard);
|
||||
while (! imageDelivered)
|
||||
{
|
||||
try
|
||||
@@ -464,7 +469,7 @@ public class GtkSelection implements Transferable
|
||||
if (! urisDelivered)
|
||||
{
|
||||
requestInProgress = true;
|
||||
requestURIs();
|
||||
requestURIs(clipboard);
|
||||
while (! urisDelivered)
|
||||
{
|
||||
try
|
||||
@@ -547,7 +552,7 @@ public class GtkSelection implements Transferable
|
||||
|
||||
// Request bytes and wait till they are available.
|
||||
requestInProgress = true;
|
||||
requestBytes(target);
|
||||
requestBytes(clipboard, target);
|
||||
while (! bytesDelivered)
|
||||
{
|
||||
try
|
||||
@@ -653,12 +658,14 @@ public class GtkSelection implements Transferable
|
||||
* content is available the contentLock will be notified through
|
||||
* textAvailable, imageAvailable, urisAvailable or bytesAvailable and the
|
||||
* appropriate field is set.
|
||||
* The clipboard argument is true if we want the Clipboard, and false
|
||||
* if we want the (primary) selection.
|
||||
*/
|
||||
private native void requestText();
|
||||
private native void requestImage();
|
||||
private native void requestURIs();
|
||||
private native void requestBytes(String target);
|
||||
private native void requestText(boolean clipboard);
|
||||
private native void requestImage(boolean clipboard);
|
||||
private native void requestURIs(boolean clipboard);
|
||||
private native void requestBytes(boolean clipboard, String target);
|
||||
|
||||
/* Similar to the above but for requesting the supported targets. */
|
||||
private native void requestMimeTypes();
|
||||
private native void requestMimeTypes(boolean clipboard);
|
||||
}
|
||||
|
||||
@@ -361,7 +361,16 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
|
||||
if (secman != null)
|
||||
secman.checkSystemClipboardAccess();
|
||||
|
||||
return GtkClipboard.getInstance();
|
||||
return GtkClipboard.getClipboardInstance();
|
||||
}
|
||||
|
||||
public Clipboard getSystemSelection()
|
||||
{
|
||||
SecurityManager secman = System.getSecurityManager();
|
||||
if (secman != null)
|
||||
secman.checkSystemClipboardAccess();
|
||||
|
||||
return GtkClipboard.getSelectionInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -570,6 +579,11 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
|
||||
return q;
|
||||
}
|
||||
|
||||
public Cursor createCustomCursor(Image image, Point hotspot, String name)
|
||||
{
|
||||
return new GtkCursor(image, hotspot, name);
|
||||
}
|
||||
|
||||
protected native void loadSystemColors (int[] systemColors);
|
||||
|
||||
public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent e)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* GtkWindowPeer.java -- Implements WindowPeer with GTK
|
||||
Copyright (C) 1998, 1999, 2002, 2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 1998, 1999, 2002, 2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
@@ -42,7 +42,9 @@ import java.awt.AWTEvent;
|
||||
import java.awt.Component;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.PaintEvent;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.peer.WindowPeer;
|
||||
@@ -62,20 +64,37 @@ public class GtkWindowPeer extends GtkContainerPeer
|
||||
private boolean hasBeenShown = false;
|
||||
private int oldState = Frame.NORMAL;
|
||||
|
||||
// Cached awt window component location, width and height.
|
||||
private int x, y, width, height;
|
||||
|
||||
native void gtkWindowSetTitle (String title);
|
||||
native void gtkWindowSetResizable (boolean resizable);
|
||||
native void gtkWindowSetModal (boolean modal);
|
||||
|
||||
native void realize ();
|
||||
|
||||
int getWidth ()
|
||||
/** Returns the cached width of the AWT window component. */
|
||||
int getX ()
|
||||
{
|
||||
return awtComponent.getWidth();
|
||||
return x;
|
||||
}
|
||||
|
||||
/** Returns the cached width of the AWT window component. */
|
||||
int getY ()
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
/** Returns the cached width of the AWT window component. */
|
||||
int getWidth ()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
/** Returns the cached height of the AWT window component. */
|
||||
int getHeight ()
|
||||
{
|
||||
return awtComponent.getHeight();
|
||||
return height;
|
||||
}
|
||||
|
||||
native void create (int type, boolean decorated, GtkWindowPeer parent);
|
||||
@@ -85,6 +104,10 @@ public class GtkWindowPeer extends GtkContainerPeer
|
||||
Window window = (Window) awtComponent;
|
||||
GtkWindowPeer parent_peer = null;
|
||||
Component parent = awtComponent.getParent();
|
||||
x = awtComponent.getX();
|
||||
y = awtComponent.getY();
|
||||
height = awtComponent.getHeight();
|
||||
width = awtComponent.getWidth();
|
||||
|
||||
if (!window.isFocusableWindow())
|
||||
type = GDK_WINDOW_TYPE_HINT_MENU;
|
||||
@@ -129,37 +152,28 @@ public class GtkWindowPeer extends GtkContainerPeer
|
||||
native void nativeSetLocation (int x, int y);
|
||||
native void nativeSetLocationUnlocked (int x, int y);
|
||||
|
||||
public void setLocation (int x, int y)
|
||||
// Called from show.
|
||||
protected void setLocation (int x, int y)
|
||||
{
|
||||
// prevent window_configure_cb -> awtComponent.setSize ->
|
||||
// peer.setBounds -> nativeSetBounds self-deadlock on GDK lock.
|
||||
if (Thread.currentThread() == GtkToolkit.mainThread)
|
||||
return;
|
||||
nativeSetLocation (x, y);
|
||||
}
|
||||
|
||||
public void setLocationUnlocked (int x, int y)
|
||||
{
|
||||
nativeSetLocationUnlocked (x, y);
|
||||
}
|
||||
|
||||
public void setBounds (int x, int y, int width, int height)
|
||||
{
|
||||
// prevent window_configure_cb -> awtComponent.setSize ->
|
||||
// peer.setBounds -> nativeSetBounds self-deadlock on GDK lock.
|
||||
if (Thread.currentThread() == GtkToolkit.mainThread)
|
||||
return;
|
||||
|
||||
nativeSetBounds (x, y,
|
||||
width - insets.left - insets.right,
|
||||
height - insets.top - insets.bottom);
|
||||
}
|
||||
|
||||
public void setBoundsUnlocked (int x, int y, int width, int height)
|
||||
{
|
||||
nativeSetBoundsUnlocked (x, y,
|
||||
width - insets.left - insets.right,
|
||||
height - insets.top - insets.bottom);
|
||||
if (x != getX()
|
||||
|| y != getY()
|
||||
|| width != getWidth()
|
||||
|| height != getHeight())
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
nativeSetBounds (x, y,
|
||||
width - insets.left - insets.right,
|
||||
height - insets.top - insets.bottom);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTitle (String title)
|
||||
@@ -167,15 +181,25 @@ public class GtkWindowPeer extends GtkContainerPeer
|
||||
gtkWindowSetTitle (title);
|
||||
}
|
||||
|
||||
native void setSize (int width, int height);
|
||||
|
||||
// Called from setResizable
|
||||
protected native void setSize (int width, int height);
|
||||
|
||||
/**
|
||||
* Needed by both GtkFramePeer and GtkDialogPeer subclasses, so
|
||||
* implemented here. But never actually called on a GtkWindowPeer
|
||||
* itself.
|
||||
*/
|
||||
public void setResizable (boolean resizable)
|
||||
{
|
||||
// Call setSize; otherwise when resizable is changed from true to
|
||||
// false the window will shrink to the dimensions it had before it
|
||||
// was resizable.
|
||||
setSize (awtComponent.getWidth() - insets.left - insets.right,
|
||||
awtComponent.getHeight() - insets.top - insets.bottom);
|
||||
x = awtComponent.getX();
|
||||
y = awtComponent.getY();
|
||||
width = awtComponent.getWidth();
|
||||
height = awtComponent.getHeight();
|
||||
setSize (width - insets.left - insets.right,
|
||||
height - insets.top - insets.bottom);
|
||||
gtkWindowSetResizable (resizable);
|
||||
}
|
||||
|
||||
@@ -195,23 +219,35 @@ public class GtkWindowPeer extends GtkContainerPeer
|
||||
int frame_width = width + insets.left + insets.right;
|
||||
int frame_height = height + insets.top + insets.bottom;
|
||||
|
||||
if (frame_width != awtComponent.getWidth()
|
||||
|| frame_height != awtComponent.getHeight())
|
||||
awtComponent.setSize(frame_width, frame_height);
|
||||
if (frame_width != getWidth()
|
||||
|| frame_height != getHeight())
|
||||
{
|
||||
this.width = frame_width;
|
||||
this.height = frame_height;
|
||||
q().postEvent(new ComponentEvent(awtComponent,
|
||||
ComponentEvent.COMPONENT_RESIZED));
|
||||
}
|
||||
|
||||
int frame_x = x - insets.left;
|
||||
int frame_y = y - insets.top;
|
||||
|
||||
if (frame_x != awtComponent.getX()
|
||||
|| frame_y != awtComponent.getY())
|
||||
if (frame_x != getX()
|
||||
|| frame_y != getY())
|
||||
{
|
||||
// awtComponent.setLocation(frame_x, frame_y);
|
||||
this.x = frame_x;
|
||||
this.y = frame_y;
|
||||
q().postEvent(new ComponentEvent(awtComponent,
|
||||
ComponentEvent.COMPONENT_MOVED));
|
||||
}
|
||||
}
|
||||
|
||||
public void show ()
|
||||
{
|
||||
setLocation(awtComponent.getX(), awtComponent.getY());
|
||||
x = awtComponent.getX();
|
||||
y = awtComponent.getY();
|
||||
width = awtComponent.getWidth();
|
||||
height = awtComponent.getHeight();
|
||||
setLocation(x, y);
|
||||
setVisible (true);
|
||||
}
|
||||
|
||||
@@ -244,37 +280,62 @@ public class GtkWindowPeer extends GtkContainerPeer
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
protected void postExposeEvent (int x, int y, int width, int height)
|
||||
{
|
||||
// Translate GTK co-ordinates, which do not include a window
|
||||
// frame's insets, to AWT co-ordinates, which do include a window
|
||||
// frame's insets. GtkWindowPeer should always have all-zero
|
||||
// insets but GtkFramePeer and GtkDialogPeer insets will be
|
||||
// non-zero.
|
||||
q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT,
|
||||
new Rectangle (x + insets.left,
|
||||
y + insets.top,
|
||||
width, height)));
|
||||
}
|
||||
|
||||
public boolean requestWindowFocus()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
public void handleEvent(AWTEvent event)
|
||||
public Graphics getGraphics ()
|
||||
{
|
||||
int id = event.getID();
|
||||
if (id == PaintEvent.UPDATE || id == PaintEvent.PAINT)
|
||||
{
|
||||
try
|
||||
{
|
||||
Graphics g = getGraphics();
|
||||
if (! awtComponent.isShowing() || awtComponent.getWidth() < 1
|
||||
|| awtComponent.getHeight() < 1 || g == null)
|
||||
return;
|
||||
Graphics g = super.getGraphics ();
|
||||
// Translate AWT co-ordinates, which include a window frame's
|
||||
// insets, to GTK co-ordinates, which do not include a window
|
||||
// frame's insets. GtkWindowPeer should always have all-zero
|
||||
// insets but GtkFramePeer and GtkDialogPeer insets will be
|
||||
// non-zero.
|
||||
g.translate (-insets.left, -insets.top);
|
||||
return g;
|
||||
}
|
||||
|
||||
g.setClip(((PaintEvent) event).getUpdateRect());
|
||||
protected void updateComponent (PaintEvent event)
|
||||
{
|
||||
// Do not clear anything before painting. Sun never calls
|
||||
// Window.update, only Window.paint.
|
||||
paintComponent(event);
|
||||
}
|
||||
|
||||
// Do not want to clear anything before painting.
|
||||
awtComponent.paint(g);
|
||||
protected void postMouseEvent(int id, long when, int mods, int x, int y,
|
||||
int clickCount, boolean popupTrigger)
|
||||
{
|
||||
// Translate AWT co-ordinates, which include a window frame's
|
||||
// insets, to GTK co-ordinates, which do not include a window
|
||||
// frame's insets. GtkWindowPeer should always have all-zero
|
||||
// insets but GtkFramePeer and GtkDialogPeer insets will be
|
||||
// non-zero.
|
||||
super.postMouseEvent (id, when, mods,
|
||||
x + insets.left, y + insets.top,
|
||||
clickCount, popupTrigger);
|
||||
}
|
||||
|
||||
g.dispose();
|
||||
return;
|
||||
}
|
||||
catch (InternalError e)
|
||||
{
|
||||
System.err.println(e);
|
||||
}
|
||||
}
|
||||
super.handleEvent(event);
|
||||
// We override this to keep it in sync with our internal
|
||||
// representation.
|
||||
public Rectangle getBounds()
|
||||
{
|
||||
return new Rectangle(x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -590,8 +590,7 @@ public class SwingComponentPeer
|
||||
*/
|
||||
public void setBounds(int x, int y, int width, int height)
|
||||
{
|
||||
if (swingComponent != null)
|
||||
swingComponent.getJComponent().setBounds(x, y, width, height);
|
||||
reshape(x, y, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -61,7 +61,7 @@ public class SwingContainerPeer
|
||||
*
|
||||
* @param awtCont
|
||||
*/
|
||||
public SwingContainerPeer(Container awtCont)
|
||||
public SwingContainerPeer(Component awtCont)
|
||||
{
|
||||
init(awtCont, null);
|
||||
}
|
||||
@@ -92,12 +92,7 @@ public class SwingContainerPeer
|
||||
*/
|
||||
public Insets getInsets()
|
||||
{
|
||||
Insets retVal;
|
||||
if (swingComponent != null)
|
||||
retVal = swingComponent.getJComponent().getInsets();
|
||||
else
|
||||
retVal = new Insets(0, 0, 0, 0);
|
||||
return retVal;
|
||||
return insets();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,12 +209,15 @@ public class SwingContainerPeer
|
||||
protected void handleMouseEvent(MouseEvent ev)
|
||||
{
|
||||
Component comp = awtComponent.getComponentAt(ev.getPoint());
|
||||
ComponentPeer peer = comp.getPeer();
|
||||
if (awtComponent != comp && !comp.isLightweight() && peer instanceof SwingComponentPeer)
|
||||
if (comp != null)
|
||||
{
|
||||
ev.translatePoint(comp.getX(), comp.getY());
|
||||
ev.setSource(comp);
|
||||
((SwingComponentPeer) peer).handleMouseEvent(ev);
|
||||
ComponentPeer peer = comp.getPeer();
|
||||
if (awtComponent != comp && !comp.isLightweight() && peer instanceof SwingComponentPeer)
|
||||
{
|
||||
ev.translatePoint(comp.getX(), comp.getY());
|
||||
ev.setSource(comp);
|
||||
((SwingComponentPeer) peer).handleMouseEvent(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,11 +229,14 @@ public class SwingContainerPeer
|
||||
protected void handleMouseMotionEvent(MouseEvent ev)
|
||||
{
|
||||
Component comp = awtComponent.getComponentAt(ev.getPoint());
|
||||
ComponentPeer peer = comp.getPeer();
|
||||
if (awtComponent != comp && !comp.isLightweight() && peer instanceof SwingComponentPeer)
|
||||
if (comp != null)
|
||||
{
|
||||
ev.translatePoint(comp.getX(), comp.getY());
|
||||
((SwingComponentPeer) peer).handleMouseMotionEvent(ev);
|
||||
ComponentPeer peer = comp.getPeer();
|
||||
if (awtComponent != comp && !comp.isLightweight() && peer instanceof SwingComponentPeer)
|
||||
{
|
||||
ev.translatePoint(comp.getX(), comp.getY());
|
||||
((SwingComponentPeer) peer).handleMouseMotionEvent(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -81,6 +81,34 @@ public class ClassHelper
|
||||
return name.substring(lastInd + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the class as written by the user.
|
||||
* This is used by the various reflection toString methods.
|
||||
* It differs from {@link Class#getName()} in that it prints
|
||||
* arrays with trailing "[]"s. Note that it does not treat
|
||||
* member classes specially, so a dollar sign may still appear
|
||||
* in the result. This is intentional.
|
||||
* @param klass the class
|
||||
* @return a pretty form of the class' name
|
||||
*/
|
||||
public static String getUserName(Class klass)
|
||||
{
|
||||
int arrayCount = 0;
|
||||
while (klass.isArray())
|
||||
{
|
||||
++arrayCount;
|
||||
klass = klass.getComponentType();
|
||||
}
|
||||
String name = klass.getName();
|
||||
if (arrayCount == 0)
|
||||
return name;
|
||||
StringBuilder b = new StringBuilder(name.length() + 2 * arrayCount);
|
||||
b.append(name);
|
||||
for (int i = 0; i < arrayCount; ++i)
|
||||
b.append("[]");
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
/** Cache of methods found in getAllMethods(). */
|
||||
private static Map allMethods = new HashMap();
|
||||
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
/* InstrumentationImpl.java -- GNU implementation of
|
||||
java.lang.instrument.Instrumentation
|
||||
Copyright (C) 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.lang;
|
||||
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.lang.instrument.ClassFileTransformer;
|
||||
import java.lang.instrument.ClassDefinition;
|
||||
import java.lang.instrument.UnmodifiableClassException;
|
||||
import java.lang.instrument.IllegalClassFormatException;
|
||||
|
||||
import java.security.ProtectionDomain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An Instrumentation object has transformers that will
|
||||
* be called each time a class is defined or redefined.
|
||||
* The object is given to a <code>premain</code> function
|
||||
* that is called before the <code>main</code> function.
|
||||
*
|
||||
* @author Nicolas Geoffray (nicolas.geoffray@menlina.com)
|
||||
* @since 1.5
|
||||
*/
|
||||
public final class InstrumentationImpl implements Instrumentation
|
||||
{
|
||||
|
||||
/* List of transformers */
|
||||
/* FIXME[GENERICS]: Should be ClassFileTransformer list */
|
||||
private ArrayList transformers = new ArrayList();
|
||||
|
||||
|
||||
private InstrumentationImpl()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a <code>ClassFileTransformer</class> object
|
||||
* to the instrumentation. Each time a class is defined
|
||||
* or redefined, the <code>transform</code> method of the
|
||||
* <code>transformer</code> object is called.
|
||||
*
|
||||
* @param transformer the transformer to add
|
||||
* @throws NullPointerException if transformer is null
|
||||
*/
|
||||
public void addTransformer(ClassFileTransformer transformer)
|
||||
{
|
||||
if (transformer == null)
|
||||
throw new NullPointerException();
|
||||
synchronized(transformers)
|
||||
{
|
||||
transformers.add(transformer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given transformer from the set of transformers
|
||||
* this Instrumentation object has.
|
||||
*
|
||||
* @param transformer the transformer to remove
|
||||
* @return true if the transformer was found and removed, false if
|
||||
* the transformer was not found
|
||||
* @throws NullPointerException if transformer is null
|
||||
*/
|
||||
public boolean removeTransformer(ClassFileTransformer transformer)
|
||||
{
|
||||
if (transformer == null)
|
||||
throw new NullPointerException();
|
||||
|
||||
boolean result;
|
||||
synchronized (transformers)
|
||||
{
|
||||
result = transformers.remove(transformer);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the current JVM supports class redefinition
|
||||
*
|
||||
* @return true if the current JVM supports class redefinition
|
||||
*/
|
||||
public boolean isRedefineClassesSupported()
|
||||
{
|
||||
return VMInstrumentationImpl.isRedefineClassesSupported();
|
||||
}
|
||||
|
||||
/**
|
||||
* Redefine classes present in the definitions array, with
|
||||
* the corresponding class files.
|
||||
*
|
||||
* @param definitions an array of classes to redefine
|
||||
*
|
||||
* @throws ClassNotFoundException if a class cannot be found
|
||||
* @throws UnmodifiableClassException if a class cannot be modified
|
||||
* @throws UnsupportedOperationException if the JVM does not support
|
||||
* redefinition or the redefinition made unsupported changes
|
||||
* @throws ClassFormatError if a class file is not valid
|
||||
* @throws NoClassDefFoundError if a class name is not equal to the name
|
||||
* in the class file specified
|
||||
* @throws UnsupportedClassVersionError if the class file version numbers
|
||||
* are unsupported
|
||||
* @throws ClassCircularityError if circularity occured with the new
|
||||
* classes
|
||||
* @throws LinkageError if a linkage error occurs
|
||||
* @throws NullPointerException if the definitions array is null, or any
|
||||
* of its element
|
||||
*
|
||||
* @see isRedefineClassesSupported()
|
||||
* @see addTransformer(java.lang.instrument.ClassFileTransformer)
|
||||
* @see ClassFileTransformer
|
||||
*/
|
||||
public void redefineClasses(ClassDefinition[] definitions)
|
||||
throws ClassNotFoundException,
|
||||
UnmodifiableClassException
|
||||
{
|
||||
if (!isRedefineClassesSupported())
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
VMInstrumentationImpl.redefineClasses(this, definitions);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all the classes loaded by the JVM.
|
||||
*
|
||||
* @return an array containing all the classes loaded by the JVM. The array
|
||||
* is empty if no class is loaded.
|
||||
*/
|
||||
public Class[] getAllLoadedClasses()
|
||||
{
|
||||
return VMInstrumentationImpl.getAllLoadedClasses();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the classes loaded by a given class loader
|
||||
*
|
||||
* @param loader the loader
|
||||
*
|
||||
* @return an array containing all the classes loaded by the given loader.
|
||||
* The array is empty if no class was loaded by the loader.
|
||||
*/
|
||||
public Class[] getInitiatedClasses(ClassLoader loader)
|
||||
{
|
||||
return VMInstrumentationImpl.getInitiatedClasses(loader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size of an object.
|
||||
*
|
||||
* @param objectToSize the object
|
||||
* @return the size of the object
|
||||
* @throws NullPointerException if objectToSize is null.
|
||||
*/
|
||||
public long getObjectSize(Object objectToSize)
|
||||
{
|
||||
// We alleviate the VM work
|
||||
if (objectToSize == null)
|
||||
throw new NullPointerException();
|
||||
return VMInstrumentationImpl.getObjectSize(objectToSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the VM or redefineClasses to call each transformer
|
||||
*
|
||||
* @param loader the loader of the class
|
||||
* @param className the name of the class with packages separated with "/"
|
||||
* @param classBeingRedefined the class being redefined if it's the case,
|
||||
* null otherwise
|
||||
* @param protectionDomain the protection domain of the class being defined
|
||||
* or redefined
|
||||
* @param classfileBuffer the input byte buffer in class file format
|
||||
*
|
||||
* @return the new class file
|
||||
*/
|
||||
/* FIXME[GENERICS]: Should be Class<?> */
|
||||
public byte[] callTransformers(ClassLoader loader, String className,
|
||||
Class classBeingRedefined, ProtectionDomain protectionDomain,
|
||||
byte[] classfileBuffer)
|
||||
{
|
||||
byte[] newBuffer = null;
|
||||
byte[] oldBuffer = classfileBuffer;
|
||||
ClassFileTransformer current;
|
||||
synchronized (transformers)
|
||||
{
|
||||
Iterator i = transformers.iterator();
|
||||
while (i.hasNext())
|
||||
{
|
||||
/* FIXME[GENERICS]: Remove cast */
|
||||
current = (ClassFileTransformer) i.next();
|
||||
try
|
||||
{
|
||||
newBuffer = current.transform(loader, className,
|
||||
classBeingRedefined, protectionDomain, oldBuffer);
|
||||
}
|
||||
catch (IllegalClassFormatException ignored)
|
||||
{
|
||||
//IGNORED
|
||||
}
|
||||
if (newBuffer != null)
|
||||
oldBuffer = newBuffer;
|
||||
}
|
||||
}
|
||||
return oldBuffer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/* ClassSignatureParser.java
|
||||
Copyright (C) 2005
|
||||
Free Software Foundation
|
||||
|
||||
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.lang.reflect;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ClassSignatureParser extends GenericSignatureParser
|
||||
{
|
||||
private TypeVariable[] typeParameters;
|
||||
private Type superclassType;
|
||||
private Type[] interfaceTypes;
|
||||
|
||||
public ClassSignatureParser(Class c, String signature)
|
||||
{
|
||||
super(c, c.getClassLoader(), signature);
|
||||
|
||||
if (peekChar() == '<')
|
||||
{
|
||||
typeParameters = readFormalTypeParameters();
|
||||
}
|
||||
else
|
||||
{
|
||||
typeParameters = new TypeVariable[0];
|
||||
}
|
||||
// SuperclassSignature
|
||||
superclassType = readClassTypeSignature();
|
||||
ArrayList interfaces = new ArrayList();
|
||||
while (peekChar() == 'L')
|
||||
{
|
||||
// SuperinterfaceSignature
|
||||
interfaces.add(readClassTypeSignature());
|
||||
}
|
||||
interfaceTypes = new Type[interfaces.size()];
|
||||
interfaces.toArray(interfaceTypes);
|
||||
end();
|
||||
}
|
||||
|
||||
public TypeVariable[] getTypeParameters()
|
||||
{
|
||||
TypeImpl.resolve(typeParameters);
|
||||
return typeParameters;
|
||||
}
|
||||
|
||||
public Type getSuperclassType()
|
||||
{
|
||||
superclassType = TypeImpl.resolve(superclassType);
|
||||
return superclassType;
|
||||
}
|
||||
|
||||
public Type[] getInterfaceTypes()
|
||||
{
|
||||
TypeImpl.resolve(interfaceTypes);
|
||||
return interfaceTypes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/* FieldSignatureParser.java
|
||||
Copyright (C) 2005
|
||||
Free Software Foundation
|
||||
|
||||
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.lang.reflect;
|
||||
|
||||
import java.lang.reflect.GenericSignatureFormatError;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public final class FieldSignatureParser extends GenericSignatureParser
|
||||
{
|
||||
private Type type;
|
||||
|
||||
public FieldSignatureParser(Class container, String signature)
|
||||
{
|
||||
super(container, container.getClassLoader(), signature);
|
||||
|
||||
switch (peekChar())
|
||||
{
|
||||
case 'L':
|
||||
case '[':
|
||||
case 'T':
|
||||
type = readFieldTypeSignature();
|
||||
break;
|
||||
case 'Z':
|
||||
consume('Z');
|
||||
type = boolean.class;
|
||||
break;
|
||||
case 'B':
|
||||
consume('B');
|
||||
type = byte.class;
|
||||
break;
|
||||
case 'S':
|
||||
consume('S');
|
||||
type = short.class;
|
||||
break;
|
||||
case 'C':
|
||||
consume('C');
|
||||
type = char.class;
|
||||
break;
|
||||
case 'I':
|
||||
consume('I');
|
||||
type = int.class;
|
||||
break;
|
||||
case 'F':
|
||||
consume('F');
|
||||
type = float.class;
|
||||
break;
|
||||
case 'J':
|
||||
consume('J');
|
||||
type = long.class;
|
||||
break;
|
||||
case 'D':
|
||||
consume('D');
|
||||
type = double.class;
|
||||
break;
|
||||
default:
|
||||
throw new GenericSignatureFormatError();
|
||||
}
|
||||
|
||||
end();
|
||||
}
|
||||
|
||||
public Type getFieldType()
|
||||
{
|
||||
type = TypeImpl.resolve(type);
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,622 @@
|
||||
/* GenericSignatureParser.java
|
||||
Copyright (C) 2005
|
||||
Free Software Foundation
|
||||
|
||||
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.lang.reflect;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
final class TypeVariableImpl extends TypeImpl implements TypeVariable
|
||||
{
|
||||
private GenericDeclaration decl;
|
||||
private Type[] bounds;
|
||||
private String name;
|
||||
|
||||
TypeVariableImpl(GenericDeclaration decl, Type[] bounds, String name)
|
||||
{
|
||||
this.decl = decl;
|
||||
this.bounds = bounds;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
Type resolve()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
/* FIXME[GENERICS]: Remove cast */
|
||||
public Type[] getBounds()
|
||||
{
|
||||
resolve(bounds);
|
||||
return (Type[]) bounds.clone();
|
||||
}
|
||||
|
||||
public GenericDeclaration getGenericDeclaration()
|
||||
{
|
||||
return decl;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj instanceof TypeVariableImpl)
|
||||
{
|
||||
TypeVariableImpl other = (TypeVariableImpl)obj;
|
||||
return decl.equals(other.decl) && name.equals(other.name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
return 0x5f4d5156 ^ decl.hashCode() ^ name.hashCode();
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
final class ParameterizedTypeImpl extends TypeImpl implements ParameterizedType
|
||||
{
|
||||
private String rawTypeName;
|
||||
private ClassLoader loader;
|
||||
private Class rawType;
|
||||
private Type owner;
|
||||
private Type[] typeArgs;
|
||||
|
||||
ParameterizedTypeImpl(String rawTypeName, ClassLoader loader, Type owner,
|
||||
Type[] typeArgs)
|
||||
{
|
||||
this.rawTypeName = rawTypeName;
|
||||
this.loader = loader;
|
||||
this.owner = owner;
|
||||
this.typeArgs = typeArgs;
|
||||
}
|
||||
|
||||
Type resolve()
|
||||
{
|
||||
if (rawType == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
rawType = Class.forName(rawTypeName, false, loader);
|
||||
}
|
||||
catch (ClassNotFoundException x)
|
||||
{
|
||||
throw new TypeNotPresentException(rawTypeName, x);
|
||||
}
|
||||
}
|
||||
if (typeArgs == null)
|
||||
{
|
||||
if (owner == null)
|
||||
{
|
||||
return rawType;
|
||||
}
|
||||
typeArgs = new Type[0];
|
||||
}
|
||||
resolve(typeArgs);
|
||||
owner = resolve(owner);
|
||||
return this;
|
||||
}
|
||||
|
||||
/* FIXME[GENERICS]: Remove cast */
|
||||
public Type[] getActualTypeArguments()
|
||||
{
|
||||
return (Type[]) typeArgs.clone();
|
||||
}
|
||||
|
||||
public Type getRawType()
|
||||
{
|
||||
return rawType;
|
||||
}
|
||||
|
||||
public Type getOwnerType()
|
||||
{
|
||||
return owner;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj instanceof ParameterizedTypeImpl)
|
||||
{
|
||||
ParameterizedTypeImpl other = (ParameterizedTypeImpl)obj;
|
||||
return rawType.equals(other.rawType)
|
||||
&& ((owner == null && other.owner == null)
|
||||
|| owner.equals(other.owner))
|
||||
&& Arrays.deepEquals(typeArgs, other.typeArgs);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
int h = 0x58158970 ^ rawType.hashCode();
|
||||
if (owner != null)
|
||||
{
|
||||
h ^= Integer.reverse(owner.hashCode());
|
||||
}
|
||||
for (int i = 0; i < typeArgs.length; i++)
|
||||
{
|
||||
h ^= Integer.rotateLeft(typeArgs[i].hashCode(), i);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (owner != null)
|
||||
{
|
||||
sb.append(owner);
|
||||
sb.append('.');
|
||||
sb.append(rawType.getSimpleName());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(rawTypeName);
|
||||
}
|
||||
if (typeArgs.length > 0)
|
||||
{
|
||||
sb.append('<');
|
||||
for (int i = 0; i < typeArgs.length; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
sb.append(", ");
|
||||
if (typeArgs[i] instanceof Class)
|
||||
{
|
||||
sb.append(((Class)typeArgs[i]).getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(typeArgs[i]);
|
||||
}
|
||||
}
|
||||
sb.append('>');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
final class GenericArrayTypeImpl extends TypeImpl implements GenericArrayType
|
||||
{
|
||||
private Type componentType;
|
||||
|
||||
GenericArrayTypeImpl(Type componentType)
|
||||
{
|
||||
this.componentType = componentType;
|
||||
}
|
||||
|
||||
Type resolve()
|
||||
{
|
||||
componentType = resolve(componentType);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Type getGenericComponentType()
|
||||
{
|
||||
return componentType;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj instanceof GenericArrayTypeImpl)
|
||||
{
|
||||
GenericArrayTypeImpl other = (GenericArrayTypeImpl)obj;
|
||||
return componentType.equals(other.componentType);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
return 0x4be37a7f ^ componentType.hashCode();
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return componentType + "[]";
|
||||
}
|
||||
}
|
||||
|
||||
final class UnresolvedTypeVariable extends TypeImpl implements Type
|
||||
{
|
||||
private GenericDeclaration decl;
|
||||
private String name;
|
||||
|
||||
UnresolvedTypeVariable(GenericDeclaration decl, String name)
|
||||
{
|
||||
this.decl = decl;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
Type resolve()
|
||||
{
|
||||
GenericDeclaration d = decl;
|
||||
while (d != null)
|
||||
{
|
||||
TypeVariable[] vars = d.getTypeParameters();
|
||||
for (int a = 0; a < vars.length ; ++a)
|
||||
{
|
||||
if (vars[a].getName().equals(name))
|
||||
{
|
||||
return vars[a];
|
||||
}
|
||||
}
|
||||
d = getParent(d);
|
||||
}
|
||||
throw new MalformedParameterizedTypeException();
|
||||
}
|
||||
|
||||
private static GenericDeclaration getParent(GenericDeclaration d)
|
||||
{
|
||||
if (d instanceof Class)
|
||||
{
|
||||
Method m = ((Class)d).getEnclosingMethod();
|
||||
if (m != null)
|
||||
{
|
||||
return m;
|
||||
}
|
||||
Constructor c = ((Class)d).getEnclosingConstructor();
|
||||
if (c != null)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
return ((Class)d).getEnclosingClass();
|
||||
}
|
||||
else if (d instanceof Method)
|
||||
{
|
||||
return ((Method)d).getDeclaringClass();
|
||||
}
|
||||
else if (d instanceof Constructor)
|
||||
{
|
||||
return ((Constructor)d).getDeclaringClass();
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO figure out what this represents
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class WildcardTypeImpl extends TypeImpl implements WildcardType
|
||||
{
|
||||
private Type lower;
|
||||
private Type upper;
|
||||
|
||||
WildcardTypeImpl(Type lower, Type upper)
|
||||
{
|
||||
this.lower = lower;
|
||||
this.upper = upper;
|
||||
}
|
||||
|
||||
Type resolve()
|
||||
{
|
||||
upper = resolve(upper);
|
||||
lower = resolve(lower);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Type[] getUpperBounds()
|
||||
{
|
||||
if (upper == null)
|
||||
{
|
||||
return new Type[0];
|
||||
}
|
||||
return new Type[] { upper };
|
||||
}
|
||||
|
||||
public Type[] getLowerBounds()
|
||||
{
|
||||
if (lower == null)
|
||||
{
|
||||
return new Type[0];
|
||||
}
|
||||
return new Type[] { lower };
|
||||
}
|
||||
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj instanceof WildcardTypeImpl)
|
||||
{
|
||||
WildcardTypeImpl other = (WildcardTypeImpl)obj;
|
||||
return Arrays.deepEquals(getUpperBounds(), other.getUpperBounds())
|
||||
&& Arrays.deepEquals(getLowerBounds(), other.getLowerBounds());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
int h = 0x75d074fd;
|
||||
if (upper != null)
|
||||
{
|
||||
h ^= upper.hashCode();
|
||||
}
|
||||
if (lower != null)
|
||||
{
|
||||
h ^= lower.hashCode();
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
if (lower != null)
|
||||
{
|
||||
return "? super " + lower;
|
||||
}
|
||||
if (upper == java.lang.Object.class)
|
||||
{
|
||||
return "?";
|
||||
}
|
||||
return "? extends " + upper;
|
||||
}
|
||||
}
|
||||
|
||||
class GenericSignatureParser
|
||||
{
|
||||
private ClassLoader loader;
|
||||
private GenericDeclaration container;
|
||||
private String signature;
|
||||
private int pos;
|
||||
|
||||
GenericSignatureParser(GenericDeclaration container, ClassLoader loader,
|
||||
String signature)
|
||||
{
|
||||
this.container = container;
|
||||
this.loader = loader;
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
TypeVariable[] readFormalTypeParameters()
|
||||
{
|
||||
consume('<');
|
||||
ArrayList params = new ArrayList();
|
||||
do
|
||||
{
|
||||
// TODO should we handle name clashes?
|
||||
params.add(readFormalTypeParameter());
|
||||
} while (peekChar() != '>');
|
||||
consume('>');
|
||||
TypeVariable[] list = new TypeVariable[params.size()];
|
||||
params.toArray(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
private TypeVariable readFormalTypeParameter()
|
||||
{
|
||||
String identifier = readIdentifier();
|
||||
consume(':');
|
||||
ArrayList bounds = new ArrayList();
|
||||
if (peekChar() != ':')
|
||||
{
|
||||
bounds.add(readFieldTypeSignature());
|
||||
}
|
||||
while (peekChar() == ':')
|
||||
{
|
||||
consume(':');
|
||||
bounds.add(readFieldTypeSignature());
|
||||
}
|
||||
Type[] b = new Type[bounds.size()];
|
||||
bounds.toArray(b);
|
||||
return new TypeVariableImpl(container, b, identifier);
|
||||
}
|
||||
|
||||
Type readFieldTypeSignature()
|
||||
{
|
||||
switch (peekChar())
|
||||
{
|
||||
case 'L':
|
||||
return readClassTypeSignature();
|
||||
case '[':
|
||||
return readArrayTypeSignature();
|
||||
case 'T':
|
||||
return readTypeVariableSignature();
|
||||
default:
|
||||
throw new GenericSignatureFormatError();
|
||||
}
|
||||
}
|
||||
|
||||
Type readClassTypeSignature()
|
||||
{
|
||||
consume('L');
|
||||
String className = "";
|
||||
for (;;)
|
||||
{
|
||||
String part = readIdentifier();
|
||||
if (peekChar() != '/')
|
||||
{
|
||||
className += part;
|
||||
break;
|
||||
}
|
||||
consume('/');
|
||||
className += part + ".";
|
||||
}
|
||||
Type[] typeArguments = null;
|
||||
if (peekChar() == '<')
|
||||
{
|
||||
typeArguments = readTypeArguments();
|
||||
}
|
||||
Type type = new ParameterizedTypeImpl(className, loader, null,
|
||||
typeArguments);
|
||||
while (peekChar() == '.')
|
||||
{
|
||||
consume('.');
|
||||
className += "$" + readIdentifier();
|
||||
typeArguments = null;
|
||||
if (peekChar() == '<')
|
||||
{
|
||||
typeArguments = readTypeArguments();
|
||||
}
|
||||
type = new ParameterizedTypeImpl(className, loader, type,
|
||||
typeArguments);
|
||||
}
|
||||
consume(';');
|
||||
return type;
|
||||
}
|
||||
|
||||
private Type[] readTypeArguments()
|
||||
{
|
||||
consume('<');
|
||||
ArrayList list = new ArrayList();
|
||||
do
|
||||
{
|
||||
list.add(readTypeArgument());
|
||||
} while ((peekChar() != '>'));
|
||||
consume('>');
|
||||
Type[] arr = new Type[list.size()];
|
||||
list.toArray(arr);
|
||||
return arr;
|
||||
}
|
||||
|
||||
private Type readTypeArgument()
|
||||
{
|
||||
char c = peekChar();
|
||||
if (c == '+')
|
||||
{
|
||||
consume('+');
|
||||
return new WildcardTypeImpl(null, readFieldTypeSignature());
|
||||
}
|
||||
else if (c == '-')
|
||||
{
|
||||
consume('-');
|
||||
return new WildcardTypeImpl(readFieldTypeSignature(),
|
||||
java.lang.Object.class);
|
||||
}
|
||||
else if (c == '*')
|
||||
{
|
||||
consume('*');
|
||||
return new WildcardTypeImpl(null, java.lang.Object.class);
|
||||
}
|
||||
else
|
||||
{
|
||||
return readFieldTypeSignature();
|
||||
}
|
||||
}
|
||||
|
||||
Type readArrayTypeSignature()
|
||||
{
|
||||
consume('[');
|
||||
switch (peekChar())
|
||||
{
|
||||
case 'L':
|
||||
case '[':
|
||||
case 'T':
|
||||
return new GenericArrayTypeImpl(readFieldTypeSignature());
|
||||
case 'Z':
|
||||
consume('Z');
|
||||
return boolean[].class;
|
||||
case 'B':
|
||||
consume('B');
|
||||
return byte[].class;
|
||||
case 'S':
|
||||
consume('S');
|
||||
return short[].class;
|
||||
case 'C':
|
||||
consume('C');
|
||||
return char[].class;
|
||||
case 'I':
|
||||
consume('I');
|
||||
return int[].class;
|
||||
case 'F':
|
||||
consume('F');
|
||||
return float[].class;
|
||||
case 'J':
|
||||
consume('J');
|
||||
return long[].class;
|
||||
case 'D':
|
||||
consume('D');
|
||||
return double[].class;
|
||||
default:
|
||||
throw new GenericSignatureFormatError();
|
||||
}
|
||||
}
|
||||
|
||||
Type readTypeVariableSignature()
|
||||
{
|
||||
consume('T');
|
||||
String identifier = readIdentifier();
|
||||
consume(';');
|
||||
return new UnresolvedTypeVariable(container, identifier);
|
||||
}
|
||||
|
||||
private String readIdentifier()
|
||||
{
|
||||
int start = pos;
|
||||
char c;
|
||||
do
|
||||
{
|
||||
readChar();
|
||||
c = peekChar();
|
||||
} while (";:./<>-+*".indexOf(c) == -1);
|
||||
return signature.substring(start, pos);
|
||||
}
|
||||
|
||||
final char peekChar()
|
||||
{
|
||||
if (pos == signature.length())
|
||||
return '\u0000';
|
||||
else
|
||||
return signature.charAt(pos);
|
||||
}
|
||||
|
||||
final char readChar()
|
||||
{
|
||||
return signature.charAt(pos++);
|
||||
}
|
||||
|
||||
final void consume(char c)
|
||||
{
|
||||
if (readChar() != c)
|
||||
throw new GenericSignatureFormatError();
|
||||
}
|
||||
|
||||
final void end()
|
||||
{
|
||||
if (pos != signature.length())
|
||||
throw new GenericSignatureFormatError();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/* MethodSignatureParser.java
|
||||
Copyright (C) 2005
|
||||
Free Software Foundation
|
||||
|
||||
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.lang.reflect;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class MethodSignatureParser extends GenericSignatureParser
|
||||
{
|
||||
private TypeVariable[] typeParameters;
|
||||
private Type[] argTypes;
|
||||
private Type retType;
|
||||
private Type[] throwsSigs;
|
||||
|
||||
public MethodSignatureParser(Method method, String signature)
|
||||
{
|
||||
this(method, method.getDeclaringClass().getClassLoader(), signature);
|
||||
}
|
||||
|
||||
public MethodSignatureParser(Constructor method, String signature)
|
||||
{
|
||||
this(method, method.getDeclaringClass().getClassLoader(), signature);
|
||||
}
|
||||
|
||||
private MethodSignatureParser(GenericDeclaration wrapper,
|
||||
ClassLoader loader, String signature)
|
||||
{
|
||||
super(wrapper, loader, signature);
|
||||
|
||||
if (peekChar() == '<')
|
||||
{
|
||||
typeParameters = readFormalTypeParameters();
|
||||
}
|
||||
else
|
||||
{
|
||||
typeParameters = new TypeVariable[0];
|
||||
}
|
||||
consume('(');
|
||||
ArrayList args = new ArrayList();
|
||||
while (peekChar() != ')')
|
||||
{
|
||||
args.add(readTypeSignature());
|
||||
}
|
||||
argTypes = new Type[args.size()];
|
||||
args.toArray(argTypes);
|
||||
consume(')');
|
||||
retType = readTypeSignature();
|
||||
ArrayList throwsSigs = new ArrayList();
|
||||
while (peekChar() == '^')
|
||||
{
|
||||
consume('^');
|
||||
if(peekChar() == 'T')
|
||||
{
|
||||
throwsSigs.add(readTypeVariableSignature());
|
||||
}
|
||||
else
|
||||
{
|
||||
throwsSigs.add(readClassTypeSignature());
|
||||
}
|
||||
}
|
||||
this.throwsSigs = new Type[throwsSigs.size()];
|
||||
throwsSigs.toArray(this.throwsSigs);
|
||||
end();
|
||||
}
|
||||
|
||||
public TypeVariable[] getTypeParameters()
|
||||
{
|
||||
TypeImpl.resolve(typeParameters);
|
||||
return typeParameters;
|
||||
}
|
||||
|
||||
public Type[] getGenericParameterTypes()
|
||||
{
|
||||
TypeImpl.resolve(argTypes);
|
||||
return argTypes;
|
||||
}
|
||||
|
||||
public Type getGenericReturnType()
|
||||
{
|
||||
retType = TypeImpl.resolve(retType);
|
||||
return retType;
|
||||
}
|
||||
|
||||
public Type[] getGenericExceptionTypes()
|
||||
{
|
||||
TypeImpl.resolve(throwsSigs);
|
||||
return throwsSigs;
|
||||
}
|
||||
|
||||
private Type readTypeSignature()
|
||||
{
|
||||
switch (peekChar())
|
||||
{
|
||||
case 'T':
|
||||
return readTypeVariableSignature();
|
||||
case 'L':
|
||||
return readClassTypeSignature();
|
||||
case '[':
|
||||
return readArrayTypeSignature();
|
||||
case 'Z':
|
||||
consume('Z');
|
||||
return boolean.class;
|
||||
case 'B':
|
||||
consume('B');
|
||||
return byte.class;
|
||||
case 'S':
|
||||
consume('S');
|
||||
return short.class;
|
||||
case 'C':
|
||||
consume('C');
|
||||
return char.class;
|
||||
case 'I':
|
||||
consume('I');
|
||||
return int.class;
|
||||
case 'F':
|
||||
consume('F');
|
||||
return float.class;
|
||||
case 'J':
|
||||
consume('J');
|
||||
return long.class;
|
||||
case 'D':
|
||||
consume('D');
|
||||
return double.class;
|
||||
case 'V':
|
||||
consume('V');
|
||||
return void.class;
|
||||
default:
|
||||
throw new GenericSignatureFormatError();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/* TypeImpl.java
|
||||
Copyright (C) 2005
|
||||
Free Software Foundation
|
||||
|
||||
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.lang.reflect;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
abstract class TypeImpl implements Type
|
||||
{
|
||||
abstract Type resolve();
|
||||
|
||||
static void resolve(Type[] types)
|
||||
{
|
||||
for (int i = 0; i < types.length; i++)
|
||||
{
|
||||
types[i] = resolve(types[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static Type resolve(Type type)
|
||||
{
|
||||
if (type instanceof TypeImpl)
|
||||
{
|
||||
type = ((TypeImpl) type).resolve();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,7 @@ exception statement from your version. */
|
||||
|
||||
package gnu.java.locale;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
@@ -154,5 +155,57 @@ public class LocaleHelper
|
||||
}
|
||||
return localizedString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of all the locales for which there is a
|
||||
* {@link Collator} instance. A new array is returned each time.
|
||||
*/
|
||||
public static Locale[] getCollatorLocales()
|
||||
{
|
||||
// For now we don't bother caching. This is probably
|
||||
// not called very frequently. And, we would have to
|
||||
// clone the array anyway.
|
||||
if (LocaleData.collatorLocaleNames.length == 0)
|
||||
return new Locale[] { Locale.US };
|
||||
Locale[] result = new Locale[LocaleData.collatorLocaleNames.length];
|
||||
for (int i = 0; i < result.length; ++i)
|
||||
{
|
||||
String language;
|
||||
String region = "";
|
||||
String variant = "";
|
||||
String name = LocaleData.collatorLocaleNames[i];
|
||||
|
||||
language = name.substring(0, 2);
|
||||
|
||||
if (name.length() > 2)
|
||||
region = name.substring(3);
|
||||
|
||||
int index = region.indexOf("_");
|
||||
if (index > 0)
|
||||
{
|
||||
variant = region.substring(index + 1);
|
||||
region = region.substring(0, index - 1);
|
||||
}
|
||||
|
||||
result[i] = new Locale(language, region, variant);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of locales we know of.
|
||||
*/
|
||||
public static int getLocaleCount()
|
||||
{
|
||||
return LocaleData.localeNames.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Nth locale name.
|
||||
*/
|
||||
public static String getLocaleName(int n)
|
||||
{
|
||||
return LocaleData.localeNames[n];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/* DefaultContentHandlerFactory.java
|
||||
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.net;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ContentHandler;
|
||||
import java.net.ContentHandlerFactory;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
||||
/** Content Handler for Image types, using the AWT Toolkit's image decoder. */
|
||||
class ImageHandler extends ContentHandler
|
||||
{
|
||||
static ImageHandler instance = new ImageHandler();
|
||||
|
||||
public Object getContent(URLConnection urlc) throws IOException
|
||||
{
|
||||
// FIXME: implement using ImageIO
|
||||
// ClasspathToolkit tk = (ClasspathToolkit) Toolkit.getDefaultToolkit();
|
||||
// java.awt.image.ImageProducer ip = tk.createImageProducer(urlc.getURL());
|
||||
// return ip;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public class DefaultContentHandlerFactory implements ContentHandlerFactory
|
||||
{
|
||||
/** For now, hard code the list of types that we assume should
|
||||
* be supported by the Toolkit. ClasspathToolkit should perhaps provide
|
||||
* an API to express what Image MIME types the Toolkit understands.
|
||||
*/
|
||||
private static String[] known_image_types =
|
||||
{
|
||||
"image/bmp",
|
||||
"image/gif",
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/tiff",
|
||||
"image/x-portable-anymap",
|
||||
"image/x-cmu-raster",
|
||||
"image/x-xbitmap",
|
||||
"image/x-xpixmap"
|
||||
};
|
||||
|
||||
private static HashSet imageTypes
|
||||
= new HashSet(Arrays.asList(known_image_types));
|
||||
|
||||
public ContentHandler createContentHandler(String mimeType)
|
||||
{
|
||||
if (imageTypes.contains(mimeType))
|
||||
return ImageHandler.instance;
|
||||
// Currently, only image types are handled.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/* LocalServerSocket.java -- a unix domain server socket.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is a 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 of the License, 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; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, 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.local;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
|
||||
public final class LocalServerSocket extends ServerSocket
|
||||
{
|
||||
|
||||
// Fields.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private LocalSocketImpl myImpl;
|
||||
private boolean closed;
|
||||
|
||||
// Constructors.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public LocalServerSocket () throws IOException
|
||||
{
|
||||
myImpl = new LocalSocketImpl ();
|
||||
}
|
||||
|
||||
public LocalServerSocket (SocketAddress bindPoint) throws IOException
|
||||
{
|
||||
this ();
|
||||
bind (bindPoint);
|
||||
}
|
||||
|
||||
// Instance methods.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public void bind (SocketAddress bindPoint) throws IOException
|
||||
{
|
||||
bind (bindPoint, 0);
|
||||
}
|
||||
|
||||
public void bind (SocketAddress bindPoint, int backlog) throws IOException
|
||||
{
|
||||
myImpl.doCreate ();
|
||||
myImpl.bind (bindPoint);
|
||||
myImpl.listen (backlog);
|
||||
}
|
||||
|
||||
public InetAddress getInetAddress ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getLocalPort ()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
public SocketAddress getLocalSocketAddress ()
|
||||
{
|
||||
return myImpl.getLocalAddress ();
|
||||
}
|
||||
|
||||
public Socket accept () throws IOException
|
||||
{
|
||||
LocalSocket s = new LocalSocket (true);
|
||||
myImpl.accept (s.getLocalImpl());
|
||||
s.localConnected = true;
|
||||
return s;
|
||||
}
|
||||
|
||||
public void close () throws IOException
|
||||
{
|
||||
myImpl.close ();
|
||||
myImpl.unlink ();
|
||||
closed = true;
|
||||
}
|
||||
|
||||
public boolean isBound ()
|
||||
{
|
||||
return myImpl.getLocalAddress () != null;
|
||||
}
|
||||
|
||||
public boolean isClosed ()
|
||||
{
|
||||
return closed;
|
||||
}
|
||||
|
||||
public void setSoTimeout (int timeout)
|
||||
{
|
||||
throw new UnsupportedOperationException ("local sockets do not support timeouts");
|
||||
}
|
||||
|
||||
public int getSoTimeout ()
|
||||
{
|
||||
throw new UnsupportedOperationException ("local sockets do not support timeouts");
|
||||
}
|
||||
|
||||
public void setReuseAddress (boolean b)
|
||||
{
|
||||
throw new UnsupportedOperationException ("local sockets do not support reuse address");
|
||||
}
|
||||
|
||||
public boolean getReuseAddress ()
|
||||
{
|
||||
throw new UnsupportedOperationException ("local sockets do not support reuse address");
|
||||
}
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
return LocalServerSocket.class.getName() + " [ address="
|
||||
+ myImpl.getLocalAddress() + " ]";
|
||||
}
|
||||
|
||||
public void setReceiveBufferSize (int size)
|
||||
{
|
||||
throw new UnsupportedOperationException ("local sockets do not support buffer size");
|
||||
}
|
||||
|
||||
public int getReceiveBufferSize ()
|
||||
{
|
||||
throw new UnsupportedOperationException ("local sockets do not support buffer size");
|
||||
}
|
||||
|
||||
public void setSendBufferSize (int size)
|
||||
{
|
||||
throw new UnsupportedOperationException ("local sockets do not support buffer size");
|
||||
}
|
||||
|
||||
public int getSendBufferSize ()
|
||||
{
|
||||
throw new UnsupportedOperationException ("local sockets do not support buffer size");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
/* LocalSocket.java -- a unix domain client socket.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is a 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 of the License, 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; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, 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.local;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketImpl;
|
||||
|
||||
import java.nio.channels.IllegalBlockingModeException;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
/**
|
||||
* A local, or unix-domain socket. Unix domain sockets are connected on the
|
||||
* local filesystem itself, rather than a remote address.
|
||||
*/
|
||||
public final class LocalSocket extends Socket
|
||||
{
|
||||
|
||||
// Fields.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private final LocalSocketImpl localimpl;
|
||||
boolean localClosed;
|
||||
boolean localConnected;
|
||||
|
||||
// Constructors.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public LocalSocket () throws SocketException
|
||||
{
|
||||
super ();
|
||||
localimpl = new LocalSocketImpl ();
|
||||
}
|
||||
|
||||
public LocalSocket (LocalSocketAddress addr) throws SocketException
|
||||
{
|
||||
this ();
|
||||
try
|
||||
{
|
||||
connect (addr);
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
SocketException se = new SocketException ();
|
||||
se.initCause (ioe);
|
||||
throw se;
|
||||
}
|
||||
}
|
||||
|
||||
LocalSocket (boolean nocreate) throws IOException
|
||||
{
|
||||
super ();
|
||||
localimpl = new LocalSocketImpl (nocreate);
|
||||
}
|
||||
|
||||
// Instance methods.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public void bind (SocketAddress bindpoint) throws IOException
|
||||
{
|
||||
throw new SocketException ("binding local client sockets is nonsensical");
|
||||
}
|
||||
|
||||
public void connect (SocketAddress endpoint, int timeout) throws IOException
|
||||
{
|
||||
if (isClosed ())
|
||||
{
|
||||
throw new SocketException ("socket is closed");
|
||||
}
|
||||
if (! (endpoint instanceof LocalSocketAddress))
|
||||
{
|
||||
throw new IllegalArgumentException ("socket address is not a local address");
|
||||
}
|
||||
if (getChannel() != null && !getChannel().isBlocking())
|
||||
{
|
||||
throw new IllegalBlockingModeException ();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
localimpl.doCreate ();
|
||||
localimpl.localConnect ((LocalSocketAddress) endpoint);
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
close ();
|
||||
throw ioe;
|
||||
}
|
||||
localConnected = true;
|
||||
}
|
||||
|
||||
public InetAddress getInetAddress ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public InetAddress getLocalAddress ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getPort ()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getLocalPort ()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
public SocketChannel getChannel ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public SocketAddress getLocalSocketAddress ()
|
||||
{
|
||||
return localimpl.getLocalAddress ();
|
||||
}
|
||||
|
||||
public SocketAddress getRemoteSocketAddress ()
|
||||
{
|
||||
return localimpl.getRemoteAddress ();
|
||||
}
|
||||
|
||||
public InputStream getInputStream () throws IOException
|
||||
{
|
||||
return localimpl.getInputStream ();
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream () throws IOException
|
||||
{
|
||||
return localimpl.getOutputStream ();
|
||||
}
|
||||
|
||||
public void sendUrgentData (int b) throws IOException
|
||||
{
|
||||
localimpl.sendUrgentData (b);
|
||||
}
|
||||
|
||||
public synchronized void close () throws IOException
|
||||
{
|
||||
localimpl.close ();
|
||||
localClosed = true;
|
||||
}
|
||||
|
||||
public void shutdownInput () throws IOException
|
||||
{
|
||||
localimpl.shutdownInput ();
|
||||
}
|
||||
|
||||
public void shutdownOutput () throws IOException
|
||||
{
|
||||
localimpl.shutdownOutput ();
|
||||
}
|
||||
|
||||
public boolean isClosed ()
|
||||
{
|
||||
return localClosed;
|
||||
}
|
||||
|
||||
public boolean isBound ()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isConnected ()
|
||||
{
|
||||
return localConnected;
|
||||
}
|
||||
|
||||
// Unsupported methods.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public void setTcpNoDelay (boolean b) throws SocketException
|
||||
{
|
||||
throw new SocketException ("local sockets do not support this option");
|
||||
}
|
||||
|
||||
public boolean getTcpNoDelay() throws SocketException
|
||||
{
|
||||
throw new SocketException ("local sockets do not support this option");
|
||||
}
|
||||
|
||||
public void setSoLinger (boolean b, int i) throws SocketException
|
||||
{
|
||||
throw new SocketException ("local sockets do not support this option");
|
||||
}
|
||||
|
||||
public int getSoLinger () throws SocketException
|
||||
{
|
||||
throw new SocketException ("local sockets do not support this option");
|
||||
}
|
||||
|
||||
public void setOOBInline (boolean b) throws SocketException
|
||||
{
|
||||
throw new SocketException ("local sockets do not support this option");
|
||||
}
|
||||
|
||||
public boolean getOOBInline () throws SocketException
|
||||
{
|
||||
throw new SocketException ("local sockets do not support this option");
|
||||
}
|
||||
|
||||
public void setSoTimeout (int i) throws SocketException
|
||||
{
|
||||
throw new SocketException ("local sockets do not support this option");
|
||||
}
|
||||
|
||||
public int getSoTimeout () throws SocketException
|
||||
{
|
||||
throw new SocketException ("local sockets do not support this option");
|
||||
}
|
||||
|
||||
public void setSendBufferSize (int i) throws SocketException
|
||||
{
|
||||
throw new SocketException ("local sockets do not support this option");
|
||||
}
|
||||
|
||||
public int getSendBufferSize() throws SocketException
|
||||
{
|
||||
throw new SocketException ("local sockets do not support this option");
|
||||
}
|
||||
|
||||
public void setReceiveBufferSize (int i) throws SocketException
|
||||
{
|
||||
throw new SocketException ("local sockets do not support this option");
|
||||
}
|
||||
|
||||
public int getReceiveBufferSize () throws SocketException
|
||||
{
|
||||
throw new SocketException ("local sockets do not support this option");
|
||||
}
|
||||
|
||||
public void setKeepAlive (boolean b) throws SocketException
|
||||
{
|
||||
throw new SocketException ("local sockets do not support this option");
|
||||
}
|
||||
|
||||
public boolean getKeepAlive () throws SocketException
|
||||
{
|
||||
throw new SocketException ("local sockets do not support this option");
|
||||
}
|
||||
|
||||
public void setTrafficClass (int i) throws SocketException
|
||||
{
|
||||
throw new SocketException ("local sockets do not support this option");
|
||||
}
|
||||
|
||||
public int getTrafficClass () throws SocketException
|
||||
{
|
||||
throw new SocketException ("local sockets do not support this option");
|
||||
}
|
||||
|
||||
public void setReuseAddress (boolean b) throws SocketException
|
||||
{
|
||||
throw new SocketException ("local sockets do not support this option");
|
||||
}
|
||||
|
||||
public boolean getReuseAddress () throws SocketException
|
||||
{
|
||||
throw new SocketException ("local sockets do not support this option");
|
||||
}
|
||||
|
||||
LocalSocketImpl getLocalImpl ()
|
||||
{
|
||||
return localimpl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/* LocalSocketAddress.java -- unix-domain socket address.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is a 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 of the License, 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; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, 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.local;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
|
||||
public final class LocalSocketAddress extends SocketAddress
|
||||
{
|
||||
|
||||
// Fields.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private final String path;
|
||||
|
||||
// Constructor.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Creates a new unix domain socket address.
|
||||
*
|
||||
* @param path The path to the socket.
|
||||
* @throws NullPointerException If <i>path</i> is <tt>null</tt>.
|
||||
*/
|
||||
public LocalSocketAddress (String path)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
throw new NullPointerException ();
|
||||
}
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
// Instance methods.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the path of the socket.
|
||||
*
|
||||
* @return The path.
|
||||
*/
|
||||
public String getPath ()
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
public boolean equals (Object o)
|
||||
{
|
||||
if (!(o instanceof LocalSocketAddress))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return getPath ().equals (((LocalSocketAddress) o).getPath ());
|
||||
}
|
||||
|
||||
public int hashCode ()
|
||||
{
|
||||
return path.hashCode();
|
||||
}
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
return super.toString() + " [ " + path + " ]";
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user