feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
56
jdkSrc/jdk8/sun/java2d/DefaultDisposerRecord.java
Normal file
56
jdkSrc/jdk8/sun/java2d/DefaultDisposerRecord.java
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
/**
|
||||
* This class is the default DisposerRecord implementation which
|
||||
* holds pointers to the native disposal method and the data to be disposed.
|
||||
*/
|
||||
public class DefaultDisposerRecord implements DisposerRecord {
|
||||
private long dataPointer;
|
||||
private long disposerMethodPointer;
|
||||
|
||||
public DefaultDisposerRecord(long disposerMethodPointer, long dataPointer) {
|
||||
this.disposerMethodPointer = disposerMethodPointer;
|
||||
this.dataPointer = dataPointer;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
invokeNativeDispose(disposerMethodPointer,
|
||||
dataPointer);
|
||||
}
|
||||
|
||||
public long getDataPointer() {
|
||||
return dataPointer;
|
||||
}
|
||||
|
||||
public long getDisposerMethodPointer() {
|
||||
return disposerMethodPointer;
|
||||
}
|
||||
|
||||
public static native void invokeNativeDispose(long disposerMethodPointer,
|
||||
long dataPointer);
|
||||
}
|
||||
41
jdkSrc/jdk8/sun/java2d/DestSurfaceProvider.java
Normal file
41
jdkSrc/jdk8/sun/java2d/DestSurfaceProvider.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
import sun.java2d.pipe.hw.*;
|
||||
|
||||
/**
|
||||
* Classes implementing this interface provide access to their
|
||||
* destination surfaces.
|
||||
*/
|
||||
public interface DestSurfaceProvider {
|
||||
/**
|
||||
* Returns a surface currently used as a destination surface for rendering.
|
||||
*
|
||||
* @return destination surface
|
||||
*/
|
||||
public Surface getDestSurface();
|
||||
}
|
||||
262
jdkSrc/jdk8/sun/java2d/Disposer.java
Normal file
262
jdkSrc/jdk8/sun/java2d/Disposer.java
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
import sun.misc.ThreadGroupUtils;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.PhantomReference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
* This class is used for registering and disposing the native
|
||||
* data associated with java objects.
|
||||
*
|
||||
* The object can register itself by calling one of the addRecord
|
||||
* methods and providing either the pointer to the native disposal
|
||||
* method or a descendant of the DisposerRecord class with overridden
|
||||
* dispose() method.
|
||||
*
|
||||
* When the object becomes unreachable, the dispose() method
|
||||
* of the associated DisposerRecord object will be called.
|
||||
*
|
||||
* @see DisposerRecord
|
||||
*/
|
||||
public class Disposer implements Runnable {
|
||||
private static final ReferenceQueue queue = new ReferenceQueue();
|
||||
private static final Hashtable records = new Hashtable();
|
||||
|
||||
private static Disposer disposerInstance;
|
||||
public static final int WEAK = 0;
|
||||
public static final int PHANTOM = 1;
|
||||
public static int refType = PHANTOM;
|
||||
|
||||
static {
|
||||
java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
System.loadLibrary("awt");
|
||||
return null;
|
||||
}
|
||||
});
|
||||
initIDs();
|
||||
String type = (String) java.security.AccessController.doPrivileged(
|
||||
new sun.security.action.GetPropertyAction("sun.java2d.reftype"));
|
||||
if (type != null) {
|
||||
if (type.equals("weak")) {
|
||||
refType = WEAK;
|
||||
System.err.println("Using WEAK refs");
|
||||
} else {
|
||||
refType = PHANTOM;
|
||||
System.err.println("Using PHANTOM refs");
|
||||
}
|
||||
}
|
||||
disposerInstance = new Disposer();
|
||||
AccessController.doPrivileged(
|
||||
(PrivilegedAction<Void>) () -> {
|
||||
/* The thread must be a member of a thread group
|
||||
* which will not get GCed before VM exit.
|
||||
* Make its parent the top-level thread group.
|
||||
*/
|
||||
ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
|
||||
Thread t = new Thread(rootTG, disposerInstance, "Java2D Disposer");
|
||||
t.setContextClassLoader(null);
|
||||
t.setDaemon(true);
|
||||
t.setPriority(Thread.MAX_PRIORITY);
|
||||
t.start();
|
||||
return null;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the object and the native data for later disposal.
|
||||
* @param target Object to be registered
|
||||
* @param disposeMethod pointer to the native disposal method
|
||||
* @param pData pointer to the data to be passed to the
|
||||
* native disposal method
|
||||
*/
|
||||
public static void addRecord(Object target,
|
||||
long disposeMethod, long pData)
|
||||
{
|
||||
disposerInstance.add(target,
|
||||
new DefaultDisposerRecord(disposeMethod, pData));
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the object and the native data for later disposal.
|
||||
* @param target Object to be registered
|
||||
* @param rec the associated DisposerRecord object
|
||||
* @see DisposerRecord
|
||||
*/
|
||||
public static void addRecord(Object target, DisposerRecord rec) {
|
||||
disposerInstance.add(target, rec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual registration of the target object to be disposed.
|
||||
* @param target Object to be registered, or if target is an instance
|
||||
* of DisposerTarget, its associated disposer referent
|
||||
* will be the Object that is registered
|
||||
* @param rec the associated DisposerRecord object
|
||||
* @see DisposerRecord
|
||||
*/
|
||||
synchronized void add(Object target, DisposerRecord rec) {
|
||||
if (target instanceof DisposerTarget) {
|
||||
target = ((DisposerTarget)target).getDisposerReferent();
|
||||
}
|
||||
java.lang.ref.Reference ref;
|
||||
if (refType == PHANTOM) {
|
||||
ref = new PhantomReference(target, queue);
|
||||
} else {
|
||||
ref = new WeakReference(target, queue);
|
||||
}
|
||||
records.put(ref, rec);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (true) {
|
||||
try {
|
||||
Object obj = queue.remove();
|
||||
((Reference)obj).clear();
|
||||
DisposerRecord rec = (DisposerRecord)records.remove(obj);
|
||||
rec.dispose();
|
||||
obj = null;
|
||||
rec = null;
|
||||
clearDeferredRecords();
|
||||
} catch (Exception e) {
|
||||
System.out.println("Exception while removing reference.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a marker interface that, if implemented, means it
|
||||
* doesn't acquire any special locks, and is safe to
|
||||
* be disposed in the poll loop on whatever thread
|
||||
* which happens to be the Toolkit thread, is in use.
|
||||
*/
|
||||
public static interface PollDisposable {
|
||||
};
|
||||
|
||||
private static ArrayList<DisposerRecord> deferredRecords = null;
|
||||
|
||||
private static void clearDeferredRecords() {
|
||||
if (deferredRecords == null || deferredRecords.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (int i=0;i<deferredRecords.size(); i++) {
|
||||
try {
|
||||
DisposerRecord rec = deferredRecords.get(i);
|
||||
rec.dispose();
|
||||
} catch (Exception e) {
|
||||
System.out.println("Exception while disposing deferred rec.");
|
||||
}
|
||||
}
|
||||
deferredRecords.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* Set to indicate the queue is presently being polled.
|
||||
*/
|
||||
public static volatile boolean pollingQueue = false;
|
||||
|
||||
/*
|
||||
* The pollRemove() method is called back from a dispose method
|
||||
* that is running on the toolkit thread and wants to
|
||||
* dispose any pending refs that are safe to be disposed
|
||||
* on that thread.
|
||||
*/
|
||||
public static void pollRemove() {
|
||||
|
||||
/* This should never be called recursively, so this check
|
||||
* is just a safeguard against the unexpected.
|
||||
*/
|
||||
if (pollingQueue) {
|
||||
return;
|
||||
}
|
||||
Object obj;
|
||||
pollingQueue = true;
|
||||
int freed = 0;
|
||||
int deferred = 0;
|
||||
try {
|
||||
while ((obj = queue.poll()) != null
|
||||
&& freed < 10000 && deferred < 100) {
|
||||
freed++;
|
||||
((Reference)obj).clear();
|
||||
DisposerRecord rec = (DisposerRecord)records.remove(obj);
|
||||
if (rec instanceof PollDisposable) {
|
||||
rec.dispose();
|
||||
obj = null;
|
||||
rec = null;
|
||||
} else {
|
||||
if (rec == null) { // shouldn't happen, but just in case.
|
||||
continue;
|
||||
}
|
||||
deferred++;
|
||||
if (deferredRecords == null) {
|
||||
deferredRecords = new ArrayList<DisposerRecord>(5);
|
||||
}
|
||||
deferredRecords.add(rec);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Exception while removing reference.");
|
||||
} finally {
|
||||
pollingQueue = false;
|
||||
}
|
||||
}
|
||||
|
||||
private static native void initIDs();
|
||||
|
||||
/*
|
||||
* This was added for use by the 2D font implementation to avoid creation
|
||||
* of an additional disposer thread.
|
||||
* WARNING: this thread class monitors a specific queue, so a reference
|
||||
* added here must have been created with this queue. Failure to do
|
||||
* so will clutter the records hashmap and no one will be cleaning up
|
||||
* the reference queue.
|
||||
*/
|
||||
public static void addReference(Reference ref, DisposerRecord rec) {
|
||||
records.put(ref, rec);
|
||||
}
|
||||
|
||||
public static void addObjectRecord(Object obj, DisposerRecord rec) {
|
||||
records.put(new WeakReference(obj, queue) , rec);
|
||||
}
|
||||
|
||||
/* This is intended for use in conjunction with addReference(..)
|
||||
*/
|
||||
public static ReferenceQueue getQueue() {
|
||||
return queue;
|
||||
}
|
||||
|
||||
}
|
||||
34
jdkSrc/jdk8/sun/java2d/DisposerRecord.java
Normal file
34
jdkSrc/jdk8/sun/java2d/DisposerRecord.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
/**
|
||||
* This class is used to hold the resource to be
|
||||
* disposed.
|
||||
*/
|
||||
public interface DisposerRecord {
|
||||
public void dispose();
|
||||
}
|
||||
38
jdkSrc/jdk8/sun/java2d/DisposerTarget.java
Normal file
38
jdkSrc/jdk8/sun/java2d/DisposerTarget.java
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
/**
|
||||
* This is an interface which should be implemented by
|
||||
* the classes which use Disposer.
|
||||
*/
|
||||
public interface DisposerTarget {
|
||||
/**
|
||||
* Returns an object which will be
|
||||
* used as the referent in the ReferenceQueue
|
||||
*/
|
||||
public Object getDisposerReferent();
|
||||
}
|
||||
39
jdkSrc/jdk8/sun/java2d/FontSupport.java
Normal file
39
jdkSrc/jdk8/sun/java2d/FontSupport.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
import sun.awt.FontConfiguration;
|
||||
|
||||
/**
|
||||
* Font support for graphics environment
|
||||
*/
|
||||
public interface FontSupport {
|
||||
|
||||
/**
|
||||
* Returns the current font configuration.
|
||||
*/
|
||||
public FontConfiguration getFontConfiguration();
|
||||
}
|
||||
103
jdkSrc/jdk8/sun/java2d/HeadlessGraphicsEnvironment.java
Normal file
103
jdkSrc/jdk8/sun/java2d/HeadlessGraphicsEnvironment.java
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.HeadlessException;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.Font;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.awt.print.PrinterJob;
|
||||
import java.util.Map;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Locale;
|
||||
import java.util.Vector;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.MissingResourceException;
|
||||
import java.io.IOException;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.File;
|
||||
import java.util.NoSuchElementException;
|
||||
import sun.awt.FontConfiguration;
|
||||
import java.util.TreeMap;
|
||||
import java.util.Set;
|
||||
import java.awt.font.TextAttribute;
|
||||
import java.io.InputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.util.Properties;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
|
||||
/**
|
||||
* Headless decorator implementation of a SunGraphicsEnvironment
|
||||
*/
|
||||
|
||||
public class HeadlessGraphicsEnvironment extends GraphicsEnvironment {
|
||||
|
||||
private GraphicsEnvironment ge;
|
||||
|
||||
public HeadlessGraphicsEnvironment(GraphicsEnvironment ge) {
|
||||
this.ge = ge;
|
||||
}
|
||||
|
||||
public GraphicsDevice[] getScreenDevices()
|
||||
throws HeadlessException {
|
||||
throw new HeadlessException();
|
||||
}
|
||||
|
||||
public GraphicsDevice getDefaultScreenDevice()
|
||||
throws HeadlessException {
|
||||
throw new HeadlessException();
|
||||
}
|
||||
|
||||
public Point getCenterPoint() throws HeadlessException {
|
||||
throw new HeadlessException();
|
||||
}
|
||||
|
||||
public Rectangle getMaximumWindowBounds() throws HeadlessException {
|
||||
throw new HeadlessException();
|
||||
}
|
||||
|
||||
public Graphics2D createGraphics(BufferedImage img) {
|
||||
return ge.createGraphics(img); }
|
||||
|
||||
public Font[] getAllFonts() { return ge.getAllFonts(); }
|
||||
|
||||
public String[] getAvailableFontFamilyNames() {
|
||||
return ge.getAvailableFontFamilyNames(); }
|
||||
|
||||
public String[] getAvailableFontFamilyNames(Locale l) {
|
||||
return ge.getAvailableFontFamilyNames(l); }
|
||||
|
||||
/* Used by FontManager : internal API */
|
||||
public GraphicsEnvironment getSunGraphicsEnvironment() {
|
||||
return ge;
|
||||
}
|
||||
}
|
||||
55
jdkSrc/jdk8/sun/java2d/InvalidPipeException.java
Normal file
55
jdkSrc/jdk8/sun/java2d/InvalidPipeException.java
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
/**
|
||||
* Signals that some part of a graphics pipeline is not in an appropriate
|
||||
* state for the requested operation. The most likely cause of this is
|
||||
* an asynchronous change to the configuration of the destination surface
|
||||
* since the current set of rendering loops was chosen. Other potential
|
||||
* causes are the appearance or disappearance of overlapping opaque
|
||||
* windows which toggle the need to use platform graphics or direct
|
||||
* graphics access.
|
||||
*/
|
||||
public class InvalidPipeException extends IllegalStateException {
|
||||
/**
|
||||
* Constructs an InvalidPipeException with no detail message.
|
||||
* A detail message is a String that describes this particular exception.
|
||||
*/
|
||||
public InvalidPipeException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an InvalidPipeException with the specified detail
|
||||
* message. A detail message is a String that describes this particular
|
||||
* exception.
|
||||
* @param s the String that contains a detailed message
|
||||
*/
|
||||
public InvalidPipeException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
159
jdkSrc/jdk8/sun/java2d/NullSurfaceData.java
Normal file
159
jdkSrc/jdk8/sun/java2d/NullSurfaceData.java
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
|
||||
import sun.java2d.StateTrackable.State;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.java2d.pipe.NullPipe;
|
||||
|
||||
/**
|
||||
* This class provides an empty implementation of the SurfaceData
|
||||
* abstract superclass. All operations on it translate into NOP
|
||||
* or harmless operations.
|
||||
*/
|
||||
public class NullSurfaceData extends SurfaceData {
|
||||
public static final SurfaceData theInstance = new NullSurfaceData();
|
||||
|
||||
private NullSurfaceData() {
|
||||
super(State.IMMUTABLE, SurfaceType.Any, ColorModel.getRGBdefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this SurfaceData object to the invalid state. All Graphics
|
||||
* objects must get a new SurfaceData object via the refresh method
|
||||
* and revalidate their pipelines before continuing.
|
||||
*/
|
||||
public void invalidate() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new SurfaceData object that represents the current state
|
||||
* of the destination that this SurfaceData object describes.
|
||||
* This method is typically called when the SurfaceData is invalidated.
|
||||
*/
|
||||
public SurfaceData getReplacement() {
|
||||
return this;
|
||||
}
|
||||
|
||||
private final static NullPipe nullpipe = new NullPipe();
|
||||
|
||||
public void validatePipe(SunGraphics2D sg2d) {
|
||||
sg2d.drawpipe = nullpipe;
|
||||
sg2d.fillpipe = nullpipe;
|
||||
sg2d.shapepipe = nullpipe;
|
||||
sg2d.textpipe = nullpipe;
|
||||
sg2d.imagepipe = nullpipe;
|
||||
}
|
||||
|
||||
public GraphicsConfiguration getDeviceConfiguration() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a readable Raster which contains the pixels for the
|
||||
* specified rectangular region of the destination surface.
|
||||
* The coordinate origin of the returned Raster is the same as
|
||||
* the device space origin of the destination surface.
|
||||
* In some cases the returned Raster might also be writeable.
|
||||
* In most cases, the returned Raster might contain more pixels
|
||||
* than requested.
|
||||
*
|
||||
* @see useTightBBoxes
|
||||
*/
|
||||
public Raster getRaster(int x, int y, int w, int h) {
|
||||
throw new InvalidPipeException("should be NOP");
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the pixel accessibility of the destination surface
|
||||
* suggest that rendering algorithms might want to take
|
||||
* extra time to calculate a more accurate bounding box for
|
||||
* the operation being performed?
|
||||
* The typical case when this will be true is when a copy of
|
||||
* the pixels has to be made when doing a getRaster. The
|
||||
* fewer pixels copied, the faster the operation will go.
|
||||
*
|
||||
* @see getRaster
|
||||
*/
|
||||
public boolean useTightBBoxes() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pixel data for the specified Argb value packed
|
||||
* into an integer for easy storage and conveyance.
|
||||
*/
|
||||
public int pixelFor(int rgb) {
|
||||
return rgb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Argb representation for the specified integer value
|
||||
* which is packed in the format of the associated ColorModel.
|
||||
*/
|
||||
public int rgbFor(int pixel) {
|
||||
return pixel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bounds of the destination surface.
|
||||
*/
|
||||
public Rectangle getBounds() {
|
||||
return new Rectangle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs Security Permissions checks to see if a Custom
|
||||
* Composite object should be allowed access to the pixels
|
||||
* of this surface.
|
||||
*/
|
||||
protected void checkCustomComposite() {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a copyarea within this surface. Returns
|
||||
* false if there is no algorithm to perform the copyarea
|
||||
* given the current settings of the SunGraphics2D.
|
||||
*/
|
||||
public boolean copyArea(SunGraphics2D sg2d,
|
||||
int x, int y, int w, int h, int dx, int dy)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns destination Image associated with this SurfaceData (null)
|
||||
*/
|
||||
public Object getDestination() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
43
jdkSrc/jdk8/sun/java2d/ReentrantContext.java
Normal file
43
jdkSrc/jdk8/sun/java2d/ReentrantContext.java
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package sun.java2d;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
|
||||
/**
|
||||
* ReentrantContext is a base class to hold thread-local data supporting
|
||||
* reentrancy in either a ThreadLocal or a ConcurrentLinkedQueue
|
||||
*
|
||||
* @see ReentrantContextProvider
|
||||
*/
|
||||
public class ReentrantContext {
|
||||
// usage stored as a byte
|
||||
byte usage = ReentrantContextProvider.USAGE_TL_INACTIVE;
|
||||
/*
|
||||
* Reference to this instance (hard, soft or weak).
|
||||
* @see ReentrantContextProvider#refType
|
||||
*/
|
||||
Reference<? extends ReentrantContext> reference = null;
|
||||
}
|
||||
169
jdkSrc/jdk8/sun/java2d/ReentrantContextProvider.java
Normal file
169
jdkSrc/jdk8/sun/java2d/ReentrantContextProvider.java
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package sun.java2d;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* This abstract ReentrantContextProvider helper class manages the creation,
|
||||
* storage, and retrieval of concrete ReentrantContext instances which can be
|
||||
* subclassed to hold cached contextual data.
|
||||
*
|
||||
* It supports reentrancy as every call to acquire() provides a new unique context
|
||||
* instance that must later be returned for reuse by a call to release(ctx)
|
||||
* (typically in a try/finally block).
|
||||
*
|
||||
* It has a couple of abstract implementations which store references in a queue
|
||||
* and/or thread-local storage.
|
||||
* The Providers can be configured to hold ReentrantContext instances in memory
|
||||
* using hard, soft or weak references.
|
||||
*
|
||||
* The acquire() and release() methods are used to retrieve and return the contexts.
|
||||
*
|
||||
* The {@code newContext()} method remains abstract in all implementations and
|
||||
* must be provided by the module to create a new subclass of ReentrantContext
|
||||
* with the appropriate contextual data in it.
|
||||
*
|
||||
* Sample Usage:
|
||||
* - create a subclass ReentrantContextImpl to hold the thread state:
|
||||
*
|
||||
* static final class ReentrantContextImpl extends ReentrantContext {
|
||||
* // specific cached data
|
||||
* }
|
||||
*
|
||||
* - create the appropriate ReentrantContextProvider:
|
||||
*
|
||||
* private static final ReentrantContextProvider<ReentrantContextImpl> contextProvider =
|
||||
* new ReentrantContextProviderTL<ReentrantContextImpl>(ReentrantContextProvider.REF_WEAK)
|
||||
* {
|
||||
* @Override
|
||||
* protected ReentrantContextImpl newContext() {
|
||||
* return new ReentrantContextImpl();
|
||||
* }
|
||||
* };
|
||||
* ...
|
||||
* void someMethod() {
|
||||
* ReentrantContextImpl ctx = contextProvider.acquire();
|
||||
* try {
|
||||
* // use the context
|
||||
* } finally {
|
||||
* contextProvider.release(ctx);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @param <K> ReentrantContext subclass
|
||||
*
|
||||
* @see ReentrantContext
|
||||
*/
|
||||
public abstract class ReentrantContextProvider<K extends ReentrantContext>
|
||||
{
|
||||
// thread-local storage: inactive
|
||||
static final byte USAGE_TL_INACTIVE = 0;
|
||||
// thread-local storage: in use
|
||||
static final byte USAGE_TL_IN_USE = 1;
|
||||
// CLQ storage
|
||||
static final byte USAGE_CLQ = 2;
|
||||
|
||||
// hard reference
|
||||
public static final int REF_HARD = 0;
|
||||
// soft reference
|
||||
public static final int REF_SOFT = 1;
|
||||
// weak reference
|
||||
public static final int REF_WEAK = 2;
|
||||
|
||||
/* members */
|
||||
// internal reference type
|
||||
private final int refType;
|
||||
|
||||
/**
|
||||
* Create a new ReentrantContext provider using the given reference type
|
||||
* among hard, soft or weak
|
||||
*
|
||||
* @param refType reference type
|
||||
*/
|
||||
protected ReentrantContextProvider(final int refType) {
|
||||
this.refType = refType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ReentrantContext instance
|
||||
*
|
||||
* @return new ReentrantContext instance
|
||||
*/
|
||||
protected abstract K newContext();
|
||||
|
||||
/**
|
||||
* Give a ReentrantContext instance for the current thread
|
||||
*
|
||||
* @return ReentrantContext instance
|
||||
*/
|
||||
public abstract K acquire();
|
||||
|
||||
/**
|
||||
* Restore the given ReentrantContext instance for reuse
|
||||
*
|
||||
* @param ctx ReentrantContext instance
|
||||
*/
|
||||
public abstract void release(K ctx);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected final Reference<K> getOrCreateReference(final K ctx) {
|
||||
if (ctx.reference == null) {
|
||||
// Create the reference:
|
||||
switch (refType) {
|
||||
case REF_HARD:
|
||||
ctx.reference = new HardReference<K>(ctx);
|
||||
break;
|
||||
case REF_SOFT:
|
||||
ctx.reference = new SoftReference<K>(ctx);
|
||||
break;
|
||||
default:
|
||||
case REF_WEAK:
|
||||
ctx.reference = new WeakReference<K>(ctx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (Reference<K>) ctx.reference;
|
||||
}
|
||||
|
||||
/* Missing HardReference implementation */
|
||||
static final class HardReference<V> extends WeakReference<V> {
|
||||
// kept strong reference:
|
||||
private final V strongRef;
|
||||
|
||||
HardReference(final V referent) {
|
||||
// no referent needed for the parent WeakReference:
|
||||
super(null);
|
||||
this.strongRef = referent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get() {
|
||||
return strongRef;
|
||||
}
|
||||
}
|
||||
}
|
||||
89
jdkSrc/jdk8/sun/java2d/ReentrantContextProviderCLQ.java
Normal file
89
jdkSrc/jdk8/sun/java2d/ReentrantContextProviderCLQ.java
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package sun.java2d;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
/**
|
||||
* This ReentrantContextProvider implementation uses one ConcurrentLinkedQueue
|
||||
* to store all ReentrantContext instances (thread and its child contexts)
|
||||
*
|
||||
* Note: this implementation keeps less contexts in memory depending on the
|
||||
* concurrent active threads in contrary to a ThreadLocal provider. However,
|
||||
* it is slower in highly concurrent workloads.
|
||||
*
|
||||
* @param <K> ReentrantContext subclass
|
||||
*/
|
||||
public abstract class ReentrantContextProviderCLQ<K extends ReentrantContext>
|
||||
extends ReentrantContextProvider<K>
|
||||
{
|
||||
// ReentrantContext queue to store all contexts
|
||||
private final ConcurrentLinkedQueue<Reference<K>> ctxQueue
|
||||
= new ConcurrentLinkedQueue<Reference<K>>();
|
||||
|
||||
/**
|
||||
* Create a new ReentrantContext provider using the given reference type
|
||||
* among hard, soft or weak based using a ConcurrentLinkedQueue storage
|
||||
*
|
||||
* @param refType reference type
|
||||
*/
|
||||
public ReentrantContextProviderCLQ(final int refType) {
|
||||
super(refType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Give a ReentrantContext instance for the current thread
|
||||
*
|
||||
* @return ReentrantContext instance
|
||||
*/
|
||||
@Override
|
||||
public final K acquire() {
|
||||
K ctx = null;
|
||||
// Drain queue if all referent are null:
|
||||
Reference<K> ref = null;
|
||||
while ((ctx == null) && ((ref = ctxQueue.poll()) != null)) {
|
||||
ctx = ref.get();
|
||||
}
|
||||
if (ctx == null) {
|
||||
// create a new ReentrantContext if none is available
|
||||
ctx = newContext();
|
||||
ctx.usage = USAGE_CLQ;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the given ReentrantContext instance for reuse
|
||||
*
|
||||
* @param ctx ReentrantContext instance
|
||||
*/
|
||||
@Override
|
||||
public final void release(final K ctx) {
|
||||
if (ctx.usage == USAGE_CLQ) {
|
||||
ctxQueue.offer(getOrCreateReference(ctx));
|
||||
}
|
||||
}
|
||||
}
|
||||
123
jdkSrc/jdk8/sun/java2d/ReentrantContextProviderTL.java
Normal file
123
jdkSrc/jdk8/sun/java2d/ReentrantContextProviderTL.java
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package sun.java2d;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
|
||||
/**
|
||||
* This ReentrantContextProvider implementation uses a ThreadLocal to hold
|
||||
* the first ReentrantContext per thread and a ReentrantContextProviderCLQ to
|
||||
* store child ReentrantContext instances needed during recursion.
|
||||
*
|
||||
* Note: this implementation may keep up to one context in memory per thread.
|
||||
* Child contexts for recursive uses are stored in the queue using a WEAK
|
||||
* reference by default unless specified in the 2 argument constructor.
|
||||
*
|
||||
* @param <K> ReentrantContext subclass
|
||||
*/
|
||||
public abstract class ReentrantContextProviderTL<K extends ReentrantContext>
|
||||
extends ReentrantContextProvider<K>
|
||||
{
|
||||
// Thread-local storage:
|
||||
private final ThreadLocal<Reference<K>> ctxTL
|
||||
= new ThreadLocal<Reference<K>>();
|
||||
|
||||
// ReentrantContext CLQ provider for child contexts:
|
||||
private final ReentrantContextProviderCLQ<K> ctxProviderCLQ;
|
||||
|
||||
/**
|
||||
* Create a new ReentrantContext provider using the given reference type
|
||||
* among hard, soft or weak.
|
||||
* It uses weak reference for the child contexts.
|
||||
*
|
||||
* @param refType reference type
|
||||
*/
|
||||
public ReentrantContextProviderTL(final int refType) {
|
||||
this(refType, REF_WEAK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ReentrantContext provider using the given reference types
|
||||
* among hard, soft or weak
|
||||
*
|
||||
* @param refTypeTL reference type used by ThreadLocal
|
||||
* @param refTypeCLQ reference type used by ReentrantContextProviderCLQ
|
||||
*/
|
||||
public ReentrantContextProviderTL(final int refTypeTL, final int refTypeCLQ)
|
||||
{
|
||||
super(refTypeTL);
|
||||
|
||||
final ReentrantContextProviderTL<K> parent = this;
|
||||
|
||||
this.ctxProviderCLQ = new ReentrantContextProviderCLQ<K>(refTypeCLQ) {
|
||||
@Override
|
||||
protected K newContext() {
|
||||
return parent.newContext();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Give a ReentrantContext instance for the current thread
|
||||
*
|
||||
* @return ReentrantContext instance
|
||||
*/
|
||||
@Override
|
||||
public final K acquire() {
|
||||
K ctx = null;
|
||||
final Reference<K> ref = ctxTL.get();
|
||||
if (ref != null) {
|
||||
ctx = ref.get();
|
||||
}
|
||||
if (ctx == null) {
|
||||
// create a new ReentrantContext if none is available
|
||||
ctx = newContext();
|
||||
// update thread local reference:
|
||||
ctxTL.set(getOrCreateReference(ctx));
|
||||
}
|
||||
// Check reentrance:
|
||||
if (ctx.usage == USAGE_TL_INACTIVE) {
|
||||
ctx.usage = USAGE_TL_IN_USE;
|
||||
} else {
|
||||
// get or create another ReentrantContext from CLQ provider:
|
||||
ctx = ctxProviderCLQ.acquire();
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the given ReentrantContext instance for reuse
|
||||
*
|
||||
* @param ctx ReentrantContext instance
|
||||
*/
|
||||
@Override
|
||||
public final void release(final K ctx) {
|
||||
if (ctx.usage == USAGE_TL_IN_USE) {
|
||||
ctx.usage = USAGE_TL_INACTIVE;
|
||||
} else {
|
||||
ctxProviderCLQ.release(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
136
jdkSrc/jdk8/sun/java2d/ScreenUpdateManager.java
Normal file
136
jdkSrc/jdk8/sun/java2d/ScreenUpdateManager.java
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import sun.awt.Win32GraphicsConfig;
|
||||
import sun.awt.windows.WComponentPeer;
|
||||
import sun.java2d.d3d.D3DScreenUpdateManager;
|
||||
import sun.java2d.windows.WindowsFlags;
|
||||
|
||||
/**
|
||||
* This class handles the creation of on-screen surfaces and
|
||||
* corresponding graphics objects.
|
||||
*
|
||||
* By default it delegates the surface creation to the
|
||||
* particular GraphicsConfiguration classes.
|
||||
*/
|
||||
public class ScreenUpdateManager {
|
||||
private static ScreenUpdateManager theInstance;
|
||||
|
||||
protected ScreenUpdateManager() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a SunGraphics2D object for the surface,
|
||||
* given the parameters.
|
||||
*
|
||||
* @param sd surface data for which a graphics is to be created
|
||||
* @param peer peer which owns the surface
|
||||
* @param fgColor fg color to be used in the graphics
|
||||
* @param bgColor bg color to be used in the graphics
|
||||
* @param font font to be used in the graphics
|
||||
* @return a SunGraphics2D object for rendering to the passed surface
|
||||
*/
|
||||
public synchronized Graphics2D createGraphics(SurfaceData sd,
|
||||
WComponentPeer peer, Color fgColor, Color bgColor, Font font)
|
||||
{
|
||||
return new SunGraphics2D(sd, fgColor, bgColor, font);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns the surface for the peer. This surface becomes
|
||||
* managed by this manager. To remove the surface from the managed list
|
||||
* {@code}dropScreenSurface(SurfaceData){@code} will need to be called.
|
||||
*
|
||||
* The default implementation delegates surface creation
|
||||
* to the passed in GraphicsConfiguration object.
|
||||
*
|
||||
* @param gc graphics configuration for which the surface is to be created
|
||||
* @param peer peer for which the onscreen surface is to be created
|
||||
* @param bbNum number of back-buffers requested for this peer
|
||||
* @param isResize whether this surface is being created in response to
|
||||
* a component resize event
|
||||
* @return a SurfaceData to be used for on-screen rendering for this peer.
|
||||
* @see #dropScreenSurface(SurfaceData)
|
||||
*/
|
||||
public SurfaceData createScreenSurface(Win32GraphicsConfig gc,
|
||||
WComponentPeer peer, int bbNum,
|
||||
boolean isResize)
|
||||
{
|
||||
return gc.createSurfaceData(peer, bbNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops the passed surface from the list of managed surfaces.
|
||||
*
|
||||
* Nothing happens if the surface wasn't managed by this manager.
|
||||
*
|
||||
* @param sd SurfaceData to be removed from the list of managed surfaces
|
||||
*/
|
||||
public void dropScreenSurface(SurfaceData sd) {}
|
||||
|
||||
/**
|
||||
* Returns a replacement SurfaceData for the invalid passed one.
|
||||
*
|
||||
* This method should be used by SurfaceData's created by
|
||||
* the ScreenUpdateManager for providing replacement surfaces.
|
||||
*
|
||||
* @param peer to which the old surface belongs
|
||||
* @param oldsd the old (invalid) surface to get replaced
|
||||
* @return a replacement surface
|
||||
* @see sun.java2d.d3d.D3DSurfaceData.D3DWindowSurfaceData#getReplacement()
|
||||
* @see sun.java2d.windows.GDIWindowSurfaceData#getReplacement()
|
||||
*/
|
||||
public SurfaceData getReplacementScreenSurface(WComponentPeer peer,
|
||||
SurfaceData oldsd)
|
||||
{
|
||||
SurfaceData surfaceData = peer.getSurfaceData();
|
||||
if (surfaceData == null || surfaceData.isValid()) {
|
||||
return surfaceData;
|
||||
}
|
||||
peer.replaceSurfaceData();
|
||||
return peer.getSurfaceData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an (singleton) instance of the screen surfaces
|
||||
* manager class.
|
||||
* @return instance of onscreen surfaces manager
|
||||
*/
|
||||
public static synchronized ScreenUpdateManager getInstance() {
|
||||
if (theInstance == null) {
|
||||
if (WindowsFlags.isD3DEnabled()) {
|
||||
theInstance = new D3DScreenUpdateManager();
|
||||
} else {
|
||||
theInstance = new ScreenUpdateManager();
|
||||
}
|
||||
}
|
||||
return theInstance;
|
||||
}
|
||||
}
|
||||
393
jdkSrc/jdk8/sun/java2d/Spans.java
Normal file
393
jdkSrc/jdk8/sun/java2d/Spans.java
Normal file
@@ -0,0 +1,393 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2000, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* Maintains a list of half-open intervals, called Spans.
|
||||
* A Span can be tested against the list of Spans
|
||||
* for intersection.
|
||||
*/
|
||||
public class Spans {
|
||||
|
||||
/**
|
||||
* This class will sort and collapse its span
|
||||
* entries after this many span additions via
|
||||
* the <code>add</code> method.
|
||||
*/
|
||||
private static final int kMaxAddsSinceSort = 256;
|
||||
|
||||
/**
|
||||
* Holds a list of individual
|
||||
* Span instances.
|
||||
*/
|
||||
private List mSpans = new Vector(kMaxAddsSinceSort);
|
||||
|
||||
/**
|
||||
* The number of <code>Span</code>
|
||||
* instances that have been added
|
||||
* to this object without a sort
|
||||
* and collapse taking place.
|
||||
*/
|
||||
private int mAddsSinceSort = 0;
|
||||
|
||||
public Spans() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a span covering the half open interval
|
||||
* including <code>start</code> up to
|
||||
* but not including <code>end</code>.
|
||||
*/
|
||||
public void add(float start, float end) {
|
||||
|
||||
if (mSpans != null) {
|
||||
mSpans.add(new Span(start, end));
|
||||
|
||||
if (++mAddsSinceSort >= kMaxAddsSinceSort) {
|
||||
sortAndCollapse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a span which covers the entire range.
|
||||
* This call is logically equivalent to
|
||||
* <code>add(Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY)</code>
|
||||
* The result of making this call is that
|
||||
* all future <code>add</code> calls are ignored
|
||||
* and the <code>intersects</code> method always
|
||||
* returns true.
|
||||
*/
|
||||
public void addInfinite() {
|
||||
mSpans = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the span defined by the half-open
|
||||
* interval from <code>start</code> up to,
|
||||
* but not including, <code>end</code> intersects
|
||||
* any of the spans defined by this instance.
|
||||
*/
|
||||
public boolean intersects(float start, float end) {
|
||||
boolean doesIntersect;
|
||||
|
||||
if (mSpans != null) {
|
||||
|
||||
/* If we have added any spans since we last
|
||||
* sorted and collapsed our list of spans
|
||||
* then we need to resort and collapse.
|
||||
*/
|
||||
if (mAddsSinceSort > 0) {
|
||||
sortAndCollapse();
|
||||
}
|
||||
|
||||
/* The SpanIntersection comparator considers
|
||||
* two spans equal if they intersect. If
|
||||
* the search finds a match then we have an
|
||||
* intersection.
|
||||
*/
|
||||
int found = Collections.binarySearch(mSpans,
|
||||
new Span(start, end),
|
||||
SpanIntersection.instance);
|
||||
|
||||
doesIntersect = found >= 0;
|
||||
|
||||
/* The addInfinite() method has been invoked so
|
||||
* everything intersect this instance.
|
||||
*/
|
||||
} else {
|
||||
doesIntersect = true;
|
||||
}
|
||||
|
||||
return doesIntersect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the spans in ascending order by their
|
||||
* start position. After the spans are sorted
|
||||
* collapse any spans that intersect into a
|
||||
* single span. The result is a sorted,
|
||||
* non-overlapping list of spans.
|
||||
*/
|
||||
private void sortAndCollapse() {
|
||||
|
||||
Collections.sort(mSpans);
|
||||
mAddsSinceSort = 0;
|
||||
|
||||
Iterator iter = mSpans.iterator();
|
||||
|
||||
/* Have 'span' start at the first span in
|
||||
* the collection. The collection may be empty
|
||||
* so we're careful.
|
||||
*/
|
||||
Span span = null;
|
||||
if (iter.hasNext()) {
|
||||
span = (Span) iter.next();
|
||||
}
|
||||
|
||||
/* Loop over the spans collapsing those that intersect
|
||||
* into a single span.
|
||||
*/
|
||||
while (iter.hasNext()) {
|
||||
|
||||
Span nextSpan = (Span) iter.next();
|
||||
|
||||
/* The spans are in ascending start position
|
||||
* order and so the next span's starting point
|
||||
* is either in the span we are trying to grow
|
||||
* or it is beyond the first span and thus the
|
||||
* two spans do not intersect.
|
||||
*
|
||||
* span: <----------<
|
||||
* nextSpan: <------ (intersects)
|
||||
* nextSpan: <------ (doesn't intersect)
|
||||
*
|
||||
* If the spans intersect then we'll remove
|
||||
* nextSpan from the list. If nextSpan's
|
||||
* ending was beyond the first's then
|
||||
* we extend the first.
|
||||
*
|
||||
* span: <----------<
|
||||
* nextSpan: <-----< (don't change span)
|
||||
* nextSpan: <-----------< (grow span)
|
||||
*/
|
||||
|
||||
if (span.subsume(nextSpan)) {
|
||||
iter.remove();
|
||||
|
||||
/* The next span did not intersect the current
|
||||
* span and so it can not be collapsed. Instead
|
||||
* it becomes the start of the next set of spans
|
||||
* to be collapsed.
|
||||
*/
|
||||
} else {
|
||||
span = nextSpan;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// For debugging.
|
||||
|
||||
private void printSpans() {
|
||||
System.out.println("----------");
|
||||
if (mSpans != null) {
|
||||
Iterator iter = mSpans.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Span span = (Span) iter.next();
|
||||
System.out.println(span);
|
||||
}
|
||||
}
|
||||
System.out.println("----------");
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Holds a single half-open interval.
|
||||
*/
|
||||
static class Span implements Comparable {
|
||||
|
||||
/**
|
||||
* The span includes the starting point.
|
||||
*/
|
||||
private float mStart;
|
||||
|
||||
/**
|
||||
* The span goes up to but does not include
|
||||
* the ending point.
|
||||
*/
|
||||
private float mEnd;
|
||||
|
||||
/**
|
||||
* Create a half-open interval including
|
||||
* <code>start</code> but not including
|
||||
* <code>end</code>.
|
||||
*/
|
||||
Span(float start, float end) {
|
||||
mStart = start;
|
||||
mEnd = end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the start of the <code>Span</code>.
|
||||
* The start is considered part of the
|
||||
* half-open interval.
|
||||
*/
|
||||
final float getStart() {
|
||||
return mStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the end of the <code>Span</code>.
|
||||
* The end is not considered part of the
|
||||
* half-open interval.
|
||||
*/
|
||||
final float getEnd() {
|
||||
return mEnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the initial position of the
|
||||
* <code>Span</code>.
|
||||
*/
|
||||
final void setStart(float start) {
|
||||
mStart = start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the terminal position of the
|
||||
* <code>Span</code>.
|
||||
*/
|
||||
final void setEnd(float end) {
|
||||
mEnd = end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to alter this <code>Span</code>
|
||||
* to include <code>otherSpan</code> without
|
||||
* altering this span's starting position.
|
||||
* If <code>otherSpan</code> can be so consumed
|
||||
* by this <code>Span</code> then <code>true</code>
|
||||
* is returned.
|
||||
*/
|
||||
boolean subsume(Span otherSpan) {
|
||||
|
||||
/* We can only subsume 'otherSpan' if
|
||||
* its starting position lies in our
|
||||
* interval.
|
||||
*/
|
||||
boolean isSubsumed = contains(otherSpan.mStart);
|
||||
|
||||
/* If the other span's starting position
|
||||
* was in our interval and the other span
|
||||
* was longer than this span, then we need
|
||||
* to grow this span to cover the difference.
|
||||
*/
|
||||
if (isSubsumed && otherSpan.mEnd > mEnd) {
|
||||
mEnd = otherSpan.mEnd;
|
||||
}
|
||||
|
||||
return isSubsumed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the passed in position
|
||||
* lies in the half-open interval defined
|
||||
* by this <code>Span</code>.
|
||||
*/
|
||||
boolean contains(float pos) {
|
||||
return mStart <= pos && pos < mEnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rank spans according to their starting
|
||||
* position. The end position is ignored
|
||||
* in this ranking.
|
||||
*/
|
||||
public int compareTo(Object o) {
|
||||
Span otherSpan = (Span) o;
|
||||
float otherStart = otherSpan.getStart();
|
||||
int result;
|
||||
|
||||
if (mStart < otherStart) {
|
||||
result = -1;
|
||||
} else if (mStart > otherStart) {
|
||||
result = 1;
|
||||
} else {
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Span: " + mStart + " to " + mEnd;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This class ranks a pair of <code>Span</code>
|
||||
* instances. If the instances intersect they
|
||||
* are deemed equal otherwise they are ranked
|
||||
* by their relative position. Use
|
||||
* <code>SpanIntersection.instance</code> to
|
||||
* get the single instance of this class.
|
||||
*/
|
||||
static class SpanIntersection implements Comparator {
|
||||
|
||||
/**
|
||||
* This class is a Singleton and the following
|
||||
* is the single instance.
|
||||
*/
|
||||
static final SpanIntersection instance =
|
||||
new SpanIntersection();
|
||||
|
||||
/**
|
||||
* Only this class can create instances of itself.
|
||||
*/
|
||||
private SpanIntersection() {
|
||||
|
||||
}
|
||||
|
||||
public int compare(Object o1, Object o2) {
|
||||
int result;
|
||||
Span span1 = (Span) o1;
|
||||
Span span2 = (Span) o2;
|
||||
|
||||
/* Span 1 is entirely to the left of span2.
|
||||
* span1: <-----<
|
||||
* span2: <-----<
|
||||
*/
|
||||
if (span1.getEnd() <= span2.getStart()) {
|
||||
result = -1;
|
||||
|
||||
/* Span 2 is entirely to the right of span2.
|
||||
* span1: <-----<
|
||||
* span2: <-----<
|
||||
*/
|
||||
} else if (span1.getStart() >= span2.getEnd()) {
|
||||
result = 1;
|
||||
|
||||
/* Otherwise they intersect and we declare them equal.
|
||||
*/
|
||||
} else {
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
256
jdkSrc/jdk8/sun/java2d/StateTrackable.java
Normal file
256
jdkSrc/jdk8/sun/java2d/StateTrackable.java
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
/**
|
||||
* This interface is implemented by classes which contain complex state
|
||||
* so that other objects can track whether or not their state has changed
|
||||
* since earlier interactions with the object.
|
||||
* <p>
|
||||
* The suggested usage pattern for code that manages some trackable data
|
||||
* is as follows:
|
||||
* <pre>
|
||||
* class Trackable implements StateTrackable {
|
||||
* TrackedInfo data;
|
||||
* State curState = STABLE;
|
||||
* StateTracker curTracker = null;
|
||||
* // Hypothetical method to return a static piece of our tracked data.
|
||||
* // Assume that Datum is either a copy of some piece of the tracked
|
||||
* // data or that it is itself immutable.
|
||||
* public Datum getSomeDatum(int key) {
|
||||
* // No need to modify the state for this type of "get" call.
|
||||
* return data.getDatum(key);
|
||||
* }
|
||||
* // Hypothetical method to return a raw reference to our tracked data.
|
||||
* public TrackedInfo getRawHandleToInfo() {
|
||||
* // Since we are returning a raw reference to our tracked
|
||||
* // data and since we can not track what the caller will
|
||||
* // do with that reference, we can no longer track the
|
||||
* // state of this data.
|
||||
* synchronized (this) {
|
||||
* // Note: modifying both curState and curTracker requires
|
||||
* // synchronization against the getStateTracker method.
|
||||
* curState = UNTRACKABLE;
|
||||
* curTracker = null;
|
||||
* }
|
||||
* return data;
|
||||
* }
|
||||
* // Hypothetical method to set a single piece of data to some
|
||||
* // new static value.
|
||||
* public void setSomeDatum(int key, Datum datum) {
|
||||
* data.setDatum(key, datum);
|
||||
* // We do not need to change state for this, we simply
|
||||
* // invalidate the outstanding StateTracker objects.
|
||||
* // Note: setting curTracker to null requires no synchronization.
|
||||
* curTracker = null;
|
||||
* }
|
||||
* // getStateTracker must be synchronized against any code that
|
||||
* // changes the State.
|
||||
* public synchronized StateTracker getStateTracker() {
|
||||
* StateTracker st = curTracker;
|
||||
* if (st == null) {
|
||||
* switch (curState) {
|
||||
* case IMMUTABLE: st = StateTracker.ALWAYS_CURRENT; break;
|
||||
* case STABLE: st = new Tracker(this); break;
|
||||
* case DYNAMIC: st = StateTracker.NEVER_CURRENT; break;
|
||||
* case UNTRACKABLE: st = StateTracker.NEVER_CURRENT; break;
|
||||
* }
|
||||
* curTracker = st;
|
||||
* }
|
||||
* return st;
|
||||
* }
|
||||
*
|
||||
* static class Tracker implements StateTracker {
|
||||
* Trackable theTrackable;
|
||||
* public Tracker(Trackable t) {
|
||||
* theTrackable = t;
|
||||
* }
|
||||
* public boolean isCurrent() {
|
||||
* return (theTrackable.curTracker == this);
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* Note that the mechanism shown above for invalidating outstanding
|
||||
* StateTracker objects is not the most theoretically conservative
|
||||
* way to implement state tracking in a "set" method.
|
||||
* There is a small window of opportunity after the data has changed
|
||||
* before the outstanding StateTracker objects are invalidated and
|
||||
* where they will indicate that the data is still the same as when
|
||||
* they were instantiated.
|
||||
* While this is technically inaccurate, it is acceptable since the more
|
||||
* conservative approaches to state management are much more complex and
|
||||
* cost much more in terms of performance for a very small gain in
|
||||
* correctness.
|
||||
* For example:
|
||||
* <p>
|
||||
* The most conservative approach would be to synchronize all accesses
|
||||
* and all modifications to the data, including its State.
|
||||
* This would require synchronized blocks around some potentially large
|
||||
* bodies of code which would impact the multi-threaded scalability of
|
||||
* the implementation.
|
||||
* Further, if data is to be coordinated or transferred between two
|
||||
* trackable objects then both would need to be synchronized raising
|
||||
* the possibility of deadlock unless some strict rules of priority
|
||||
* for the locking of the objects were established and followed
|
||||
* religiously.
|
||||
* Either or both of these drawbacks makes such an implementation
|
||||
* infeasible.
|
||||
* <p>
|
||||
* A less conservative approach would be to change the state of the
|
||||
* trackable object to DYNAMIC during all modifications of the data
|
||||
* and then to change it back to STABLE after those modifications
|
||||
* are complete.
|
||||
* While this state transition more accurately reflects the temporary
|
||||
* loss of tracking during the modification phase, in reality the
|
||||
* time period of the modifications would be small in most cases
|
||||
* and the 2 changes of state would each require synchronization.
|
||||
* <p>
|
||||
* In comparison the act of setting the <code>curTracker</code>
|
||||
* reference to null in the usage pattern above effectively invalidates
|
||||
* all outstanding <code>Tracker</code> objects as soon as possible
|
||||
* after the change to the data and requires very little code and no
|
||||
* synchronization to implement.
|
||||
* <p>
|
||||
* In the end it is up to the implementor of a StateTrackable object
|
||||
* how fine the granularity of State updates should be managed based
|
||||
* on the frequency and atomicity of the modifications and the
|
||||
* consequences of returning an inaccurate State for a particularly
|
||||
* small window of opportunity.
|
||||
* Most implementations are likely to follow the liberal, but efficient
|
||||
* guidelines found in the usage pattern proposed above.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public interface StateTrackable {
|
||||
/**
|
||||
* An enumeration describing the current state of a trackable
|
||||
* object.
|
||||
* These values describe how often the complex data contained
|
||||
* in a trackable object can be changed and whether or not it
|
||||
* makes sense to try to track the data in its current state.
|
||||
* @see StateTrackable#getState
|
||||
* @since 1.7
|
||||
*/
|
||||
public enum State {
|
||||
/**
|
||||
* The complex data will never change again.
|
||||
* Information related to the current contents of the complex
|
||||
* data can be calculated and cached indefinitely with no
|
||||
* further checks to see if the information is stale.
|
||||
*/
|
||||
IMMUTABLE,
|
||||
|
||||
/**
|
||||
* The complex data is currently stable, but could change at
|
||||
* some point in the future.
|
||||
* Information related to the current contents of the complex
|
||||
* data can be calculated and cached, but a StateTracker should
|
||||
* be used to verify the freshness of such precalculated data
|
||||
* before each future use.
|
||||
*/
|
||||
STABLE,
|
||||
|
||||
/**
|
||||
* The complex data is currently in flux and is frequently
|
||||
* changing.
|
||||
* While information related to the current contents of the
|
||||
* complex data could be calculated and cached, there is a
|
||||
* reasonably high probability that the cached information
|
||||
* would be found to be out of date by the next time it is
|
||||
* used.
|
||||
* It may also be the case that the current contents are
|
||||
* temporarily untrackable, but that they may become trackable
|
||||
* again in the future.
|
||||
*/
|
||||
DYNAMIC,
|
||||
|
||||
/**
|
||||
* The complex data can currently be changed by external
|
||||
* references and agents in a way that cannot be tracked.
|
||||
* If any information about the current contents of the complex
|
||||
* data were to be cached, there would be no way to determine
|
||||
* whether or not that cached information was out of date.
|
||||
*/
|
||||
UNTRACKABLE,
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the general state of the complex data held by this
|
||||
* object.
|
||||
* This return value can be used to determine if it makes
|
||||
* strategic sense to try and cache information about the current
|
||||
* contents of this object.
|
||||
* The StateTracker returned from the getStateTracker() method
|
||||
* will further aid in determining when the data has been
|
||||
* changed so that the caches can be verified upon future uses.
|
||||
* @return the current state of trackability of the complex
|
||||
* data stored in this object.
|
||||
* @see #getStateTracker
|
||||
* @since 1.7
|
||||
*/
|
||||
public State getState();
|
||||
|
||||
/**
|
||||
* Returns an object which can track future changes to the
|
||||
* complex data stored in this object.
|
||||
* If an external agent caches information about the complex
|
||||
* data of this object, it should first get a StateTracker
|
||||
* object from this method so that it can check if such
|
||||
* information is current upon future uses.
|
||||
* Note that a valid StateTracker will always be returned
|
||||
* regardless of the return value of getState(), but in some
|
||||
* cases the StateTracker may be a trivial implementation
|
||||
* which always returns the same value from its
|
||||
* {@link StateTracker#isCurrent isCurrent} method.
|
||||
* <ul>
|
||||
* <li>If the current state is {@link State#IMMUTABLE IMMUTABLE},
|
||||
* this StateTracker and any future StateTracker objects
|
||||
* returned from this method will always indicate that
|
||||
* the state has not changed.</li>
|
||||
* <li>If the current state is {@link State#UNTRACKABLE UNTRACKABLE},
|
||||
* this StateTracker and any future StateTracker objects
|
||||
* returned from this method will always indicate that
|
||||
* the state has changed.</li>
|
||||
* <li>If the current state is {@link State#DYNAMIC DYNAMIC},
|
||||
* this StateTracker may always indicate that the current
|
||||
* state has changed, but another StateTracker returned
|
||||
* from this method in the future when the state has changed
|
||||
* to {@link State#STABLE STABLE} will correctly track changes.</li>
|
||||
* <li>Otherwise the current state is {@link State#STABLE STABLE}
|
||||
* and this StateTracker will indicate whether or not the
|
||||
* data has changed since the time at which it was fetched
|
||||
* from the object.</li>
|
||||
* </ul>
|
||||
* @return an object implementing the StateTracker interface
|
||||
* that tracks whether changes have been made to the complex
|
||||
* contents of this object since it was returned.
|
||||
* @see State
|
||||
* @see #getState
|
||||
* @since 1.7
|
||||
*/
|
||||
public StateTracker getStateTracker();
|
||||
}
|
||||
256
jdkSrc/jdk8/sun/java2d/StateTrackableDelegate.java
Normal file
256
jdkSrc/jdk8/sun/java2d/StateTrackableDelegate.java
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
import sun.java2d.StateTrackable.State;
|
||||
import static sun.java2d.StateTrackable.State.*;
|
||||
|
||||
/**
|
||||
* This class provides a basic pre-packaged implementation of the
|
||||
* complete {@link StateTrackable} interface with implementations
|
||||
* of the required methods in the interface and methods to manage
|
||||
* transitions in the state of the object.
|
||||
* Classes which wish to implement StateTrackable could create an
|
||||
* instance of this class and delegate all of their implementations
|
||||
* for {@code StateTrackable} methods to the corresponding methods
|
||||
* of this class.
|
||||
*/
|
||||
public final class StateTrackableDelegate implements StateTrackable {
|
||||
/**
|
||||
* The {@code UNTRACKABLE_DELEGATE} provides an implementation
|
||||
* of the StateTrackable interface that is permanently in the
|
||||
* {@link State#UNTRACKABLE UNTRACKABLE} state.
|
||||
*/
|
||||
public final static StateTrackableDelegate UNTRACKABLE_DELEGATE =
|
||||
new StateTrackableDelegate(UNTRACKABLE);
|
||||
|
||||
/**
|
||||
* The {@code IMMUTABLE_DELEGATE} provides an implementation
|
||||
* of the StateTrackable interface that is permanently in the
|
||||
* {@link State#IMMUTABLE IMMUTABLE} state.
|
||||
*/
|
||||
public final static StateTrackableDelegate IMMUTABLE_DELEGATE =
|
||||
new StateTrackableDelegate(IMMUTABLE);
|
||||
|
||||
/**
|
||||
* Returns a {@code StateTrackableDelegate} instance with the
|
||||
* specified initial {@link State State}.
|
||||
* If the specified {@code State} is
|
||||
* {@link State#UNTRACKABLE UNTRACKABLE} or
|
||||
* {@link State#IMMUTABLE IMMUTABLE}
|
||||
* then the approprirate static instance
|
||||
* {@link #UNTRACKABLE_DELEGATE} or {@link #IMMUTABLE_DELEGATE}
|
||||
* is returned.
|
||||
*/
|
||||
public static StateTrackableDelegate createInstance(State state) {
|
||||
switch (state) {
|
||||
case UNTRACKABLE:
|
||||
return UNTRACKABLE_DELEGATE;
|
||||
case STABLE:
|
||||
return new StateTrackableDelegate(STABLE);
|
||||
case DYNAMIC:
|
||||
return new StateTrackableDelegate(DYNAMIC);
|
||||
case IMMUTABLE:
|
||||
return IMMUTABLE_DELEGATE;
|
||||
default:
|
||||
throw new InternalError("unknown state");
|
||||
}
|
||||
}
|
||||
|
||||
private State theState;
|
||||
StateTracker theTracker; // package private for easy access from tracker
|
||||
private int numDynamicAgents;
|
||||
|
||||
/**
|
||||
* Constructs a StateTrackableDelegate object with the specified
|
||||
* initial State.
|
||||
*/
|
||||
private StateTrackableDelegate(State state) {
|
||||
this.theState = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 1.7
|
||||
*/
|
||||
public State getState() {
|
||||
return theState;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 1.7
|
||||
*/
|
||||
public synchronized StateTracker getStateTracker() {
|
||||
StateTracker st = theTracker;
|
||||
if (st == null) {
|
||||
switch (theState) {
|
||||
case IMMUTABLE:
|
||||
st = StateTracker.ALWAYS_CURRENT;
|
||||
break;
|
||||
case STABLE:
|
||||
st = new StateTracker() {
|
||||
public boolean isCurrent() {
|
||||
return (theTracker == this);
|
||||
}
|
||||
};
|
||||
break;
|
||||
case DYNAMIC:
|
||||
// We return the NEVER_CURRENT tracker, but that is
|
||||
// just temporary while we are in the DYNAMIC state.
|
||||
// NO BREAK
|
||||
case UNTRACKABLE:
|
||||
st = StateTracker.NEVER_CURRENT;
|
||||
break;
|
||||
}
|
||||
theTracker = st;
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method provides an easy way for delegating classes to
|
||||
* change the overall {@link State State} of the delegate to
|
||||
* {@link State#IMMUTABLE IMMUTABLE}.
|
||||
* @throws IllegalStateException if the current state is
|
||||
* {@link State#UNTRACKABLE UNTRACKABLE}
|
||||
* @see #setUntrackable
|
||||
* @since 1.7
|
||||
*/
|
||||
public synchronized void setImmutable() {
|
||||
if (theState == UNTRACKABLE || theState == DYNAMIC) {
|
||||
throw new IllegalStateException("UNTRACKABLE or DYNAMIC "+
|
||||
"objects cannot become IMMUTABLE");
|
||||
}
|
||||
theState = IMMUTABLE;
|
||||
theTracker = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method provides an easy way for delegating classes to
|
||||
* change the overall {@link State State} of the delegate to
|
||||
* {@link State#UNTRACKABLE UNTRACKABLE}.
|
||||
* This method is typically called when references to the
|
||||
* internal data buffers have been made public.
|
||||
* @throws IllegalStateException if the current state is
|
||||
* {@link State#IMMUTABLE IMMUTABLE}
|
||||
* @see #setImmutable
|
||||
* @since 1.7
|
||||
*/
|
||||
public synchronized void setUntrackable() {
|
||||
if (theState == IMMUTABLE) {
|
||||
throw new IllegalStateException("IMMUTABLE objects cannot "+
|
||||
"become UNTRACKABLE");
|
||||
}
|
||||
theState = UNTRACKABLE;
|
||||
theTracker = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method provides an easy way for delegating classes to
|
||||
* manage temporarily setting the overall {@link State State}
|
||||
* of the delegate to {@link State#DYNAMIC DYNAMIC}
|
||||
* during well-defined time frames of dynamic pixel updating.
|
||||
* This method should be called once before each flow of control
|
||||
* that might dynamically update the pixels in an uncontrolled
|
||||
* or unpredictable fashion.
|
||||
* <p>
|
||||
* The companion method {@link #removeDynamicAgent} method should
|
||||
* also be called once after each such flow of control has ended.
|
||||
* Failing to call the remove method will result in this object
|
||||
* permanently becoming {@link State#DYNAMIC DYNAMIC}
|
||||
* and therefore effectively untrackable.
|
||||
* <p>
|
||||
* This method will only change the {@link State State} of the
|
||||
* delegate if it is currently {@link State#STABLE STABLE}.
|
||||
*
|
||||
* @throws IllegalStateException if the current state is
|
||||
* {@link State#IMMUTABLE IMMUTABLE}
|
||||
* @since 1.7
|
||||
*/
|
||||
public synchronized void addDynamicAgent() {
|
||||
if (theState == IMMUTABLE) {
|
||||
throw new IllegalStateException("Cannot change state from "+
|
||||
"IMMUTABLE");
|
||||
}
|
||||
++numDynamicAgents;
|
||||
if (theState == STABLE) {
|
||||
theState = DYNAMIC;
|
||||
theTracker = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method provides an easy way for delegating classes to
|
||||
* manage restoring the overall {@link State State} of the
|
||||
* delegate back to {@link State#STABLE STABLE}
|
||||
* after a well-defined time frame of dynamic pixel updating.
|
||||
* This method should be called once after each flow of control
|
||||
* that might dynamically update the pixels in an uncontrolled
|
||||
* or unpredictable fashion has ended.
|
||||
* <p>
|
||||
* The companion method {@link #addDynamicAgent} method should
|
||||
* have been called at some point before each such flow of
|
||||
* control began.
|
||||
* If this method is called without having previously called
|
||||
* the add method, the {@link State State} of this object
|
||||
* will become unreliable.
|
||||
* <p>
|
||||
* This method will only change the {@link State State} of the
|
||||
* delegate if the number of outstanding dynamic agents has
|
||||
* gone to 0 and it is currently
|
||||
* {@link State#DYNAMIC DYNAMIC}.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
protected synchronized void removeDynamicAgent() {
|
||||
if (--numDynamicAgents == 0 && theState == DYNAMIC) {
|
||||
theState = STABLE;
|
||||
theTracker = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method provides an easy way for delegating classes to
|
||||
* indicate that the contents have changed.
|
||||
* This method will invalidate outstanding StateTracker objects
|
||||
* so that any other agents which maintain cached information
|
||||
* about the pixels will know to refresh their cached copies.
|
||||
* This method should be called after every modification to
|
||||
* the data, such as any calls to any of the setElem methods.
|
||||
* <p>
|
||||
* Note that, for efficiency, this method does not check the
|
||||
* {@link State State} of the object to see if it is compatible
|
||||
* with being marked dirty
|
||||
* (i.e. not {@link State#IMMUTABLE IMMUTABLE}).
|
||||
* It is up to the callers to enforce the fact that an
|
||||
* {@code IMMUTABLE} delegate is never modified.
|
||||
* @since 1.7
|
||||
*/
|
||||
public final void markDirty() {
|
||||
theTracker = null;
|
||||
}
|
||||
}
|
||||
104
jdkSrc/jdk8/sun/java2d/StateTracker.java
Normal file
104
jdkSrc/jdk8/sun/java2d/StateTracker.java
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
/**
|
||||
* This interface is used to track changes to the complex data of an
|
||||
* object that implements the StateTrackable interface.
|
||||
* <p>
|
||||
* The usage pattern for code accessing the trackable data is as follows:
|
||||
* <pre>
|
||||
* StateTrackable trackedobject;
|
||||
* MyInfo cacheddata;
|
||||
* StateTracker cachetracker;
|
||||
* public synchronized MyInfo getInfoAbout(StateTrackable obj) {
|
||||
* if (trackedobject != obj || !cachetracker.isCurrent()) {
|
||||
* // Note: Always call getStateTracker() before
|
||||
* // caching any data about the objct...
|
||||
* cachetracker = obj.getStateTracker();
|
||||
* cacheddata = calculateInfoFrom(obj);
|
||||
* trackedobject = obj;
|
||||
* }
|
||||
* return cacheddata;
|
||||
* }
|
||||
* </pre>
|
||||
* Note that the sample code above works correctly regardless of the
|
||||
* {@link StateTrackable.State State} of the complex data of the object,
|
||||
* but it may be inefficient to store precalculated information about
|
||||
* an object whose current {@link StateTrackable.State State} is
|
||||
* {@link StateTrackable.State#UNTRACKABLE UNTRACKABLE}
|
||||
* and it is unnecessary to perform the {@link #isCurrent} test for
|
||||
* data whose current {@link StateTrackable.State State} is
|
||||
* {@link StateTrackable.State#IMMUTABLE IMMUTABLE}.
|
||||
* Optimizations to the sample code for either or both of those terminal
|
||||
* States may be of benefit for some use cases, but is left out of the
|
||||
* example to reduce its complexity.
|
||||
*
|
||||
* @see StateTrackable.State
|
||||
* @since 1.7
|
||||
*/
|
||||
public interface StateTracker {
|
||||
/**
|
||||
* An implementation of the StateTracker interface which
|
||||
* always returns true.
|
||||
* This implementation is useful for objects whose current
|
||||
* {@link StateTrackable.State State} is
|
||||
* {@link StateTrackable.State#IMMUTABLE IMMUTABLE}.
|
||||
* @since 1.7
|
||||
*/
|
||||
public StateTracker ALWAYS_CURRENT = new StateTracker() {
|
||||
public boolean isCurrent() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* An implementation of the StateTracker interface which
|
||||
* always returns false.
|
||||
* This implementation is useful for objects whose current
|
||||
* {@link StateTrackable.State State} is
|
||||
* {@link StateTrackable.State#UNTRACKABLE UNTRACKABLE}.
|
||||
* This implementation may also be useful for some objects
|
||||
* whose current {@link StateTrackable.State State} is
|
||||
* {@link StateTrackable.State#DYNAMIC DYNAMIC}.
|
||||
* @since 1.7
|
||||
*/
|
||||
public StateTracker NEVER_CURRENT = new StateTracker() {
|
||||
public boolean isCurrent() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true iff the contents of the complex data of the
|
||||
* associated StateTrackable object have not changed since
|
||||
* the time that this StateTracker was returned from its
|
||||
* getStateTracker() method.
|
||||
* @see StateTrackable
|
||||
* @since 1.7
|
||||
*/
|
||||
public boolean isCurrent();
|
||||
}
|
||||
129
jdkSrc/jdk8/sun/java2d/SunCompositeContext.java
Normal file
129
jdkSrc/jdk8/sun/java2d/SunCompositeContext.java
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2002, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
import java.awt.Composite;
|
||||
import java.awt.CompositeContext;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import sun.awt.image.BufImgSurfaceData;
|
||||
import sun.java2d.loops.XORComposite;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.Blit;
|
||||
|
||||
public class SunCompositeContext implements CompositeContext {
|
||||
ColorModel srcCM;
|
||||
ColorModel dstCM;
|
||||
Composite composite;
|
||||
CompositeType comptype;
|
||||
|
||||
public SunCompositeContext(AlphaComposite ac,
|
||||
ColorModel s, ColorModel d)
|
||||
{
|
||||
if (s == null) {
|
||||
throw new NullPointerException("Source color model cannot be null");
|
||||
}
|
||||
if (d == null) {
|
||||
throw new NullPointerException("Destination color model cannot be null");
|
||||
}
|
||||
srcCM = s;
|
||||
dstCM = d;
|
||||
this.composite = ac;
|
||||
this.comptype = CompositeType.forAlphaComposite(ac);
|
||||
}
|
||||
|
||||
public SunCompositeContext(XORComposite xc,
|
||||
ColorModel s, ColorModel d)
|
||||
{
|
||||
if (s == null) {
|
||||
throw new NullPointerException("Source color model cannot be null");
|
||||
}
|
||||
if (d == null) {
|
||||
throw new NullPointerException("Destination color model cannot be null");
|
||||
}
|
||||
srcCM = s;
|
||||
dstCM = d;
|
||||
this.composite = xc;
|
||||
this.comptype = CompositeType.Xor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release resources allocated for context.
|
||||
*/
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method composes the two source tiles
|
||||
* and places the result in the destination tile. Note that
|
||||
* the destination can be the same object as either
|
||||
* the first or second source.
|
||||
* @param src1 The first source tile for the compositing operation.
|
||||
* @param src2 The second source tile for the compositing operation.
|
||||
* @param dst The tile where the result of the operation is stored.
|
||||
*/
|
||||
public void compose(Raster srcArg, Raster dstIn, WritableRaster dstOut) {
|
||||
WritableRaster src;
|
||||
int w;
|
||||
int h;
|
||||
|
||||
if (dstIn != dstOut) {
|
||||
dstOut.setDataElements(0, 0, dstIn);
|
||||
}
|
||||
|
||||
// REMIND: We should be able to create a SurfaceData from just
|
||||
// a non-writable Raster and a ColorModel. Since we need to
|
||||
// create a SurfaceData from a BufferedImage then we need to
|
||||
// make a WritableRaster since it is needed to construct a
|
||||
// BufferedImage.
|
||||
if (srcArg instanceof WritableRaster) {
|
||||
src = (WritableRaster) srcArg;
|
||||
} else {
|
||||
src = srcArg.createCompatibleWritableRaster();
|
||||
src.setDataElements(0, 0, srcArg);
|
||||
}
|
||||
|
||||
w = Math.min(src.getWidth(), dstIn.getWidth());
|
||||
h = Math.min(src.getHeight(), dstIn.getHeight());
|
||||
|
||||
BufferedImage srcImg = new BufferedImage(srcCM, src,
|
||||
srcCM.isAlphaPremultiplied(),
|
||||
null);
|
||||
BufferedImage dstImg = new BufferedImage(dstCM, dstOut,
|
||||
dstCM.isAlphaPremultiplied(),
|
||||
null);
|
||||
|
||||
SurfaceData srcData = BufImgSurfaceData.createData(srcImg);
|
||||
SurfaceData dstData = BufImgSurfaceData.createData(dstImg);
|
||||
Blit blit = Blit.getFromCache(srcData.getSurfaceType(),
|
||||
comptype,
|
||||
dstData.getSurfaceType());
|
||||
blit.Blit(srcData, dstData, composite, null, 0, 0, 0, 0, w, h);
|
||||
}
|
||||
}
|
||||
3596
jdkSrc/jdk8/sun/java2d/SunGraphics2D.java
Normal file
3596
jdkSrc/jdk8/sun/java2d/SunGraphics2D.java
Normal file
File diff suppressed because it is too large
Load Diff
342
jdkSrc/jdk8/sun/java2d/SunGraphicsEnvironment.java
Normal file
342
jdkSrc/jdk8/sun/java2d/SunGraphicsEnvironment.java
Normal file
@@ -0,0 +1,342 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
import java.awt.AWTError;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.font.TextAttribute;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.peer.ComponentPeer;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.TreeMap;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import sun.awt.AppContext;
|
||||
import sun.awt.DisplayChangedListener;
|
||||
import sun.awt.FontConfiguration;
|
||||
import sun.awt.SunDisplayChanger;
|
||||
import sun.font.CompositeFontDescriptor;
|
||||
import sun.font.Font2D;
|
||||
import sun.font.FontManager;
|
||||
import sun.font.FontManagerFactory;
|
||||
import sun.font.FontManagerForSGE;
|
||||
import sun.font.NativeFont;
|
||||
|
||||
/**
|
||||
* This is an implementation of a GraphicsEnvironment object for the
|
||||
* default local GraphicsEnvironment.
|
||||
*
|
||||
* @see GraphicsDevice
|
||||
* @see GraphicsConfiguration
|
||||
*/
|
||||
public abstract class SunGraphicsEnvironment extends GraphicsEnvironment
|
||||
implements DisplayChangedListener {
|
||||
|
||||
public static boolean isOpenSolaris;
|
||||
private static Font defaultFont;
|
||||
|
||||
public SunGraphicsEnvironment() {
|
||||
java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction() {
|
||||
public Object run() {
|
||||
String version = System.getProperty("os.version", "0.0");
|
||||
try {
|
||||
float ver = Float.parseFloat(version);
|
||||
if (ver > 5.10f) {
|
||||
File f = new File("/etc/release");
|
||||
FileInputStream fis = new FileInputStream(f);
|
||||
InputStreamReader isr
|
||||
= new InputStreamReader(fis, "ISO-8859-1");
|
||||
BufferedReader br = new BufferedReader(isr);
|
||||
String line = br.readLine();
|
||||
if (line.indexOf("OpenSolaris") >= 0) {
|
||||
isOpenSolaris = true;
|
||||
} else {
|
||||
/* We are using isOpenSolaris as meaning
|
||||
* we know the Solaris commercial fonts aren't
|
||||
* present. "Solaris Next" (03/10) did not
|
||||
* include these even though its was not
|
||||
* OpenSolaris. Need to revisit how this is
|
||||
* handled but for now as in 6ux, we'll use
|
||||
* the test for a standard font resource as
|
||||
* being an indicator as to whether we need
|
||||
* to treat this as OpenSolaris from a font
|
||||
* config perspective.
|
||||
*/
|
||||
String courierNew =
|
||||
"/usr/openwin/lib/X11/fonts/TrueType/CourierNew.ttf";
|
||||
File courierFile = new File(courierNew);
|
||||
isOpenSolaris = !courierFile.exists();
|
||||
}
|
||||
fis.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
/* Establish the default font to be used by SG2D etc */
|
||||
defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12);
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected GraphicsDevice[] screens;
|
||||
|
||||
/**
|
||||
* Returns an array of all of the screen devices.
|
||||
*/
|
||||
public synchronized GraphicsDevice[] getScreenDevices() {
|
||||
GraphicsDevice[] ret = screens;
|
||||
if (ret == null) {
|
||||
int num = getNumScreens();
|
||||
ret = new GraphicsDevice[num];
|
||||
for (int i = 0; i < num; i++) {
|
||||
ret[i] = makeScreenDevice(i);
|
||||
}
|
||||
screens = ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of screen devices of this graphics environment.
|
||||
*
|
||||
* @return the number of screen devices of this graphics environment
|
||||
*/
|
||||
protected abstract int getNumScreens();
|
||||
|
||||
/**
|
||||
* Create and return the screen device with the specified number. The
|
||||
* device with number <code>0</code> will be the default device (returned
|
||||
* by {@link #getDefaultScreenDevice()}.
|
||||
*
|
||||
* @param screennum the number of the screen to create
|
||||
*
|
||||
* @return the created screen device
|
||||
*/
|
||||
protected abstract GraphicsDevice makeScreenDevice(int screennum);
|
||||
|
||||
/**
|
||||
* Returns the default screen graphics device.
|
||||
*/
|
||||
public GraphicsDevice getDefaultScreenDevice() {
|
||||
GraphicsDevice[] screens = getScreenDevices();
|
||||
if (screens.length == 0) {
|
||||
throw new AWTError("no screen devices");
|
||||
}
|
||||
return screens[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Graphics2D object for rendering into the
|
||||
* given BufferedImage.
|
||||
* @throws NullPointerException if BufferedImage argument is null
|
||||
*/
|
||||
public Graphics2D createGraphics(BufferedImage img) {
|
||||
if (img == null) {
|
||||
throw new NullPointerException("BufferedImage cannot be null");
|
||||
}
|
||||
SurfaceData sd = SurfaceData.getPrimarySurfaceData(img);
|
||||
return new SunGraphics2D(sd, Color.white, Color.black, defaultFont);
|
||||
}
|
||||
|
||||
public static FontManagerForSGE getFontManagerForSGE() {
|
||||
FontManager fm = FontManagerFactory.getInstance();
|
||||
return (FontManagerForSGE) fm;
|
||||
}
|
||||
|
||||
/* Modifies the behaviour of a subsequent call to preferLocaleFonts()
|
||||
* to use Mincho instead of Gothic for dialoginput in JA locales
|
||||
* on windows. Not needed on other platforms.
|
||||
*
|
||||
* DO NOT MOVE OR RENAME OR OTHERWISE ALTER THIS METHOD.
|
||||
* ITS USED BY SOME NON-JRE INTERNAL CODE.
|
||||
*/
|
||||
public static void useAlternateFontforJALocales() {
|
||||
getFontManagerForSGE().useAlternateFontforJALocales();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all fonts available in this environment.
|
||||
*/
|
||||
public Font[] getAllFonts() {
|
||||
FontManagerForSGE fm = getFontManagerForSGE();
|
||||
Font[] installedFonts = fm.getAllInstalledFonts();
|
||||
Font[] created = fm.getCreatedFonts();
|
||||
if (created == null || created.length == 0) {
|
||||
return installedFonts;
|
||||
} else {
|
||||
int newlen = installedFonts.length + created.length;
|
||||
Font [] fonts = java.util.Arrays.copyOf(installedFonts, newlen);
|
||||
System.arraycopy(created, 0, fonts,
|
||||
installedFonts.length, created.length);
|
||||
return fonts;
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getAvailableFontFamilyNames(Locale requestedLocale) {
|
||||
FontManagerForSGE fm = getFontManagerForSGE();
|
||||
String[] installed = fm.getInstalledFontFamilyNames(requestedLocale);
|
||||
/* Use a new TreeMap as used in getInstalledFontFamilyNames
|
||||
* and insert all the keys in lower case, so that the sort order
|
||||
* is the same as the installed families. This preserves historical
|
||||
* behaviour and inserts new families in the right place.
|
||||
* It would have been marginally more efficient to directly obtain
|
||||
* the tree map and just insert new entries, but not so much as
|
||||
* to justify the extra internal interface.
|
||||
*/
|
||||
TreeMap<String, String> map = fm.getCreatedFontFamilyNames();
|
||||
if (map == null || map.size() == 0) {
|
||||
return installed;
|
||||
} else {
|
||||
for (int i=0; i<installed.length; i++) {
|
||||
map.put(installed[i].toLowerCase(requestedLocale),
|
||||
installed[i]);
|
||||
}
|
||||
String[] retval = new String[map.size()];
|
||||
Object [] keyNames = map.keySet().toArray();
|
||||
for (int i=0; i < keyNames.length; i++) {
|
||||
retval[i] = (String)map.get(keyNames[i]);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getAvailableFontFamilyNames() {
|
||||
return getAvailableFontFamilyNames(Locale.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bounds of a GraphicsDevice, less its screen insets.
|
||||
* See also java.awt.GraphicsEnvironment.getUsableBounds();
|
||||
*/
|
||||
public static Rectangle getUsableBounds(GraphicsDevice gd) {
|
||||
GraphicsConfiguration gc = gd.getDefaultConfiguration();
|
||||
Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc);
|
||||
Rectangle usableBounds = gc.getBounds();
|
||||
|
||||
usableBounds.x += insets.left;
|
||||
usableBounds.y += insets.top;
|
||||
usableBounds.width -= (insets.left + insets.right);
|
||||
usableBounds.height -= (insets.top + insets.bottom);
|
||||
|
||||
return usableBounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* From the DisplayChangedListener interface; called
|
||||
* when the display mode has been changed.
|
||||
*/
|
||||
public void displayChanged() {
|
||||
// notify screens in device array to do display update stuff
|
||||
for (GraphicsDevice gd : getScreenDevices()) {
|
||||
if (gd instanceof DisplayChangedListener) {
|
||||
((DisplayChangedListener) gd).displayChanged();
|
||||
}
|
||||
}
|
||||
|
||||
// notify SunDisplayChanger list (e.g. VolatileSurfaceManagers and
|
||||
// SurfaceDataProxies) about the display change event
|
||||
displayChanger.notifyListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the DisplayChangedListener interface:
|
||||
* propagate this event to listeners
|
||||
*/
|
||||
public void paletteChanged() {
|
||||
displayChanger.notifyPaletteChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true when the display is local, false for remote displays.
|
||||
*
|
||||
* @return true when the display is local, false for remote displays
|
||||
*/
|
||||
public abstract boolean isDisplayLocal();
|
||||
|
||||
/*
|
||||
* ----DISPLAY CHANGE SUPPORT----
|
||||
*/
|
||||
|
||||
protected SunDisplayChanger displayChanger = new SunDisplayChanger();
|
||||
|
||||
/**
|
||||
* Add a DisplayChangeListener to be notified when the display settings
|
||||
* are changed.
|
||||
*/
|
||||
public void addDisplayChangedListener(DisplayChangedListener client) {
|
||||
displayChanger.add(client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a DisplayChangeListener from Win32GraphicsEnvironment
|
||||
*/
|
||||
public void removeDisplayChangedListener(DisplayChangedListener client) {
|
||||
displayChanger.remove(client);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----END DISPLAY CHANGE SUPPORT----
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns true if FlipBufferStrategy with COPIED buffer contents
|
||||
* is preferred for this peer's GraphicsConfiguration over
|
||||
* BlitBufferStrategy, false otherwise.
|
||||
*
|
||||
* The reason FlipBS could be preferred is that in some configurations
|
||||
* an accelerated copy to the screen is supported (like Direct3D 9)
|
||||
*
|
||||
* @return true if flip strategy should be used, false otherwise
|
||||
*/
|
||||
public boolean isFlipStrategyPreferred(ComponentPeer peer) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
34
jdkSrc/jdk8/sun/java2d/Surface.java
Normal file
34
jdkSrc/jdk8/sun/java2d/Surface.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
/**
|
||||
* This is a tag interface for a surface.
|
||||
* @see sun.java2d.SurfaceData
|
||||
* @see sun.java2d.pipe.hw.AccelSurface
|
||||
*/
|
||||
public interface Surface {
|
||||
}
|
||||
1075
jdkSrc/jdk8/sun/java2d/SurfaceData.java
Normal file
1075
jdkSrc/jdk8/sun/java2d/SurfaceData.java
Normal file
File diff suppressed because it is too large
Load Diff
528
jdkSrc/jdk8/sun/java2d/SurfaceDataProxy.java
Normal file
528
jdkSrc/jdk8/sun/java2d/SurfaceDataProxy.java
Normal file
@@ -0,0 +1,528 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
|
||||
import sun.awt.DisplayChangedListener;
|
||||
import sun.java2d.StateTrackable.State;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.java2d.loops.Blit;
|
||||
import sun.java2d.loops.BlitBg;
|
||||
import sun.awt.image.SurfaceManager;
|
||||
import sun.awt.image.SurfaceManager.FlushableCacheData;
|
||||
|
||||
import java.security.AccessController;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
* The proxy class encapsulates the logic for managing alternate
|
||||
* SurfaceData representations of a primary SurfaceData.
|
||||
* The main class will handle tracking the state changes of the
|
||||
* primary SurfaceData and updating the associated SurfaceData
|
||||
* proxy variants.
|
||||
* <p>
|
||||
* Subclasses have 2 main responsibilities:
|
||||
* <ul>
|
||||
* <li> Override the isSupportedOperation() method to determine if
|
||||
* a given operation can be accelerated with a given source
|
||||
* SurfaceData
|
||||
* <li> Override the validateSurfaceData() method to create or update
|
||||
* a given accelerated surface to hold the pixels for the indicated
|
||||
* source SurfaceData
|
||||
* </ul>
|
||||
* If necessary, a subclass may also override the updateSurfaceData
|
||||
* method to transfer the pixels to the accelerated surface.
|
||||
* By default the parent class will transfer the pixels using a
|
||||
* standard Blit operation between the two SurfaceData objects.
|
||||
*/
|
||||
public abstract class SurfaceDataProxy
|
||||
implements DisplayChangedListener, SurfaceManager.FlushableCacheData
|
||||
{
|
||||
private static boolean cachingAllowed;
|
||||
private static int defaultThreshold;
|
||||
|
||||
static {
|
||||
cachingAllowed = true;
|
||||
String manimg = AccessController.doPrivileged(
|
||||
new GetPropertyAction("sun.java2d.managedimages"));
|
||||
if (manimg != null && manimg.equals("false")) {
|
||||
cachingAllowed = false;
|
||||
System.out.println("Disabling managed images");
|
||||
}
|
||||
|
||||
defaultThreshold = 1;
|
||||
String num = AccessController.doPrivileged(
|
||||
new GetPropertyAction("sun.java2d.accthreshold"));
|
||||
if (num != null) {
|
||||
try {
|
||||
int parsed = Integer.parseInt(num);
|
||||
if (parsed >= 0) {
|
||||
defaultThreshold = parsed;
|
||||
System.out.println("New Default Acceleration Threshold: " +
|
||||
defaultThreshold);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
System.err.println("Error setting new threshold:" + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isCachingAllowed() {
|
||||
return cachingAllowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if an alternate form for the srcData is needed
|
||||
* and appropriate from the given operational parameters.
|
||||
*/
|
||||
public abstract boolean isSupportedOperation(SurfaceData srcData,
|
||||
int txtype,
|
||||
CompositeType comp,
|
||||
Color bgColor);
|
||||
|
||||
/**
|
||||
* Construct an alternate form of the given SurfaceData.
|
||||
* The contents of the returned SurfaceData may be undefined
|
||||
* since the calling code will take care of updating the
|
||||
* contents with a subsequent call to updateSurfaceData.
|
||||
* <p>
|
||||
* If the method returns null then there was a problem with
|
||||
* allocating the accelerated surface. The getRetryTracker()
|
||||
* method will be called to track when to attempt another
|
||||
* revalidation.
|
||||
*/
|
||||
public abstract SurfaceData validateSurfaceData(SurfaceData srcData,
|
||||
SurfaceData cachedData,
|
||||
int w, int h);
|
||||
|
||||
/**
|
||||
* If the subclass is unable to validate or create a cached
|
||||
* SurfaceData then this method will be used to get a
|
||||
* StateTracker object that will indicate when to attempt
|
||||
* to validate the surface again. Subclasses may return
|
||||
* trackers which count down an ever increasing threshold
|
||||
* to provide hysteresis on creating surfaces during low
|
||||
* memory conditions. The default implementation just waits
|
||||
* another "threshold" number of accesses before trying again.
|
||||
*/
|
||||
public StateTracker getRetryTracker(SurfaceData srcData) {
|
||||
return new CountdownTracker(threshold);
|
||||
}
|
||||
|
||||
public static class CountdownTracker implements StateTracker {
|
||||
private int countdown;
|
||||
|
||||
public CountdownTracker(int threshold) {
|
||||
this.countdown = threshold;
|
||||
}
|
||||
|
||||
public synchronized boolean isCurrent() {
|
||||
return (--countdown >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This instance is for cases where a caching implementation
|
||||
* determines that a particular source image will never need
|
||||
* to be cached - either the source SurfaceData was of an
|
||||
* incompatible type, or it was in an UNTRACKABLE state or
|
||||
* some other factor is discovered that permanently prevents
|
||||
* acceleration or caching.
|
||||
* This class optimally implements NOP variants of all necessary
|
||||
* methods to avoid caching with a minimum of fuss.
|
||||
*/
|
||||
public static SurfaceDataProxy UNCACHED = new SurfaceDataProxy(0) {
|
||||
@Override
|
||||
public boolean isAccelerated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedOperation(SurfaceData srcData,
|
||||
int txtype,
|
||||
CompositeType comp,
|
||||
Color bgColor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceData validateSurfaceData(SurfaceData srcData,
|
||||
SurfaceData cachedData,
|
||||
int w, int h)
|
||||
{
|
||||
throw new InternalError("UNCACHED should never validate SDs");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceData replaceData(SurfaceData srcData,
|
||||
int txtype,
|
||||
CompositeType comp,
|
||||
Color bgColor)
|
||||
{
|
||||
// Not necessary to override this, but doing so is faster
|
||||
return srcData;
|
||||
}
|
||||
};
|
||||
|
||||
// The number of attempts to copy from a STABLE source before
|
||||
// a cached copy is created or updated.
|
||||
private int threshold;
|
||||
|
||||
/*
|
||||
* Source tracking data
|
||||
*
|
||||
* Every time that srcTracker is out of date we will reset numtries
|
||||
* to threshold and set the cacheTracker to one that is non-current.
|
||||
* numtries will then count down to 0 at which point the cacheTracker
|
||||
* will remind us that we need to update the cachedSD before we can
|
||||
* use it.
|
||||
*
|
||||
* Note that since these fields interrelate we should synchronize
|
||||
* whenever we update them, but it should be OK to read them
|
||||
* without synchronization.
|
||||
*/
|
||||
private StateTracker srcTracker;
|
||||
private int numtries;
|
||||
|
||||
/*
|
||||
* Cached data
|
||||
*
|
||||
* We cache a SurfaceData created by the subclass in cachedSD and
|
||||
* track its state (isValid and !surfaceLost) in cacheTracker.
|
||||
*
|
||||
* Also, when we want to note that cachedSD needs to be updated
|
||||
* we replace the cacheTracker with a NEVER_CURRENT tracker which
|
||||
* will cause us to try to revalidate and update the surface on
|
||||
* next use.
|
||||
*/
|
||||
private SurfaceData cachedSD;
|
||||
private StateTracker cacheTracker;
|
||||
|
||||
/*
|
||||
* Are we still the best object to control caching of data
|
||||
* for the source image?
|
||||
*/
|
||||
private boolean valid;
|
||||
|
||||
/**
|
||||
* Create a SurfaceData proxy manager that attempts to create
|
||||
* and cache a variant copy of the source SurfaceData after
|
||||
* the default threshold number of attempts to copy from the
|
||||
* STABLE source.
|
||||
*/
|
||||
public SurfaceDataProxy() {
|
||||
this(defaultThreshold);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a SurfaceData proxy manager that attempts to create
|
||||
* and cache a variant copy of the source SurfaceData after
|
||||
* the specified threshold number of attempts to copy from
|
||||
* the STABLE source.
|
||||
*/
|
||||
public SurfaceDataProxy(int threshold) {
|
||||
this.threshold = threshold;
|
||||
|
||||
this.srcTracker = StateTracker.NEVER_CURRENT;
|
||||
// numtries will be reset on first use
|
||||
this.cacheTracker = StateTracker.NEVER_CURRENT;
|
||||
|
||||
this.valid = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true iff this SurfaceData proxy is still the best
|
||||
* way to control caching of the given source on the given
|
||||
* destination.
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the valid state to false so that the next time this
|
||||
* proxy is fetched to generate a replacement SurfaceData,
|
||||
* the code in SurfaceData knows to replace the proxy first.
|
||||
*/
|
||||
public void invalidate() {
|
||||
this.valid = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush all cached resources as per the FlushableCacheData interface.
|
||||
* The deaccelerated parameter indicates if the flush is
|
||||
* happening because the associated surface is no longer
|
||||
* being accelerated (for instance the acceleration priority
|
||||
* is set below the threshold needed for acceleration).
|
||||
* Returns a boolean that indicates if the cached object is
|
||||
* no longer needed and should be removed from the cache.
|
||||
*/
|
||||
public boolean flush(boolean deaccelerated) {
|
||||
if (deaccelerated) {
|
||||
invalidate();
|
||||
}
|
||||
flush();
|
||||
return !isValid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Actively flushes (drops and invalidates) the cached surface
|
||||
* so that it can be reclaimed quickly.
|
||||
*/
|
||||
public synchronized void flush() {
|
||||
SurfaceData csd = this.cachedSD;
|
||||
this.cachedSD = null;
|
||||
this.cacheTracker = StateTracker.NEVER_CURRENT;
|
||||
if (csd != null) {
|
||||
csd.flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true iff this SurfaceData proxy is still valid
|
||||
* and if it has a currently cached replacement that is also
|
||||
* valid and current.
|
||||
*/
|
||||
public boolean isAccelerated() {
|
||||
return (isValid() &&
|
||||
srcTracker.isCurrent() &&
|
||||
cacheTracker.isCurrent());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should be called from subclasses which create
|
||||
* cached SurfaceData objects that depend on the current
|
||||
* properties of the display.
|
||||
*/
|
||||
protected void activateDisplayListener() {
|
||||
GraphicsEnvironment ge =
|
||||
GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
// We could have a HeadlessGE at this point, so double-check before
|
||||
// assuming anything.
|
||||
// Also, no point in listening to display change events if
|
||||
// the image is never going to be accelerated.
|
||||
if (ge instanceof SunGraphicsEnvironment) {
|
||||
((SunGraphicsEnvironment)ge).addDisplayChangedListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when the display mode has changed.
|
||||
* This method will invalidate and drop the internal cachedSD object.
|
||||
*/
|
||||
public void displayChanged() {
|
||||
flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when the palette has changed.
|
||||
*/
|
||||
public void paletteChanged() {
|
||||
// We could potentially get away with just resetting cacheTracker
|
||||
// here but there is a small window of vulnerability in the
|
||||
// replaceData method where we could be just finished with
|
||||
// updating the cachedSD when this method is called and even
|
||||
// though we set a non-current cacheTracker here it will then
|
||||
// immediately get set to a current one by the thread that is
|
||||
// updating the cachedSD. It is safer to just replace the
|
||||
// srcTracker with a non-current version that will trigger a
|
||||
// full update cycle the next time this proxy is used.
|
||||
// The downside is having to go through a full threshold count
|
||||
// before we can update and use our cache again, but palette
|
||||
// changes should be relatively rare...
|
||||
this.srcTracker = StateTracker.NEVER_CURRENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method attempts to replace the srcData with a cached version.
|
||||
* It relies on the subclass to determine if the cached version will
|
||||
* be useful given the operational parameters.
|
||||
* This method checks any preexisting cached copy for being "up to date"
|
||||
* and tries to update it if it is stale or non-existant and the
|
||||
* appropriate number of accesses have occurred since it last was stale.
|
||||
* <p>
|
||||
* An outline of the process is as follows:
|
||||
* <ol>
|
||||
* <li> Check the operational parameters (txtype, comp, bgColor)
|
||||
* to make sure that the operation is supported. Return the
|
||||
* original SurfaceData if the operation cannot be accelerated.
|
||||
* <li> Check the tracker for the source surface to see if it has
|
||||
* remained stable since it was last cached. Update the state
|
||||
* variables to cause both a threshold countdown and an update
|
||||
* of the cached copy if it is not. (Setting cacheTracker to
|
||||
* NEVER_CURRENT effectively marks it as "needing to be updated".)
|
||||
* <li> Check the tracker for the cached copy to see if is still
|
||||
* valid and up to date. Note that the cacheTracker may be
|
||||
* non-current if either something happened to the cached copy
|
||||
* (eg. surfaceLost) or if the source was out of date and the
|
||||
* cacheTracker was set to NEVER_CURRENT to force an update.
|
||||
* Decrement the countdown and copy the source to the cache
|
||||
* as necessary and then update the variables to show that
|
||||
* the cached copy is stable.
|
||||
* </ol>
|
||||
*/
|
||||
public SurfaceData replaceData(SurfaceData srcData,
|
||||
int txtype,
|
||||
CompositeType comp,
|
||||
Color bgColor)
|
||||
{
|
||||
if (isSupportedOperation(srcData, txtype, comp, bgColor)) {
|
||||
// First deal with tracking the source.
|
||||
if (!srcTracker.isCurrent()) {
|
||||
synchronized (this) {
|
||||
this.numtries = threshold;
|
||||
this.srcTracker = srcData.getStateTracker();
|
||||
this.cacheTracker = StateTracker.NEVER_CURRENT;
|
||||
}
|
||||
|
||||
if (!srcTracker.isCurrent()) {
|
||||
// Dynamic or Untrackable (or a very recent modification)
|
||||
if (srcData.getState() == State.UNTRACKABLE) {
|
||||
// UNTRACKABLE means we can never cache again.
|
||||
|
||||
// Invalidate so we get replaced next time we are used
|
||||
// (presumably with an UNCACHED proxy).
|
||||
invalidate();
|
||||
|
||||
// Aggressively drop our reference to the cachedSD
|
||||
// in case this proxy is not consulted again (and
|
||||
// thus replaced) for a long time.
|
||||
flush();
|
||||
}
|
||||
return srcData;
|
||||
}
|
||||
}
|
||||
|
||||
// Then deal with checking the validity of the cached SurfaceData
|
||||
SurfaceData csd = this.cachedSD;
|
||||
if (!cacheTracker.isCurrent()) {
|
||||
// Next make sure the dust has settled
|
||||
synchronized (this) {
|
||||
if (numtries > 0) {
|
||||
--numtries;
|
||||
return srcData;
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle r = srcData.getBounds();
|
||||
int w = r.width;
|
||||
int h = r.height;
|
||||
|
||||
// Snapshot the tracker in case it changes while
|
||||
// we are updating the cached SD...
|
||||
StateTracker curTracker = srcTracker;
|
||||
|
||||
csd = validateSurfaceData(srcData, csd, w, h);
|
||||
if (csd == null) {
|
||||
synchronized (this) {
|
||||
if (curTracker == srcTracker) {
|
||||
this.cacheTracker = getRetryTracker(srcData);
|
||||
this.cachedSD = null;
|
||||
}
|
||||
}
|
||||
return srcData;
|
||||
}
|
||||
|
||||
updateSurfaceData(srcData, csd, w, h);
|
||||
if (!csd.isValid()) {
|
||||
return srcData;
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
// We only reset these variables if the tracker from
|
||||
// before the surface update is still in use and current
|
||||
// Note that we must use a srcTracker that was fetched
|
||||
// from before the update process to make sure that we
|
||||
// do not lose some pixel changes in the shuffle.
|
||||
if (curTracker == srcTracker && curTracker.isCurrent()) {
|
||||
this.cacheTracker = csd.getStateTracker();
|
||||
this.cachedSD = csd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (csd != null) {
|
||||
return csd;
|
||||
}
|
||||
}
|
||||
|
||||
return srcData;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the default implementation for updating the cached
|
||||
* SurfaceData from the source (primary) SurfaceData.
|
||||
* A simple Blit is used to copy the pixels from the source to
|
||||
* the destination SurfaceData.
|
||||
* A subclass can override this implementation if a more complex
|
||||
* operation is required to update its cached copies.
|
||||
*/
|
||||
public void updateSurfaceData(SurfaceData srcData,
|
||||
SurfaceData dstData,
|
||||
int w, int h)
|
||||
{
|
||||
SurfaceType srcType = srcData.getSurfaceType();
|
||||
SurfaceType dstType = dstData.getSurfaceType();
|
||||
Blit blit = Blit.getFromCache(srcType,
|
||||
CompositeType.SrcNoEa,
|
||||
dstType);
|
||||
blit.Blit(srcData, dstData,
|
||||
AlphaComposite.Src, null,
|
||||
0, 0, 0, 0, w, h);
|
||||
dstData.markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an alternate implementation for updating the cached
|
||||
* SurfaceData from the source (primary) SurfaceData using a
|
||||
* background color for transparent pixels.
|
||||
* A simple BlitBg is used to copy the pixels from the source to
|
||||
* the destination SurfaceData with the specified bgColor.
|
||||
* A subclass can override the normal updateSurfaceData method
|
||||
* and call this implementation instead if it wants to use color
|
||||
* keying for bitmask images.
|
||||
*/
|
||||
public void updateSurfaceDataBg(SurfaceData srcData,
|
||||
SurfaceData dstData,
|
||||
int w, int h, Color bgColor)
|
||||
{
|
||||
SurfaceType srcType = srcData.getSurfaceType();
|
||||
SurfaceType dstType = dstData.getSurfaceType();
|
||||
BlitBg blitbg = BlitBg.getFromCache(srcType,
|
||||
CompositeType.SrcNoEa,
|
||||
dstType);
|
||||
blitbg.BlitBg(srcData, dstData,
|
||||
AlphaComposite.Src, null, bgColor.getRGB(),
|
||||
0, 0, 0, 0, w, h);
|
||||
dstData.markDirty();
|
||||
}
|
||||
}
|
||||
91
jdkSrc/jdk8/sun/java2d/SurfaceManagerFactory.java
Normal file
91
jdkSrc/jdk8/sun/java2d/SurfaceManagerFactory.java
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
import sun.awt.image.VolatileSurfaceManager;
|
||||
|
||||
/**
|
||||
* This factory creates platform specific VolatileSurfaceManager
|
||||
* implementations.
|
||||
*
|
||||
* There are two platform specific SurfaceManagerFactories in OpenJDK,
|
||||
* UnixSurfaceManagerFactory and WindowsSurfaceManagerFactory.
|
||||
* The actually used SurfaceManagerFactory is set by the respective platform
|
||||
* GraphicsEnvironment implementations in the static initializer.
|
||||
*/
|
||||
public abstract class SurfaceManagerFactory {
|
||||
|
||||
/**
|
||||
* The single shared instance.
|
||||
*/
|
||||
private static SurfaceManagerFactory instance;
|
||||
|
||||
/**
|
||||
* Returns the surface manager factory instance. This returns a factory
|
||||
* that has been set by {@link #setInstance(SurfaceManagerFactory)}.
|
||||
*
|
||||
* @return the surface manager factory
|
||||
*/
|
||||
public synchronized static SurfaceManagerFactory getInstance() {
|
||||
|
||||
if (instance == null) {
|
||||
throw new IllegalStateException("No SurfaceManagerFactory set.");
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the surface manager factory. This may only be called once, and it
|
||||
* may not be set back to {@code null} when the factory is already
|
||||
* instantiated.
|
||||
*
|
||||
* @param factory the factory to set
|
||||
*/
|
||||
public synchronized static void setInstance(SurfaceManagerFactory factory) {
|
||||
|
||||
if (factory == null) {
|
||||
// We don't want to allow setting this to null at any time.
|
||||
throw new IllegalArgumentException("factory must be non-null");
|
||||
}
|
||||
|
||||
if (instance != null) {
|
||||
// We don't want to re-set the instance at any time.
|
||||
throw new IllegalStateException("The surface manager factory is already initialized");
|
||||
}
|
||||
|
||||
instance = factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of a VolatileSurfaceManager given any
|
||||
* arbitrary SunVolatileImage. An optional context Object can be supplied
|
||||
* as a way for the caller to pass pipeline-specific context data to
|
||||
* the VolatileSurfaceManager (such as a backbuffer handle, for example).
|
||||
*/
|
||||
public abstract VolatileSurfaceManager
|
||||
createVolatileManager(SunVolatileImage image, Object context);
|
||||
}
|
||||
65
jdkSrc/jdk8/sun/java2d/WindowsSurfaceManagerFactory.java
Normal file
65
jdkSrc/jdk8/sun/java2d/WindowsSurfaceManagerFactory.java
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import sun.awt.image.BufImgVolatileSurfaceManager;
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
import sun.awt.image.VolatileSurfaceManager;
|
||||
import sun.java2d.d3d.D3DGraphicsConfig;
|
||||
import sun.java2d.d3d.D3DVolatileSurfaceManager;
|
||||
import sun.java2d.opengl.WGLGraphicsConfig;
|
||||
import sun.java2d.opengl.WGLVolatileSurfaceManager;
|
||||
|
||||
/**
|
||||
* The SurfaceManagerFactory that creates VolatileSurfaceManager
|
||||
* implementations for the Windows volatile images.
|
||||
*/
|
||||
public class WindowsSurfaceManagerFactory extends SurfaceManagerFactory {
|
||||
|
||||
/**
|
||||
* Creates a new instance of a VolatileSurfaceManager given any
|
||||
* arbitrary SunVolatileImage. An optional context Object can be supplied
|
||||
* as a way for the caller to pass pipeline-specific context data to
|
||||
* the VolatileSurfaceManager (such as a backbuffer handle, for example).
|
||||
*
|
||||
* For Windows platforms, this method returns a Windows-specific
|
||||
* VolatileSurfaceManager.
|
||||
*/
|
||||
public VolatileSurfaceManager createVolatileManager(SunVolatileImage vImg,
|
||||
Object context)
|
||||
{
|
||||
GraphicsConfiguration gc = vImg.getGraphicsConfig();
|
||||
if (gc instanceof D3DGraphicsConfig) {
|
||||
return new D3DVolatileSurfaceManager(vImg, context);
|
||||
} else if (gc instanceof WGLGraphicsConfig) {
|
||||
return new WGLVolatileSurfaceManager(vImg, context);
|
||||
} else {
|
||||
return new BufImgVolatileSurfaceManager(vImg, context);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
37
jdkSrc/jdk8/sun/java2d/cmm/CMMServiceProvider.java
Normal file
37
jdkSrc/jdk8/sun/java2d/cmm/CMMServiceProvider.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.cmm;
|
||||
|
||||
public abstract class CMMServiceProvider {
|
||||
public final PCMM getColorManagementModule() {
|
||||
if (CMSManager.canCreateModule()) {
|
||||
return getModule();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract PCMM getModule();
|
||||
}
|
||||
177
jdkSrc/jdk8/sun/java2d/cmm/CMSManager.java
Normal file
177
jdkSrc/jdk8/sun/java2d/cmm/CMSManager.java
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.cmm;
|
||||
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.color.ICC_Profile;
|
||||
import java.awt.color.CMMException;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
public class CMSManager {
|
||||
public static ColorSpace GRAYspace; // These two fields allow access
|
||||
public static ColorSpace LINEAR_RGBspace; // to java.awt.color.ColorSpace
|
||||
// private fields from other
|
||||
// packages. The fields are set
|
||||
// by java.awt.color.ColorSpace
|
||||
// and read by
|
||||
// java.awt.image.ColorModel.
|
||||
|
||||
private static PCMM cmmImpl = null;
|
||||
|
||||
public static synchronized PCMM getModule() {
|
||||
if (cmmImpl != null) {
|
||||
return cmmImpl;
|
||||
}
|
||||
|
||||
CMMServiceProvider spi = AccessController.doPrivileged(
|
||||
new PrivilegedAction<CMMServiceProvider>() {
|
||||
public CMMServiceProvider run() {
|
||||
String cmmClass = System.getProperty(
|
||||
"sun.java2d.cmm", "sun.java2d.cmm.lcms.LcmsServiceProvider");
|
||||
|
||||
ServiceLoader<CMMServiceProvider> cmmLoader
|
||||
= ServiceLoader.loadInstalled(CMMServiceProvider.class);
|
||||
|
||||
CMMServiceProvider spi = null;
|
||||
|
||||
for (CMMServiceProvider cmm : cmmLoader) {
|
||||
spi = cmm;
|
||||
if (cmm.getClass().getName().equals(cmmClass)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return spi;
|
||||
}
|
||||
});
|
||||
|
||||
cmmImpl = spi.getColorManagementModule();
|
||||
|
||||
if (cmmImpl == null) {
|
||||
throw new CMMException("Cannot initialize Color Management System."+
|
||||
"No CM module found");
|
||||
}
|
||||
|
||||
GetPropertyAction gpa = new GetPropertyAction("sun.java2d.cmm.trace");
|
||||
String cmmTrace = (String)AccessController.doPrivileged(gpa);
|
||||
if (cmmTrace != null) {
|
||||
cmmImpl = new CMMTracer(cmmImpl);
|
||||
}
|
||||
|
||||
return cmmImpl;
|
||||
}
|
||||
|
||||
static synchronized boolean canCreateModule() {
|
||||
return (cmmImpl == null);
|
||||
}
|
||||
|
||||
/* CMM trace routines */
|
||||
|
||||
public static class CMMTracer implements PCMM {
|
||||
PCMM tcmm;
|
||||
String cName ;
|
||||
|
||||
public CMMTracer(PCMM tcmm) {
|
||||
this.tcmm = tcmm;
|
||||
cName = tcmm.getClass().getName();
|
||||
}
|
||||
|
||||
public Profile loadProfile(byte[] data) {
|
||||
System.err.print(cName + ".loadProfile");
|
||||
Profile p = tcmm.loadProfile(data);
|
||||
System.err.printf("(ID=%s)\n", p.toString());
|
||||
return p;
|
||||
}
|
||||
|
||||
public void freeProfile(Profile p) {
|
||||
System.err.printf(cName + ".freeProfile(ID=%s)\n", p.toString());
|
||||
tcmm.freeProfile(p);
|
||||
}
|
||||
|
||||
public int getProfileSize(Profile p) {
|
||||
System.err.print(cName + ".getProfileSize(ID=" + p + ")");
|
||||
int size = tcmm.getProfileSize(p);
|
||||
System.err.println("=" + size);
|
||||
return size;
|
||||
}
|
||||
|
||||
public void getProfileData(Profile p, byte[] data) {
|
||||
System.err.print(cName + ".getProfileData(ID=" + p + ") ");
|
||||
System.err.println("requested " + data.length + " byte(s)");
|
||||
tcmm.getProfileData(p, data);
|
||||
}
|
||||
|
||||
public int getTagSize(Profile p, int tagSignature) {
|
||||
System.err.printf(cName + ".getTagSize(ID=%x, TagSig=%s)",
|
||||
p, signatureToString(tagSignature));
|
||||
int size = tcmm.getTagSize(p, tagSignature);
|
||||
System.err.println("=" + size);
|
||||
return size;
|
||||
}
|
||||
|
||||
public void getTagData(Profile p, int tagSignature,
|
||||
byte[] data) {
|
||||
System.err.printf(cName + ".getTagData(ID=%x, TagSig=%s)",
|
||||
p, signatureToString(tagSignature));
|
||||
System.err.println(" requested " + data.length + " byte(s)");
|
||||
tcmm.getTagData(p, tagSignature, data);
|
||||
}
|
||||
|
||||
public void setTagData(Profile p, int tagSignature,
|
||||
byte[] data) {
|
||||
System.err.print(cName + ".setTagData(ID=" + p +
|
||||
", TagSig=" + tagSignature + ")");
|
||||
System.err.println(" sending " + data.length + " byte(s)");
|
||||
tcmm.setTagData(p, tagSignature, data);
|
||||
}
|
||||
|
||||
/* methods for creating ColorTransforms */
|
||||
public ColorTransform createTransform(ICC_Profile profile,
|
||||
int renderType,
|
||||
int transformType) {
|
||||
System.err.println(cName + ".createTransform(ICC_Profile,int,int)");
|
||||
return tcmm.createTransform(profile, renderType, transformType);
|
||||
}
|
||||
|
||||
public ColorTransform createTransform(ColorTransform[] transforms) {
|
||||
System.err.println(cName + ".createTransform(ColorTransform[])");
|
||||
return tcmm.createTransform(transforms);
|
||||
}
|
||||
|
||||
private static String signatureToString(int sig) {
|
||||
return String.format("%c%c%c%c",
|
||||
(char)(0xff & (sig >> 24)),
|
||||
(char)(0xff & (sig >> 16)),
|
||||
(char)(0xff & (sig >> 8)),
|
||||
(char)(0xff & (sig )));
|
||||
}
|
||||
}
|
||||
}
|
||||
53
jdkSrc/jdk8/sun/java2d/cmm/ColorTransform.java
Normal file
53
jdkSrc/jdk8/sun/java2d/cmm/ColorTransform.java
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.cmm;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
|
||||
public interface ColorTransform {
|
||||
public int Any = -1;/* any rendering type, whichever is
|
||||
available */
|
||||
/* search order is icPerceptual,
|
||||
icRelativeColorimetric, icSaturation */
|
||||
|
||||
/* Transform types */
|
||||
public int In = 1;
|
||||
public int Out = 2;
|
||||
public int Gamut = 3;
|
||||
public int Simulation = 4;
|
||||
|
||||
public int getNumInComponents();
|
||||
public int getNumOutComponents();
|
||||
public void colorConvert(BufferedImage src, BufferedImage dst);
|
||||
public void colorConvert(Raster src, WritableRaster dst,
|
||||
float[] srcMinVal, float[]srcMaxVal,
|
||||
float[] dstMinVal, float[]dstMaxVal);
|
||||
public void colorConvert(Raster src, WritableRaster dst);
|
||||
public short[] colorConvert(short[] src, short[] dest);
|
||||
public byte[] colorConvert (byte[] src, byte[] dest);
|
||||
}
|
||||
48
jdkSrc/jdk8/sun/java2d/cmm/PCMM.java
Normal file
48
jdkSrc/jdk8/sun/java2d/cmm/PCMM.java
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.cmm;
|
||||
|
||||
import java.awt.color.ICC_Profile;
|
||||
|
||||
/* Pluggable CMM interface */
|
||||
|
||||
public interface PCMM {
|
||||
|
||||
/* methods invoked from ICC_Profile */
|
||||
public Profile loadProfile(byte[] data);
|
||||
public void freeProfile(Profile p);
|
||||
public int getProfileSize(Profile p);
|
||||
public void getProfileData(Profile p, byte[] data);
|
||||
public void getTagData(Profile p, int tagSignature, byte[] data);
|
||||
public int getTagSize(Profile p, int tagSignature);
|
||||
public void setTagData(Profile p, int tagSignature, byte[] data);
|
||||
|
||||
/* methods for creating ColorTransforms */
|
||||
public ColorTransform createTransform(ICC_Profile profile, int renderType,
|
||||
int transformType);
|
||||
|
||||
public ColorTransform createTransform(ColorTransform[] transforms);
|
||||
}
|
||||
43
jdkSrc/jdk8/sun/java2d/cmm/Profile.java
Normal file
43
jdkSrc/jdk8/sun/java2d/cmm/Profile.java
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.cmm;
|
||||
|
||||
import java.awt.color.CMMException;
|
||||
|
||||
public class Profile {
|
||||
private final long nativePtr;
|
||||
|
||||
protected Profile(long ptr) {
|
||||
nativePtr = ptr;
|
||||
}
|
||||
|
||||
protected final long getNativePtr() {
|
||||
if (nativePtr == 0L) {
|
||||
throw new CMMException("Invalid profile: ptr is null");
|
||||
}
|
||||
return nativePtr;
|
||||
}
|
||||
}
|
||||
41
jdkSrc/jdk8/sun/java2d/cmm/ProfileActivator.java
Normal file
41
jdkSrc/jdk8/sun/java2d/cmm/ProfileActivator.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.cmm;
|
||||
|
||||
import java.awt.color.ProfileDataException;
|
||||
|
||||
/**
|
||||
* An interface to allow the ProfileDeferralMgr to activate a
|
||||
* deferred profile.
|
||||
*/
|
||||
public interface ProfileActivator {
|
||||
|
||||
/**
|
||||
* Activate a previously deferred ICC_Profile object.
|
||||
*/
|
||||
public void activate() throws ProfileDataException;
|
||||
|
||||
}
|
||||
114
jdkSrc/jdk8/sun/java2d/cmm/ProfileDataVerifier.java
Normal file
114
jdkSrc/jdk8/sun/java2d/cmm/ProfileDataVerifier.java
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.cmm;
|
||||
|
||||
public class ProfileDataVerifier {
|
||||
/**
|
||||
* Throws an IllegalArgumentException if the data does not correspond
|
||||
* to a valid ICC Profile.
|
||||
*
|
||||
* @param data the specified profile data.
|
||||
*/
|
||||
public static void verify(byte[] data) {
|
||||
if (data == null) {
|
||||
throw new IllegalArgumentException("Invalid ICC Profile Data");
|
||||
}
|
||||
|
||||
if (data.length < TOC_OFFSET) {
|
||||
// not enough data for profile header
|
||||
throw new IllegalArgumentException("Invalid ICC Profile Data");
|
||||
}
|
||||
|
||||
// check profile size
|
||||
final int size = readInt32(data, 0);
|
||||
final int tagCount = readInt32(data, HEADER_SIZE);
|
||||
|
||||
if (tagCount < 0 || tagCount > MAX_TAG_COUNT) {
|
||||
throw new IllegalArgumentException("Invalid ICC Profile Data");
|
||||
}
|
||||
|
||||
if (size < (TOC_OFFSET + (tagCount * TOC_RECORD_SIZE)) ||
|
||||
size > data.length)
|
||||
{
|
||||
throw new IllegalArgumentException("Invalid ICC Profile Data");
|
||||
}
|
||||
|
||||
final int sig = readInt32(data, 36);
|
||||
|
||||
if (PROFILE_FILE_SIGNATURE != sig) {
|
||||
throw new IllegalArgumentException("Invalid ICC Profile Data");
|
||||
}
|
||||
|
||||
// verify table of content
|
||||
for (int i = 0; i < tagCount; i++) {
|
||||
final int tag_offset = getTagOffset(i, data);
|
||||
final int tag_size = getTagSize(i, data);
|
||||
|
||||
if (tag_offset < TOC_OFFSET || tag_offset > size) {
|
||||
throw new IllegalArgumentException("Invalid ICC Profile Data");
|
||||
}
|
||||
|
||||
if (tag_size < 0 ||
|
||||
tag_size > (Integer.MAX_VALUE - tag_offset) ||
|
||||
tag_size + tag_offset > size)
|
||||
{
|
||||
throw new IllegalArgumentException("Invalid ICC Profile Data");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int getTagOffset(int idx, byte[] data) {
|
||||
final int pos = TOC_OFFSET + idx * TOC_RECORD_SIZE + 4;
|
||||
return readInt32(data, pos);
|
||||
}
|
||||
|
||||
private static int getTagSize(int idx, byte[] data) {
|
||||
final int pos = TOC_OFFSET + idx * TOC_RECORD_SIZE + 8;
|
||||
return readInt32(data, pos);
|
||||
}
|
||||
|
||||
private static int readInt32(byte[] data, int off) {
|
||||
int res = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
res = res << 8;
|
||||
|
||||
res |= (0xff & data[off++]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lcms limit for the number of tags: 100
|
||||
* Kcms limit for the number of tags: N/A
|
||||
*/
|
||||
private static final int MAX_TAG_COUNT = 100;
|
||||
|
||||
private static final int HEADER_SIZE = 128;
|
||||
private static final int TOC_OFFSET = HEADER_SIZE + 4;
|
||||
private static final int TOC_RECORD_SIZE = 12;
|
||||
|
||||
private static final int PROFILE_FILE_SIGNATURE = 0x61637370;
|
||||
}
|
||||
61
jdkSrc/jdk8/sun/java2d/cmm/ProfileDeferralInfo.java
Normal file
61
jdkSrc/jdk8/sun/java2d/cmm/ProfileDeferralInfo.java
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.cmm;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
/**
|
||||
* A class to pass information about a profile to be loaded from
|
||||
* a file to the static getInstance(InputStream) method of
|
||||
* ICC_Profile. Loading of the profile data and initialization
|
||||
* of the CMM is to be deferred as long as possible.
|
||||
*/
|
||||
public class ProfileDeferralInfo extends InputStream {
|
||||
|
||||
public int colorSpaceType, numComponents, profileClass;
|
||||
public String filename;
|
||||
|
||||
public ProfileDeferralInfo(String fn, int type, int ncomp, int pclass) {
|
||||
|
||||
super();
|
||||
filename = fn;
|
||||
colorSpaceType = type;
|
||||
numComponents = ncomp;
|
||||
profileClass = pclass;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implements the abstract read() method of InputStream.
|
||||
*/
|
||||
public int read() throws IOException {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
119
jdkSrc/jdk8/sun/java2d/cmm/ProfileDeferralMgr.java
Normal file
119
jdkSrc/jdk8/sun/java2d/cmm/ProfileDeferralMgr.java
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.cmm;
|
||||
|
||||
import java.awt.color.ProfileDataException;
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
/**
|
||||
* A class to manage the deferral of CMM initialization of profile
|
||||
* data for internal ICC_Profile objects - i.e. when we "trust" that
|
||||
* the profile data is valid and we think it may not be needed. An
|
||||
* example is the sRGB profile which gets loaded by any program doing
|
||||
* graphics, but which may not be needed if the program does not need
|
||||
* high quality color conversion.
|
||||
*/
|
||||
public class ProfileDeferralMgr {
|
||||
|
||||
public static boolean deferring = true;
|
||||
private static Vector<ProfileActivator> aVector;
|
||||
|
||||
/**
|
||||
* Records a ProfileActivator object whose activate method will
|
||||
* be called if the CMM needs to be activated.
|
||||
*/
|
||||
public static void registerDeferral(ProfileActivator pa) {
|
||||
|
||||
if (!deferring) {
|
||||
return;
|
||||
}
|
||||
if (aVector == null) {
|
||||
aVector = new Vector<ProfileActivator>(3, 3);
|
||||
}
|
||||
aVector.addElement(pa);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes a ProfileActivator object from the vector of ProfileActivator
|
||||
* objects whose activate method will be called if the CMM needs to be
|
||||
* activated.
|
||||
*/
|
||||
public static void unregisterDeferral(ProfileActivator pa) {
|
||||
|
||||
if (!deferring) {
|
||||
return;
|
||||
}
|
||||
if (aVector == null) {
|
||||
return;
|
||||
}
|
||||
aVector.removeElement(pa);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a ProfileActivator object from the vector of ProfileActivator
|
||||
* objects whose activate method will be called if the CMM needs to be
|
||||
* activated.
|
||||
*/
|
||||
public static void activateProfiles() {
|
||||
|
||||
int i, n;
|
||||
|
||||
deferring = false;
|
||||
if (aVector == null) {
|
||||
return;
|
||||
}
|
||||
n = aVector.size();
|
||||
for (ProfileActivator pa : aVector) {
|
||||
try {
|
||||
pa.activate();
|
||||
} catch (ProfileDataException e) {
|
||||
/*
|
||||
* Ignore profile activation error for now:
|
||||
* such exception is pssible due to absence
|
||||
* or corruption of standard color profile.
|
||||
* As for now we expect all profiles should
|
||||
* be shiped with jre and presence of this
|
||||
* exception is indication of some configuration
|
||||
* problem in jre installation.
|
||||
*
|
||||
* NB: we still are greedy loading deferred profiles
|
||||
* and load them all if any of them is needed.
|
||||
* Therefore broken profile (if any) might be never used.
|
||||
* If there will be attempt to use broken profile then
|
||||
* it will result in CMMException.
|
||||
*/
|
||||
}
|
||||
}
|
||||
aVector.removeAllElements();
|
||||
aVector = null;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
221
jdkSrc/jdk8/sun/java2d/cmm/lcms/LCMS.java
Normal file
221
jdkSrc/jdk8/sun/java2d/cmm/lcms/LCMS.java
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.cmm.lcms;
|
||||
|
||||
import java.awt.color.CMMException;
|
||||
import java.awt.color.ICC_Profile;
|
||||
import sun.java2d.cmm.ColorTransform;
|
||||
import sun.java2d.cmm.PCMM;
|
||||
import sun.java2d.cmm.Profile;
|
||||
import sun.java2d.cmm.lcms.LCMSProfile.TagData;
|
||||
|
||||
public class LCMS implements PCMM {
|
||||
|
||||
/* methods invoked from ICC_Profile */
|
||||
@Override
|
||||
public Profile loadProfile(byte[] data) {
|
||||
final Object disposerRef = new Object();
|
||||
|
||||
final long ptr = loadProfileNative(data, disposerRef);
|
||||
|
||||
if (ptr != 0L) {
|
||||
return new LCMSProfile(ptr, disposerRef);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private native long loadProfileNative(byte[] data, Object ref);
|
||||
|
||||
private LCMSProfile getLcmsProfile(Profile p) {
|
||||
if (p instanceof LCMSProfile) {
|
||||
return (LCMSProfile)p;
|
||||
}
|
||||
throw new CMMException("Invalid profile: " + p);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void freeProfile(Profile p) {
|
||||
// we use disposer, so this method does nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProfileSize(final Profile p) {
|
||||
synchronized (p) {
|
||||
return getProfileSizeNative(getLcmsProfile(p).getLcmsPtr());
|
||||
}
|
||||
}
|
||||
|
||||
private native int getProfileSizeNative(long ptr);
|
||||
|
||||
@Override
|
||||
public void getProfileData(final Profile p, byte[] data) {
|
||||
synchronized (p) {
|
||||
getProfileDataNative(getLcmsProfile(p).getLcmsPtr(), data);
|
||||
}
|
||||
}
|
||||
|
||||
private native void getProfileDataNative(long ptr, byte[] data);
|
||||
|
||||
@Override
|
||||
public int getTagSize(Profile p, int tagSignature) {
|
||||
final LCMSProfile profile = getLcmsProfile(p);
|
||||
|
||||
synchronized (profile) {
|
||||
TagData t = profile.getTag(tagSignature);
|
||||
return t == null ? 0 : t.getSize();
|
||||
}
|
||||
}
|
||||
|
||||
static native byte[] getTagNative(long profileID, int signature);
|
||||
|
||||
@Override
|
||||
public void getTagData(Profile p, int tagSignature, byte[] data)
|
||||
{
|
||||
final LCMSProfile profile = getLcmsProfile(p);
|
||||
|
||||
synchronized (profile) {
|
||||
TagData t = profile.getTag(tagSignature);
|
||||
if (t != null) {
|
||||
t.copyDataTo(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setTagData(Profile p, int tagSignature, byte[] data) {
|
||||
final LCMSProfile profile = getLcmsProfile(p);
|
||||
|
||||
synchronized (profile) {
|
||||
profile.clearTagCache();
|
||||
|
||||
// Now we are going to update the profile with new tag data
|
||||
// In some cases, we may change the pointer to the native
|
||||
// profile.
|
||||
//
|
||||
// If we fail to write tag data for any reason, the old pointer
|
||||
// should be used.
|
||||
setTagDataNative(profile.getLcmsPtr(),
|
||||
tagSignature, data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes supplied data as a tag into the profile.
|
||||
* Destroys old profile, if new one was successfully
|
||||
* created.
|
||||
*
|
||||
* Returns valid pointer to new profile.
|
||||
*
|
||||
* Throws CMMException if operation fails, preserve old profile from
|
||||
* destruction.
|
||||
*/
|
||||
private native void setTagDataNative(long ptr, int tagSignature,
|
||||
byte[] data);
|
||||
|
||||
public synchronized static native LCMSProfile getProfileID(ICC_Profile profile);
|
||||
|
||||
/* Helper method used from LCMSColorTransfrom */
|
||||
static long createTransform(
|
||||
LCMSProfile[] profiles, int renderType,
|
||||
int inFormatter, boolean isInIntPacked,
|
||||
int outFormatter, boolean isOutIntPacked,
|
||||
Object disposerRef)
|
||||
{
|
||||
long[] ptrs = new long[profiles.length];
|
||||
|
||||
for (int i = 0; i < profiles.length; i++) {
|
||||
if (profiles[i] == null) throw new CMMException("Unknown profile ID");
|
||||
|
||||
ptrs[i] = profiles[i].getLcmsPtr();
|
||||
}
|
||||
|
||||
return createNativeTransform(ptrs, renderType, inFormatter,
|
||||
isInIntPacked, outFormatter, isOutIntPacked, disposerRef);
|
||||
}
|
||||
|
||||
private static native long createNativeTransform(
|
||||
long[] profileIDs, int renderType,
|
||||
int inFormatter, boolean isInIntPacked,
|
||||
int outFormatter, boolean isOutIntPacked,
|
||||
Object disposerRef);
|
||||
|
||||
/**
|
||||
* Constructs ColorTransform object corresponding to an ICC_profile
|
||||
*/
|
||||
public ColorTransform createTransform(ICC_Profile profile,
|
||||
int renderType,
|
||||
int transformType)
|
||||
{
|
||||
return new LCMSTransform(profile, renderType, renderType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an ColorTransform object from a list of ColorTransform
|
||||
* objects
|
||||
*/
|
||||
public synchronized ColorTransform createTransform(
|
||||
ColorTransform[] transforms)
|
||||
{
|
||||
return new LCMSTransform(transforms);
|
||||
}
|
||||
|
||||
/* methods invoked from LCMSTransform */
|
||||
public static native void colorConvert(LCMSTransform trans,
|
||||
LCMSImageLayout src,
|
||||
LCMSImageLayout dest);
|
||||
public static native void freeTransform(long ID);
|
||||
|
||||
public static native void initLCMS(Class Trans, Class IL, Class Pf);
|
||||
|
||||
private LCMS() {};
|
||||
|
||||
private static LCMS theLcms = null;
|
||||
|
||||
static synchronized PCMM getModule() {
|
||||
if (theLcms != null) {
|
||||
return theLcms;
|
||||
}
|
||||
|
||||
java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction() {
|
||||
public Object run() {
|
||||
/* We need to load awt here because of usage trace and
|
||||
* disposer frameworks
|
||||
*/
|
||||
System.loadLibrary("awt");
|
||||
System.loadLibrary("lcms");
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
initLCMS(LCMSTransform.class, LCMSImageLayout.class, ICC_Profile.class);
|
||||
|
||||
theLcms = new LCMS();
|
||||
|
||||
return theLcms;
|
||||
}
|
||||
}
|
||||
449
jdkSrc/jdk8/sun/java2d/cmm/lcms/LCMSImageLayout.java
Normal file
449
jdkSrc/jdk8/sun/java2d/cmm/lcms/LCMSImageLayout.java
Normal file
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package sun.java2d.cmm.lcms;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ComponentColorModel;
|
||||
import java.awt.image.ComponentSampleModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.SampleModel;
|
||||
import sun.awt.image.ByteComponentRaster;
|
||||
import sun.awt.image.ShortComponentRaster;
|
||||
import sun.awt.image.IntegerComponentRaster;
|
||||
|
||||
class LCMSImageLayout {
|
||||
|
||||
public static int BYTES_SH(int x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
public static int EXTRA_SH(int x) {
|
||||
return x << 7;
|
||||
}
|
||||
|
||||
public static int CHANNELS_SH(int x) {
|
||||
return x << 3;
|
||||
}
|
||||
public static final int SWAPFIRST = 1 << 14;
|
||||
public static final int DOSWAP = 1 << 10;
|
||||
public static final int PT_RGB_8 =
|
||||
CHANNELS_SH(3) | BYTES_SH(1);
|
||||
public static final int PT_GRAY_8 =
|
||||
CHANNELS_SH(1) | BYTES_SH(1);
|
||||
public static final int PT_GRAY_16 =
|
||||
CHANNELS_SH(1) | BYTES_SH(2);
|
||||
public static final int PT_RGBA_8 =
|
||||
EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1);
|
||||
public static final int PT_ARGB_8 =
|
||||
EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1) | SWAPFIRST;
|
||||
public static final int PT_BGR_8 =
|
||||
DOSWAP | CHANNELS_SH(3) | BYTES_SH(1);
|
||||
public static final int PT_ABGR_8 =
|
||||
DOSWAP | EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1);
|
||||
public static final int PT_BGRA_8 = EXTRA_SH(1) | CHANNELS_SH(3)
|
||||
| BYTES_SH(1) | DOSWAP | SWAPFIRST;
|
||||
public static final int DT_BYTE = 0;
|
||||
public static final int DT_SHORT = 1;
|
||||
public static final int DT_INT = 2;
|
||||
public static final int DT_DOUBLE = 3;
|
||||
boolean isIntPacked = false;
|
||||
int pixelType;
|
||||
int dataType;
|
||||
int width;
|
||||
int height;
|
||||
int nextRowOffset;
|
||||
private int nextPixelOffset;
|
||||
int offset;
|
||||
|
||||
/* This flag indicates whether the image can be processed
|
||||
* at once by doTransfrom() native call. Otherwise, the
|
||||
* image is processed scan by scan.
|
||||
*/
|
||||
private boolean imageAtOnce = false;
|
||||
Object dataArray;
|
||||
|
||||
private int dataArrayLength; /* in bytes */
|
||||
|
||||
private LCMSImageLayout(int np, int pixelType, int pixelSize)
|
||||
throws ImageLayoutException
|
||||
{
|
||||
this.pixelType = pixelType;
|
||||
width = np;
|
||||
height = 1;
|
||||
nextPixelOffset = pixelSize;
|
||||
nextRowOffset = safeMult(pixelSize, np);
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
private LCMSImageLayout(int width, int height, int pixelType,
|
||||
int pixelSize)
|
||||
throws ImageLayoutException
|
||||
{
|
||||
this.pixelType = pixelType;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
nextPixelOffset = pixelSize;
|
||||
nextRowOffset = safeMult(pixelSize, width);
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
|
||||
public LCMSImageLayout(byte[] data, int np, int pixelType, int pixelSize)
|
||||
throws ImageLayoutException
|
||||
{
|
||||
this(np, pixelType, pixelSize);
|
||||
dataType = DT_BYTE;
|
||||
dataArray = data;
|
||||
dataArrayLength = data.length;
|
||||
|
||||
verify();
|
||||
}
|
||||
|
||||
public LCMSImageLayout(short[] data, int np, int pixelType, int pixelSize)
|
||||
throws ImageLayoutException
|
||||
{
|
||||
this(np, pixelType, pixelSize);
|
||||
dataType = DT_SHORT;
|
||||
dataArray = data;
|
||||
dataArrayLength = 2 * data.length;
|
||||
|
||||
verify();
|
||||
}
|
||||
|
||||
public LCMSImageLayout(int[] data, int np, int pixelType, int pixelSize)
|
||||
throws ImageLayoutException
|
||||
{
|
||||
this(np, pixelType, pixelSize);
|
||||
dataType = DT_INT;
|
||||
dataArray = data;
|
||||
dataArrayLength = 4 * data.length;
|
||||
|
||||
verify();
|
||||
}
|
||||
|
||||
public LCMSImageLayout(double[] data, int np, int pixelType, int pixelSize)
|
||||
throws ImageLayoutException
|
||||
{
|
||||
this(np, pixelType, pixelSize);
|
||||
dataType = DT_DOUBLE;
|
||||
dataArray = data;
|
||||
dataArrayLength = 8 * data.length;
|
||||
|
||||
verify();
|
||||
}
|
||||
|
||||
private LCMSImageLayout() {
|
||||
}
|
||||
|
||||
/* This method creates a layout object for given image.
|
||||
* Returns null if the image is not supported by current implementation.
|
||||
*/
|
||||
public static LCMSImageLayout createImageLayout(BufferedImage image) throws ImageLayoutException {
|
||||
LCMSImageLayout l = new LCMSImageLayout();
|
||||
|
||||
switch (image.getType()) {
|
||||
case BufferedImage.TYPE_INT_RGB:
|
||||
l.pixelType = PT_ARGB_8;
|
||||
l.isIntPacked = true;
|
||||
break;
|
||||
case BufferedImage.TYPE_INT_ARGB:
|
||||
l.pixelType = PT_ARGB_8;
|
||||
l.isIntPacked = true;
|
||||
break;
|
||||
case BufferedImage.TYPE_INT_BGR:
|
||||
l.pixelType = PT_ABGR_8;
|
||||
l.isIntPacked = true;
|
||||
break;
|
||||
case BufferedImage.TYPE_3BYTE_BGR:
|
||||
l.pixelType = PT_BGR_8;
|
||||
break;
|
||||
case BufferedImage.TYPE_4BYTE_ABGR:
|
||||
l.pixelType = PT_ABGR_8;
|
||||
break;
|
||||
case BufferedImage.TYPE_BYTE_GRAY:
|
||||
l.pixelType = PT_GRAY_8;
|
||||
break;
|
||||
case BufferedImage.TYPE_USHORT_GRAY:
|
||||
l.pixelType = PT_GRAY_16;
|
||||
break;
|
||||
default:
|
||||
/* ColorConvertOp creates component images as
|
||||
* default destination, so this kind of images
|
||||
* has to be supported.
|
||||
*/
|
||||
ColorModel cm = image.getColorModel();
|
||||
if (cm instanceof ComponentColorModel) {
|
||||
ComponentColorModel ccm = (ComponentColorModel) cm;
|
||||
|
||||
// verify whether the component size is fine
|
||||
int[] cs = ccm.getComponentSize();
|
||||
for (int s : cs) {
|
||||
if (s != 8) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return createImageLayout(image.getRaster());
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
l.width = image.getWidth();
|
||||
l.height = image.getHeight();
|
||||
|
||||
switch (image.getType()) {
|
||||
case BufferedImage.TYPE_INT_RGB:
|
||||
case BufferedImage.TYPE_INT_ARGB:
|
||||
case BufferedImage.TYPE_INT_BGR:
|
||||
do {
|
||||
IntegerComponentRaster intRaster = (IntegerComponentRaster)
|
||||
image.getRaster();
|
||||
l.nextRowOffset = safeMult(4, intRaster.getScanlineStride());
|
||||
l.nextPixelOffset = safeMult(4, intRaster.getPixelStride());
|
||||
l.offset = safeMult(4, intRaster.getDataOffset(0));
|
||||
l.dataArray = intRaster.getDataStorage();
|
||||
l.dataArrayLength = 4 * intRaster.getDataStorage().length;
|
||||
l.dataType = DT_INT;
|
||||
|
||||
if (l.nextRowOffset == l.width * 4 * intRaster.getPixelStride()) {
|
||||
l.imageAtOnce = true;
|
||||
}
|
||||
} while (false);
|
||||
break;
|
||||
|
||||
case BufferedImage.TYPE_3BYTE_BGR:
|
||||
case BufferedImage.TYPE_4BYTE_ABGR:
|
||||
do {
|
||||
ByteComponentRaster byteRaster = (ByteComponentRaster)
|
||||
image.getRaster();
|
||||
l.nextRowOffset = byteRaster.getScanlineStride();
|
||||
l.nextPixelOffset = byteRaster.getPixelStride();
|
||||
|
||||
int firstBand = image.getSampleModel().getNumBands() - 1;
|
||||
l.offset = byteRaster.getDataOffset(firstBand);
|
||||
l.dataArray = byteRaster.getDataStorage();
|
||||
l.dataArrayLength = byteRaster.getDataStorage().length;
|
||||
l.dataType = DT_BYTE;
|
||||
if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) {
|
||||
l.imageAtOnce = true;
|
||||
}
|
||||
} while (false);
|
||||
break;
|
||||
|
||||
case BufferedImage.TYPE_BYTE_GRAY:
|
||||
do {
|
||||
ByteComponentRaster byteRaster = (ByteComponentRaster)
|
||||
image.getRaster();
|
||||
l.nextRowOffset = byteRaster.getScanlineStride();
|
||||
l.nextPixelOffset = byteRaster.getPixelStride();
|
||||
|
||||
l.dataArrayLength = byteRaster.getDataStorage().length;
|
||||
l.offset = byteRaster.getDataOffset(0);
|
||||
l.dataArray = byteRaster.getDataStorage();
|
||||
l.dataType = DT_BYTE;
|
||||
|
||||
if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) {
|
||||
l.imageAtOnce = true;
|
||||
}
|
||||
} while (false);
|
||||
break;
|
||||
|
||||
case BufferedImage.TYPE_USHORT_GRAY:
|
||||
do {
|
||||
ShortComponentRaster shortRaster = (ShortComponentRaster)
|
||||
image.getRaster();
|
||||
l.nextRowOffset = safeMult(2, shortRaster.getScanlineStride());
|
||||
l.nextPixelOffset = safeMult(2, shortRaster.getPixelStride());
|
||||
|
||||
l.offset = safeMult(2, shortRaster.getDataOffset(0));
|
||||
l.dataArray = shortRaster.getDataStorage();
|
||||
l.dataArrayLength = 2 * shortRaster.getDataStorage().length;
|
||||
l.dataType = DT_SHORT;
|
||||
|
||||
if (l.nextRowOffset == l.width * 2 * shortRaster.getPixelStride()) {
|
||||
l.imageAtOnce = true;
|
||||
}
|
||||
} while (false);
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
l.verify();
|
||||
return l;
|
||||
}
|
||||
|
||||
private static enum BandOrder {
|
||||
DIRECT,
|
||||
INVERTED,
|
||||
ARBITRARY,
|
||||
UNKNOWN;
|
||||
|
||||
public static BandOrder getBandOrder(int[] bandOffsets) {
|
||||
BandOrder order = UNKNOWN;
|
||||
|
||||
int numBands = bandOffsets.length;
|
||||
|
||||
for (int i = 0; (order != ARBITRARY) && (i < bandOffsets.length); i++) {
|
||||
switch (order) {
|
||||
case UNKNOWN:
|
||||
if (bandOffsets[i] == i) {
|
||||
order = DIRECT;
|
||||
} else if (bandOffsets[i] == (numBands - 1 - i)) {
|
||||
order = INVERTED;
|
||||
} else {
|
||||
order = ARBITRARY;
|
||||
}
|
||||
break;
|
||||
case DIRECT:
|
||||
if (bandOffsets[i] != i) {
|
||||
order = ARBITRARY;
|
||||
}
|
||||
break;
|
||||
case INVERTED:
|
||||
if (bandOffsets[i] != (numBands - 1 - i)) {
|
||||
order = ARBITRARY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return order;
|
||||
}
|
||||
}
|
||||
|
||||
private void verify() throws ImageLayoutException {
|
||||
|
||||
if (offset < 0 || offset >= dataArrayLength) {
|
||||
throw new ImageLayoutException("Invalid image layout");
|
||||
}
|
||||
|
||||
if (nextPixelOffset != getBytesPerPixel(pixelType)) {
|
||||
throw new ImageLayoutException("Invalid image layout");
|
||||
}
|
||||
|
||||
int lastScanOffset = safeMult(nextRowOffset, (height - 1));
|
||||
|
||||
int lastPixelOffset = safeMult(nextPixelOffset, (width -1 ));
|
||||
|
||||
lastPixelOffset = safeAdd(lastPixelOffset, lastScanOffset);
|
||||
|
||||
int off = safeAdd(offset, lastPixelOffset);
|
||||
|
||||
if (off < 0 || off >= dataArrayLength) {
|
||||
throw new ImageLayoutException("Invalid image layout");
|
||||
}
|
||||
}
|
||||
|
||||
static int safeAdd(int a, int b) throws ImageLayoutException {
|
||||
long res = a;
|
||||
res += b;
|
||||
if (res < Integer.MIN_VALUE || res > Integer.MAX_VALUE) {
|
||||
throw new ImageLayoutException("Invalid image layout");
|
||||
}
|
||||
return (int)res;
|
||||
}
|
||||
|
||||
static int safeMult(int a, int b) throws ImageLayoutException {
|
||||
long res = a;
|
||||
res *= b;
|
||||
if (res < Integer.MIN_VALUE || res > Integer.MAX_VALUE) {
|
||||
throw new ImageLayoutException("Invalid image layout");
|
||||
}
|
||||
return (int)res;
|
||||
}
|
||||
|
||||
public static class ImageLayoutException extends Exception {
|
||||
public ImageLayoutException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
public static LCMSImageLayout createImageLayout(Raster r) {
|
||||
LCMSImageLayout l = new LCMSImageLayout();
|
||||
if (r instanceof ByteComponentRaster &&
|
||||
r.getSampleModel() instanceof ComponentSampleModel) {
|
||||
ByteComponentRaster br = (ByteComponentRaster)r;
|
||||
|
||||
ComponentSampleModel csm = (ComponentSampleModel)r.getSampleModel();
|
||||
|
||||
l.pixelType = CHANNELS_SH(br.getNumBands()) | BYTES_SH(1);
|
||||
|
||||
int[] bandOffsets = csm.getBandOffsets();
|
||||
BandOrder order = BandOrder.getBandOrder(bandOffsets);
|
||||
|
||||
int firstBand = 0;
|
||||
switch (order) {
|
||||
case INVERTED:
|
||||
l.pixelType |= DOSWAP;
|
||||
firstBand = csm.getNumBands() - 1;
|
||||
break;
|
||||
case DIRECT:
|
||||
// do nothing
|
||||
break;
|
||||
default:
|
||||
// unable to create the image layout;
|
||||
return null;
|
||||
}
|
||||
|
||||
l.nextRowOffset = br.getScanlineStride();
|
||||
l.nextPixelOffset = br.getPixelStride();
|
||||
|
||||
l.offset = br.getDataOffset(firstBand);
|
||||
l.dataArray = br.getDataStorage();
|
||||
l.dataType = DT_BYTE;
|
||||
|
||||
l.width = br.getWidth();
|
||||
l.height = br.getHeight();
|
||||
|
||||
if (l.nextRowOffset == l.width * br.getPixelStride()) {
|
||||
l.imageAtOnce = true;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives number of bytes per pixel from the pixel format.
|
||||
* Following bit fields are used here:
|
||||
* [0..2] - bytes per sample
|
||||
* [3..6] - number of color samples per pixel
|
||||
* [7..9] - number of non-color samples per pixel
|
||||
*
|
||||
* A complete description of the pixel format can be found
|
||||
* here: lcms2.h, lines 651 - 667.
|
||||
*
|
||||
* @param pixelType pixel format in lcms2 notation.
|
||||
* @return number of bytes per pixel for given pixel format.
|
||||
*/
|
||||
private static int getBytesPerPixel(int pixelType) {
|
||||
int bytesPerSample = (0x7 & pixelType);
|
||||
int colorSamplesPerPixel = 0xF & (pixelType >> 3);
|
||||
int extraSamplesPerPixel = 0x7 & (pixelType >> 7);
|
||||
|
||||
return bytesPerSample * (colorSamplesPerPixel + extraSamplesPerPixel);
|
||||
}
|
||||
}
|
||||
109
jdkSrc/jdk8/sun/java2d/cmm/lcms/LCMSProfile.java
Normal file
109
jdkSrc/jdk8/sun/java2d/cmm/lcms/LCMSProfile.java
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.cmm.lcms;
|
||||
|
||||
import java.awt.color.CMMException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import sun.java2d.cmm.Profile;
|
||||
|
||||
final class LCMSProfile extends Profile {
|
||||
private final TagCache tagCache;
|
||||
|
||||
private final Object disposerReferent;
|
||||
|
||||
LCMSProfile(long ptr, Object ref) {
|
||||
super(ptr);
|
||||
|
||||
disposerReferent = ref;
|
||||
|
||||
tagCache = new TagCache(this);
|
||||
}
|
||||
|
||||
final long getLcmsPtr() {
|
||||
return this.getNativePtr();
|
||||
}
|
||||
|
||||
TagData getTag(int sig) {
|
||||
return tagCache.getTag(sig);
|
||||
}
|
||||
|
||||
void clearTagCache() {
|
||||
tagCache.clear();
|
||||
}
|
||||
|
||||
static class TagCache {
|
||||
final LCMSProfile profile;
|
||||
private HashMap<Integer, TagData> tags;
|
||||
|
||||
TagCache(LCMSProfile p) {
|
||||
profile = p;
|
||||
tags = new HashMap<>();
|
||||
}
|
||||
|
||||
TagData getTag(int sig) {
|
||||
TagData t = tags.get(sig);
|
||||
if (t == null) {
|
||||
byte[] tagData = LCMS.getTagNative(profile.getNativePtr(), sig);
|
||||
if (tagData != null) {
|
||||
t = new TagData(sig, tagData);
|
||||
tags.put(sig, t);
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
tags.clear();
|
||||
}
|
||||
}
|
||||
|
||||
static class TagData {
|
||||
private int signature;
|
||||
private byte[] data;
|
||||
|
||||
TagData(int sig, byte[] data) {
|
||||
this.signature = sig;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
int getSize() {
|
||||
return data.length;
|
||||
}
|
||||
|
||||
byte[] getData() {
|
||||
return Arrays.copyOf(data, data.length);
|
||||
}
|
||||
|
||||
void copyDataTo(byte[] dst) {
|
||||
System.arraycopy(data, 0, dst, 0, data.length);
|
||||
}
|
||||
|
||||
int getSignature() {
|
||||
return signature;
|
||||
}
|
||||
}
|
||||
}
|
||||
660
jdkSrc/jdk8/sun/java2d/cmm/lcms/LCMSTransform.java
Normal file
660
jdkSrc/jdk8/sun/java2d/cmm/lcms/LCMSTransform.java
Normal file
@@ -0,0 +1,660 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
*** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
|
||||
*** As an unpublished work pursuant to Title 17 of the United ***
|
||||
*** States Code. All rights reserved. ***
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************/
|
||||
|
||||
package sun.java2d.cmm.lcms;
|
||||
|
||||
import java.awt.color.ICC_Profile;
|
||||
import java.awt.color.ProfileDataException;
|
||||
import java.awt.color.CMMException;
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.DirectColorModel;
|
||||
import java.awt.image.ComponentColorModel;
|
||||
import java.awt.image.SampleModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.SinglePixelPackedSampleModel;
|
||||
import java.awt.image.ComponentSampleModel;
|
||||
import sun.java2d.cmm.*;
|
||||
import sun.java2d.cmm.lcms.*;
|
||||
import static sun.java2d.cmm.lcms.LCMSImageLayout.ImageLayoutException;
|
||||
|
||||
|
||||
public class LCMSTransform implements ColorTransform {
|
||||
long ID;
|
||||
private int inFormatter = 0;
|
||||
private boolean isInIntPacked = false;
|
||||
private int outFormatter = 0;
|
||||
private boolean isOutIntPacked = false;
|
||||
|
||||
ICC_Profile[] profiles;
|
||||
LCMSProfile[] lcmsProfiles;
|
||||
int renderType;
|
||||
int transformType;
|
||||
|
||||
private int numInComponents = -1;
|
||||
private int numOutComponents = -1;
|
||||
|
||||
private Object disposerReferent = new Object();
|
||||
|
||||
/* the class initializer */
|
||||
static {
|
||||
if (ProfileDeferralMgr.deferring) {
|
||||
ProfileDeferralMgr.activateProfiles();
|
||||
}
|
||||
}
|
||||
|
||||
public LCMSTransform(ICC_Profile profile, int renderType,
|
||||
int transformType)
|
||||
{
|
||||
/* Actually, it is not a complete transform but just part of it */
|
||||
profiles = new ICC_Profile[1];
|
||||
profiles[0] = profile;
|
||||
lcmsProfiles = new LCMSProfile[1];
|
||||
lcmsProfiles[0] = LCMS.getProfileID(profile);
|
||||
this.renderType = (renderType == ColorTransform.Any)?
|
||||
ICC_Profile.icPerceptual : renderType;
|
||||
this.transformType = transformType;
|
||||
|
||||
/* Note that ICC_Profile.getNumComponents() is quite expensive
|
||||
* (it may results in a reading of the profile header).
|
||||
* So, here we cache the number of components of input and
|
||||
* output profiles for further usage.
|
||||
*/
|
||||
numInComponents = profiles[0].getNumComponents();
|
||||
numOutComponents = profiles[profiles.length - 1].getNumComponents();
|
||||
}
|
||||
|
||||
public LCMSTransform (ColorTransform[] transforms) {
|
||||
int size = 0;
|
||||
for (int i=0; i < transforms.length; i++) {
|
||||
size+=((LCMSTransform)transforms[i]).profiles.length;
|
||||
}
|
||||
profiles = new ICC_Profile[size];
|
||||
lcmsProfiles = new LCMSProfile[size];
|
||||
int j = 0;
|
||||
for (int i=0; i < transforms.length; i++) {
|
||||
LCMSTransform curTrans = (LCMSTransform)transforms[i];
|
||||
System.arraycopy(curTrans.profiles, 0, profiles, j,
|
||||
curTrans.profiles.length);
|
||||
System.arraycopy(curTrans.lcmsProfiles, 0, lcmsProfiles, j,
|
||||
curTrans.lcmsProfiles.length);
|
||||
j += curTrans.profiles.length;
|
||||
}
|
||||
renderType = ((LCMSTransform)transforms[0]).renderType;
|
||||
|
||||
/* Note that ICC_Profile.getNumComponents() is quite expensive
|
||||
* (it may results in a reading of the profile header).
|
||||
* So, here we cache the number of components of input and
|
||||
* output profiles for further usage.
|
||||
*/
|
||||
numInComponents = profiles[0].getNumComponents();
|
||||
numOutComponents = profiles[profiles.length - 1].getNumComponents();
|
||||
}
|
||||
|
||||
public int getNumInComponents() {
|
||||
return numInComponents;
|
||||
}
|
||||
|
||||
public int getNumOutComponents() {
|
||||
return numOutComponents;
|
||||
}
|
||||
|
||||
private synchronized void doTransform(LCMSImageLayout in,
|
||||
LCMSImageLayout out) {
|
||||
// update native transfrom if needed
|
||||
if (ID == 0L ||
|
||||
inFormatter != in.pixelType || isInIntPacked != in.isIntPacked ||
|
||||
outFormatter != out.pixelType || isOutIntPacked != out.isIntPacked)
|
||||
{
|
||||
|
||||
if (ID != 0L) {
|
||||
// Disposer will destroy forgotten transform
|
||||
disposerReferent = new Object();
|
||||
}
|
||||
inFormatter = in.pixelType;
|
||||
isInIntPacked = in.isIntPacked;
|
||||
|
||||
outFormatter = out.pixelType;
|
||||
isOutIntPacked = out.isIntPacked;
|
||||
|
||||
ID = LCMS.createTransform(lcmsProfiles, renderType,
|
||||
inFormatter, isInIntPacked,
|
||||
outFormatter, isOutIntPacked,
|
||||
disposerReferent);
|
||||
}
|
||||
|
||||
LCMS.colorConvert(this, in, out);
|
||||
}
|
||||
|
||||
public void colorConvert(BufferedImage src, BufferedImage dst) {
|
||||
LCMSImageLayout srcIL, dstIL;
|
||||
try {
|
||||
if (!dst.getColorModel().hasAlpha()) {
|
||||
dstIL = LCMSImageLayout.createImageLayout(dst);
|
||||
|
||||
if (dstIL != null) {
|
||||
srcIL = LCMSImageLayout.createImageLayout(src);
|
||||
if (srcIL != null) {
|
||||
doTransform(srcIL, dstIL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ImageLayoutException e) {
|
||||
throw new CMMException("Unable to convert images");
|
||||
}
|
||||
|
||||
Raster srcRas = src.getRaster();
|
||||
WritableRaster dstRas = dst.getRaster();
|
||||
ColorModel srcCM = src.getColorModel();
|
||||
ColorModel dstCM = dst.getColorModel();
|
||||
int w = src.getWidth();
|
||||
int h = src.getHeight();
|
||||
int srcNumComp = srcCM.getNumColorComponents();
|
||||
int dstNumComp = dstCM.getNumColorComponents();
|
||||
int precision = 8;
|
||||
float maxNum = 255.0f;
|
||||
for (int i = 0; i < srcNumComp; i++) {
|
||||
if (srcCM.getComponentSize(i) > 8) {
|
||||
precision = 16;
|
||||
maxNum = 65535.0f;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < dstNumComp; i++) {
|
||||
if (dstCM.getComponentSize(i) > 8) {
|
||||
precision = 16;
|
||||
maxNum = 65535.0f;
|
||||
}
|
||||
}
|
||||
float[] srcMinVal = new float[srcNumComp];
|
||||
float[] srcInvDiffMinMax = new float[srcNumComp];
|
||||
ColorSpace cs = srcCM.getColorSpace();
|
||||
for (int i = 0; i < srcNumComp; i++) {
|
||||
srcMinVal[i] = cs.getMinValue(i);
|
||||
srcInvDiffMinMax[i] = maxNum / (cs.getMaxValue(i) - srcMinVal[i]);
|
||||
}
|
||||
cs = dstCM.getColorSpace();
|
||||
float[] dstMinVal = new float[dstNumComp];
|
||||
float[] dstDiffMinMax = new float[dstNumComp];
|
||||
for (int i = 0; i < dstNumComp; i++) {
|
||||
dstMinVal[i] = cs.getMinValue(i);
|
||||
dstDiffMinMax[i] = (cs.getMaxValue(i) - dstMinVal[i]) / maxNum;
|
||||
}
|
||||
boolean dstHasAlpha = dstCM.hasAlpha();
|
||||
boolean needSrcAlpha = srcCM.hasAlpha() && dstHasAlpha;
|
||||
float[] dstColor;
|
||||
if (dstHasAlpha) {
|
||||
dstColor = new float[dstNumComp + 1];
|
||||
} else {
|
||||
dstColor = new float[dstNumComp];
|
||||
}
|
||||
if (precision == 8) {
|
||||
byte[] srcLine = new byte[w * srcNumComp];
|
||||
byte[] dstLine = new byte[w * dstNumComp];
|
||||
Object pixel;
|
||||
float[] color;
|
||||
float[] alpha = null;
|
||||
if (needSrcAlpha) {
|
||||
alpha = new float[w];
|
||||
}
|
||||
int idx;
|
||||
// TODO check for src npixels = dst npixels
|
||||
try {
|
||||
srcIL = new LCMSImageLayout(
|
||||
srcLine, srcLine.length/getNumInComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(1), getNumInComponents());
|
||||
dstIL = new LCMSImageLayout(
|
||||
dstLine, dstLine.length/getNumOutComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
|
||||
} catch (ImageLayoutException e) {
|
||||
throw new CMMException("Unable to convert images");
|
||||
}
|
||||
// process each scanline
|
||||
for (int y = 0; y < h; y++) {
|
||||
// convert src scanline
|
||||
pixel = null;
|
||||
color = null;
|
||||
idx = 0;
|
||||
for (int x = 0; x < w; x++) {
|
||||
pixel = srcRas.getDataElements(x, y, pixel);
|
||||
color = srcCM.getNormalizedComponents(pixel, color, 0);
|
||||
for (int i = 0; i < srcNumComp; i++) {
|
||||
srcLine[idx++] = (byte)
|
||||
((color[i] - srcMinVal[i]) * srcInvDiffMinMax[i] +
|
||||
0.5f);
|
||||
}
|
||||
if (needSrcAlpha) {
|
||||
alpha[x] = color[srcNumComp];
|
||||
}
|
||||
}
|
||||
// color convert srcLine to dstLine
|
||||
doTransform(srcIL, dstIL);
|
||||
|
||||
// convert dst scanline
|
||||
pixel = null;
|
||||
idx = 0;
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int i = 0; i < dstNumComp; i++) {
|
||||
dstColor[i] = ((float) (dstLine[idx++] & 0xff)) *
|
||||
dstDiffMinMax[i] + dstMinVal[i];
|
||||
}
|
||||
if (needSrcAlpha) {
|
||||
dstColor[dstNumComp] = alpha[x];
|
||||
} else if (dstHasAlpha) {
|
||||
dstColor[dstNumComp] = 1.0f;
|
||||
}
|
||||
pixel = dstCM.getDataElements(dstColor, 0, pixel);
|
||||
dstRas.setDataElements(x, y, pixel);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
short[] srcLine = new short[w * srcNumComp];
|
||||
short[] dstLine = new short[w * dstNumComp];
|
||||
Object pixel;
|
||||
float[] color;
|
||||
float[] alpha = null;
|
||||
if (needSrcAlpha) {
|
||||
alpha = new float[w];
|
||||
}
|
||||
int idx;
|
||||
try {
|
||||
srcIL = new LCMSImageLayout(
|
||||
srcLine, srcLine.length/getNumInComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
|
||||
|
||||
dstIL = new LCMSImageLayout(
|
||||
dstLine, dstLine.length/getNumOutComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
|
||||
} catch (ImageLayoutException e) {
|
||||
throw new CMMException("Unable to convert images");
|
||||
}
|
||||
// process each scanline
|
||||
for (int y = 0; y < h; y++) {
|
||||
// convert src scanline
|
||||
pixel = null;
|
||||
color = null;
|
||||
idx = 0;
|
||||
for (int x = 0; x < w; x++) {
|
||||
pixel = srcRas.getDataElements(x, y, pixel);
|
||||
color = srcCM.getNormalizedComponents(pixel, color, 0);
|
||||
for (int i = 0; i < srcNumComp; i++) {
|
||||
srcLine[idx++] = (short)
|
||||
((color[i] - srcMinVal[i]) * srcInvDiffMinMax[i] +
|
||||
0.5f);
|
||||
}
|
||||
if (needSrcAlpha) {
|
||||
alpha[x] = color[srcNumComp];
|
||||
}
|
||||
}
|
||||
// color convert srcLine to dstLine
|
||||
doTransform(srcIL, dstIL);
|
||||
|
||||
// convert dst scanline
|
||||
pixel = null;
|
||||
idx = 0;
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int i = 0; i < dstNumComp; i++) {
|
||||
dstColor[i] = ((float) (dstLine[idx++] & 0xffff)) *
|
||||
dstDiffMinMax[i] + dstMinVal[i];
|
||||
}
|
||||
if (needSrcAlpha) {
|
||||
dstColor[dstNumComp] = alpha[x];
|
||||
} else if (dstHasAlpha) {
|
||||
dstColor[dstNumComp] = 1.0f;
|
||||
}
|
||||
pixel = dstCM.getDataElements(dstColor, 0, pixel);
|
||||
dstRas.setDataElements(x, y, pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void colorConvert(Raster src, WritableRaster dst,
|
||||
float[] srcMinVal, float[]srcMaxVal,
|
||||
float[] dstMinVal, float[]dstMaxVal) {
|
||||
LCMSImageLayout srcIL, dstIL;
|
||||
|
||||
// Can't pass src and dst directly to CMM, so process per scanline
|
||||
SampleModel srcSM = src.getSampleModel();
|
||||
SampleModel dstSM = dst.getSampleModel();
|
||||
int srcTransferType = src.getTransferType();
|
||||
int dstTransferType = dst.getTransferType();
|
||||
boolean srcIsFloat, dstIsFloat;
|
||||
if ((srcTransferType == DataBuffer.TYPE_FLOAT) ||
|
||||
(srcTransferType == DataBuffer.TYPE_DOUBLE)) {
|
||||
srcIsFloat = true;
|
||||
} else {
|
||||
srcIsFloat = false;
|
||||
}
|
||||
if ((dstTransferType == DataBuffer.TYPE_FLOAT) ||
|
||||
(dstTransferType == DataBuffer.TYPE_DOUBLE)) {
|
||||
dstIsFloat = true;
|
||||
} else {
|
||||
dstIsFloat = false;
|
||||
}
|
||||
int w = src.getWidth();
|
||||
int h = src.getHeight();
|
||||
int srcNumBands = src.getNumBands();
|
||||
int dstNumBands = dst.getNumBands();
|
||||
float[] srcScaleFactor = new float[srcNumBands];
|
||||
float[] dstScaleFactor = new float[dstNumBands];
|
||||
float[] srcUseMinVal = new float[srcNumBands];
|
||||
float[] dstUseMinVal = new float[dstNumBands];
|
||||
for (int i = 0; i < srcNumBands; i++) {
|
||||
if (srcIsFloat) {
|
||||
srcScaleFactor[i] = 65535.0f / (srcMaxVal[i] - srcMinVal[i]);
|
||||
srcUseMinVal[i] = srcMinVal[i];
|
||||
} else {
|
||||
if (srcTransferType == DataBuffer.TYPE_SHORT) {
|
||||
srcScaleFactor[i] = 65535.0f / 32767.0f;
|
||||
} else {
|
||||
srcScaleFactor[i] = 65535.0f /
|
||||
((float) ((1 << srcSM.getSampleSize(i)) - 1));
|
||||
}
|
||||
srcUseMinVal[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < dstNumBands; i++) {
|
||||
if (dstIsFloat) {
|
||||
dstScaleFactor[i] = (dstMaxVal[i] - dstMinVal[i]) / 65535.0f;
|
||||
dstUseMinVal[i] = dstMinVal[i];
|
||||
} else {
|
||||
if (dstTransferType == DataBuffer.TYPE_SHORT) {
|
||||
dstScaleFactor[i] = 32767.0f / 65535.0f;
|
||||
} else {
|
||||
dstScaleFactor[i] =
|
||||
((float) ((1 << dstSM.getSampleSize(i)) - 1)) /
|
||||
65535.0f;
|
||||
}
|
||||
dstUseMinVal[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
int ys = src.getMinY();
|
||||
int yd = dst.getMinY();
|
||||
int xs, xd;
|
||||
float sample;
|
||||
short[] srcLine = new short[w * srcNumBands];
|
||||
short[] dstLine = new short[w * dstNumBands];
|
||||
int idx;
|
||||
try {
|
||||
srcIL = new LCMSImageLayout(
|
||||
srcLine, srcLine.length/getNumInComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
|
||||
|
||||
dstIL = new LCMSImageLayout(
|
||||
dstLine, dstLine.length/getNumOutComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
|
||||
} catch (ImageLayoutException e) {
|
||||
throw new CMMException("Unable to convert rasters");
|
||||
}
|
||||
// process each scanline
|
||||
for (int y = 0; y < h; y++, ys++, yd++) {
|
||||
// get src scanline
|
||||
xs = src.getMinX();
|
||||
idx = 0;
|
||||
for (int x = 0; x < w; x++, xs++) {
|
||||
for (int i = 0; i < srcNumBands; i++) {
|
||||
sample = src.getSampleFloat(xs, ys, i);
|
||||
srcLine[idx++] = (short)
|
||||
((sample - srcUseMinVal[i]) * srcScaleFactor[i] + 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
// color convert srcLine to dstLine
|
||||
doTransform(srcIL, dstIL);
|
||||
|
||||
// store dst scanline
|
||||
xd = dst.getMinX();
|
||||
idx = 0;
|
||||
for (int x = 0; x < w; x++, xd++) {
|
||||
for (int i = 0; i < dstNumBands; i++) {
|
||||
sample = ((dstLine[idx++] & 0xffff) * dstScaleFactor[i]) +
|
||||
dstUseMinVal[i];
|
||||
dst.setSample(xd, yd, i, sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void colorConvert(Raster src, WritableRaster dst) {
|
||||
|
||||
LCMSImageLayout srcIL, dstIL;
|
||||
dstIL = LCMSImageLayout.createImageLayout(dst);
|
||||
if (dstIL != null) {
|
||||
srcIL = LCMSImageLayout.createImageLayout(src);
|
||||
if (srcIL != null) {
|
||||
doTransform(srcIL, dstIL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Can't pass src and dst directly to CMM, so process per scanline
|
||||
SampleModel srcSM = src.getSampleModel();
|
||||
SampleModel dstSM = dst.getSampleModel();
|
||||
int srcTransferType = src.getTransferType();
|
||||
int dstTransferType = dst.getTransferType();
|
||||
int w = src.getWidth();
|
||||
int h = src.getHeight();
|
||||
int srcNumBands = src.getNumBands();
|
||||
int dstNumBands = dst.getNumBands();
|
||||
int precision = 8;
|
||||
float maxNum = 255.0f;
|
||||
for (int i = 0; i < srcNumBands; i++) {
|
||||
if (srcSM.getSampleSize(i) > 8) {
|
||||
precision = 16;
|
||||
maxNum = 65535.0f;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < dstNumBands; i++) {
|
||||
if (dstSM.getSampleSize(i) > 8) {
|
||||
precision = 16;
|
||||
maxNum = 65535.0f;
|
||||
}
|
||||
}
|
||||
float[] srcScaleFactor = new float[srcNumBands];
|
||||
float[] dstScaleFactor = new float[dstNumBands];
|
||||
for (int i = 0; i < srcNumBands; i++) {
|
||||
if (srcTransferType == DataBuffer.TYPE_SHORT) {
|
||||
srcScaleFactor[i] = maxNum / 32767.0f;
|
||||
} else {
|
||||
srcScaleFactor[i] = maxNum /
|
||||
((float) ((1 << srcSM.getSampleSize(i)) - 1));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < dstNumBands; i++) {
|
||||
if (dstTransferType == DataBuffer.TYPE_SHORT) {
|
||||
dstScaleFactor[i] = 32767.0f / maxNum;
|
||||
} else {
|
||||
dstScaleFactor[i] =
|
||||
((float) ((1 << dstSM.getSampleSize(i)) - 1)) / maxNum;
|
||||
}
|
||||
}
|
||||
int ys = src.getMinY();
|
||||
int yd = dst.getMinY();
|
||||
int xs, xd;
|
||||
int sample;
|
||||
if (precision == 8) {
|
||||
byte[] srcLine = new byte[w * srcNumBands];
|
||||
byte[] dstLine = new byte[w * dstNumBands];
|
||||
int idx;
|
||||
// TODO check for src npixels = dst npixels
|
||||
try {
|
||||
srcIL = new LCMSImageLayout(
|
||||
srcLine, srcLine.length/getNumInComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(1), getNumInComponents());
|
||||
dstIL = new LCMSImageLayout(
|
||||
dstLine, dstLine.length/getNumOutComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
|
||||
} catch (ImageLayoutException e) {
|
||||
throw new CMMException("Unable to convert rasters");
|
||||
}
|
||||
// process each scanline
|
||||
for (int y = 0; y < h; y++, ys++, yd++) {
|
||||
// get src scanline
|
||||
xs = src.getMinX();
|
||||
idx = 0;
|
||||
for (int x = 0; x < w; x++, xs++) {
|
||||
for (int i = 0; i < srcNumBands; i++) {
|
||||
sample = src.getSample(xs, ys, i);
|
||||
srcLine[idx++] = (byte)
|
||||
((sample * srcScaleFactor[i]) + 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
// color convert srcLine to dstLine
|
||||
doTransform(srcIL, dstIL);
|
||||
|
||||
// store dst scanline
|
||||
xd = dst.getMinX();
|
||||
idx = 0;
|
||||
for (int x = 0; x < w; x++, xd++) {
|
||||
for (int i = 0; i < dstNumBands; i++) {
|
||||
sample = (int) (((dstLine[idx++] & 0xff) *
|
||||
dstScaleFactor[i]) + 0.5f);
|
||||
dst.setSample(xd, yd, i, sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
short[] srcLine = new short[w * srcNumBands];
|
||||
short[] dstLine = new short[w * dstNumBands];
|
||||
int idx;
|
||||
|
||||
try {
|
||||
srcIL = new LCMSImageLayout(
|
||||
srcLine, srcLine.length/getNumInComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
|
||||
|
||||
dstIL = new LCMSImageLayout(
|
||||
dstLine, dstLine.length/getNumOutComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
|
||||
} catch (ImageLayoutException e) {
|
||||
throw new CMMException("Unable to convert rasters");
|
||||
}
|
||||
// process each scanline
|
||||
for (int y = 0; y < h; y++, ys++, yd++) {
|
||||
// get src scanline
|
||||
xs = src.getMinX();
|
||||
idx = 0;
|
||||
for (int x = 0; x < w; x++, xs++) {
|
||||
for (int i = 0; i < srcNumBands; i++) {
|
||||
sample = src.getSample(xs, ys, i);
|
||||
srcLine[idx++] = (short)
|
||||
((sample * srcScaleFactor[i]) + 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
// color convert srcLine to dstLine
|
||||
doTransform(srcIL, dstIL);
|
||||
|
||||
// store dst scanline
|
||||
xd = dst.getMinX();
|
||||
idx = 0;
|
||||
for (int x = 0; x < w; x++, xd++) {
|
||||
for (int i = 0; i < dstNumBands; i++) {
|
||||
sample = (int) (((dstLine[idx++] & 0xffff) *
|
||||
dstScaleFactor[i]) + 0.5f);
|
||||
dst.setSample(xd, yd, i, sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* convert an array of colors in short format */
|
||||
/* each color is a contiguous set of array elements */
|
||||
/* the number of colors is (size of the array) / (number of input/output
|
||||
components */
|
||||
public short[] colorConvert(short[] src, short[] dst) {
|
||||
|
||||
if (dst == null) {
|
||||
dst = new short [(src.length/getNumInComponents())*getNumOutComponents()];
|
||||
}
|
||||
|
||||
try {
|
||||
LCMSImageLayout srcIL = new LCMSImageLayout(
|
||||
src, src.length/getNumInComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
|
||||
|
||||
LCMSImageLayout dstIL = new LCMSImageLayout(
|
||||
dst, dst.length/getNumOutComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
|
||||
|
||||
doTransform(srcIL, dstIL);
|
||||
|
||||
return dst;
|
||||
} catch (ImageLayoutException e) {
|
||||
throw new CMMException("Unable to convert data");
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] colorConvert(byte[] src, byte[] dst) {
|
||||
if (dst == null) {
|
||||
dst = new byte [(src.length/getNumInComponents())*getNumOutComponents()];
|
||||
}
|
||||
|
||||
try {
|
||||
LCMSImageLayout srcIL = new LCMSImageLayout(
|
||||
src, src.length/getNumInComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(1), getNumInComponents());
|
||||
|
||||
LCMSImageLayout dstIL = new LCMSImageLayout(
|
||||
dst, dst.length/getNumOutComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
|
||||
|
||||
doTransform(srcIL, dstIL);
|
||||
|
||||
return dst;
|
||||
} catch (ImageLayoutException e) {
|
||||
throw new CMMException("Unable to convert data");
|
||||
}
|
||||
}
|
||||
}
|
||||
36
jdkSrc/jdk8/sun/java2d/cmm/lcms/LcmsServiceProvider.java
Normal file
36
jdkSrc/jdk8/sun/java2d/cmm/lcms/LcmsServiceProvider.java
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.cmm.lcms;
|
||||
|
||||
import sun.java2d.cmm.CMMServiceProvider;
|
||||
import sun.java2d.cmm.PCMM;
|
||||
|
||||
public final class LcmsServiceProvider extends CMMServiceProvider {
|
||||
@Override
|
||||
protected PCMM getModule() {
|
||||
return LCMS.getModule();
|
||||
}
|
||||
}
|
||||
888
jdkSrc/jdk8/sun/java2d/d3d/D3DBlitLoops.java
Normal file
888
jdkSrc/jdk8/sun/java2d/d3d/D3DBlitLoops.java
Normal file
@@ -0,0 +1,888 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Composite;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.AffineTransformOp;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.annotation.Native;
|
||||
import sun.java2d.ScreenUpdateManager;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.Blit;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.loops.GraphicsPrimitiveMgr;
|
||||
import sun.java2d.loops.ScaledBlit;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.java2d.loops.TransformBlit;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.java2d.pipe.RenderBuffer;
|
||||
import sun.java2d.pipe.RenderQueue;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
import sun.java2d.windows.GDIWindowSurfaceData;
|
||||
|
||||
final class D3DBlitLoops {
|
||||
|
||||
static void register() {
|
||||
Blit blitIntArgbPreToSurface =
|
||||
new D3DSwToSurfaceBlit(SurfaceType.IntArgbPre,
|
||||
D3DSurfaceData.ST_INT_ARGB_PRE);
|
||||
Blit blitIntArgbPreToTexture =
|
||||
new D3DSwToTextureBlit(SurfaceType.IntArgbPre,
|
||||
D3DSurfaceData.ST_INT_ARGB_PRE);
|
||||
TransformBlit transformBlitIntArgbPreToSurface =
|
||||
new D3DSwToSurfaceTransform(SurfaceType.IntArgbPre,
|
||||
D3DSurfaceData.ST_INT_ARGB_PRE);
|
||||
GraphicsPrimitive[] primitives = {
|
||||
// prevent D3DSurface -> Screen blits
|
||||
new D3DSurfaceToGDIWindowSurfaceBlit(),
|
||||
new D3DSurfaceToGDIWindowSurfaceScale(),
|
||||
new D3DSurfaceToGDIWindowSurfaceTransform(),
|
||||
|
||||
// surface->surface ops
|
||||
new D3DSurfaceToSurfaceBlit(),
|
||||
new D3DSurfaceToSurfaceScale(),
|
||||
new D3DSurfaceToSurfaceTransform(),
|
||||
|
||||
// render-to-texture surface->surface ops
|
||||
new D3DRTTSurfaceToSurfaceBlit(),
|
||||
new D3DRTTSurfaceToSurfaceScale(),
|
||||
new D3DRTTSurfaceToSurfaceTransform(),
|
||||
|
||||
// surface->sw ops
|
||||
new D3DSurfaceToSwBlit(SurfaceType.IntArgb,
|
||||
D3DSurfaceData.ST_INT_ARGB),
|
||||
|
||||
// sw->surface ops
|
||||
blitIntArgbPreToSurface,
|
||||
new D3DSwToSurfaceBlit(SurfaceType.IntArgb,
|
||||
D3DSurfaceData.ST_INT_ARGB),
|
||||
new D3DSwToSurfaceBlit(SurfaceType.IntRgb,
|
||||
D3DSurfaceData.ST_INT_RGB),
|
||||
new D3DSwToSurfaceBlit(SurfaceType.IntBgr,
|
||||
D3DSurfaceData.ST_INT_BGR),
|
||||
new D3DSwToSurfaceBlit(SurfaceType.ThreeByteBgr,
|
||||
D3DSurfaceData.ST_3BYTE_BGR),
|
||||
new D3DSwToSurfaceBlit(SurfaceType.Ushort565Rgb,
|
||||
D3DSurfaceData.ST_USHORT_565_RGB),
|
||||
new D3DSwToSurfaceBlit(SurfaceType.Ushort555Rgb,
|
||||
D3DSurfaceData.ST_USHORT_555_RGB),
|
||||
new D3DSwToSurfaceBlit(SurfaceType.ByteIndexed,
|
||||
D3DSurfaceData.ST_BYTE_INDEXED),
|
||||
// REMIND: we don't have a native sw loop to back this loop up
|
||||
// new D3DSwToSurfaceBlit(SurfaceType.ByteIndexedBm,
|
||||
// D3DSurfaceData.ST_BYTE_INDEXED_BM),
|
||||
new D3DGeneralBlit(D3DSurfaceData.D3DSurface,
|
||||
CompositeType.AnyAlpha,
|
||||
blitIntArgbPreToSurface),
|
||||
|
||||
new D3DSwToSurfaceScale(SurfaceType.IntArgb,
|
||||
D3DSurfaceData.ST_INT_ARGB),
|
||||
new D3DSwToSurfaceScale(SurfaceType.IntArgbPre,
|
||||
D3DSurfaceData.ST_INT_ARGB_PRE),
|
||||
new D3DSwToSurfaceScale(SurfaceType.IntRgb,
|
||||
D3DSurfaceData.ST_INT_RGB),
|
||||
new D3DSwToSurfaceScale(SurfaceType.IntBgr,
|
||||
D3DSurfaceData.ST_INT_BGR),
|
||||
new D3DSwToSurfaceScale(SurfaceType.ThreeByteBgr,
|
||||
D3DSurfaceData.ST_3BYTE_BGR),
|
||||
new D3DSwToSurfaceScale(SurfaceType.Ushort565Rgb,
|
||||
D3DSurfaceData.ST_USHORT_565_RGB),
|
||||
new D3DSwToSurfaceScale(SurfaceType.Ushort555Rgb,
|
||||
D3DSurfaceData.ST_USHORT_555_RGB),
|
||||
new D3DSwToSurfaceScale(SurfaceType.ByteIndexed,
|
||||
D3DSurfaceData.ST_BYTE_INDEXED),
|
||||
// REMIND: we don't have a native sw loop to back this loop up
|
||||
// new D3DSwToSurfaceScale(SurfaceType.ByteIndexedBm,
|
||||
// D3DSurfaceData.ST_BYTE_INDEXED_BM),
|
||||
|
||||
new D3DSwToSurfaceTransform(SurfaceType.IntArgb,
|
||||
D3DSurfaceData.ST_INT_ARGB),
|
||||
new D3DSwToSurfaceTransform(SurfaceType.IntRgb,
|
||||
D3DSurfaceData.ST_INT_RGB),
|
||||
new D3DSwToSurfaceTransform(SurfaceType.IntBgr,
|
||||
D3DSurfaceData.ST_INT_BGR),
|
||||
new D3DSwToSurfaceTransform(SurfaceType.ThreeByteBgr,
|
||||
D3DSurfaceData.ST_3BYTE_BGR),
|
||||
new D3DSwToSurfaceTransform(SurfaceType.Ushort565Rgb,
|
||||
D3DSurfaceData.ST_USHORT_565_RGB),
|
||||
new D3DSwToSurfaceTransform(SurfaceType.Ushort555Rgb,
|
||||
D3DSurfaceData.ST_USHORT_555_RGB),
|
||||
new D3DSwToSurfaceTransform(SurfaceType.ByteIndexed,
|
||||
D3DSurfaceData.ST_BYTE_INDEXED),
|
||||
// REMIND: we don't have a native sw loop to back this loop up
|
||||
// new D3DSwToSurfaceTransform(SurfaceType.ByteIndexedBm,
|
||||
// D3DSurfaceData.ST_BYTE_INDEXED_BM),
|
||||
transformBlitIntArgbPreToSurface,
|
||||
|
||||
new D3DGeneralTransformedBlit(transformBlitIntArgbPreToSurface),
|
||||
|
||||
// texture->surface ops
|
||||
new D3DTextureToSurfaceBlit(),
|
||||
new D3DTextureToSurfaceScale(),
|
||||
new D3DTextureToSurfaceTransform(),
|
||||
|
||||
// sw->texture ops
|
||||
blitIntArgbPreToTexture,
|
||||
new D3DSwToTextureBlit(SurfaceType.IntRgb,
|
||||
D3DSurfaceData.ST_INT_RGB),
|
||||
new D3DSwToTextureBlit(SurfaceType.IntArgb,
|
||||
D3DSurfaceData.ST_INT_ARGB),
|
||||
new D3DSwToTextureBlit(SurfaceType.IntBgr,
|
||||
D3DSurfaceData.ST_INT_BGR),
|
||||
new D3DSwToTextureBlit(SurfaceType.ThreeByteBgr,
|
||||
D3DSurfaceData.ST_3BYTE_BGR),
|
||||
new D3DSwToTextureBlit(SurfaceType.Ushort565Rgb,
|
||||
D3DSurfaceData.ST_USHORT_565_RGB),
|
||||
new D3DSwToTextureBlit(SurfaceType.Ushort555Rgb,
|
||||
D3DSurfaceData.ST_USHORT_555_RGB),
|
||||
new D3DSwToTextureBlit(SurfaceType.ByteIndexed,
|
||||
D3DSurfaceData.ST_BYTE_INDEXED),
|
||||
// REMIND: we don't have a native sw loop to back this loop up
|
||||
// new D3DSwToTextureBlit(SurfaceType.ByteIndexedBm,
|
||||
// D3DSurfaceData.ST_BYTE_INDEXED_BM),
|
||||
new D3DGeneralBlit(D3DSurfaceData.D3DTexture,
|
||||
CompositeType.SrcNoEa,
|
||||
blitIntArgbPreToTexture),
|
||||
};
|
||||
GraphicsPrimitiveMgr.register(primitives);
|
||||
}
|
||||
|
||||
/**
|
||||
* The following offsets are used to pack the parameters in
|
||||
* createPackedParams(). (They are also used at the native level when
|
||||
* unpacking the params.)
|
||||
*/
|
||||
@Native private static final int OFFSET_SRCTYPE = 16;
|
||||
@Native private static final int OFFSET_HINT = 8;
|
||||
@Native private static final int OFFSET_TEXTURE = 3;
|
||||
@Native private static final int OFFSET_RTT = 2;
|
||||
@Native private static final int OFFSET_XFORM = 1;
|
||||
@Native private static final int OFFSET_ISOBLIT = 0;
|
||||
|
||||
/**
|
||||
* Packs the given parameters into a single int value in order to save
|
||||
* space on the rendering queue.
|
||||
*/
|
||||
private static int createPackedParams(boolean isoblit, boolean texture,
|
||||
boolean rtt, boolean xform,
|
||||
int hint, int srctype)
|
||||
{
|
||||
return
|
||||
((srctype << OFFSET_SRCTYPE) |
|
||||
(hint << OFFSET_HINT ) |
|
||||
((texture ? 1 : 0) << OFFSET_TEXTURE) |
|
||||
((rtt ? 1 : 0) << OFFSET_RTT ) |
|
||||
((xform ? 1 : 0) << OFFSET_XFORM ) |
|
||||
((isoblit ? 1 : 0) << OFFSET_ISOBLIT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues a BLIT operation with the given parameters. Note that the
|
||||
* RenderQueue lock must be held before calling this method.
|
||||
*/
|
||||
private static void enqueueBlit(RenderQueue rq,
|
||||
SurfaceData src, SurfaceData dst,
|
||||
int packedParams,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(72, 24);
|
||||
buf.putInt(BLIT);
|
||||
buf.putInt(packedParams);
|
||||
buf.putInt(sx1).putInt(sy1);
|
||||
buf.putInt(sx2).putInt(sy2);
|
||||
buf.putDouble(dx1).putDouble(dy1);
|
||||
buf.putDouble(dx2).putDouble(dy2);
|
||||
buf.putLong(src.getNativeOps());
|
||||
buf.putLong(dst.getNativeOps());
|
||||
}
|
||||
|
||||
static void Blit(SurfaceData srcData, SurfaceData dstData,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform xform, int hint,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
int srctype, boolean texture)
|
||||
{
|
||||
int ctxflags = 0;
|
||||
if (srcData.getTransparency() == Transparency.OPAQUE) {
|
||||
ctxflags |= D3DContext.SRC_IS_OPAQUE;
|
||||
}
|
||||
|
||||
D3DSurfaceData d3dDst = (D3DSurfaceData)dstData;
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
// make sure the RenderQueue keeps a hard reference to the
|
||||
// source (sysmem) SurfaceData to prevent it from being
|
||||
// disposed while the operation is processed on the QFT
|
||||
rq.addReference(srcData);
|
||||
|
||||
if (texture) {
|
||||
// make sure we have a current context before uploading
|
||||
// the sysmem data to the texture object
|
||||
D3DContext.setScratchSurface(d3dDst.getContext());
|
||||
} else {
|
||||
D3DContext.validateContext(d3dDst, d3dDst,
|
||||
clip, comp, xform, null, null,
|
||||
ctxflags);
|
||||
}
|
||||
|
||||
int packedParams = createPackedParams(false, texture,
|
||||
false, xform != null,
|
||||
hint, srctype);
|
||||
enqueueBlit(rq, srcData, dstData,
|
||||
packedParams,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2);
|
||||
|
||||
// always flush immediately, since we (currently) have no means
|
||||
// of tracking changes to the system memory surface
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
|
||||
if (d3dDst.getType() == D3DSurfaceData.WINDOW) {
|
||||
// flush immediately when copying to the screen to improve
|
||||
// responsiveness of applications using VI or BI backbuffers
|
||||
D3DScreenUpdateManager mgr =
|
||||
(D3DScreenUpdateManager)ScreenUpdateManager.getInstance();
|
||||
mgr.runUpdateNow();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: The srcImg and biop parameters are only used when invoked
|
||||
* from the D3DBufImgOps.renderImageWithOp() method; in all other cases,
|
||||
* this method can be called with null values for those two parameters,
|
||||
* and they will be effectively ignored.
|
||||
*/
|
||||
static void IsoBlit(SurfaceData srcData, SurfaceData dstData,
|
||||
BufferedImage srcImg, BufferedImageOp biop,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform xform, int hint,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
boolean texture)
|
||||
{
|
||||
int ctxflags = 0;
|
||||
if (srcData.getTransparency() == Transparency.OPAQUE) {
|
||||
ctxflags |= D3DContext.SRC_IS_OPAQUE;
|
||||
}
|
||||
|
||||
D3DSurfaceData d3dDst = (D3DSurfaceData)dstData;
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
boolean rtt = false;
|
||||
rq.lock();
|
||||
try {
|
||||
D3DSurfaceData d3dSrc = (D3DSurfaceData)srcData;
|
||||
int srctype = d3dSrc.getType();
|
||||
D3DSurfaceData srcCtxData = d3dSrc;
|
||||
if (srctype == D3DSurfaceData.TEXTURE) {
|
||||
rtt = false;
|
||||
} else {
|
||||
// the source is a backbuffer, or render-to-texture
|
||||
// surface; we set rtt to true to differentiate this kind
|
||||
// of surface from a regular texture object
|
||||
rtt = true;
|
||||
}
|
||||
|
||||
D3DContext.validateContext(srcCtxData, d3dDst,
|
||||
clip, comp, xform, null, null,
|
||||
ctxflags);
|
||||
|
||||
if (biop != null) {
|
||||
D3DBufImgOps.enableBufImgOp(rq, d3dSrc, srcImg, biop);
|
||||
}
|
||||
|
||||
int packedParams = createPackedParams(true, texture,
|
||||
rtt, xform != null,
|
||||
hint, 0 /*unused*/);
|
||||
enqueueBlit(rq, srcData, dstData,
|
||||
packedParams,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2);
|
||||
|
||||
if (biop != null) {
|
||||
D3DBufImgOps.disableBufImgOp(rq, biop);
|
||||
}
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
|
||||
if (rtt && (d3dDst.getType() == D3DSurfaceData.WINDOW)) {
|
||||
// we only have to flush immediately when copying from a
|
||||
// (non-texture) surface to the screen; otherwise Swing apps
|
||||
// might appear unresponsive until the auto-flush completes
|
||||
D3DScreenUpdateManager mgr =
|
||||
(D3DScreenUpdateManager)ScreenUpdateManager.getInstance();
|
||||
mgr.runUpdateNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class D3DSurfaceToSurfaceBlit extends Blit {
|
||||
|
||||
D3DSurfaceToSurfaceBlit() {
|
||||
super(D3DSurfaceData.D3DSurface,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
D3DBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DSurfaceToSurfaceScale extends ScaledBlit {
|
||||
|
||||
D3DSurfaceToSurfaceScale() {
|
||||
super(D3DSurfaceData.D3DSurface,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
public void Scale(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
D3DBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DSurfaceToSurfaceTransform extends TransformBlit {
|
||||
|
||||
D3DSurfaceToSurfaceTransform() {
|
||||
super(D3DSurfaceData.D3DSurface,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
public void Transform(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform at, int hint,
|
||||
int sx, int sy, int dx, int dy,
|
||||
int w, int h)
|
||||
{
|
||||
D3DBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, at, hint,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DRTTSurfaceToSurfaceBlit extends Blit {
|
||||
|
||||
D3DRTTSurfaceToSurfaceBlit() {
|
||||
super(D3DSurfaceData.D3DSurfaceRTT,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
D3DBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DRTTSurfaceToSurfaceScale extends ScaledBlit {
|
||||
|
||||
D3DRTTSurfaceToSurfaceScale() {
|
||||
super(D3DSurfaceData.D3DSurfaceRTT,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
public void Scale(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
D3DBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DRTTSurfaceToSurfaceTransform extends TransformBlit {
|
||||
|
||||
D3DRTTSurfaceToSurfaceTransform() {
|
||||
super(D3DSurfaceData.D3DSurfaceRTT,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
public void Transform(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform at, int hint,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
D3DBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, at, hint,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DSurfaceToSwBlit extends Blit {
|
||||
|
||||
private int typeval;
|
||||
|
||||
// REMIND: destination will actually be opaque/premultiplied...
|
||||
D3DSurfaceToSwBlit(SurfaceType dstType, int typeval) {
|
||||
super(D3DSurfaceData.D3DSurface,
|
||||
CompositeType.SrcNoEa,
|
||||
dstType);
|
||||
this.typeval = typeval;
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy,
|
||||
int w, int h)
|
||||
{
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
// make sure the RenderQueue keeps a hard reference to the
|
||||
// destination (sysmem) SurfaceData to prevent it from being
|
||||
// disposed while the operation is processed on the QFT
|
||||
rq.addReference(dst);
|
||||
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
D3DContext.setScratchSurface(((D3DSurfaceData)src).getContext());
|
||||
|
||||
rq.ensureCapacityAndAlignment(48, 32);
|
||||
buf.putInt(SURFACE_TO_SW_BLIT);
|
||||
buf.putInt(sx).putInt(sy);
|
||||
buf.putInt(dx).putInt(dy);
|
||||
buf.putInt(w).putInt(h);
|
||||
buf.putInt(typeval);
|
||||
buf.putLong(src.getNativeOps());
|
||||
buf.putLong(dst.getNativeOps());
|
||||
|
||||
// always flush immediately
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class D3DSwToSurfaceBlit extends Blit {
|
||||
|
||||
private int typeval;
|
||||
|
||||
D3DSwToSurfaceBlit(SurfaceType srcType, int typeval) {
|
||||
super(srcType,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
this.typeval = typeval;
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
D3DBlitLoops.Blit(src, dst,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
typeval, false);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DSwToSurfaceScale extends ScaledBlit {
|
||||
|
||||
private int typeval;
|
||||
|
||||
D3DSwToSurfaceScale(SurfaceType srcType, int typeval) {
|
||||
super(srcType,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
this.typeval = typeval;
|
||||
}
|
||||
|
||||
public void Scale(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
D3DBlitLoops.Blit(src, dst,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2,
|
||||
typeval, false);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DSwToSurfaceTransform extends TransformBlit {
|
||||
|
||||
private int typeval;
|
||||
|
||||
D3DSwToSurfaceTransform(SurfaceType srcType, int typeval) {
|
||||
super(srcType,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
this.typeval = typeval;
|
||||
}
|
||||
|
||||
public void Transform(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform at, int hint,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
D3DBlitLoops.Blit(src, dst,
|
||||
comp, clip, at, hint,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
typeval, false);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DSwToTextureBlit extends Blit {
|
||||
|
||||
private int typeval;
|
||||
|
||||
D3DSwToTextureBlit(SurfaceType srcType, int typeval) {
|
||||
super(srcType,
|
||||
CompositeType.SrcNoEa,
|
||||
D3DSurfaceData.D3DTexture);
|
||||
this.typeval = typeval;
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
D3DBlitLoops.Blit(src, dst,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
typeval, true);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DTextureToSurfaceBlit extends Blit {
|
||||
|
||||
D3DTextureToSurfaceBlit() {
|
||||
super(D3DSurfaceData.D3DTexture,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
D3DBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DTextureToSurfaceScale extends ScaledBlit {
|
||||
|
||||
D3DTextureToSurfaceScale() {
|
||||
super(D3DSurfaceData.D3DTexture,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
public void Scale(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
D3DBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DTextureToSurfaceTransform extends TransformBlit {
|
||||
|
||||
D3DTextureToSurfaceTransform() {
|
||||
super(D3DSurfaceData.D3DTexture,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
public void Transform(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform at, int hint,
|
||||
int sx, int sy, int dx, int dy,
|
||||
int w, int h)
|
||||
{
|
||||
D3DBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, at, hint,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This general Blit implementation converts any source surface to an
|
||||
* intermediate IntArgbPre surface, and then uses the more specific
|
||||
* IntArgbPre->D3DSurface/Texture loop to get the intermediate
|
||||
* (premultiplied) surface down to D3D using simple blit.
|
||||
*/
|
||||
class D3DGeneralBlit extends Blit {
|
||||
|
||||
private final Blit performop;
|
||||
private WeakReference srcTmp;
|
||||
|
||||
D3DGeneralBlit(SurfaceType dstType,
|
||||
CompositeType compType,
|
||||
Blit performop)
|
||||
{
|
||||
super(SurfaceType.Any, compType, dstType);
|
||||
this.performop = performop;
|
||||
}
|
||||
|
||||
public synchronized void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy,
|
||||
int w, int h)
|
||||
{
|
||||
Blit convertsrc = Blit.getFromCache(src.getSurfaceType(),
|
||||
CompositeType.SrcNoEa,
|
||||
SurfaceType.IntArgbPre);
|
||||
|
||||
SurfaceData cachedSrc = null;
|
||||
if (srcTmp != null) {
|
||||
// use cached intermediate surface, if available
|
||||
cachedSrc = (SurfaceData)srcTmp.get();
|
||||
}
|
||||
|
||||
// convert source to IntArgbPre
|
||||
src = convertFrom(convertsrc, src, sx, sy, w, h,
|
||||
cachedSrc, BufferedImage.TYPE_INT_ARGB_PRE);
|
||||
|
||||
// copy IntArgbPre intermediate surface to D3D surface
|
||||
performop.Blit(src, dst, comp, clip,
|
||||
0, 0, dx, dy, w, h);
|
||||
|
||||
if (src != cachedSrc) {
|
||||
// cache the intermediate surface
|
||||
srcTmp = new WeakReference(src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This general TransformedBlit implementation converts any source surface to an
|
||||
* intermediate IntArgbPre surface, and then uses the more specific
|
||||
* IntArgbPre->D3DSurface/Texture loop to get the intermediate
|
||||
* (premultiplied) surface down to D3D using simple transformBlit.
|
||||
*/
|
||||
final class D3DGeneralTransformedBlit extends TransformBlit {
|
||||
|
||||
private final TransformBlit performop;
|
||||
private WeakReference<SurfaceData> srcTmp;
|
||||
|
||||
D3DGeneralTransformedBlit(final TransformBlit performop) {
|
||||
super(SurfaceType.Any, CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
this.performop = performop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void Transform(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform at, int hint, int srcx,
|
||||
int srcy, int dstx, int dsty, int width,
|
||||
int height){
|
||||
Blit convertsrc = Blit.getFromCache(src.getSurfaceType(),
|
||||
CompositeType.SrcNoEa,
|
||||
SurfaceType.IntArgbPre);
|
||||
// use cached intermediate surface, if available
|
||||
final SurfaceData cachedSrc = srcTmp != null ? srcTmp.get() : null;
|
||||
// convert source to IntArgbPre
|
||||
src = convertFrom(convertsrc, src, srcx, srcy, width, height, cachedSrc,
|
||||
BufferedImage.TYPE_INT_ARGB_PRE);
|
||||
|
||||
// transform IntArgbPre intermediate surface to D3D surface
|
||||
performop.Transform(src, dst, comp, clip, at, hint, 0, 0, dstx, dsty,
|
||||
width, height);
|
||||
|
||||
if (src != cachedSrc) {
|
||||
// cache the intermediate surface
|
||||
srcTmp = new WeakReference<>(src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The following classes prohibit copying D3DSurfaces to the screen
|
||||
* (the D3D->sysmem->GDI path is known to be very very slow).
|
||||
*
|
||||
* Note: we used to disable hw acceleration for the surafce manager associated
|
||||
* with the source surface in these loops but it proved to be too cautious.
|
||||
*
|
||||
* In most cases d3d->screen copy happens only during some transitional
|
||||
* period where the accelerated destination surface is being recreated or
|
||||
* restored (for example, when Swing's backbuffer VI is copied to the screen
|
||||
* but the D3DScreenSurfaceManager couldn't restore its surface).
|
||||
*
|
||||
* An exception is if for some reason we could not enable accelerated on-screen
|
||||
* rendering for this window for some permanent reason (like window being too
|
||||
* small, or a present BufferStrategy).
|
||||
*
|
||||
* This meant that we'd disable hw acceleration after the first failure
|
||||
* completely (at least until the src image is recreated which in case of
|
||||
* Swing back-buffer happens only after resize).
|
||||
*
|
||||
* Now we delegate to the VISM to figure out if the acceleration needs to
|
||||
* be disabled or if we can wait for a while until the onscreen accelerated
|
||||
* can resume (by marking the source surface lost and making sure the
|
||||
* VISM has a chance to use the backup surface).
|
||||
*
|
||||
*/
|
||||
|
||||
class D3DSurfaceToGDIWindowSurfaceBlit extends Blit {
|
||||
|
||||
D3DSurfaceToGDIWindowSurfaceBlit() {
|
||||
super(D3DSurfaceData.D3DSurface,
|
||||
CompositeType.AnyAlpha,
|
||||
GDIWindowSurfaceData.AnyGdi);
|
||||
}
|
||||
@Override
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
// see comment above
|
||||
D3DVolatileSurfaceManager.handleVItoScreenOp(src, dst);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class D3DSurfaceToGDIWindowSurfaceScale extends ScaledBlit {
|
||||
|
||||
D3DSurfaceToGDIWindowSurfaceScale() {
|
||||
super(D3DSurfaceData.D3DSurface,
|
||||
CompositeType.AnyAlpha,
|
||||
GDIWindowSurfaceData.AnyGdi);
|
||||
}
|
||||
@Override
|
||||
public void Scale(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
// see comment above
|
||||
D3DVolatileSurfaceManager.handleVItoScreenOp(src, dst);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DSurfaceToGDIWindowSurfaceTransform extends TransformBlit {
|
||||
|
||||
D3DSurfaceToGDIWindowSurfaceTransform() {
|
||||
super(D3DSurfaceData.D3DSurface,
|
||||
CompositeType.AnyAlpha,
|
||||
GDIWindowSurfaceData.AnyGdi);
|
||||
}
|
||||
@Override
|
||||
public void Transform(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform at, int hint,
|
||||
int sx, int sy, int dx, int dy,
|
||||
int w, int h)
|
||||
{
|
||||
// see comment above
|
||||
D3DVolatileSurfaceManager.handleVItoScreenOp(src, dst);
|
||||
}
|
||||
}
|
||||
116
jdkSrc/jdk8/sun/java2d/d3d/D3DBufImgOps.java
Normal file
116
jdkSrc/jdk8/sun/java2d/d3d/D3DBufImgOps.java
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.image.AffineTransformOp;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.awt.image.ConvolveOp;
|
||||
import java.awt.image.LookupOp;
|
||||
import java.awt.image.RescaleOp;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.pipe.BufferedBufImgOps;
|
||||
import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
|
||||
|
||||
class D3DBufImgOps extends BufferedBufImgOps {
|
||||
|
||||
/**
|
||||
* This method is called from D3DDrawImage.transformImage() only. It
|
||||
* validates the provided BufferedImageOp to determine whether the op
|
||||
* is one that can be accelerated by the D3D pipeline. If the operation
|
||||
* cannot be completed for any reason, this method returns false;
|
||||
* otherwise, the given BufferedImage is rendered to the destination
|
||||
* using the provided BufferedImageOp and this method returns true.
|
||||
*/
|
||||
static boolean renderImageWithOp(SunGraphics2D sg, BufferedImage img,
|
||||
BufferedImageOp biop, int x, int y)
|
||||
{
|
||||
// Validate the provided BufferedImage (make sure it is one that
|
||||
// is supported, and that its properties are acceleratable)
|
||||
if (biop instanceof ConvolveOp) {
|
||||
if (!isConvolveOpValid((ConvolveOp)biop)) {
|
||||
return false;
|
||||
}
|
||||
} else if (biop instanceof RescaleOp) {
|
||||
if (!isRescaleOpValid((RescaleOp)biop, img)) {
|
||||
return false;
|
||||
}
|
||||
} else if (biop instanceof LookupOp) {
|
||||
if (!isLookupOpValid((LookupOp)biop, img)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// No acceleration for other BufferedImageOps (yet)
|
||||
return false;
|
||||
}
|
||||
|
||||
SurfaceData dstData = sg.surfaceData;
|
||||
if (!(dstData instanceof D3DSurfaceData) ||
|
||||
(sg.interpolationType == AffineTransformOp.TYPE_BICUBIC) ||
|
||||
(sg.compositeState > SunGraphics2D.COMP_ALPHA))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SurfaceData srcData =
|
||||
dstData.getSourceSurfaceData(img, sg.TRANSFORM_ISIDENT,
|
||||
CompositeType.SrcOver, null);
|
||||
if (!(srcData instanceof D3DSurfaceData)) {
|
||||
// REMIND: this hack tries to ensure that we have a cached texture
|
||||
srcData =
|
||||
dstData.getSourceSurfaceData(img, sg.TRANSFORM_ISIDENT,
|
||||
CompositeType.SrcOver, null);
|
||||
if (!(srcData instanceof D3DSurfaceData)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that the source surface is actually a texture and that
|
||||
// shaders are supported
|
||||
D3DSurfaceData d3dSrc = (D3DSurfaceData)srcData;
|
||||
D3DGraphicsDevice gd =
|
||||
(D3DGraphicsDevice)d3dSrc.getDeviceConfiguration().getDevice();
|
||||
if (d3dSrc.getType() != D3DSurfaceData.TEXTURE ||
|
||||
!gd.isCapPresent(CAPS_LCD_SHADER))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int sw = img.getWidth();
|
||||
int sh = img.getHeight();
|
||||
D3DBlitLoops.IsoBlit(srcData, dstData,
|
||||
img, biop,
|
||||
sg.composite, sg.getCompClip(),
|
||||
sg.transform, sg.interpolationType,
|
||||
0, 0, sw, sh,
|
||||
x, y, x+sw, y+sh,
|
||||
true);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
190
jdkSrc/jdk8/sun/java2d/d3d/D3DContext.java
Normal file
190
jdkSrc/jdk8/sun/java2d/d3d/D3DContext.java
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.lang.annotation.Native;
|
||||
import sun.java2d.pipe.BufferedContext;
|
||||
import sun.java2d.pipe.RenderBuffer;
|
||||
import sun.java2d.pipe.RenderQueue;
|
||||
import sun.java2d.pipe.hw.ContextCapabilities;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
import static sun.java2d.pipe.hw.ContextCapabilities.*;
|
||||
import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
|
||||
|
||||
/**
|
||||
* Note that the RenderQueue lock must be acquired before calling any of
|
||||
* the methods in this class.
|
||||
*/
|
||||
class D3DContext extends BufferedContext {
|
||||
|
||||
private final D3DGraphicsDevice device;
|
||||
|
||||
D3DContext(RenderQueue rq, D3DGraphicsDevice device) {
|
||||
super(rq);
|
||||
this.device = device;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates the currentContext field to ensure that we properly
|
||||
* revalidate the D3DContext (make it current, etc.) next time through
|
||||
* the validate() method. This is typically invoked from methods
|
||||
* that affect the current context state (e.g. disposing a context or
|
||||
* surface).
|
||||
*/
|
||||
static void invalidateCurrentContext() {
|
||||
// assert D3DRenderQueue.getInstance().lock.isHeldByCurrentThread();
|
||||
|
||||
// invalidate the current Java-level context so that we
|
||||
// revalidate everything the next time around
|
||||
if (currentContext != null) {
|
||||
currentContext.invalidateContext();
|
||||
currentContext = null;
|
||||
}
|
||||
|
||||
// invalidate the context reference at the native level, and
|
||||
// then flush the queue so that we have no pending operations
|
||||
// dependent on the current context
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.ensureCapacity(4);
|
||||
rq.getBuffer().putInt(INVALIDATE_CONTEXT);
|
||||
rq.flushNow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current context on the native level to be the one passed as
|
||||
* the argument.
|
||||
* If the context is not the same as the defaultContext the latter
|
||||
* will be reset to null.
|
||||
*
|
||||
* This call is needed when copying from a SW surface to a Texture
|
||||
* (the upload test) or copying from d3d to SW surface to make sure we
|
||||
* have the correct current context.
|
||||
*
|
||||
* @param d3dc the context to be made current on the native level
|
||||
*/
|
||||
static void setScratchSurface(D3DContext d3dc) {
|
||||
// assert D3DRenderQueue.getInstance().lock.isHeldByCurrentThread();
|
||||
|
||||
// invalidate the current context
|
||||
if (d3dc != currentContext) {
|
||||
currentContext = null;
|
||||
}
|
||||
|
||||
// set the scratch context
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacity(8);
|
||||
buf.putInt(SET_SCRATCH_SURFACE);
|
||||
buf.putInt(d3dc.getDevice().getScreen());
|
||||
}
|
||||
|
||||
public RenderQueue getRenderQueue() {
|
||||
return D3DRenderQueue.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveState() {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
|
||||
// reset all attributes of this and current contexts
|
||||
invalidateContext();
|
||||
invalidateCurrentContext();
|
||||
|
||||
setScratchSurface(this);
|
||||
|
||||
// save the state on the native level
|
||||
rq.ensureCapacity(4);
|
||||
buf.putInt(SAVE_STATE);
|
||||
rq.flushNow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreState() {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
|
||||
// reset all attributes of this and current contexts
|
||||
invalidateContext();
|
||||
invalidateCurrentContext();
|
||||
|
||||
setScratchSurface(this);
|
||||
|
||||
// restore the state on the native level
|
||||
rq.ensureCapacity(4);
|
||||
buf.putInt(RESTORE_STATE);
|
||||
rq.flushNow();
|
||||
}
|
||||
|
||||
D3DGraphicsDevice getDevice() {
|
||||
return device;
|
||||
}
|
||||
|
||||
static class D3DContextCaps extends ContextCapabilities {
|
||||
/**
|
||||
* Indicates the presence of pixel shaders (v2.0 or greater).
|
||||
* This cap will only be set if the hardware supports the minimum number
|
||||
* of texture units.
|
||||
*/
|
||||
@Native static final int CAPS_LCD_SHADER = (FIRST_PRIVATE_CAP << 0);
|
||||
/**
|
||||
* Indicates the presence of pixel shaders (v2.0 or greater).
|
||||
* This cap will only be set if the hardware meets our
|
||||
* minimum requirements.
|
||||
*/
|
||||
@Native static final int CAPS_BIOP_SHADER = (FIRST_PRIVATE_CAP << 1);
|
||||
/**
|
||||
* Indicates that the device was successfully initialized and can
|
||||
* be safely used.
|
||||
*/
|
||||
@Native static final int CAPS_DEVICE_OK = (FIRST_PRIVATE_CAP << 2);
|
||||
/**
|
||||
* Indicates that the device has all of the necessary capabilities
|
||||
* to support the Antialiasing Pixel Shader program.
|
||||
*/
|
||||
@Native static final int CAPS_AA_SHADER = (FIRST_PRIVATE_CAP << 3);
|
||||
|
||||
D3DContextCaps(int caps, String adapterId) {
|
||||
super(caps, adapterId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer buf = new StringBuffer(super.toString());
|
||||
if ((caps & CAPS_LCD_SHADER) != 0) {
|
||||
buf.append("CAPS_LCD_SHADER|");
|
||||
}
|
||||
if ((caps & CAPS_BIOP_SHADER) != 0) {
|
||||
buf.append("CAPS_BIOP_SHADER|");
|
||||
}
|
||||
if ((caps & CAPS_AA_SHADER) != 0) {
|
||||
buf.append("CAPS_AA_SHADER|");
|
||||
}
|
||||
if ((caps & CAPS_DEVICE_OK) != 0) {
|
||||
buf.append("CAPS_DEVICE_OK|");
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
101
jdkSrc/jdk8/sun/java2d/d3d/D3DDrawImage.java
Normal file
101
jdkSrc/jdk8/sun/java2d/d3d/D3DDrawImage.java
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Image;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.AffineTransformOp;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.java2d.loops.TransformBlit;
|
||||
import sun.java2d.pipe.DrawImage;
|
||||
|
||||
public class D3DDrawImage extends DrawImage {
|
||||
|
||||
@Override
|
||||
protected void renderImageXform(SunGraphics2D sg, Image img,
|
||||
AffineTransform tx, int interpType,
|
||||
int sx1, int sy1, int sx2, int sy2,
|
||||
Color bgColor)
|
||||
{
|
||||
// punt to the MediaLib-based transformImage() in the superclass if:
|
||||
// - bicubic interpolation is specified
|
||||
// - a background color is specified and will be used
|
||||
// - an appropriate TransformBlit primitive could not be found
|
||||
if (interpType != AffineTransformOp.TYPE_BICUBIC) {
|
||||
SurfaceData dstData = sg.surfaceData;
|
||||
SurfaceData srcData =
|
||||
dstData.getSourceSurfaceData(img,
|
||||
sg.TRANSFORM_GENERIC,
|
||||
sg.imageComp,
|
||||
bgColor);
|
||||
|
||||
if (srcData != null && !isBgOperation(srcData, bgColor)) {
|
||||
SurfaceType srcType = srcData.getSurfaceType();
|
||||
SurfaceType dstType = dstData.getSurfaceType();
|
||||
TransformBlit blit = TransformBlit.getFromCache(srcType,
|
||||
sg.imageComp,
|
||||
dstType);
|
||||
|
||||
if (blit != null) {
|
||||
blit.Transform(srcData, dstData,
|
||||
sg.composite, sg.getCompClip(),
|
||||
tx, interpType,
|
||||
sx1, sy1, 0, 0, sx2-sx1, sy2-sy1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.renderImageXform(sg, img, tx, interpType,
|
||||
sx1, sy1, sx2, sy2, bgColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transformImage(SunGraphics2D sg, BufferedImage img,
|
||||
BufferedImageOp op, int x, int y)
|
||||
{
|
||||
if (op != null) {
|
||||
if (op instanceof AffineTransformOp) {
|
||||
AffineTransformOp atop = (AffineTransformOp) op;
|
||||
transformImage(sg, img, x, y,
|
||||
atop.getTransform(),
|
||||
atop.getInterpolationType());
|
||||
return;
|
||||
} else {
|
||||
if (D3DBufImgOps.renderImageWithOp(sg, img, op, x, y)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
img = op.filter(img, null);
|
||||
}
|
||||
copyImage(sg, img, x, y, null);
|
||||
}
|
||||
}
|
||||
327
jdkSrc/jdk8/sun/java2d/d3d/D3DGraphicsConfig.java
Normal file
327
jdkSrc/jdk8/sun/java2d/d3d/D3DGraphicsConfig.java
Normal file
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.BufferCapabilities;
|
||||
import java.awt.BufferCapabilities.FlipContents;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.ImageCapabilities;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.DirectColorModel;
|
||||
import java.awt.image.VolatileImage;
|
||||
import sun.awt.Win32GraphicsConfig;
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
import sun.awt.image.SurfaceManager;
|
||||
import sun.awt.windows.WComponentPeer;
|
||||
import sun.java2d.Surface;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.pipe.hw.AccelDeviceEventNotifier;
|
||||
import sun.java2d.pipe.hw.AccelTypedVolatileImage;
|
||||
import sun.java2d.pipe.hw.AccelGraphicsConfig;
|
||||
import sun.java2d.pipe.hw.AccelSurface;
|
||||
import sun.java2d.pipe.hw.ContextCapabilities;
|
||||
import static sun.java2d.pipe.hw.AccelSurface.*;
|
||||
import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
|
||||
import sun.java2d.pipe.hw.AccelDeviceEventListener;
|
||||
|
||||
public class D3DGraphicsConfig
|
||||
extends Win32GraphicsConfig
|
||||
implements AccelGraphicsConfig
|
||||
{
|
||||
private static ImageCapabilities imageCaps = new D3DImageCaps();
|
||||
|
||||
private BufferCapabilities bufferCaps;
|
||||
private D3DGraphicsDevice device;
|
||||
|
||||
protected D3DGraphicsConfig(D3DGraphicsDevice device) {
|
||||
super(device, 0);
|
||||
this.device = device;
|
||||
}
|
||||
|
||||
public SurfaceData createManagedSurface(int w, int h, int transparency) {
|
||||
return D3DSurfaceData.createData(this, w, h,
|
||||
getColorModel(transparency),
|
||||
null,
|
||||
D3DSurfaceData.TEXTURE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void displayChanged() {
|
||||
super.displayChanged();
|
||||
// the context could hold a reference to a D3DSurfaceData, which in
|
||||
// turn has a reference back to this D3DGraphicsConfig, so in order
|
||||
// for this instance to be disposed we need to break the connection
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
D3DContext.invalidateCurrentContext();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorModel getColorModel(int transparency) {
|
||||
switch (transparency) {
|
||||
case Transparency.OPAQUE:
|
||||
// REMIND: once the ColorModel spec is changed, this should be
|
||||
// an opaque premultiplied DCM...
|
||||
return new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
|
||||
case Transparency.BITMASK:
|
||||
return new DirectColorModel(25, 0xff0000, 0xff00, 0xff, 0x1000000);
|
||||
case Transparency.TRANSLUCENT:
|
||||
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
|
||||
return new DirectColorModel(cs, 32,
|
||||
0xff0000, 0xff00, 0xff, 0xff000000,
|
||||
true, DataBuffer.TYPE_INT);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ("D3DGraphicsConfig[dev="+screen+",pixfmt="+visual+"]");
|
||||
}
|
||||
|
||||
/**
|
||||
* The following methods are invoked from WComponentPeer.java rather
|
||||
* than having the Win32-dependent implementations hardcoded in that
|
||||
* class. This way the appropriate actions are taken based on the peer's
|
||||
* GraphicsConfig, whether it is a Win32GraphicsConfig or a
|
||||
* D3DGraphicsConfig.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new SurfaceData that will be associated with the given
|
||||
* WComponentPeer. D3D9 doesn't allow rendering to the screen,
|
||||
* so a GDI surface will be returned.
|
||||
*/
|
||||
@Override
|
||||
public SurfaceData createSurfaceData(WComponentPeer peer,
|
||||
int numBackBuffers)
|
||||
{
|
||||
return super.createSurfaceData(peer, numBackBuffers);
|
||||
}
|
||||
|
||||
/**
|
||||
* The following methods correspond to the multibuffering methods in
|
||||
* WComponentPeer.java...
|
||||
*/
|
||||
|
||||
/**
|
||||
* Checks that the requested configuration is natively supported; if not,
|
||||
* an AWTException is thrown.
|
||||
*/
|
||||
@Override
|
||||
public void assertOperationSupported(Component target,
|
||||
int numBuffers,
|
||||
BufferCapabilities caps)
|
||||
throws AWTException
|
||||
{
|
||||
if (numBuffers < 2 || numBuffers > 4) {
|
||||
throw new AWTException("Only 2-4 buffers supported");
|
||||
}
|
||||
if (caps.getFlipContents() == BufferCapabilities.FlipContents.COPIED &&
|
||||
numBuffers != 2)
|
||||
{
|
||||
throw new AWTException("FlipContents.COPIED is only" +
|
||||
"supported for 2 buffers");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a D3D-based backbuffer for the given peer and returns the
|
||||
* image wrapper.
|
||||
*/
|
||||
@Override
|
||||
public VolatileImage createBackBuffer(WComponentPeer peer) {
|
||||
Component target = (Component)peer.getTarget();
|
||||
// it is possible for the component to have size 0x0, adjust it to
|
||||
// be at least 1x1 to avoid IAE
|
||||
int w = Math.max(1, target.getWidth());
|
||||
int h = Math.max(1, target.getHeight());
|
||||
return new SunVolatileImage(target, w, h, Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the native D3D flip operation for the given target Component.
|
||||
*/
|
||||
@Override
|
||||
public void flip(WComponentPeer peer,
|
||||
Component target, VolatileImage backBuffer,
|
||||
int x1, int y1, int x2, int y2,
|
||||
BufferCapabilities.FlipContents flipAction)
|
||||
{
|
||||
// REMIND: we should actually get a surface data for the
|
||||
// backBuffer's VI
|
||||
SurfaceManager d3dvsm =
|
||||
SurfaceManager.getManager(backBuffer);
|
||||
SurfaceData sd = d3dvsm.getPrimarySurfaceData();
|
||||
if (sd instanceof D3DSurfaceData) {
|
||||
D3DSurfaceData d3dsd = (D3DSurfaceData)sd;
|
||||
D3DSurfaceData.swapBuffers(d3dsd, x1, y1, x2, y2);
|
||||
} else {
|
||||
// the surface was likely lost could not have been restored
|
||||
Graphics g = peer.getGraphics();
|
||||
try {
|
||||
g.drawImage(backBuffer,
|
||||
x1, y1, x2, y2,
|
||||
x1, y1, x2, y2,
|
||||
null);
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) {
|
||||
Graphics g = backBuffer.getGraphics();
|
||||
try {
|
||||
g.setColor(target.getBackground());
|
||||
g.fillRect(0, 0,
|
||||
backBuffer.getWidth(),
|
||||
backBuffer.getHeight());
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class D3DBufferCaps extends BufferCapabilities {
|
||||
public D3DBufferCaps() {
|
||||
// REMIND: should we indicate that the front-buffer
|
||||
// (the on-screen rendering) is not accelerated?
|
||||
super(imageCaps, imageCaps, FlipContents.UNDEFINED);
|
||||
}
|
||||
@Override
|
||||
public boolean isMultiBufferAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferCapabilities getBufferCapabilities() {
|
||||
if (bufferCaps == null) {
|
||||
bufferCaps = new D3DBufferCaps();
|
||||
}
|
||||
return bufferCaps;
|
||||
}
|
||||
|
||||
private static class D3DImageCaps extends ImageCapabilities {
|
||||
private D3DImageCaps() {
|
||||
super(true);
|
||||
}
|
||||
@Override
|
||||
public boolean isTrueVolatile() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageCapabilities getImageCapabilities() {
|
||||
return imageCaps;
|
||||
}
|
||||
|
||||
D3DGraphicsDevice getD3DDevice() {
|
||||
return device;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see sun.java2d.pipe.hw.BufferedContextProvider#getContext
|
||||
*/
|
||||
@Override
|
||||
public D3DContext getContext() {
|
||||
return device.getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see sun.java2d.pipe.hw.AccelGraphicsConfig#createCompatibleVolatileImage
|
||||
*/
|
||||
@Override
|
||||
public VolatileImage
|
||||
createCompatibleVolatileImage(int width, int height,
|
||||
int transparency, int type)
|
||||
{
|
||||
if (type == FLIP_BACKBUFFER || type == WINDOW || type == UNDEFINED ||
|
||||
transparency == Transparency.BITMASK)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
boolean isOpaque = transparency == Transparency.OPAQUE;
|
||||
if (type == RT_TEXTURE) {
|
||||
int cap = isOpaque ? CAPS_RT_TEXTURE_OPAQUE : CAPS_RT_TEXTURE_ALPHA;
|
||||
if (!device.isCapPresent(cap)) {
|
||||
return null;
|
||||
}
|
||||
} else if (type == RT_PLAIN) {
|
||||
if (!isOpaque && !device.isCapPresent(CAPS_RT_PLAIN_ALPHA)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
SunVolatileImage vi = new AccelTypedVolatileImage(this, width, height,
|
||||
transparency, type);
|
||||
Surface sd = vi.getDestSurface();
|
||||
if (!(sd instanceof AccelSurface) ||
|
||||
((AccelSurface)sd).getType() != type)
|
||||
{
|
||||
vi.flush();
|
||||
vi = null;
|
||||
}
|
||||
|
||||
return vi;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see sun.java2d.pipe.hw.AccelGraphicsConfig#getContextCapabilities
|
||||
*/
|
||||
@Override
|
||||
public ContextCapabilities getContextCapabilities() {
|
||||
return device.getContextCapabilities();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDeviceEventListener(AccelDeviceEventListener l) {
|
||||
AccelDeviceEventNotifier.addListener(l, device.getScreen());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeDeviceEventListener(AccelDeviceEventListener l) {
|
||||
AccelDeviceEventNotifier.removeListener(l);
|
||||
}
|
||||
}
|
||||
503
jdkSrc/jdk8/sun/java2d/d3d/D3DGraphicsDevice.java
Normal file
503
jdkSrc/jdk8/sun/java2d/d3d/D3DGraphicsDevice.java
Normal file
@@ -0,0 +1,503 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Dialog;
|
||||
import java.awt.DisplayMode;
|
||||
import java.awt.Frame;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowListener;
|
||||
import java.awt.peer.WindowPeer;
|
||||
import java.util.ArrayList;
|
||||
import sun.awt.Win32GraphicsDevice;
|
||||
import sun.awt.windows.WWindowPeer;
|
||||
import sun.java2d.pipe.hw.ContextCapabilities;
|
||||
import sun.java2d.windows.WindowsFlags;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
|
||||
import sun.java2d.d3d.D3DContext.D3DContextCaps;
|
||||
|
||||
/**
|
||||
* This class implements D3D-specific functionality, such as fullscreen
|
||||
* exclusive mode and display changes. It is kept separate from
|
||||
* Win32GraphicsDevice to help avoid overburdening the parent class.
|
||||
*/
|
||||
public class D3DGraphicsDevice extends Win32GraphicsDevice {
|
||||
private D3DContext context;
|
||||
|
||||
private static boolean d3dAvailable;
|
||||
|
||||
private ContextCapabilities d3dCaps;
|
||||
|
||||
private static native boolean initD3D();
|
||||
|
||||
static {
|
||||
// loading the library doesn't help because we need the
|
||||
// toolkit thread running, so we have to call getDefaultToolkit()
|
||||
Toolkit.getDefaultToolkit();
|
||||
d3dAvailable = initD3D();
|
||||
if (d3dAvailable) {
|
||||
// we don't use pixel formats for the d3d pipeline
|
||||
pfDisabled = true;
|
||||
sun.misc.PerfCounter.getD3DAvailable().set(1);
|
||||
} else {
|
||||
sun.misc.PerfCounter.getD3DAvailable().set(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to construct a Direct3D-enabled GraphicsDevice.
|
||||
*
|
||||
* @return a D3DGraphicsDevice if it could be created
|
||||
* successfully, null otherwise.
|
||||
*/
|
||||
public static D3DGraphicsDevice createDevice(int screen) {
|
||||
if (!d3dAvailable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ContextCapabilities d3dCaps = getDeviceCaps(screen);
|
||||
// could not initialize the device successfully
|
||||
if ((d3dCaps.getCaps() & CAPS_DEVICE_OK) == 0) {
|
||||
if (WindowsFlags.isD3DVerbose()) {
|
||||
System.out.println("Could not enable Direct3D pipeline on " +
|
||||
"screen " + screen);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (WindowsFlags.isD3DVerbose()) {
|
||||
System.out.println("Direct3D pipeline enabled on screen " + screen);
|
||||
}
|
||||
|
||||
D3DGraphicsDevice gd = new D3DGraphicsDevice(screen, d3dCaps);
|
||||
return gd;
|
||||
}
|
||||
|
||||
private static native int getDeviceCapsNative(int screen);
|
||||
private static native String getDeviceIdNative(int screen);
|
||||
private static ContextCapabilities getDeviceCaps(final int screen) {
|
||||
ContextCapabilities d3dCaps = null;
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
class Result {
|
||||
int caps;
|
||||
String id;
|
||||
};
|
||||
final Result res = new Result();
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
res.caps = getDeviceCapsNative(screen);
|
||||
res.id = getDeviceIdNative(screen);
|
||||
}
|
||||
});
|
||||
d3dCaps = new D3DContextCaps(res.caps, res.id);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
|
||||
return d3dCaps != null ? d3dCaps : new D3DContextCaps(CAPS_EMPTY, null);
|
||||
}
|
||||
|
||||
public final boolean isCapPresent(int cap) {
|
||||
return ((d3dCaps.getCaps() & cap) != 0);
|
||||
}
|
||||
|
||||
private D3DGraphicsDevice(int screennum, ContextCapabilities d3dCaps) {
|
||||
super(screennum);
|
||||
descString = "D3DGraphicsDevice[screen="+screennum;
|
||||
this.d3dCaps = d3dCaps;
|
||||
context = new D3DContext(D3DRenderQueue.getInstance(), this);
|
||||
}
|
||||
|
||||
public boolean isD3DEnabledOnDevice() {
|
||||
return isValid() && isCapPresent(CAPS_DEVICE_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if d3d pipeline has been successfully initialized.
|
||||
* @return true if d3d pipeline is initialized, false otherwise
|
||||
*/
|
||||
public static boolean isD3DAvailable() {
|
||||
return d3dAvailable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the owning Frame for a given Window. Used in setFSWindow below
|
||||
* to set the properties of the owning Frame when a Window goes
|
||||
* into fullscreen mode.
|
||||
*/
|
||||
private Frame getToplevelOwner(Window w) {
|
||||
Window owner = w;
|
||||
while (owner != null) {
|
||||
owner = owner.getOwner();
|
||||
if (owner instanceof Frame) {
|
||||
return (Frame) owner;
|
||||
}
|
||||
}
|
||||
// could get here if passed Window is an owner-less Dialog
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean fsStatus;
|
||||
private Rectangle ownerOrigBounds = null;
|
||||
private boolean ownerWasVisible;
|
||||
private Window realFSWindow;
|
||||
private WindowListener fsWindowListener;
|
||||
private boolean fsWindowWasAlwaysOnTop;
|
||||
private static native boolean enterFullScreenExclusiveNative(int screen,
|
||||
long hwnd);
|
||||
|
||||
@Override
|
||||
protected void enterFullScreenExclusive(final int screen, WindowPeer wp)
|
||||
{
|
||||
final WWindowPeer wpeer = (WWindowPeer)realFSWindow.getPeer();
|
||||
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
long hwnd = wpeer.getHWnd();
|
||||
if (hwnd == 0l) {
|
||||
// window is disposed
|
||||
fsStatus = false;
|
||||
return;
|
||||
}
|
||||
fsStatus = enterFullScreenExclusiveNative(screen, hwnd);
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
if (!fsStatus) {
|
||||
super.enterFullScreenExclusive(screen, wp);
|
||||
}
|
||||
}
|
||||
|
||||
private static native boolean exitFullScreenExclusiveNative(int screen);
|
||||
@Override
|
||||
protected void exitFullScreenExclusive(final int screen, WindowPeer w) {
|
||||
if (fsStatus) {
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
exitFullScreenExclusiveNative(screen);
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
} else {
|
||||
super.exitFullScreenExclusive(screen, w);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* WindowAdapter class for the full-screen frame, responsible for
|
||||
* restoring the devices. This is important to do because unless the device
|
||||
* is restored it will not go back into the FS mode once alt+tabbed out.
|
||||
* This is a problem for windows for which we do not do any d3d-related
|
||||
* operations (like when we disabled on-screen rendering).
|
||||
*
|
||||
* REMIND: we create an instance per each full-screen device while a single
|
||||
* instance would suffice (but requires more management).
|
||||
*/
|
||||
private static class D3DFSWindowAdapter extends WindowAdapter {
|
||||
@Override
|
||||
public void windowDeactivated(WindowEvent e) {
|
||||
D3DRenderQueue.getInstance().restoreDevices();
|
||||
}
|
||||
@Override
|
||||
public void windowActivated(WindowEvent e) {
|
||||
D3DRenderQueue.getInstance().restoreDevices();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addFSWindowListener(Window w) {
|
||||
// if the window is not a toplevel (has an owner) we have to use the
|
||||
// real toplevel to enter the full-screen mode with (4933099).
|
||||
if (!(w instanceof Frame) && !(w instanceof Dialog) &&
|
||||
(realFSWindow = getToplevelOwner(w)) != null)
|
||||
{
|
||||
ownerOrigBounds = realFSWindow.getBounds();
|
||||
WWindowPeer fp = (WWindowPeer)realFSWindow.getPeer();
|
||||
|
||||
ownerWasVisible = realFSWindow.isVisible();
|
||||
Rectangle r = w.getBounds();
|
||||
// we use operations on peer instead of component because calling
|
||||
// them on component will take the tree lock
|
||||
fp.reshape(r.x, r.y, r.width, r.height);
|
||||
fp.setVisible(true);
|
||||
} else {
|
||||
realFSWindow = w;
|
||||
}
|
||||
|
||||
fsWindowWasAlwaysOnTop = realFSWindow.isAlwaysOnTop();
|
||||
((WWindowPeer)realFSWindow.getPeer()).setAlwaysOnTop(true);
|
||||
|
||||
fsWindowListener = new D3DFSWindowAdapter();
|
||||
realFSWindow.addWindowListener(fsWindowListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeFSWindowListener(Window w) {
|
||||
realFSWindow.removeWindowListener(fsWindowListener);
|
||||
fsWindowListener = null;
|
||||
|
||||
/**
|
||||
* Bug 4933099: There is some funny-business to deal with when this
|
||||
* method is called with a Window instead of a Frame. See 4836744
|
||||
* for more information on this. One side-effect of our workaround
|
||||
* for the problem is that the owning Frame of a Window may end
|
||||
* up getting resized during the fullscreen process. When we
|
||||
* return from fullscreen mode, we should resize the Frame to
|
||||
* its original size (just like the Window is being resized
|
||||
* to its original size in GraphicsDevice).
|
||||
*/
|
||||
WWindowPeer wpeer = (WWindowPeer)realFSWindow.getPeer();
|
||||
if (wpeer != null) {
|
||||
if (ownerOrigBounds != null) {
|
||||
// if the window went into fs mode before it was realized it
|
||||
// could have (0,0) dimensions
|
||||
if (ownerOrigBounds.width == 0) ownerOrigBounds.width = 1;
|
||||
if (ownerOrigBounds.height == 0) ownerOrigBounds.height = 1;
|
||||
wpeer.reshape(ownerOrigBounds.x, ownerOrigBounds.y,
|
||||
ownerOrigBounds.width, ownerOrigBounds.height);
|
||||
if (!ownerWasVisible) {
|
||||
wpeer.setVisible(false);
|
||||
}
|
||||
ownerOrigBounds = null;
|
||||
}
|
||||
if (!fsWindowWasAlwaysOnTop) {
|
||||
wpeer.setAlwaysOnTop(false);
|
||||
}
|
||||
}
|
||||
|
||||
realFSWindow = null;
|
||||
}
|
||||
|
||||
private static native DisplayMode getCurrentDisplayModeNative(int screen);
|
||||
@Override
|
||||
protected DisplayMode getCurrentDisplayMode(final int screen) {
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
class Result {
|
||||
DisplayMode dm = null;
|
||||
};
|
||||
final Result res = new Result();
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
res.dm = getCurrentDisplayModeNative(screen);
|
||||
}
|
||||
});
|
||||
if (res.dm == null) {
|
||||
return super.getCurrentDisplayMode(screen);
|
||||
}
|
||||
return res.dm;
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
private static native void configDisplayModeNative(int screen, long hwnd,
|
||||
int width, int height,
|
||||
int bitDepth,
|
||||
int refreshRate);
|
||||
@Override
|
||||
protected void configDisplayMode(final int screen, final WindowPeer w,
|
||||
final int width, final int height,
|
||||
final int bitDepth, final int refreshRate)
|
||||
{
|
||||
// we entered fs mode via gdi
|
||||
if (!fsStatus) {
|
||||
super.configDisplayMode(screen, w, width, height, bitDepth,
|
||||
refreshRate);
|
||||
return;
|
||||
}
|
||||
|
||||
final WWindowPeer wpeer = (WWindowPeer)realFSWindow.getPeer();
|
||||
|
||||
// REMIND: we do this before we switch the display mode, so
|
||||
// the dimensions may be exceeding the dimensions of the screen,
|
||||
// is this a problem?
|
||||
|
||||
// update the bounds of the owner frame
|
||||
if (getFullScreenWindow() != realFSWindow) {
|
||||
Rectangle screenBounds = getDefaultConfiguration().getBounds();
|
||||
wpeer.reshape(screenBounds.x, screenBounds.y, width, height);
|
||||
}
|
||||
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
long hwnd = wpeer.getHWnd();
|
||||
if (hwnd == 0l) {
|
||||
// window is disposed
|
||||
return;
|
||||
}
|
||||
// REMIND: do we really need a window here?
|
||||
// we should probably just use the current one
|
||||
configDisplayModeNative(screen, hwnd, width, height,
|
||||
bitDepth, refreshRate);
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private static native void enumDisplayModesNative(int screen,
|
||||
ArrayList modes);
|
||||
@Override
|
||||
protected void enumDisplayModes(final int screen, final ArrayList modes) {
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
enumDisplayModesNative(screen, modes);
|
||||
}
|
||||
});
|
||||
if (modes.size() == 0) {
|
||||
modes.add(getCurrentDisplayModeNative(screen));
|
||||
}
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private static native long getAvailableAcceleratedMemoryNative(int screen);
|
||||
@Override
|
||||
public int getAvailableAcceleratedMemory() {
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
class Result {
|
||||
long mem = 0L;
|
||||
};
|
||||
final Result res = new Result();
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
res.mem = getAvailableAcceleratedMemoryNative(getScreen());
|
||||
}
|
||||
});
|
||||
return (int)res.mem;
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsConfiguration[] getConfigurations() {
|
||||
if (configs == null) {
|
||||
if (isD3DEnabledOnDevice()) {
|
||||
defaultConfig = getDefaultConfiguration();
|
||||
if (defaultConfig != null) {
|
||||
configs = new GraphicsConfiguration[1];
|
||||
configs[0] = defaultConfig;
|
||||
return configs.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.getConfigurations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsConfiguration getDefaultConfiguration() {
|
||||
if (defaultConfig == null) {
|
||||
if (isD3DEnabledOnDevice()) {
|
||||
defaultConfig = new D3DGraphicsConfig(this);
|
||||
} else {
|
||||
defaultConfig = super.getDefaultConfiguration();
|
||||
}
|
||||
}
|
||||
return defaultConfig;
|
||||
}
|
||||
|
||||
private static native boolean isD3DAvailableOnDeviceNative(int screen);
|
||||
// REMIND: this method is not used now, we use caps instead
|
||||
public static boolean isD3DAvailableOnDevice(final int screen) {
|
||||
if (!d3dAvailable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// REMIND: should we cache the result per device somehow,
|
||||
// and then reset and retry it on display change?
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
class Result {
|
||||
boolean avail = false;
|
||||
};
|
||||
final Result res = new Result();
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
res.avail = isD3DAvailableOnDeviceNative(screen);
|
||||
}
|
||||
});
|
||||
return res.avail;
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
D3DContext getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
ContextCapabilities getContextCapabilities() {
|
||||
return d3dCaps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayChanged() {
|
||||
super.displayChanged();
|
||||
// REMIND: make sure this works when the device is lost and we don't
|
||||
// disable d3d too eagerly
|
||||
if (d3dAvailable) {
|
||||
d3dCaps = getDeviceCaps(getScreen());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void invalidate(int defaultScreen) {
|
||||
super.invalidate(defaultScreen);
|
||||
// REMIND: this is a bit excessive, isD3DEnabledOnDevice will return
|
||||
// false anyway because the device is invalid
|
||||
d3dCaps = new D3DContextCaps(CAPS_EMPTY, null);
|
||||
}
|
||||
}
|
||||
69
jdkSrc/jdk8/sun/java2d/d3d/D3DMaskBlit.java
Normal file
69
jdkSrc/jdk8/sun/java2d/d3d/D3DMaskBlit.java
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Composite;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.loops.GraphicsPrimitiveMgr;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.java2d.pipe.BufferedMaskBlit;
|
||||
import static sun.java2d.loops.CompositeType.*;
|
||||
import static sun.java2d.loops.SurfaceType.*;
|
||||
|
||||
class D3DMaskBlit extends BufferedMaskBlit {
|
||||
|
||||
static void register() {
|
||||
GraphicsPrimitive[] primitives = {
|
||||
new D3DMaskBlit(IntArgb, SrcOver),
|
||||
new D3DMaskBlit(IntArgbPre, SrcOver),
|
||||
new D3DMaskBlit(IntRgb, SrcOver),
|
||||
new D3DMaskBlit(IntRgb, SrcNoEa),
|
||||
new D3DMaskBlit(IntBgr, SrcOver),
|
||||
new D3DMaskBlit(IntBgr, SrcNoEa),
|
||||
};
|
||||
GraphicsPrimitiveMgr.register(primitives);
|
||||
}
|
||||
|
||||
private D3DMaskBlit(SurfaceType srcType,
|
||||
CompositeType compType)
|
||||
{
|
||||
super(D3DRenderQueue.getInstance(),
|
||||
srcType, compType, D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateContext(SurfaceData dstData,
|
||||
Composite comp, Region clip)
|
||||
{
|
||||
D3DSurfaceData d3dDst = (D3DSurfaceData)dstData;
|
||||
D3DContext.validateContext(d3dDst, d3dDst,
|
||||
clip, comp, null, null, null,
|
||||
D3DContext.NO_CONTEXT_FLAGS);
|
||||
}
|
||||
}
|
||||
82
jdkSrc/jdk8/sun/java2d/d3d/D3DMaskFill.java
Normal file
82
jdkSrc/jdk8/sun/java2d/d3d/D3DMaskFill.java
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Composite;
|
||||
import sun.java2d.InvalidPipeException;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.loops.GraphicsPrimitiveMgr;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.java2d.pipe.BufferedMaskFill;
|
||||
import static sun.java2d.loops.CompositeType.*;
|
||||
import static sun.java2d.loops.SurfaceType.*;
|
||||
|
||||
class D3DMaskFill extends BufferedMaskFill {
|
||||
|
||||
static void register() {
|
||||
GraphicsPrimitive[] primitives = {
|
||||
new D3DMaskFill(AnyColor, SrcOver),
|
||||
new D3DMaskFill(OpaqueColor, SrcNoEa),
|
||||
new D3DMaskFill(GradientPaint, SrcOver),
|
||||
new D3DMaskFill(OpaqueGradientPaint, SrcNoEa),
|
||||
new D3DMaskFill(LinearGradientPaint, SrcOver),
|
||||
new D3DMaskFill(OpaqueLinearGradientPaint, SrcNoEa),
|
||||
new D3DMaskFill(RadialGradientPaint, SrcOver),
|
||||
new D3DMaskFill(OpaqueRadialGradientPaint, SrcNoEa),
|
||||
new D3DMaskFill(TexturePaint, SrcOver),
|
||||
new D3DMaskFill(OpaqueTexturePaint, SrcNoEa),
|
||||
};
|
||||
GraphicsPrimitiveMgr.register(primitives);
|
||||
}
|
||||
|
||||
protected D3DMaskFill(SurfaceType srcType, CompositeType compType) {
|
||||
super(D3DRenderQueue.getInstance(),
|
||||
srcType, compType, D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected native void maskFill(int x, int y, int w, int h,
|
||||
int maskoff, int maskscan, int masklen,
|
||||
byte[] mask);
|
||||
|
||||
@Override
|
||||
protected void validateContext(SunGraphics2D sg2d,
|
||||
Composite comp, int ctxflags)
|
||||
{
|
||||
D3DSurfaceData dstData;
|
||||
try {
|
||||
dstData = (D3DSurfaceData) sg2d.surfaceData;
|
||||
} catch (ClassCastException e) {
|
||||
throw new InvalidPipeException("wrong surface data type: " +
|
||||
sg2d.surfaceData);
|
||||
}
|
||||
D3DContext.validateContext(dstData, dstData,
|
||||
sg2d.getCompClip(), comp,
|
||||
null, sg2d.paint, sg2d, ctxflags);
|
||||
}
|
||||
}
|
||||
234
jdkSrc/jdk8/sun/java2d/d3d/D3DPaints.java
Normal file
234
jdkSrc/jdk8/sun/java2d/d3d/D3DPaints.java
Normal file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.LinearGradientPaint;
|
||||
import java.awt.MultipleGradientPaint;
|
||||
import java.awt.MultipleGradientPaint.ColorSpaceType;
|
||||
import java.awt.MultipleGradientPaint.CycleMethod;
|
||||
import java.awt.TexturePaint;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.lang.annotation.Native;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
|
||||
|
||||
abstract class D3DPaints {
|
||||
|
||||
/**
|
||||
* Holds all registered implementations, using the corresponding
|
||||
* SunGraphics2D.PAINT_* constant as the hash key.
|
||||
*/
|
||||
private static Map<Integer, D3DPaints> impls =
|
||||
new HashMap<Integer, D3DPaints>(4, 1.0f);
|
||||
|
||||
static {
|
||||
impls.put(SunGraphics2D.PAINT_GRADIENT, new Gradient());
|
||||
impls.put(SunGraphics2D.PAINT_LIN_GRADIENT, new LinearGradient());
|
||||
impls.put(SunGraphics2D.PAINT_RAD_GRADIENT, new RadialGradient());
|
||||
impls.put(SunGraphics2D.PAINT_TEXTURE, new Texture());
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to locate an implementation corresponding to the paint state
|
||||
* of the provided SunGraphics2D object. If no implementation can be
|
||||
* found, or if the paint cannot be accelerated under the conditions
|
||||
* of the SunGraphics2D, this method returns false; otherwise, returns
|
||||
* true.
|
||||
*/
|
||||
static boolean isValid(SunGraphics2D sg2d) {
|
||||
D3DPaints impl = impls.get(sg2d.paintState);
|
||||
return (impl != null && impl.isPaintValid(sg2d));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this implementation is able to accelerate the
|
||||
* Paint object associated with, and under the conditions of, the
|
||||
* provided SunGraphics2D instance; otherwise returns false.
|
||||
*/
|
||||
abstract boolean isPaintValid(SunGraphics2D sg2d);
|
||||
|
||||
/************************* GradientPaint support ****************************/
|
||||
|
||||
private static class Gradient extends D3DPaints {
|
||||
private Gradient() {}
|
||||
|
||||
/**
|
||||
* Returns true if the given GradientPaint instance can be
|
||||
* used by the accelerated D3DPaints.Gradient implementation.
|
||||
* A GradientPaint is considered valid only if the destination
|
||||
* has support for fragment shaders.
|
||||
*/
|
||||
@Override
|
||||
boolean isPaintValid(SunGraphics2D sg2d) {
|
||||
D3DSurfaceData dstData = (D3DSurfaceData)sg2d.surfaceData;
|
||||
D3DGraphicsDevice gd = (D3DGraphicsDevice)
|
||||
dstData.getDeviceConfiguration().getDevice();
|
||||
return gd.isCapPresent(CAPS_LCD_SHADER);
|
||||
}
|
||||
}
|
||||
|
||||
/************************** TexturePaint support ****************************/
|
||||
|
||||
private static class Texture extends D3DPaints {
|
||||
private Texture() {}
|
||||
|
||||
/**
|
||||
* Returns true if the given TexturePaint instance can be used by the
|
||||
* accelerated BufferedPaints.Texture implementation.
|
||||
*
|
||||
* A TexturePaint is considered valid if the following conditions
|
||||
* are met:
|
||||
* - the texture image dimensions are power-of-two
|
||||
* - the texture image can be (or is already) cached in a D3D
|
||||
* texture object
|
||||
*/
|
||||
@Override
|
||||
public boolean isPaintValid(SunGraphics2D sg2d) {
|
||||
TexturePaint paint = (TexturePaint)sg2d.paint;
|
||||
D3DSurfaceData dstData = (D3DSurfaceData)sg2d.surfaceData;
|
||||
BufferedImage bi = paint.getImage();
|
||||
|
||||
// verify that the texture image dimensions are pow2
|
||||
D3DGraphicsDevice gd =
|
||||
(D3DGraphicsDevice)dstData.getDeviceConfiguration().getDevice();
|
||||
int imgw = bi.getWidth();
|
||||
int imgh = bi.getHeight();
|
||||
if (!gd.isCapPresent(CAPS_TEXNONPOW2)) {
|
||||
if ((imgw & (imgw - 1)) != 0 || (imgh & (imgh - 1)) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// verify that the texture image is square if it has to be
|
||||
if (!gd.isCapPresent(CAPS_TEXNONSQUARE) && imgw != imgh)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SurfaceData srcData =
|
||||
dstData.getSourceSurfaceData(bi, sg2d.TRANSFORM_ISIDENT,
|
||||
CompositeType.SrcOver, null);
|
||||
if (!(srcData instanceof D3DSurfaceData)) {
|
||||
// REMIND: this is a hack that attempts to cache the system
|
||||
// memory image from the TexturePaint instance into a
|
||||
// D3D texture...
|
||||
srcData =
|
||||
dstData.getSourceSurfaceData(bi, sg2d.TRANSFORM_ISIDENT,
|
||||
CompositeType.SrcOver, null);
|
||||
if (!(srcData instanceof D3DSurfaceData)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// verify that the source surface is actually a texture
|
||||
D3DSurfaceData d3dData = (D3DSurfaceData)srcData;
|
||||
if (d3dData.getType() != D3DSurfaceData.TEXTURE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/****************** Shared MultipleGradientPaint support ********************/
|
||||
|
||||
private static abstract class MultiGradient extends D3DPaints {
|
||||
|
||||
/**
|
||||
* Note that this number is lower than the MULTI_MAX_FRACTIONS
|
||||
* defined in the superclass. The D3D pipeline now uses a
|
||||
* slightly more complicated shader (to avoid the gradient banding
|
||||
* issues), which has a higher instruction count. To ensure that
|
||||
* all versions of the shader can be compiled for PS 2.0 hardware,
|
||||
* we need to cap this maximum value at 8.
|
||||
*/
|
||||
@Native public static final int MULTI_MAX_FRACTIONS_D3D = 8;
|
||||
|
||||
protected MultiGradient() {}
|
||||
|
||||
/**
|
||||
* Returns true if the given MultipleGradientPaint instance can be
|
||||
* used by the accelerated D3DPaints.MultiGradient implementation.
|
||||
* A MultipleGradientPaint is considered valid if the following
|
||||
* conditions are met:
|
||||
* - the number of gradient "stops" is <= MAX_FRACTIONS
|
||||
* - the destination has support for fragment shaders
|
||||
*/
|
||||
@Override
|
||||
boolean isPaintValid(SunGraphics2D sg2d) {
|
||||
MultipleGradientPaint paint = (MultipleGradientPaint)sg2d.paint;
|
||||
// REMIND: ugh, this creates garbage; would be nicer if
|
||||
// we had a MultipleGradientPaint.getNumStops() method...
|
||||
if (paint.getFractions().length > MULTI_MAX_FRACTIONS_D3D) {
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DSurfaceData dstData = (D3DSurfaceData)sg2d.surfaceData;
|
||||
D3DGraphicsDevice gd = (D3DGraphicsDevice)
|
||||
dstData.getDeviceConfiguration().getDevice();
|
||||
if (!gd.isCapPresent(CAPS_LCD_SHADER)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/********************** LinearGradientPaint support *************************/
|
||||
|
||||
private static class LinearGradient extends MultiGradient {
|
||||
private LinearGradient() {}
|
||||
|
||||
@Override
|
||||
boolean isPaintValid(SunGraphics2D sg2d) {
|
||||
LinearGradientPaint paint = (LinearGradientPaint)sg2d.paint;
|
||||
|
||||
if (paint.getFractions().length == 2 &&
|
||||
paint.getCycleMethod() != CycleMethod.REPEAT &&
|
||||
paint.getColorSpace() != ColorSpaceType.LINEAR_RGB)
|
||||
{
|
||||
D3DSurfaceData dstData = (D3DSurfaceData)sg2d.surfaceData;
|
||||
D3DGraphicsDevice gd = (D3DGraphicsDevice)
|
||||
dstData.getDeviceConfiguration().getDevice();
|
||||
if (gd.isCapPresent(CAPS_LCD_SHADER)) {
|
||||
// we can delegate to the optimized two-color gradient
|
||||
// codepath, which should be faster
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return super.isPaintValid(sg2d);
|
||||
}
|
||||
}
|
||||
|
||||
/********************** RadialGradientPaint support *************************/
|
||||
|
||||
private static class RadialGradient extends MultiGradient {
|
||||
private RadialGradient() {}
|
||||
}
|
||||
}
|
||||
159
jdkSrc/jdk8/sun/java2d/d3d/D3DRenderQueue.java
Normal file
159
jdkSrc/jdk8/sun/java2d/d3d/D3DRenderQueue.java
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import sun.java2d.ScreenUpdateManager;
|
||||
import sun.java2d.pipe.RenderBuffer;
|
||||
import sun.java2d.pipe.RenderQueue;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
|
||||
/**
|
||||
* D3D-specific implementation of RenderQueue.
|
||||
*/
|
||||
public class D3DRenderQueue extends RenderQueue {
|
||||
|
||||
private static D3DRenderQueue theInstance;
|
||||
private static Thread rqThread;
|
||||
|
||||
private D3DRenderQueue() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the single D3DRenderQueue instance. If it has not yet been
|
||||
* initialized, this method will first construct the single instance
|
||||
* before returning it.
|
||||
*/
|
||||
public static synchronized D3DRenderQueue getInstance() {
|
||||
if (theInstance == null) {
|
||||
theInstance = new D3DRenderQueue();
|
||||
// no need to lock, noone has reference to this instance yet
|
||||
theInstance.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
rqThread = Thread.currentThread();
|
||||
}
|
||||
});
|
||||
}
|
||||
return theInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the single D3DRenderQueue instance synchronously. If an
|
||||
* D3DRenderQueue has not yet been instantiated, this method is a no-op.
|
||||
* This method is useful in the case of Toolkit.sync(), in which we want
|
||||
* to flush the D3D pipeline, but only if the D3D pipeline is currently
|
||||
* enabled. Since this class has few external dependencies, callers need
|
||||
* not be concerned that calling this method will trigger initialization
|
||||
* of the D3D pipeline and related classes.
|
||||
*/
|
||||
public static void sync() {
|
||||
if (theInstance != null) {
|
||||
// need to make sure any/all screen surfaces are presented prior
|
||||
// to completing the sync operation
|
||||
D3DScreenUpdateManager mgr =
|
||||
(D3DScreenUpdateManager)ScreenUpdateManager.getInstance();
|
||||
mgr.runUpdateNow();
|
||||
|
||||
theInstance.lock();
|
||||
try {
|
||||
theInstance.ensureCapacity(4);
|
||||
theInstance.getBuffer().putInt(SYNC);
|
||||
theInstance.flushNow();
|
||||
} finally {
|
||||
theInstance.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to restore the devices if they're in the lost state.
|
||||
* (used when a full-screen window is activated/deactivated)
|
||||
*/
|
||||
public static void restoreDevices() {
|
||||
D3DRenderQueue rq = getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
rq.ensureCapacity(4);
|
||||
rq.getBuffer().putInt(RESTORE_DEVICES);
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if current thread is the render queue thread,
|
||||
* false otherwise
|
||||
*/
|
||||
public static boolean isRenderQueueThread() {
|
||||
return (Thread.currentThread() == rqThread);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes the native memory associated with the given native
|
||||
* graphics config info pointer on the single queue flushing thread.
|
||||
*/
|
||||
public static void disposeGraphicsConfig(long pConfigInfo) {
|
||||
D3DRenderQueue rq = getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(12, 4);
|
||||
buf.putInt(DISPOSE_CONFIG);
|
||||
buf.putLong(pConfigInfo);
|
||||
|
||||
// this call is expected to complete synchronously, so flush now
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void flushNow() {
|
||||
// assert lock.isHeldByCurrentThread();
|
||||
flushBuffer(null);
|
||||
}
|
||||
|
||||
public void flushAndInvokeNow(Runnable r) {
|
||||
// assert lock.isHeldByCurrentThread();
|
||||
flushBuffer(r);
|
||||
}
|
||||
|
||||
private native void flushBuffer(long buf, int limit, Runnable task);
|
||||
|
||||
private void flushBuffer(Runnable task) {
|
||||
// assert lock.isHeldByCurrentThread();
|
||||
int limit = buf.position();
|
||||
if (limit > 0 || task != null) {
|
||||
// process the queue
|
||||
flushBuffer(buf.getAddress(), limit, task);
|
||||
}
|
||||
// reset the buffer position
|
||||
buf.clear();
|
||||
// clear the set of references, since we no longer need them
|
||||
refSet.clear();
|
||||
}
|
||||
}
|
||||
223
jdkSrc/jdk8/sun/java2d/d3d/D3DRenderer.java
Normal file
223
jdkSrc/jdk8/sun/java2d/d3d/D3DRenderer.java
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Transparency;
|
||||
import java.awt.geom.Path2D;
|
||||
import sun.java2d.InvalidPipeException;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.pipe.BufferedPaints;
|
||||
import sun.java2d.pipe.BufferedRenderPipe;
|
||||
import sun.java2d.pipe.RenderQueue;
|
||||
import sun.java2d.pipe.SpanIterator;
|
||||
import sun.java2d.pipe.ParallelogramPipe;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
|
||||
class D3DRenderer extends BufferedRenderPipe {
|
||||
|
||||
D3DRenderer(RenderQueue rq) {
|
||||
super(rq);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateContext(SunGraphics2D sg2d) {
|
||||
int ctxflags =
|
||||
sg2d.paint.getTransparency() == Transparency.OPAQUE ?
|
||||
D3DContext.SRC_IS_OPAQUE : D3DContext.NO_CONTEXT_FLAGS;
|
||||
D3DSurfaceData dstData;
|
||||
try {
|
||||
dstData = (D3DSurfaceData)sg2d.surfaceData;
|
||||
} catch (ClassCastException e) {
|
||||
throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
|
||||
}
|
||||
D3DContext.validateContext(dstData, dstData,
|
||||
sg2d.getCompClip(), sg2d.composite,
|
||||
null, sg2d.paint, sg2d, ctxflags);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateContextAA(SunGraphics2D sg2d) {
|
||||
int ctxflags = D3DContext.NO_CONTEXT_FLAGS;
|
||||
D3DSurfaceData dstData;
|
||||
try {
|
||||
dstData = (D3DSurfaceData)sg2d.surfaceData;
|
||||
} catch (ClassCastException e) {
|
||||
throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
|
||||
}
|
||||
D3DContext.validateContext(dstData, dstData,
|
||||
sg2d.getCompClip(), sg2d.composite,
|
||||
null, sg2d.paint, sg2d, ctxflags);
|
||||
}
|
||||
|
||||
void copyArea(SunGraphics2D sg2d,
|
||||
int x, int y, int w, int h, int dx, int dy)
|
||||
{
|
||||
rq.lock();
|
||||
try {
|
||||
int ctxflags =
|
||||
sg2d.surfaceData.getTransparency() == Transparency.OPAQUE ?
|
||||
D3DContext.SRC_IS_OPAQUE : D3DContext.NO_CONTEXT_FLAGS;
|
||||
D3DSurfaceData dstData;
|
||||
try {
|
||||
dstData = (D3DSurfaceData)sg2d.surfaceData;
|
||||
} catch (ClassCastException e) {
|
||||
throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
|
||||
}
|
||||
D3DContext.validateContext(dstData, dstData,
|
||||
sg2d.getCompClip(), sg2d.composite,
|
||||
null, null, null, ctxflags);
|
||||
|
||||
rq.ensureCapacity(28);
|
||||
buf.putInt(COPY_AREA);
|
||||
buf.putInt(x).putInt(y).putInt(w).putInt(h);
|
||||
buf.putInt(dx).putInt(dy);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
protected native void drawPoly(int[] xPoints, int[] yPoints,
|
||||
int nPoints, boolean isClosed,
|
||||
int transX, int transY);
|
||||
|
||||
D3DRenderer traceWrap() {
|
||||
return new Tracer(this);
|
||||
}
|
||||
|
||||
private class Tracer extends D3DRenderer {
|
||||
private D3DRenderer d3dr;
|
||||
Tracer(D3DRenderer d3dr) {
|
||||
super(d3dr.rq);
|
||||
this.d3dr = d3dr;
|
||||
}
|
||||
public ParallelogramPipe getAAParallelogramPipe() {
|
||||
final ParallelogramPipe realpipe = d3dr.getAAParallelogramPipe();
|
||||
return new ParallelogramPipe() {
|
||||
public void fillParallelogram(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DFillAAParallelogram");
|
||||
realpipe.fillParallelogram(sg2d,
|
||||
ux1, uy1, ux2, uy2,
|
||||
x, y, dx1, dy1, dx2, dy2);
|
||||
}
|
||||
public void drawParallelogram(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double lw1, double lw2)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DDrawAAParallelogram");
|
||||
realpipe.drawParallelogram(sg2d,
|
||||
ux1, uy1, ux2, uy2,
|
||||
x, y, dx1, dy1, dx2, dy2,
|
||||
lw1, lw2);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected void validateContext(SunGraphics2D sg2d) {
|
||||
d3dr.validateContext(sg2d);
|
||||
}
|
||||
public void drawLine(SunGraphics2D sg2d,
|
||||
int x1, int y1, int x2, int y2)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DDrawLine");
|
||||
d3dr.drawLine(sg2d, x1, y1, x2, y2);
|
||||
}
|
||||
public void drawRect(SunGraphics2D sg2d, int x, int y, int w, int h) {
|
||||
GraphicsPrimitive.tracePrimitive("D3DDrawRect");
|
||||
d3dr.drawRect(sg2d, x, y, w, h);
|
||||
}
|
||||
protected void drawPoly(SunGraphics2D sg2d,
|
||||
int[] xPoints, int[] yPoints,
|
||||
int nPoints, boolean isClosed)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DDrawPoly");
|
||||
d3dr.drawPoly(sg2d, xPoints, yPoints, nPoints, isClosed);
|
||||
}
|
||||
public void fillRect(SunGraphics2D sg2d, int x, int y, int w, int h) {
|
||||
GraphicsPrimitive.tracePrimitive("D3DFillRect");
|
||||
d3dr.fillRect(sg2d, x, y, w, h);
|
||||
}
|
||||
protected void drawPath(SunGraphics2D sg2d,
|
||||
Path2D.Float p2df, int transx, int transy)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DDrawPath");
|
||||
d3dr.drawPath(sg2d, p2df, transx, transy);
|
||||
}
|
||||
protected void fillPath(SunGraphics2D sg2d,
|
||||
Path2D.Float p2df, int transx, int transy)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DFillPath");
|
||||
d3dr.fillPath(sg2d, p2df, transx, transy);
|
||||
}
|
||||
protected void fillSpans(SunGraphics2D sg2d, SpanIterator si,
|
||||
int transx, int transy)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DFillSpans");
|
||||
d3dr.fillSpans(sg2d, si, transx, transy);
|
||||
}
|
||||
public void fillParallelogram(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DFillParallelogram");
|
||||
d3dr.fillParallelogram(sg2d,
|
||||
ux1, uy1, ux2, uy2,
|
||||
x, y, dx1, dy1, dx2, dy2);
|
||||
}
|
||||
public void drawParallelogram(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double lw1, double lw2)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DDrawParallelogram");
|
||||
d3dr.drawParallelogram(sg2d,
|
||||
ux1, uy1, ux2, uy2,
|
||||
x, y, dx1, dy1, dx2, dy2, lw1, lw2);
|
||||
}
|
||||
public void copyArea(SunGraphics2D sg2d,
|
||||
int x, int y, int w, int h, int dx, int dy)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DCopyArea");
|
||||
d3dr.copyArea(sg2d, x, y, w, h, dx, dy);
|
||||
}
|
||||
}
|
||||
}
|
||||
536
jdkSrc/jdk8/sun/java2d/d3d/D3DScreenUpdateManager.java
Normal file
536
jdkSrc/jdk8/sun/java2d/d3d/D3DScreenUpdateManager.java
Normal file
@@ -0,0 +1,536 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Window;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.misc.ThreadGroupUtils;
|
||||
import sun.awt.Win32GraphicsConfig;
|
||||
import sun.awt.windows.WComponentPeer;
|
||||
import sun.java2d.InvalidPipeException;
|
||||
import sun.java2d.ScreenUpdateManager;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.windows.GDIWindowSurfaceData;
|
||||
import sun.java2d.d3d.D3DSurfaceData.D3DWindowSurfaceData;
|
||||
import sun.java2d.windows.WindowsFlags;
|
||||
|
||||
/**
|
||||
* This class handles rendering to the screen with the D3D pipeline.
|
||||
*
|
||||
* Since it is not possible to render directly to the front buffer
|
||||
* with D3D9, we create a swap chain surface (with COPY effect) in place of the
|
||||
* GDIWindowSurfaceData. A background thread handles the swap chain flips.
|
||||
*
|
||||
* There are some restrictions to which windows we would use this for.
|
||||
* @see #createScreenSurface()
|
||||
*/
|
||||
public class D3DScreenUpdateManager extends ScreenUpdateManager
|
||||
implements Runnable
|
||||
{
|
||||
/**
|
||||
* A window must be at least MIN_WIN_SIZE in one or both dimensions
|
||||
* to be considered for the update manager.
|
||||
*/
|
||||
private static final int MIN_WIN_SIZE = 150;
|
||||
|
||||
private volatile boolean done;
|
||||
private volatile Thread screenUpdater;
|
||||
private boolean needsUpdateNow;
|
||||
|
||||
/**
|
||||
* Object used by the screen updater thread for waiting
|
||||
*/
|
||||
private Object runLock = new Object();
|
||||
/**
|
||||
* List of D3DWindowSurfaceData surfaces. Surfaces are added to the
|
||||
* list when a graphics object is created, and removed when the surface
|
||||
* is invalidated.
|
||||
*/
|
||||
private ArrayList<D3DWindowSurfaceData> d3dwSurfaces;
|
||||
/**
|
||||
* Cache of GDIWindowSurfaceData surfaces corresponding to the
|
||||
* D3DWindowSurfaceData surfaces. Surfaces are added to the list when
|
||||
* a d3dw surface is lost and could not be restored (due to lack of vram,
|
||||
* for example), and removed then the d3dw surface is invalidated.
|
||||
*/
|
||||
private HashMap<D3DWindowSurfaceData, GDIWindowSurfaceData> gdiSurfaces;
|
||||
|
||||
public D3DScreenUpdateManager() {
|
||||
done = false;
|
||||
AccessController.doPrivileged(
|
||||
(PrivilegedAction<Void>) () -> {
|
||||
ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
|
||||
Thread shutdown = new Thread(rootTG, () -> {
|
||||
done = true;
|
||||
wakeUpUpdateThread();
|
||||
});
|
||||
shutdown.setContextClassLoader(null);
|
||||
try {
|
||||
Runtime.getRuntime().addShutdownHook(shutdown);
|
||||
} catch (Exception e) {
|
||||
done = true;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* If possible, creates a D3DWindowSurfaceData (which is actually
|
||||
* a back-buffer surface). If the creation fails, returns GDI
|
||||
* onscreen surface instead.
|
||||
*
|
||||
* Note that the created D3D surface does not initialize the native
|
||||
* resources (and is marked lost) to avoid wasting video memory. It is
|
||||
* restored when a graphics object is requested from the peer.
|
||||
*
|
||||
* Note that this method is called from a synchronized block in
|
||||
* WComponentPeer, so we don't need to synchronize
|
||||
*
|
||||
* Note that we only create a substibute d3dw surface if certain conditions
|
||||
* are met
|
||||
* <ul>
|
||||
* <li>the fake d3d rendering on screen is not disabled via flag
|
||||
* <li>d3d on the device is enabled
|
||||
* <li>surface is larger than MIN_WIN_SIZE (don't bother for smaller ones)
|
||||
* <li>it doesn't have a backBuffer for a BufferStrategy already
|
||||
* <li>the peer is either Canvas, Panel, Window, Frame,
|
||||
* Dialog or EmbeddedFrame
|
||||
* </ul>
|
||||
*
|
||||
* @param gc GraphicsConfiguration on associated with the surface
|
||||
* @param peer peer for which the surface is to be created
|
||||
* @param bbNum number of back-buffers requested. if this number is >0,
|
||||
* method returns GDI surface (we don't want to have two swap chains)
|
||||
* @param isResize whether this surface is being created in response to
|
||||
* a component resize event. This determines whether a repaint event will
|
||||
* be issued after a surface is created: it will be if <code>isResize</code>
|
||||
* is <code>true</code>.
|
||||
* @return surface data to be use for onscreen rendering
|
||||
*/
|
||||
@Override
|
||||
public SurfaceData createScreenSurface(Win32GraphicsConfig gc,
|
||||
WComponentPeer peer,
|
||||
int bbNum, boolean isResize)
|
||||
{
|
||||
if (done || !(gc instanceof D3DGraphicsConfig)) {
|
||||
return super.createScreenSurface(gc, peer, bbNum, isResize);
|
||||
}
|
||||
|
||||
SurfaceData sd = null;
|
||||
|
||||
if (canUseD3DOnScreen(peer, gc, bbNum)) {
|
||||
try {
|
||||
// note that the created surface will be in the "lost"
|
||||
// state, it will be restored prior to rendering to it
|
||||
// for the first time. This is done so that vram is not
|
||||
// wasted for surfaces never rendered to
|
||||
sd = D3DSurfaceData.createData(peer);
|
||||
} catch (InvalidPipeException ipe) {
|
||||
sd = null;
|
||||
}
|
||||
}
|
||||
if (sd == null) {
|
||||
sd = GDIWindowSurfaceData.createData(peer);
|
||||
// note that we do not add this surface to the list of cached gdi
|
||||
// surfaces as there's no d3dw surface to associate it with;
|
||||
// this peer will have a gdi surface until next time a surface
|
||||
// will need to be replaced
|
||||
}
|
||||
|
||||
if (isResize) {
|
||||
// since we'd potentially replaced the back-buffer surface
|
||||
// (either with another bb, or a gdi one), the
|
||||
// component will need to be completely repainted;
|
||||
// this only need to be done when the surface is created in
|
||||
// response to a resize event since when a component is created it
|
||||
// will be repainted anyway
|
||||
repaintPeerTarget(peer);
|
||||
}
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if we can use a d3d surface for onscreen rendering for this
|
||||
* peer.
|
||||
* We only create onscreen d3d surfaces if the following conditions are met:
|
||||
* - d3d is enabled on this device and onscreen emulation is enabled
|
||||
* - window is big enough to bother (either dimension > MIN_WIN_SIZE)
|
||||
* - this heavyweight doesn't have a BufferStrategy
|
||||
* - if we are in full-screen mode then it must be the peer of the
|
||||
* full-screen window (since there could be only one SwapChain in fs)
|
||||
* and it must not have any heavyweight children
|
||||
* (as Present() doesn't respect component clipping in fullscreen mode)
|
||||
* - it's one of the classes likely to have custom rendering worth
|
||||
* accelerating
|
||||
*
|
||||
* @returns true if we can use a d3d surface for this peer's onscreen
|
||||
* rendering
|
||||
*/
|
||||
public static boolean canUseD3DOnScreen(final WComponentPeer peer,
|
||||
final Win32GraphicsConfig gc,
|
||||
final int bbNum)
|
||||
{
|
||||
if (!(gc instanceof D3DGraphicsConfig)) {
|
||||
return false;
|
||||
}
|
||||
D3DGraphicsConfig d3dgc = (D3DGraphicsConfig)gc;
|
||||
D3DGraphicsDevice d3dgd = d3dgc.getD3DDevice();
|
||||
String peerName = peer.getClass().getName();
|
||||
Rectangle r = peer.getBounds();
|
||||
Component target = (Component)peer.getTarget();
|
||||
Window fsw = d3dgd.getFullScreenWindow();
|
||||
|
||||
return
|
||||
WindowsFlags.isD3DOnScreenEnabled() &&
|
||||
d3dgd.isD3DEnabledOnDevice() &&
|
||||
peer.isAccelCapable() &&
|
||||
(r.width > MIN_WIN_SIZE || r.height > MIN_WIN_SIZE) &&
|
||||
bbNum == 0 &&
|
||||
(fsw == null || (fsw == target && !hasHWChildren(target))) &&
|
||||
(peerName.equals("sun.awt.windows.WCanvasPeer") ||
|
||||
peerName.equals("sun.awt.windows.WDialogPeer") ||
|
||||
peerName.equals("sun.awt.windows.WPanelPeer") ||
|
||||
peerName.equals("sun.awt.windows.WWindowPeer") ||
|
||||
peerName.equals("sun.awt.windows.WFramePeer") ||
|
||||
peerName.equals("sun.awt.windows.WEmbeddedFramePeer"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a graphics object for the passed in surface data. If
|
||||
* the surface is lost, it is restored.
|
||||
* If the surface wasn't lost or the restoration was successful
|
||||
* the surface is added to the list of maintained surfaces
|
||||
* (if it hasn't been already).
|
||||
*
|
||||
* If the updater thread hasn't been created yet , it will be created and
|
||||
* started.
|
||||
*
|
||||
* @param sd surface data for which to create SunGraphics2D
|
||||
* @param peer peer associated with the surface data
|
||||
* @param fgColor fg color to be used in graphics
|
||||
* @param bgColor bg color to be used in graphics
|
||||
* @param font font to be used in graphics
|
||||
* @return a SunGraphics2D object for the surface (or for temp GDI
|
||||
* surface data)
|
||||
*/
|
||||
@Override
|
||||
public Graphics2D createGraphics(SurfaceData sd,
|
||||
WComponentPeer peer, Color fgColor, Color bgColor, Font font)
|
||||
{
|
||||
if (!done && sd instanceof D3DWindowSurfaceData) {
|
||||
D3DWindowSurfaceData d3dw = (D3DWindowSurfaceData)sd;
|
||||
if (!d3dw.isSurfaceLost() || validate(d3dw)) {
|
||||
trackScreenSurface(d3dw);
|
||||
return new SunGraphics2D(sd, fgColor, bgColor, font);
|
||||
}
|
||||
// could not restore the d3dw surface, use the cached gdi surface
|
||||
// instead for this graphics object; note that we do not track
|
||||
// this new gdi surface, it is only used for this graphics
|
||||
// object
|
||||
sd = getGdiSurface(d3dw);
|
||||
}
|
||||
return super.createGraphics(sd, peer, fgColor, bgColor, font);
|
||||
}
|
||||
|
||||
/**
|
||||
* Posts a repaint event for the peer's target to the EDT
|
||||
* @param peer for which target's the repaint should be issued
|
||||
*/
|
||||
private void repaintPeerTarget(WComponentPeer peer) {
|
||||
Component target = (Component)peer.getTarget();
|
||||
Rectangle bounds = AWTAccessor.getComponentAccessor().getBounds(target);
|
||||
// the system-level painting operations should call the handlePaint()
|
||||
// method of the WComponentPeer class to repaint the component;
|
||||
// calling repaint() forces AWT to make call to update()
|
||||
peer.handlePaint(0, 0, bounds.width, bounds.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a surface to the list of tracked surfaces.
|
||||
*
|
||||
* @param d3dw the surface to be added
|
||||
*/
|
||||
private void trackScreenSurface(SurfaceData sd) {
|
||||
if (!done && sd instanceof D3DWindowSurfaceData) {
|
||||
synchronized (this) {
|
||||
if (d3dwSurfaces == null) {
|
||||
d3dwSurfaces = new ArrayList<D3DWindowSurfaceData>();
|
||||
}
|
||||
D3DWindowSurfaceData d3dw = (D3DWindowSurfaceData)sd;
|
||||
if (!d3dwSurfaces.contains(d3dw)) {
|
||||
d3dwSurfaces.add(d3dw);
|
||||
}
|
||||
}
|
||||
startUpdateThread();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void dropScreenSurface(SurfaceData sd) {
|
||||
if (d3dwSurfaces != null && sd instanceof D3DWindowSurfaceData) {
|
||||
D3DWindowSurfaceData d3dw = (D3DWindowSurfaceData)sd;
|
||||
removeGdiSurface(d3dw);
|
||||
d3dwSurfaces.remove(d3dw);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceData getReplacementScreenSurface(WComponentPeer peer,
|
||||
SurfaceData sd)
|
||||
{
|
||||
SurfaceData newSurface = super.getReplacementScreenSurface(peer, sd);
|
||||
// if some outstanding graphics context wants to get a replacement we
|
||||
// need to make sure that the new surface (if it is accelerated) is
|
||||
// being tracked
|
||||
trackScreenSurface(newSurface);
|
||||
return newSurface;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the gdi surface corresponding to the passed d3dw surface
|
||||
* from list of the cached gdi surfaces.
|
||||
*
|
||||
* @param d3dw surface for which associated gdi surface is to be removed
|
||||
*/
|
||||
private void removeGdiSurface(final D3DWindowSurfaceData d3dw) {
|
||||
if (gdiSurfaces != null) {
|
||||
GDIWindowSurfaceData gdisd = gdiSurfaces.get(d3dw);
|
||||
if (gdisd != null) {
|
||||
gdisd.invalidate();
|
||||
gdiSurfaces.remove(d3dw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the update thread hasn't yet been created, it will be;
|
||||
* otherwise it is awaken
|
||||
*/
|
||||
private synchronized void startUpdateThread() {
|
||||
if (screenUpdater == null) {
|
||||
screenUpdater = AccessController.doPrivileged(
|
||||
(PrivilegedAction<Thread>) () -> {
|
||||
ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
|
||||
Thread t = new Thread(rootTG,
|
||||
D3DScreenUpdateManager.this,
|
||||
"D3D Screen Updater");
|
||||
// REMIND: should it be higher?
|
||||
t.setPriority(Thread.NORM_PRIORITY + 2);
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
});
|
||||
screenUpdater.start();
|
||||
} else {
|
||||
wakeUpUpdateThread();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wakes up the screen updater thread.
|
||||
*
|
||||
* This method is not synchronous, it doesn't wait
|
||||
* for the updater thread to complete the updates.
|
||||
*
|
||||
* It should be used when it is not necessary to wait for the
|
||||
* completion, for example, when a new surface had been added
|
||||
* to the list of tracked surfaces (which means that it's about
|
||||
* to be rendered to).
|
||||
*/
|
||||
public void wakeUpUpdateThread() {
|
||||
synchronized (runLock) {
|
||||
runLock.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wakes up the screen updater thread and waits for the completion
|
||||
* of the update.
|
||||
*
|
||||
* This method is called from Toolkit.sync() or
|
||||
* when there was a copy from a VI to the screen
|
||||
* so that swing applications would not appear to be
|
||||
* sluggish.
|
||||
*/
|
||||
public void runUpdateNow() {
|
||||
synchronized (this) {
|
||||
// nothing to do if the updater thread hadn't been started or if
|
||||
// there are no tracked surfaces
|
||||
if (done || screenUpdater == null ||
|
||||
d3dwSurfaces == null || d3dwSurfaces.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
synchronized (runLock) {
|
||||
needsUpdateNow = true;
|
||||
runLock.notifyAll();
|
||||
while (needsUpdateNow) {
|
||||
try {
|
||||
runLock.wait();
|
||||
} catch (InterruptedException e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (!done) {
|
||||
synchronized (runLock) {
|
||||
// If the list is empty, suspend the thread until a
|
||||
// new surface is added. Note that we have to check before
|
||||
// wait() (and inside the runLock), otherwise we could miss a
|
||||
// notify() when a new surface is added and sleep forever.
|
||||
long timeout = d3dwSurfaces.size() > 0 ? 100 : 0;
|
||||
|
||||
// don't go to sleep if there's a thread waiting for an update
|
||||
if (!needsUpdateNow) {
|
||||
try { runLock.wait(timeout); }
|
||||
catch (InterruptedException e) {}
|
||||
}
|
||||
// if we were woken up, there are probably surfaces in the list,
|
||||
// no need to check if the list is empty
|
||||
}
|
||||
|
||||
// make a copy to avoid synchronization during the loop
|
||||
D3DWindowSurfaceData surfaces[] = new D3DWindowSurfaceData[] {};
|
||||
synchronized (this) {
|
||||
surfaces = d3dwSurfaces.toArray(surfaces);
|
||||
}
|
||||
for (D3DWindowSurfaceData sd : surfaces) {
|
||||
// skip invalid surfaces (they could have become invalid
|
||||
// after we made a copy of the list) - just a precaution
|
||||
if (sd.isValid() && (sd.isDirty() || sd.isSurfaceLost())) {
|
||||
if (!sd.isSurfaceLost()) {
|
||||
// the flip and the clearing of the dirty state
|
||||
// must be done under the lock, otherwise it's
|
||||
// possible to miss an update to the surface
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
Rectangle r = sd.getBounds();
|
||||
D3DSurfaceData.swapBuffers(sd, 0, 0,
|
||||
r.width, r.height);
|
||||
sd.markClean();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
} else if (!validate(sd)) {
|
||||
// it is possible that the validation may never
|
||||
// succeed, we need to detect this and replace
|
||||
// the d3dw surface with gdi; the replacement of
|
||||
// the surface will also trigger a repaint
|
||||
sd.getPeer().replaceSurfaceDataLater();
|
||||
}
|
||||
}
|
||||
}
|
||||
synchronized (runLock) {
|
||||
needsUpdateNow = false;
|
||||
runLock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the passed surface if it was lost, resets the lost status.
|
||||
* @param sd surface to be validated
|
||||
* @return true if surface wasn't lost or if restoration was successful,
|
||||
* false otherwise
|
||||
*/
|
||||
private boolean validate(D3DWindowSurfaceData sd) {
|
||||
if (sd.isSurfaceLost()) {
|
||||
try {
|
||||
sd.restoreSurface();
|
||||
// if succeeded, first fill the surface with bg color
|
||||
// note: use the non-synch method to avoid incorrect lock order
|
||||
Color bg = sd.getPeer().getBackgroundNoSync();
|
||||
SunGraphics2D sg2d = new SunGraphics2D(sd, bg, bg, null);
|
||||
sg2d.fillRect(0, 0, sd.getBounds().width, sd.getBounds().height);
|
||||
sg2d.dispose();
|
||||
// now clean the dirty status so that we don't flip it
|
||||
// next time before it gets repainted; it is safe
|
||||
// to do without the lock because we will issue a
|
||||
// repaint anyway so we will not lose any rendering
|
||||
sd.markClean();
|
||||
// since the surface was successfully restored we need to
|
||||
// repaint whole window to repopulate the back-buffer
|
||||
repaintPeerTarget(sd.getPeer());
|
||||
} catch (InvalidPipeException ipe) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates (or returns a cached one) gdi surface for the same peer as
|
||||
* the passed d3dw surface has.
|
||||
*
|
||||
* @param d3dw surface used as key into the cache
|
||||
* @return gdi window surface associated with the d3d window surfaces' peer
|
||||
*/
|
||||
private synchronized SurfaceData getGdiSurface(D3DWindowSurfaceData d3dw) {
|
||||
if (gdiSurfaces == null) {
|
||||
gdiSurfaces =
|
||||
new HashMap<D3DWindowSurfaceData, GDIWindowSurfaceData>();
|
||||
}
|
||||
GDIWindowSurfaceData gdisd = gdiSurfaces.get(d3dw);
|
||||
if (gdisd == null) {
|
||||
gdisd = GDIWindowSurfaceData.createData(d3dw.getPeer());
|
||||
gdiSurfaces.put(d3dw, gdisd);
|
||||
}
|
||||
return gdisd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the component has heavyweight children.
|
||||
*
|
||||
* @param comp component to check for hw children
|
||||
* @return true if Component has heavyweight children
|
||||
*/
|
||||
private static boolean hasHWChildren(Component comp) {
|
||||
if (comp instanceof Container) {
|
||||
for (Component c : ((Container)comp).getComponents()) {
|
||||
if (c.getPeer() instanceof WComponentPeer || hasHWChildren(c)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
990
jdkSrc/jdk8/sun/java2d/d3d/D3DSurfaceData.java
Normal file
990
jdkSrc/jdk8/sun/java2d/d3d/D3DSurfaceData.java
Normal file
@@ -0,0 +1,990 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.BufferCapabilities;
|
||||
import java.awt.Component;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Image;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.DirectColorModel;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.SampleModel;
|
||||
import java.awt.image.SinglePixelPackedSampleModel;
|
||||
import sun.awt.SunHints;
|
||||
import sun.awt.image.DataBufferNative;
|
||||
import sun.awt.image.PixelConverter;
|
||||
import sun.awt.image.SurfaceManager;
|
||||
import sun.awt.image.WritableRasterNative;
|
||||
import sun.awt.windows.WComponentPeer;
|
||||
import sun.java2d.pipe.hw.AccelSurface;
|
||||
import sun.java2d.InvalidPipeException;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.loops.MaskFill;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.pipe.ParallelogramPipe;
|
||||
import sun.java2d.pipe.PixelToParallelogramConverter;
|
||||
import sun.java2d.pipe.RenderBuffer;
|
||||
import sun.java2d.pipe.TextPipe;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
|
||||
import static sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType.*;
|
||||
import sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType;
|
||||
import java.awt.BufferCapabilities.FlipContents;
|
||||
import java.awt.Window;
|
||||
import sun.awt.SunToolkit;
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
import sun.java2d.ScreenUpdateManager;
|
||||
import sun.java2d.StateTracker;
|
||||
import sun.java2d.SurfaceDataProxy;
|
||||
import sun.java2d.pipe.hw.ExtendedBufferCapabilities;
|
||||
|
||||
/**
|
||||
* This class describes a D3D "surface", that is, a region of pixels
|
||||
* managed via D3D. An D3DSurfaceData can be tagged with one of three
|
||||
* different SurfaceType objects for the purpose of registering loops, etc.
|
||||
* This diagram shows the hierarchy of D3D SurfaceTypes:
|
||||
*
|
||||
* Any
|
||||
* / \
|
||||
* D3DSurface D3DTexture
|
||||
* |
|
||||
* D3DSurfaceRTT
|
||||
*
|
||||
* D3DSurface
|
||||
* This kind of surface can be rendered to using D3D APIs. It is also
|
||||
* possible to copy a D3DSurface to another D3DSurface (or to itself).
|
||||
*
|
||||
* D3DTexture
|
||||
* This kind of surface cannot be rendered to using D3D (in the same sense
|
||||
* as in D3DSurface). However, it is possible to upload a region of pixels
|
||||
* to a D3DTexture object via Lock/UnlockRect(). One can also copy a
|
||||
* surface of type D3DTexture to a D3DSurface by binding the texture
|
||||
* to a quad and then rendering it to the destination surface (this process
|
||||
* is known as "texture mapping").
|
||||
*
|
||||
* D3DSurfaceRTT
|
||||
* This kind of surface can be thought of as a sort of hybrid between
|
||||
* D3DSurface and D3DTexture, in that one can render to this kind of
|
||||
* surface as if it were of type D3DSurface, but the process of copying
|
||||
* this kind of surface to another is more like a D3DTexture. (Note that
|
||||
* "RTT" stands for "render-to-texture".)
|
||||
*
|
||||
* In addition to these SurfaceType variants, we have also defined some
|
||||
* constants that describe in more detail the type of underlying D3D
|
||||
* surface. This table helps explain the relationships between those
|
||||
* "type" constants and their corresponding SurfaceType:
|
||||
*
|
||||
* D3D Type Corresponding SurfaceType
|
||||
* -------- -------------------------
|
||||
* RT_PLAIN D3DSurface
|
||||
* TEXTURE D3DTexture
|
||||
* FLIP_BACKBUFFER D3DSurface
|
||||
* RT_TEXTURE D3DSurfaceRTT
|
||||
*/
|
||||
public class D3DSurfaceData extends SurfaceData implements AccelSurface {
|
||||
|
||||
/**
|
||||
* To be used with getNativeResource() only.
|
||||
* @see #getNativeResource()
|
||||
*/
|
||||
public static final int D3D_DEVICE_RESOURCE= 100;
|
||||
/*
|
||||
* Surface types.
|
||||
* We use these surface types when copying from a sw surface
|
||||
* to a surface or texture.
|
||||
*/
|
||||
public static final int ST_INT_ARGB = 0;
|
||||
public static final int ST_INT_ARGB_PRE = 1;
|
||||
public static final int ST_INT_ARGB_BM = 2;
|
||||
public static final int ST_INT_RGB = 3;
|
||||
public static final int ST_INT_BGR = 4;
|
||||
public static final int ST_USHORT_565_RGB = 5;
|
||||
public static final int ST_USHORT_555_RGB = 6;
|
||||
public static final int ST_BYTE_INDEXED = 7;
|
||||
public static final int ST_BYTE_INDEXED_BM = 8;
|
||||
public static final int ST_3BYTE_BGR = 9;
|
||||
|
||||
/** Equals to D3DSWAPEFFECT_DISCARD */
|
||||
public static final int SWAP_DISCARD = 1;
|
||||
/** Equals to D3DSWAPEFFECT_FLIP */
|
||||
public static final int SWAP_FLIP = 2;
|
||||
/** Equals to D3DSWAPEFFECT_COPY */
|
||||
public static final int SWAP_COPY = 3;
|
||||
/*
|
||||
* SurfaceTypes
|
||||
*/
|
||||
private static final String DESC_D3D_SURFACE = "D3D Surface";
|
||||
private static final String DESC_D3D_SURFACE_RTT =
|
||||
"D3D Surface (render-to-texture)";
|
||||
private static final String DESC_D3D_TEXTURE = "D3D Texture";
|
||||
|
||||
// REMIND: regarding ArgbPre??
|
||||
static final SurfaceType D3DSurface =
|
||||
SurfaceType.Any.deriveSubType(DESC_D3D_SURFACE,
|
||||
PixelConverter.ArgbPre.instance);
|
||||
static final SurfaceType D3DSurfaceRTT =
|
||||
D3DSurface.deriveSubType(DESC_D3D_SURFACE_RTT);
|
||||
static final SurfaceType D3DTexture =
|
||||
SurfaceType.Any.deriveSubType(DESC_D3D_TEXTURE);
|
||||
|
||||
private int type;
|
||||
private int width, height;
|
||||
// these fields are set from the native code when the surface is
|
||||
// initialized
|
||||
private int nativeWidth, nativeHeight;
|
||||
protected WComponentPeer peer;
|
||||
private Image offscreenImage;
|
||||
protected D3DGraphicsDevice graphicsDevice;
|
||||
|
||||
private int swapEffect;
|
||||
private VSyncType syncType;
|
||||
private int backBuffersNum;
|
||||
|
||||
private WritableRasterNative wrn;
|
||||
|
||||
protected static D3DRenderer d3dRenderPipe;
|
||||
protected static PixelToParallelogramConverter d3dTxRenderPipe;
|
||||
protected static ParallelogramPipe d3dAAPgramPipe;
|
||||
protected static D3DTextRenderer d3dTextPipe;
|
||||
protected static D3DDrawImage d3dImagePipe;
|
||||
|
||||
private native boolean initTexture(long pData, boolean isRTT,
|
||||
boolean isOpaque);
|
||||
private native boolean initFlipBackbuffer(long pData, long pPeerData,
|
||||
int numbuffers,
|
||||
int swapEffect, int syncType);
|
||||
private native boolean initRTSurface(long pData, boolean isOpaque);
|
||||
private native void initOps(int screen, int width, int height);
|
||||
|
||||
static {
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
d3dImagePipe = new D3DDrawImage();
|
||||
d3dTextPipe = new D3DTextRenderer(rq);
|
||||
d3dRenderPipe = new D3DRenderer(rq);
|
||||
if (GraphicsPrimitive.tracingEnabled()) {
|
||||
d3dTextPipe = d3dTextPipe.traceWrap();
|
||||
d3dRenderPipe = d3dRenderPipe.traceWrap();
|
||||
//The wrapped d3dRenderPipe will wrap the AA pipe as well...
|
||||
//d3dAAPgramPipe = d3dRenderPipe.traceWrap();
|
||||
}
|
||||
d3dAAPgramPipe = d3dRenderPipe.getAAParallelogramPipe();
|
||||
d3dTxRenderPipe =
|
||||
new PixelToParallelogramConverter(d3dRenderPipe, d3dRenderPipe,
|
||||
1.0, 0.25, true);
|
||||
|
||||
D3DBlitLoops.register();
|
||||
D3DMaskFill.register();
|
||||
D3DMaskBlit.register();
|
||||
}
|
||||
|
||||
protected D3DSurfaceData(WComponentPeer peer, D3DGraphicsConfig gc,
|
||||
int width, int height, Image image,
|
||||
ColorModel cm, int numBackBuffers,
|
||||
int swapEffect, VSyncType vSyncType,
|
||||
int type)
|
||||
{
|
||||
super(getCustomSurfaceType(type), cm);
|
||||
this.graphicsDevice = gc.getD3DDevice();
|
||||
this.peer = peer;
|
||||
this.type = type;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.offscreenImage = image;
|
||||
this.backBuffersNum = numBackBuffers;
|
||||
this.swapEffect = swapEffect;
|
||||
this.syncType = vSyncType;
|
||||
|
||||
initOps(graphicsDevice.getScreen(), width, height);
|
||||
if (type == WINDOW) {
|
||||
// we put the surface into the "lost"
|
||||
// state; it will be restored by the D3DScreenUpdateManager
|
||||
// prior to rendering to it for the first time. This is done
|
||||
// so that vram is not wasted for surfaces never rendered to
|
||||
setSurfaceLost(true);
|
||||
} else {
|
||||
initSurface();
|
||||
}
|
||||
setBlitProxyKey(gc.getProxyKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {
|
||||
return D3DSurfaceDataProxy.
|
||||
createProxy(srcData,
|
||||
(D3DGraphicsConfig)graphicsDevice.getDefaultConfiguration());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a SurfaceData object representing the back buffer of a
|
||||
* double-buffered on-screen Window.
|
||||
*/
|
||||
public static D3DSurfaceData createData(WComponentPeer peer, Image image) {
|
||||
D3DGraphicsConfig gc = getGC(peer);
|
||||
if (gc == null || !peer.isAccelCapable()) {
|
||||
return null;
|
||||
}
|
||||
BufferCapabilities caps = peer.getBackBufferCaps();
|
||||
VSyncType vSyncType = VSYNC_DEFAULT;
|
||||
if (caps instanceof ExtendedBufferCapabilities) {
|
||||
vSyncType = ((ExtendedBufferCapabilities)caps).getVSync();
|
||||
}
|
||||
Rectangle r = peer.getBounds();
|
||||
BufferCapabilities.FlipContents flip = caps.getFlipContents();
|
||||
int swapEffect;
|
||||
if (flip == FlipContents.COPIED) {
|
||||
swapEffect = SWAP_COPY;
|
||||
} else if (flip == FlipContents.PRIOR) {
|
||||
swapEffect = SWAP_FLIP;
|
||||
} else { // flip == FlipContents.UNDEFINED || .BACKGROUND
|
||||
swapEffect = SWAP_DISCARD;
|
||||
}
|
||||
return new D3DSurfaceData(peer, gc, r.width, r.height,
|
||||
image, peer.getColorModel(),
|
||||
peer.getBackBuffersNum(),
|
||||
swapEffect, vSyncType, FLIP_BACKBUFFER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a WINDOW type of surface - a
|
||||
* swap chain which serves as an on-screen surface,
|
||||
* handled by the D3DScreenUpdateManager.
|
||||
*
|
||||
* Note that the native surface is not initialized
|
||||
* when the surface is created to avoid using excessive
|
||||
* resources, and the surface is placed into the lost
|
||||
* state. It will be restored prior to any rendering
|
||||
* to it.
|
||||
*
|
||||
* @param peer peer for which the onscreen surface is to be created
|
||||
* @return a D3DWindowSurfaceData (flip chain) surface
|
||||
*/
|
||||
public static D3DSurfaceData createData(WComponentPeer peer) {
|
||||
D3DGraphicsConfig gc = getGC(peer);
|
||||
if (gc == null || !peer.isAccelCapable()) {
|
||||
return null;
|
||||
}
|
||||
return new D3DWindowSurfaceData(peer, gc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a SurfaceData object representing an off-screen buffer (either
|
||||
* a plain surface or Texture).
|
||||
*/
|
||||
public static D3DSurfaceData createData(D3DGraphicsConfig gc,
|
||||
int width, int height,
|
||||
ColorModel cm,
|
||||
Image image, int type)
|
||||
{
|
||||
if (type == RT_TEXTURE) {
|
||||
boolean isOpaque = cm.getTransparency() == Transparency.OPAQUE;
|
||||
int cap = isOpaque ? CAPS_RT_TEXTURE_OPAQUE : CAPS_RT_TEXTURE_ALPHA;
|
||||
if (!gc.getD3DDevice().isCapPresent(cap)) {
|
||||
type = RT_PLAIN;
|
||||
}
|
||||
}
|
||||
D3DSurfaceData ret = null;
|
||||
try {
|
||||
ret = new D3DSurfaceData(null, gc, width, height,
|
||||
image, cm, 0, SWAP_DISCARD, VSYNC_DEFAULT,
|
||||
type);
|
||||
} catch (InvalidPipeException ipe) {
|
||||
// try again - we might have ran out of vram, and rt textures
|
||||
// could take up more than a plain surface, so it might succeed
|
||||
if (type == RT_TEXTURE) {
|
||||
// If a RT_TEXTURE was requested do not attempt to create a
|
||||
// plain surface. (note that RT_TEXTURE can only be requested
|
||||
// from a VI so the cast is safe)
|
||||
if (((SunVolatileImage)image).getForcedAccelSurfaceType() !=
|
||||
RT_TEXTURE)
|
||||
{
|
||||
type = RT_PLAIN;
|
||||
ret = new D3DSurfaceData(null, gc, width, height,
|
||||
image, cm, 0, SWAP_DISCARD,
|
||||
VSYNC_DEFAULT, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the appropriate SurfaceType corresponding to the given D3D
|
||||
* surface type constant (e.g. TEXTURE -> D3DTexture).
|
||||
*/
|
||||
private static SurfaceType getCustomSurfaceType(int d3dType) {
|
||||
switch (d3dType) {
|
||||
case TEXTURE:
|
||||
return D3DTexture;
|
||||
case RT_TEXTURE:
|
||||
return D3DSurfaceRTT;
|
||||
default:
|
||||
return D3DSurface;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean initSurfaceNow() {
|
||||
boolean isOpaque = (getTransparency() == Transparency.OPAQUE);
|
||||
switch (type) {
|
||||
case RT_PLAIN:
|
||||
return initRTSurface(getNativeOps(), isOpaque);
|
||||
case TEXTURE:
|
||||
return initTexture(getNativeOps(), false/*isRTT*/, isOpaque);
|
||||
case RT_TEXTURE:
|
||||
return initTexture(getNativeOps(), true/*isRTT*/, isOpaque);
|
||||
// REMIND: we may want to pass the exact type to the native
|
||||
// level here so that we could choose the right presentation
|
||||
// interval for the frontbuffer (immediate vs v-synced)
|
||||
case WINDOW:
|
||||
case FLIP_BACKBUFFER:
|
||||
return initFlipBackbuffer(getNativeOps(), peer.getData(),
|
||||
backBuffersNum, swapEffect,
|
||||
syncType.id());
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the appropriate D3D offscreen surface based on the value
|
||||
* of the type parameter. If the surface creation fails for any reason,
|
||||
* an OutOfMemoryError will be thrown.
|
||||
*/
|
||||
protected void initSurface() {
|
||||
// any time we create or restore the surface, recreate the raster
|
||||
synchronized (this) {
|
||||
wrn = null;
|
||||
}
|
||||
// REMIND: somewhere a puppy died
|
||||
class Status {
|
||||
boolean success = false;
|
||||
};
|
||||
final Status status = new Status();
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
status.success = initSurfaceNow();
|
||||
}
|
||||
});
|
||||
if (!status.success) {
|
||||
throw new InvalidPipeException("Error creating D3DSurface");
|
||||
}
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the D3DContext for the GraphicsConfig associated with this
|
||||
* surface.
|
||||
*/
|
||||
public final D3DContext getContext() {
|
||||
return graphicsDevice.getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns one of the surface type constants defined above.
|
||||
*/
|
||||
public final int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
private static native int dbGetPixelNative(long pData, int x, int y);
|
||||
private static native void dbSetPixelNative(long pData, int x, int y,
|
||||
int pixel);
|
||||
static class D3DDataBufferNative extends DataBufferNative {
|
||||
int pixel;
|
||||
protected D3DDataBufferNative(SurfaceData sData,
|
||||
int type, int w, int h)
|
||||
{
|
||||
super(sData, type, w, h);
|
||||
}
|
||||
|
||||
protected int getElem(final int x, final int y,
|
||||
final SurfaceData sData)
|
||||
{
|
||||
if (sData.isSurfaceLost()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int retPixel;
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
pixel = dbGetPixelNative(sData.getNativeOps(), x, y);
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
retPixel = pixel;
|
||||
rq.unlock();
|
||||
}
|
||||
return retPixel;
|
||||
}
|
||||
|
||||
protected void setElem(final int x, final int y, final int pixel,
|
||||
final SurfaceData sData)
|
||||
{
|
||||
if (sData.isSurfaceLost()) {
|
||||
return;
|
||||
}
|
||||
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
dbSetPixelNative(sData.getNativeOps(), x, y, pixel);
|
||||
}
|
||||
});
|
||||
sData.markDirty();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized Raster getRaster(int x, int y, int w, int h) {
|
||||
if (wrn == null) {
|
||||
DirectColorModel dcm = (DirectColorModel)getColorModel();
|
||||
SampleModel smHw;
|
||||
int dataType = 0;
|
||||
int scanStride = width;
|
||||
|
||||
if (dcm.getPixelSize() > 16) {
|
||||
dataType = DataBuffer.TYPE_INT;
|
||||
} else {
|
||||
// 15, 16
|
||||
dataType = DataBuffer.TYPE_USHORT;
|
||||
}
|
||||
|
||||
// note that we have to use the surface width and height here,
|
||||
// not the passed w,h
|
||||
smHw = new SinglePixelPackedSampleModel(dataType, width, height,
|
||||
scanStride, dcm.getMasks());
|
||||
DataBuffer dbn = new D3DDataBufferNative(this, dataType,
|
||||
width, height);
|
||||
wrn = WritableRasterNative.createNativeRaster(smHw, dbn);
|
||||
}
|
||||
|
||||
return wrn;
|
||||
}
|
||||
|
||||
/**
|
||||
* For now, we can only render LCD text if:
|
||||
* - the pixel shaders are available, and
|
||||
* - blending is disabled, and
|
||||
* - the source color is opaque
|
||||
* - and the destination is opaque
|
||||
*/
|
||||
public boolean canRenderLCDText(SunGraphics2D sg2d) {
|
||||
return
|
||||
graphicsDevice.isCapPresent(CAPS_LCD_SHADER) &&
|
||||
sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&
|
||||
sg2d.paintState <= SunGraphics2D.PAINT_OPAQUECOLOR &&
|
||||
sg2d.surfaceData.getTransparency() == Transparency.OPAQUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* If acceleration should no longer be used for this surface.
|
||||
* This implementation flags to the manager that it should no
|
||||
* longer attempt to re-create a D3DSurface.
|
||||
*/
|
||||
void disableAccelerationForSurface() {
|
||||
if (offscreenImage != null) {
|
||||
SurfaceManager sm = SurfaceManager.getManager(offscreenImage);
|
||||
if (sm instanceof D3DVolatileSurfaceManager) {
|
||||
setSurfaceLost(true);
|
||||
((D3DVolatileSurfaceManager)sm).setAccelerationEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void validatePipe(SunGraphics2D sg2d) {
|
||||
TextPipe textpipe;
|
||||
boolean validated = false;
|
||||
|
||||
// REMIND: the D3D pipeline doesn't support XOR!, more
|
||||
// fixes will be needed below. For now we disable D3D rendering
|
||||
// for the surface which had any XOR rendering done to.
|
||||
if (sg2d.compositeState >= sg2d.COMP_XOR) {
|
||||
super.validatePipe(sg2d);
|
||||
sg2d.imagepipe = d3dImagePipe;
|
||||
disableAccelerationForSurface();
|
||||
return;
|
||||
}
|
||||
|
||||
// D3DTextRenderer handles both AA and non-AA text, but
|
||||
// only works with the following modes:
|
||||
// (Note: For LCD text we only enter this code path if
|
||||
// canRenderLCDText() has already validated that the mode is
|
||||
// CompositeType.SrcNoEa (opaque color), which will be subsumed
|
||||
// by the CompositeType.SrcNoEa (any color) test below.)
|
||||
|
||||
if (/* CompositeType.SrcNoEa (any color) */
|
||||
(sg2d.compositeState <= sg2d.COMP_ISCOPY &&
|
||||
sg2d.paintState <= sg2d.PAINT_ALPHACOLOR) ||
|
||||
|
||||
/* CompositeType.SrcOver (any color) */
|
||||
(sg2d.compositeState == sg2d.COMP_ALPHA &&
|
||||
sg2d.paintState <= sg2d.PAINT_ALPHACOLOR &&
|
||||
(((AlphaComposite)sg2d.composite).getRule() ==
|
||||
AlphaComposite.SRC_OVER)) ||
|
||||
|
||||
/* CompositeType.Xor (any color) */
|
||||
(sg2d.compositeState == sg2d.COMP_XOR &&
|
||||
sg2d.paintState <= sg2d.PAINT_ALPHACOLOR))
|
||||
{
|
||||
textpipe = d3dTextPipe;
|
||||
} else {
|
||||
// do this to initialize textpipe correctly; we will attempt
|
||||
// to override the non-text pipes below
|
||||
super.validatePipe(sg2d);
|
||||
textpipe = sg2d.textpipe;
|
||||
validated = true;
|
||||
}
|
||||
|
||||
PixelToParallelogramConverter txPipe = null;
|
||||
D3DRenderer nonTxPipe = null;
|
||||
|
||||
if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) {
|
||||
if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR) {
|
||||
if (sg2d.compositeState <= sg2d.COMP_XOR) {
|
||||
txPipe = d3dTxRenderPipe;
|
||||
nonTxPipe = d3dRenderPipe;
|
||||
}
|
||||
} else if (sg2d.compositeState <= sg2d.COMP_ALPHA) {
|
||||
if (D3DPaints.isValid(sg2d)) {
|
||||
txPipe = d3dTxRenderPipe;
|
||||
nonTxPipe = d3dRenderPipe;
|
||||
}
|
||||
// custom paints handled by super.validatePipe() below
|
||||
}
|
||||
} else {
|
||||
if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR) {
|
||||
if (graphicsDevice.isCapPresent(CAPS_AA_SHADER) &&
|
||||
(sg2d.imageComp == CompositeType.SrcOverNoEa ||
|
||||
sg2d.imageComp == CompositeType.SrcOver))
|
||||
{
|
||||
if (!validated) {
|
||||
super.validatePipe(sg2d);
|
||||
validated = true;
|
||||
}
|
||||
PixelToParallelogramConverter aaConverter =
|
||||
new PixelToParallelogramConverter(sg2d.shapepipe,
|
||||
d3dAAPgramPipe,
|
||||
1.0/8.0, 0.499,
|
||||
false);
|
||||
sg2d.drawpipe = aaConverter;
|
||||
sg2d.fillpipe = aaConverter;
|
||||
sg2d.shapepipe = aaConverter;
|
||||
} else if (sg2d.compositeState == sg2d.COMP_XOR) {
|
||||
// install the solid pipes when AA and XOR are both enabled
|
||||
txPipe = d3dTxRenderPipe;
|
||||
nonTxPipe = d3dRenderPipe;
|
||||
}
|
||||
}
|
||||
// other cases handled by super.validatePipe() below
|
||||
}
|
||||
|
||||
if (txPipe != null) {
|
||||
if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) {
|
||||
sg2d.drawpipe = txPipe;
|
||||
sg2d.fillpipe = txPipe;
|
||||
} else if (sg2d.strokeState != sg2d.STROKE_THIN) {
|
||||
sg2d.drawpipe = txPipe;
|
||||
sg2d.fillpipe = nonTxPipe;
|
||||
} else {
|
||||
sg2d.drawpipe = nonTxPipe;
|
||||
sg2d.fillpipe = nonTxPipe;
|
||||
}
|
||||
// Note that we use the transforming pipe here because it
|
||||
// will examine the shape and possibly perform an optimized
|
||||
// operation if it can be simplified. The simplifications
|
||||
// will be valid for all STROKE and TRANSFORM types.
|
||||
sg2d.shapepipe = txPipe;
|
||||
} else {
|
||||
if (!validated) {
|
||||
super.validatePipe(sg2d);
|
||||
}
|
||||
}
|
||||
|
||||
// install the text pipe based on our earlier decision
|
||||
sg2d.textpipe = textpipe;
|
||||
|
||||
// always override the image pipe with the specialized D3D pipe
|
||||
sg2d.imagepipe = d3dImagePipe;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MaskFill getMaskFill(SunGraphics2D sg2d) {
|
||||
if (sg2d.paintState > sg2d.PAINT_ALPHACOLOR) {
|
||||
/*
|
||||
* We can only accelerate non-Color MaskFill operations if
|
||||
* all of the following conditions hold true:
|
||||
* - there is an implementation for the given paintState
|
||||
* - the current Paint can be accelerated for this destination
|
||||
* - multitexturing is available (since we need to modulate
|
||||
* the alpha mask texture with the paint texture)
|
||||
*
|
||||
* In all other cases, we return null, in which case the
|
||||
* validation code will choose a more general software-based loop.
|
||||
*/
|
||||
if (!D3DPaints.isValid(sg2d) ||
|
||||
!graphicsDevice.isCapPresent(CAPS_MULTITEXTURE))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return super.getMaskFill(sg2d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean copyArea(SunGraphics2D sg2d,
|
||||
int x, int y, int w, int h, int dx, int dy)
|
||||
{
|
||||
if (sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE &&
|
||||
sg2d.compositeState < sg2d.COMP_XOR)
|
||||
{
|
||||
x += sg2d.transX;
|
||||
y += sg2d.transY;
|
||||
|
||||
d3dRenderPipe.copyArea(sg2d, x, y, w, h, dx, dy);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(12, 4);
|
||||
buf.putInt(FLUSH_SURFACE);
|
||||
buf.putLong(getNativeOps());
|
||||
|
||||
// this call is expected to complete synchronously, so flush now
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes the native resources associated with the given D3DSurfaceData
|
||||
* (referenced by the pData parameter). This method is invoked from
|
||||
* the native Dispose() method from the Disposer thread when the
|
||||
* Java-level D3DSurfaceData object is about to go away.
|
||||
*/
|
||||
static void dispose(long pData) {
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(12, 4);
|
||||
buf.putInt(DISPOSE_SURFACE);
|
||||
buf.putLong(pData);
|
||||
|
||||
// this call is expected to complete synchronously, so flush now
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
static void swapBuffers(D3DSurfaceData sd,
|
||||
final int x1, final int y1,
|
||||
final int x2, final int y2)
|
||||
{
|
||||
long pData = sd.getNativeOps();
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
// swapBuffers can be called from the toolkit thread by swing, we
|
||||
// should detect this and prevent the deadlocks
|
||||
if (rq.isRenderQueueThread()) {
|
||||
if (!rq.tryLock()) {
|
||||
// if we could not obtain the lock, repaint the area
|
||||
// that was supposed to be swapped, and no-op this swap
|
||||
final Component target = (Component)sd.getPeer().getTarget();
|
||||
SunToolkit.executeOnEventHandlerThread(target, new Runnable() {
|
||||
public void run() {
|
||||
target.repaint(x1, y1, x2, y2);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
rq.lock();
|
||||
}
|
||||
try {
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(28, 4);
|
||||
buf.putInt(SWAP_BUFFERS);
|
||||
buf.putLong(pData);
|
||||
buf.putInt(x1);
|
||||
buf.putInt(y1);
|
||||
buf.putInt(x2);
|
||||
buf.putInt(y2);
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns destination Image associated with this SurfaceData.
|
||||
*/
|
||||
public Object getDestination() {
|
||||
return offscreenImage;
|
||||
}
|
||||
|
||||
public Rectangle getBounds() {
|
||||
if (type == FLIP_BACKBUFFER || type == WINDOW) {
|
||||
Rectangle r = peer.getBounds();
|
||||
r.x = r.y = 0;
|
||||
return r;
|
||||
} else {
|
||||
return new Rectangle(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
public Rectangle getNativeBounds() {
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
// need to lock to make sure nativeWidth and Height are consistent
|
||||
// since they are set from the render thread from the native
|
||||
// level
|
||||
rq.lock();
|
||||
try {
|
||||
// REMIND: use xyoffsets?
|
||||
return new Rectangle(nativeWidth, nativeHeight);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public GraphicsConfiguration getDeviceConfiguration() {
|
||||
return graphicsDevice.getDefaultConfiguration();
|
||||
}
|
||||
|
||||
public SurfaceData getReplacement() {
|
||||
return restoreContents(offscreenImage);
|
||||
}
|
||||
|
||||
private static D3DGraphicsConfig getGC(WComponentPeer peer) {
|
||||
GraphicsConfiguration gc;
|
||||
if (peer != null) {
|
||||
gc = peer.getGraphicsConfiguration();
|
||||
} else {
|
||||
GraphicsEnvironment env =
|
||||
GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
GraphicsDevice gd = env.getDefaultScreenDevice();
|
||||
gc = gd.getDefaultConfiguration();
|
||||
}
|
||||
return (gc instanceof D3DGraphicsConfig) ? (D3DGraphicsConfig)gc : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to restore the surface by initializing the native data
|
||||
*/
|
||||
void restoreSurface() {
|
||||
initSurface();
|
||||
}
|
||||
|
||||
WComponentPeer getPeer() {
|
||||
return peer;
|
||||
}
|
||||
|
||||
/**
|
||||
* We need to let the surface manager know that the surface is lost so
|
||||
* that for example BufferStrategy.contentsLost() returns correct result.
|
||||
* Normally the status of contentsLost is set in validate(), but in some
|
||||
* cases (like Swing's buffer per window) we intentionally don't call
|
||||
* validate from the toolkit thread but only check for the BS status.
|
||||
*/
|
||||
@Override
|
||||
public void setSurfaceLost(boolean lost) {
|
||||
super.setSurfaceLost(lost);
|
||||
if (lost && offscreenImage != null) {
|
||||
SurfaceManager sm = SurfaceManager.getManager(offscreenImage);
|
||||
sm.acceleratedSurfaceLost();
|
||||
}
|
||||
}
|
||||
|
||||
private static native long getNativeResourceNative(long sdops, int resType);
|
||||
/**
|
||||
* Returns a pointer to the native resource of specified {@code resType}
|
||||
* associated with this surface.
|
||||
*
|
||||
* Specifically, for {@code D3DSurfaceData} this method returns pointers of
|
||||
* the following:
|
||||
* <pre>
|
||||
* TEXTURE - (IDirect3DTexture9*)
|
||||
* RT_TEXTURE, RT_PLAIN - (IDirect3DSurface9*)
|
||||
* FLIP_BACKBUFFER - (IDirect3DSwapChain9*)
|
||||
* D3D_DEVICE_RESOURCE - (IDirect3DDevice9*)
|
||||
* </pre>
|
||||
*
|
||||
* Multiple resources may be available for some types (i.e. for render to
|
||||
* texture one could retrieve both a destination surface by specifying
|
||||
* RT_TEXTURE, and a texture by using TEXTURE).
|
||||
*
|
||||
* Note: the pointer returned by this method is only valid on the rendering
|
||||
* thread.
|
||||
*
|
||||
* @return pointer to the native resource of specified type or 0L if
|
||||
* such resource doesn't exist or can not be retrieved.
|
||||
* @see sun.java2d.pipe.hw.AccelSurface#getNativeResource
|
||||
*/
|
||||
public long getNativeResource(int resType) {
|
||||
return getNativeResourceNative(getNativeOps(), resType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representing an on-screen d3d surface. Since d3d can't
|
||||
* render to the screen directly, it is implemented as a swap chain,
|
||||
* controlled by D3DScreenUpdateManager.
|
||||
*
|
||||
* @see D3DScreenUpdateManager
|
||||
*/
|
||||
public static class D3DWindowSurfaceData extends D3DSurfaceData {
|
||||
StateTracker dirtyTracker;
|
||||
|
||||
public D3DWindowSurfaceData(WComponentPeer peer,
|
||||
D3DGraphicsConfig gc)
|
||||
{
|
||||
super(peer, gc,
|
||||
peer.getBounds().width, peer.getBounds().height,
|
||||
null, peer.getColorModel(), 1, SWAP_COPY, VSYNC_DEFAULT,
|
||||
WINDOW);
|
||||
dirtyTracker = getStateTracker();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* Overridden to use ScreenUpdateManager to obtain the replacement
|
||||
* surface.
|
||||
*
|
||||
* @see sun.java2d.ScreenUpdateManager#getReplacementScreenSurface
|
||||
*/
|
||||
@Override
|
||||
public SurfaceData getReplacement() {
|
||||
ScreenUpdateManager mgr = ScreenUpdateManager.getInstance();
|
||||
return mgr.getReplacementScreenSurface(peer, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns destination Component associated with this SurfaceData.
|
||||
*/
|
||||
@Override
|
||||
public Object getDestination() {
|
||||
return peer.getTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
void disableAccelerationForSurface() {
|
||||
// for on-screen surfaces we need to make sure a backup GDI surface is
|
||||
// is used until a new one is set (which may happen during a resize). We
|
||||
// don't want the screen update maanger to replace the surface right way
|
||||
// because it causes repainting issues in Swing, so we invalidate it,
|
||||
// this will prevent SUM from issuing a replaceSurfaceData call.
|
||||
setSurfaceLost(true);
|
||||
invalidate();
|
||||
flush();
|
||||
peer.disableAcceleration();
|
||||
ScreenUpdateManager.getInstance().dropScreenSurface(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
void restoreSurface() {
|
||||
if (!peer.isAccelCapable()) {
|
||||
throw new InvalidPipeException("Onscreen acceleration " +
|
||||
"disabled for this surface");
|
||||
}
|
||||
Window fsw = graphicsDevice.getFullScreenWindow();
|
||||
if (fsw != null && fsw != peer.getTarget()) {
|
||||
throw new InvalidPipeException("Can't restore onscreen surface"+
|
||||
" when in full-screen mode");
|
||||
}
|
||||
super.restoreSurface();
|
||||
// if initialization was unsuccessful, an IPE will be thrown
|
||||
// and the surface will remain lost
|
||||
setSurfaceLost(false);
|
||||
|
||||
// This is to make sure the render target is reset after this
|
||||
// surface is restored. The reason for this is that sometimes this
|
||||
// surface can be restored from multiple threads (the screen update
|
||||
// manager's thread and app's rendering thread) at the same time,
|
||||
// and when that happens the second restoration will create the
|
||||
// native resource which will not be set as render target because
|
||||
// the BufferedContext's validate method will think that since the
|
||||
// surface data object didn't change then the current render target
|
||||
// is correct and no rendering will appear on the screen.
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
getContext().invalidateContext();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDirty() {
|
||||
return !dirtyTracker.isCurrent();
|
||||
}
|
||||
|
||||
public void markClean() {
|
||||
dirtyTracker = getStateTracker();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the layered window with the contents of the surface.
|
||||
*
|
||||
* @param pd3dsd pointer to the D3DSDOps structure
|
||||
* @param pData pointer to the AwtWindow peer data
|
||||
* @param w width of the window
|
||||
* @param h height of the window
|
||||
* @see sun.awt.windows.TranslucentWindowPainter
|
||||
*/
|
||||
public static native boolean updateWindowAccelImpl(long pd3dsd, long pData,
|
||||
int w, int h);
|
||||
}
|
||||
93
jdkSrc/jdk8/sun/java2d/d3d/D3DSurfaceDataProxy.java
Normal file
93
jdkSrc/jdk8/sun/java2d/d3d/D3DSurfaceDataProxy.java
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Transparency;
|
||||
|
||||
import sun.java2d.InvalidPipeException;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.SurfaceDataProxy;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
|
||||
/**
|
||||
* The proxy class contains the logic for when to replace a
|
||||
* SurfaceData with a cached D3D Texture and the code to create
|
||||
* the accelerated surfaces.
|
||||
*/
|
||||
public class D3DSurfaceDataProxy extends SurfaceDataProxy {
|
||||
|
||||
public static SurfaceDataProxy createProxy(SurfaceData srcData,
|
||||
D3DGraphicsConfig dstConfig)
|
||||
{
|
||||
if (srcData instanceof D3DSurfaceData) {
|
||||
// srcData must be a VolatileImage which either matches
|
||||
// our pixel format or not - either way we do not cache it...
|
||||
return UNCACHED;
|
||||
}
|
||||
|
||||
return new D3DSurfaceDataProxy(dstConfig, srcData.getTransparency());
|
||||
}
|
||||
|
||||
D3DGraphicsConfig d3dgc;
|
||||
int transparency;
|
||||
|
||||
public D3DSurfaceDataProxy(D3DGraphicsConfig d3dgc, int transparency) {
|
||||
this.d3dgc = d3dgc;
|
||||
this.transparency = transparency;
|
||||
// REMIND: we may want to change this for the d3d pipeline, it's not
|
||||
// necessary to invalidate them all at once on display change
|
||||
activateDisplayListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceData validateSurfaceData(SurfaceData srcData,
|
||||
SurfaceData cachedData,
|
||||
int w, int h)
|
||||
{
|
||||
if (cachedData == null || cachedData.isSurfaceLost()) {
|
||||
try {
|
||||
cachedData = d3dgc.createManagedSurface(w, h, transparency);
|
||||
} catch (InvalidPipeException e) {
|
||||
if (!d3dgc.getD3DDevice().isD3DAvailable()) {
|
||||
invalidate();
|
||||
flush();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cachedData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedOperation(SurfaceData srcData,
|
||||
int txtype,
|
||||
CompositeType comp,
|
||||
Color bgColor)
|
||||
{
|
||||
return (bgColor == null || transparency == Transparency.OPAQUE);
|
||||
}
|
||||
}
|
||||
71
jdkSrc/jdk8/sun/java2d/d3d/D3DTextRenderer.java
Normal file
71
jdkSrc/jdk8/sun/java2d/d3d/D3DTextRenderer.java
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Composite;
|
||||
import sun.font.GlyphList;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.pipe.BufferedTextPipe;
|
||||
import sun.java2d.pipe.RenderQueue;
|
||||
|
||||
class D3DTextRenderer extends BufferedTextPipe {
|
||||
|
||||
D3DTextRenderer(RenderQueue rq) {
|
||||
super(rq);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected native void drawGlyphList(int numGlyphs, boolean usePositions,
|
||||
boolean subPixPos, boolean rgbOrder,
|
||||
int lcdContrast,
|
||||
float glOrigX, float glOrigY,
|
||||
long[] images, float[] positions);
|
||||
|
||||
@Override
|
||||
protected void validateContext(SunGraphics2D sg2d, Composite comp) {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
D3DSurfaceData d3dDst = (D3DSurfaceData)sg2d.surfaceData;
|
||||
D3DContext.validateContext(d3dDst, d3dDst,
|
||||
sg2d.getCompClip(), comp,
|
||||
null, sg2d.paint, sg2d,
|
||||
D3DContext.NO_CONTEXT_FLAGS);
|
||||
}
|
||||
|
||||
D3DTextRenderer traceWrap() {
|
||||
return new Tracer(this);
|
||||
}
|
||||
|
||||
private static class Tracer extends D3DTextRenderer {
|
||||
Tracer(D3DTextRenderer d3dtr) {
|
||||
super(d3dtr.rq);
|
||||
}
|
||||
protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) {
|
||||
GraphicsPrimitive.tracePrimitive("D3DDrawGlyphs");
|
||||
super.drawGlyphList(sg2d, gl);
|
||||
}
|
||||
}
|
||||
}
|
||||
230
jdkSrc/jdk8/sun/java2d/d3d/D3DVolatileSurfaceManager.java
Normal file
230
jdkSrc/jdk8/sun/java2d/d3d/D3DVolatileSurfaceManager.java
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Image;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.image.ColorModel;
|
||||
import sun.awt.Win32GraphicsConfig;
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
import sun.awt.image.SurfaceManager;
|
||||
import sun.awt.image.VolatileSurfaceManager;
|
||||
import sun.awt.windows.WComponentPeer;
|
||||
import sun.java2d.InvalidPipeException;
|
||||
import sun.java2d.SurfaceData;
|
||||
import static sun.java2d.pipe.hw.AccelSurface.*;
|
||||
import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
|
||||
import sun.java2d.windows.GDIWindowSurfaceData;
|
||||
|
||||
public class D3DVolatileSurfaceManager
|
||||
extends VolatileSurfaceManager
|
||||
{
|
||||
private boolean accelerationEnabled;
|
||||
private int restoreCountdown;
|
||||
|
||||
public D3DVolatileSurfaceManager(SunVolatileImage vImg, Object context) {
|
||||
super(vImg, context);
|
||||
|
||||
/*
|
||||
* We will attempt to accelerate this image only under the
|
||||
* following conditions:
|
||||
* - the image is opaque OR
|
||||
* - the image is translucent AND
|
||||
* - the GraphicsConfig supports the FBO extension OR
|
||||
* - the GraphicsConfig has a stored alpha channel
|
||||
*/
|
||||
int transparency = vImg.getTransparency();
|
||||
D3DGraphicsDevice gd = (D3DGraphicsDevice)
|
||||
vImg.getGraphicsConfig().getDevice();
|
||||
accelerationEnabled =
|
||||
(transparency == Transparency.OPAQUE) ||
|
||||
(transparency == Transparency.TRANSLUCENT &&
|
||||
(gd.isCapPresent(CAPS_RT_PLAIN_ALPHA) ||
|
||||
gd.isCapPresent(CAPS_RT_TEXTURE_ALPHA)));
|
||||
}
|
||||
|
||||
protected boolean isAccelerationEnabled() {
|
||||
return accelerationEnabled;
|
||||
}
|
||||
public void setAccelerationEnabled(boolean accelerationEnabled) {
|
||||
this.accelerationEnabled = accelerationEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a pbuffer-based SurfaceData object (or init the backbuffer
|
||||
* of an existing window if this is a double buffered GraphicsConfig).
|
||||
*/
|
||||
protected SurfaceData initAcceleratedSurface() {
|
||||
SurfaceData sData;
|
||||
Component comp = vImg.getComponent();
|
||||
WComponentPeer peer =
|
||||
(comp != null) ? (WComponentPeer)comp.getPeer() : null;
|
||||
|
||||
try {
|
||||
boolean forceback = false;
|
||||
if (context instanceof Boolean) {
|
||||
forceback = ((Boolean)context).booleanValue();
|
||||
}
|
||||
|
||||
if (forceback) {
|
||||
// peer must be non-null in this case
|
||||
sData = D3DSurfaceData.createData(peer, vImg);
|
||||
} else {
|
||||
D3DGraphicsConfig gc =
|
||||
(D3DGraphicsConfig)vImg.getGraphicsConfig();
|
||||
ColorModel cm = gc.getColorModel(vImg.getTransparency());
|
||||
int type = vImg.getForcedAccelSurfaceType();
|
||||
// if acceleration type is forced (type != UNDEFINED) then
|
||||
// use the forced type, otherwise use RT_TEXTURE
|
||||
if (type == UNDEFINED) {
|
||||
type = RT_TEXTURE;
|
||||
}
|
||||
sData = D3DSurfaceData.createData(gc,
|
||||
vImg.getWidth(),
|
||||
vImg.getHeight(),
|
||||
cm, vImg,
|
||||
type);
|
||||
}
|
||||
} catch (NullPointerException ex) {
|
||||
sData = null;
|
||||
} catch (OutOfMemoryError er) {
|
||||
sData = null;
|
||||
} catch (InvalidPipeException ipe) {
|
||||
sData = null;
|
||||
}
|
||||
|
||||
return sData;
|
||||
}
|
||||
|
||||
protected boolean isConfigValid(GraphicsConfiguration gc) {
|
||||
return ((gc == null) || (gc == vImg.getGraphicsConfig()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of iterations for restoreAcceleratedSurface to fail
|
||||
* before attempting to restore the accelerated surface.
|
||||
*
|
||||
* @see #restoreAcceleratedSurface
|
||||
* @see #handleVItoScreenOp
|
||||
*/
|
||||
private synchronized void setRestoreCountdown(int count) {
|
||||
restoreCountdown = count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that we create a new surface instead of restoring
|
||||
* an old one. This will help with D3DContext revalidation.
|
||||
*/
|
||||
@Override
|
||||
protected void restoreAcceleratedSurface() {
|
||||
synchronized (this) {
|
||||
if (restoreCountdown > 0) {
|
||||
restoreCountdown--;
|
||||
throw new
|
||||
InvalidPipeException("Will attempt to restore surface " +
|
||||
" in " + restoreCountdown);
|
||||
}
|
||||
}
|
||||
|
||||
SurfaceData sData = initAcceleratedSurface();
|
||||
if (sData != null) {
|
||||
sdAccel = sData;
|
||||
} else {
|
||||
throw new InvalidPipeException("could not restore surface");
|
||||
// REMIND: alternatively, we could try this:
|
||||
// ((D3DSurfaceData)sdAccel).restoreSurface();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We're asked to restore contents by the accelerated surface, which means
|
||||
* that it had been lost.
|
||||
*/
|
||||
@Override
|
||||
public SurfaceData restoreContents() {
|
||||
acceleratedSurfaceLost();
|
||||
return super.restoreContents();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the destination surface's peer can potentially handle accelerated
|
||||
* on-screen rendering then it is likely that the condition which resulted
|
||||
* in VI to Screen operation is temporary, so this method sets the
|
||||
* restore countdown in hope that the on-screen accelerated rendering will
|
||||
* resume. In the meantime the backup surface of the VISM will be used.
|
||||
*
|
||||
* The countdown is needed because otherwise we may never break out
|
||||
* of "do { vi.validate()..} while(vi.lost)" loop since validate() could
|
||||
* restore the source surface every time and it will get lost again on the
|
||||
* next copy attempt, and we would never get a chance to use the backup
|
||||
* surface. By using the countdown we allow the backup surface to be used
|
||||
* while the screen surface gets sorted out, or if it for some reason can
|
||||
* never be restored.
|
||||
*
|
||||
* If the destination surface's peer could never do accelerated onscreen
|
||||
* rendering then the acceleration for the SurfaceManager associated with
|
||||
* the source surface is disabled forever.
|
||||
*/
|
||||
static void handleVItoScreenOp(SurfaceData src, SurfaceData dst) {
|
||||
if (src instanceof D3DSurfaceData &&
|
||||
dst instanceof GDIWindowSurfaceData)
|
||||
{
|
||||
D3DSurfaceData d3dsd = (D3DSurfaceData)src;
|
||||
SurfaceManager mgr =
|
||||
SurfaceManager.getManager((Image)d3dsd.getDestination());
|
||||
if (mgr instanceof D3DVolatileSurfaceManager) {
|
||||
D3DVolatileSurfaceManager vsm = (D3DVolatileSurfaceManager)mgr;
|
||||
if (vsm != null) {
|
||||
d3dsd.setSurfaceLost(true);
|
||||
|
||||
GDIWindowSurfaceData wsd = (GDIWindowSurfaceData)dst;
|
||||
WComponentPeer p = wsd.getPeer();
|
||||
if (D3DScreenUpdateManager.canUseD3DOnScreen(p,
|
||||
(Win32GraphicsConfig)p.getGraphicsConfiguration(),
|
||||
p.getBackBuffersNum()))
|
||||
{
|
||||
// 10 is only chosen to be greater than the number of
|
||||
// times a sane person would call validate() inside
|
||||
// a validation loop, and to reduce thrashing between
|
||||
// accelerated and backup surfaces
|
||||
vsm.setRestoreCountdown(10);
|
||||
} else {
|
||||
vsm.setAccelerationEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initContents() {
|
||||
if (vImg.getForcedAccelSurfaceType() != TEXTURE) {
|
||||
super.initContents();
|
||||
}
|
||||
}
|
||||
}
|
||||
332
jdkSrc/jdk8/sun/java2d/loops/Blit.java
Normal file
332
jdkSrc/jdk8/sun/java2d/loops/Blit.java
Normal file
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import java.awt.Composite;
|
||||
import java.awt.CompositeContext;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.lang.ref.WeakReference;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.java2d.pipe.SpanIterator;
|
||||
|
||||
/**
|
||||
* Blit
|
||||
* 1) copies rectangle of pixels from one surface to another
|
||||
* 2) performs compositing of colors based upon a Composite
|
||||
* parameter
|
||||
*
|
||||
* precise behavior is undefined if the source surface
|
||||
* and the destination surface are the same surface
|
||||
* with overlapping regions of pixels
|
||||
*/
|
||||
|
||||
public class Blit extends GraphicsPrimitive
|
||||
{
|
||||
public static final String methodSignature = "Blit(...)".toString();
|
||||
|
||||
public static final int primTypeID = makePrimTypeID();
|
||||
|
||||
private static RenderCache blitcache = new RenderCache(20);
|
||||
|
||||
public static Blit locate(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return (Blit)
|
||||
GraphicsPrimitiveMgr.locate(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public static Blit getFromCache(SurfaceType src,
|
||||
CompositeType comp,
|
||||
SurfaceType dst)
|
||||
{
|
||||
Object o = blitcache.get(src, comp, dst);
|
||||
if (o != null) {
|
||||
return (Blit) o;
|
||||
}
|
||||
|
||||
Blit blit = locate(src, comp, dst);
|
||||
if (blit == null) {
|
||||
System.out.println("blit loop not found for:");
|
||||
System.out.println("src: "+src);
|
||||
System.out.println("comp: "+comp);
|
||||
System.out.println("dst: "+dst);
|
||||
} else {
|
||||
blitcache.put(src, comp, dst, blit);
|
||||
}
|
||||
return blit;
|
||||
}
|
||||
|
||||
protected Blit(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public Blit(long pNativePrim,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(pNativePrim, methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
/**
|
||||
* All Blit implementors must have this invoker method
|
||||
*/
|
||||
public native void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int srcx, int srcy,
|
||||
int dstx, int dsty,
|
||||
int width, int height);
|
||||
|
||||
static {
|
||||
GraphicsPrimitiveMgr.registerGeneral(new Blit(null, null, null));
|
||||
}
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
/*
|
||||
System.out.println("Constructing general blit for:");
|
||||
System.out.println("src: "+srctype);
|
||||
System.out.println("comp: "+comptype);
|
||||
System.out.println("dst: "+dsttype);
|
||||
*/
|
||||
|
||||
if (comptype.isDerivedFrom(CompositeType.Xor)) {
|
||||
GeneralXorBlit gxb = new GeneralXorBlit(srctype,
|
||||
comptype,
|
||||
dsttype);
|
||||
setupGeneralBinaryOp(gxb);
|
||||
return gxb;
|
||||
} else if (comptype.isDerivedFrom(CompositeType.AnyAlpha)) {
|
||||
return new GeneralMaskBlit(srctype, comptype, dsttype);
|
||||
} else {
|
||||
return AnyBlit.instance;
|
||||
}
|
||||
}
|
||||
|
||||
private static class AnyBlit extends Blit {
|
||||
public static AnyBlit instance = new AnyBlit();
|
||||
|
||||
public AnyBlit() {
|
||||
super(SurfaceType.Any, CompositeType.Any, SurfaceType.Any);
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData srcData,
|
||||
SurfaceData dstData,
|
||||
Composite comp,
|
||||
Region clip,
|
||||
int srcx, int srcy,
|
||||
int dstx, int dsty,
|
||||
int width, int height)
|
||||
{
|
||||
ColorModel srcCM = srcData.getColorModel();
|
||||
ColorModel dstCM = dstData.getColorModel();
|
||||
// REMIND: Should get RenderingHints from sg2d
|
||||
CompositeContext ctx = comp.createContext(srcCM, dstCM,
|
||||
new RenderingHints(null));
|
||||
Raster srcRas = srcData.getRaster(srcx, srcy, width, height);
|
||||
WritableRaster dstRas =
|
||||
(WritableRaster) dstData.getRaster(dstx, dsty, width, height);
|
||||
|
||||
if (clip == null) {
|
||||
clip = Region.getInstanceXYWH(dstx, dsty, width, height);
|
||||
}
|
||||
int span[] = {dstx, dsty, dstx+width, dsty+height};
|
||||
SpanIterator si = clip.getSpanIterator(span);
|
||||
srcx -= dstx;
|
||||
srcy -= dsty;
|
||||
while (si.nextSpan(span)) {
|
||||
int w = span[2] - span[0];
|
||||
int h = span[3] - span[1];
|
||||
Raster tmpSrcRas = srcRas.createChild(srcx + span[0], srcy + span[1],
|
||||
w, h, 0, 0, null);
|
||||
WritableRaster tmpDstRas = dstRas.createWritableChild(span[0], span[1],
|
||||
w, h, 0, 0, null);
|
||||
ctx.compose(tmpSrcRas, tmpDstRas, tmpDstRas);
|
||||
}
|
||||
ctx.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private static class GeneralMaskBlit extends Blit {
|
||||
MaskBlit performop;
|
||||
|
||||
public GeneralMaskBlit(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(srctype, comptype, dsttype);
|
||||
performop = MaskBlit.locate(srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData srcData,
|
||||
SurfaceData dstData,
|
||||
Composite comp,
|
||||
Region clip,
|
||||
int srcx, int srcy,
|
||||
int dstx, int dsty,
|
||||
int width, int height)
|
||||
{
|
||||
performop.MaskBlit(srcData, dstData, comp, clip,
|
||||
srcx, srcy, dstx, dsty,
|
||||
width, height,
|
||||
null, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private static class GeneralXorBlit
|
||||
extends Blit
|
||||
implements GeneralBinaryOp
|
||||
{
|
||||
Blit convertsrc;
|
||||
Blit convertdst;
|
||||
Blit performop;
|
||||
Blit convertresult;
|
||||
|
||||
WeakReference srcTmp;
|
||||
WeakReference dstTmp;
|
||||
|
||||
public GeneralXorBlit(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public void setPrimitives(Blit srcconverter,
|
||||
Blit dstconverter,
|
||||
GraphicsPrimitive genericop,
|
||||
Blit resconverter)
|
||||
{
|
||||
this.convertsrc = srcconverter;
|
||||
this.convertdst = dstconverter;
|
||||
this.performop = (Blit) genericop;
|
||||
this.convertresult = resconverter;
|
||||
}
|
||||
|
||||
public synchronized void Blit(SurfaceData srcData,
|
||||
SurfaceData dstData,
|
||||
Composite comp,
|
||||
Region clip,
|
||||
int srcx, int srcy,
|
||||
int dstx, int dsty,
|
||||
int width, int height)
|
||||
{
|
||||
SurfaceData src, dst;
|
||||
Region opclip;
|
||||
int sx, sy, dx, dy;
|
||||
|
||||
if (convertsrc == null) {
|
||||
src = srcData;
|
||||
sx = srcx;
|
||||
sy = srcy;
|
||||
} else {
|
||||
SurfaceData cachedSrc = null;
|
||||
if (srcTmp != null) {
|
||||
cachedSrc = (SurfaceData) srcTmp.get();
|
||||
}
|
||||
src = convertFrom(convertsrc, srcData, srcx, srcy,
|
||||
width, height, cachedSrc);
|
||||
sx = 0;
|
||||
sy = 0;
|
||||
if (src != cachedSrc) {
|
||||
srcTmp = new WeakReference(src);
|
||||
}
|
||||
}
|
||||
|
||||
if (convertdst == null) {
|
||||
dst = dstData;
|
||||
dx = dstx;
|
||||
dy = dsty;
|
||||
opclip = clip;
|
||||
} else {
|
||||
// assert: convertresult != null
|
||||
SurfaceData cachedDst = null;
|
||||
if (dstTmp != null) {
|
||||
cachedDst = (SurfaceData) dstTmp.get();
|
||||
}
|
||||
dst = convertFrom(convertdst, dstData, dstx, dsty,
|
||||
width, height, cachedDst);
|
||||
dx = 0;
|
||||
dy = 0;
|
||||
opclip = null;
|
||||
if (dst != cachedDst) {
|
||||
dstTmp = new WeakReference(dst);
|
||||
}
|
||||
}
|
||||
|
||||
performop.Blit(src, dst, comp, opclip,
|
||||
sx, sy, dx, dy,
|
||||
width, height);
|
||||
|
||||
if (convertresult != null) {
|
||||
// assert: convertdst != null
|
||||
convertTo(convertresult, dst, dstData, clip,
|
||||
dstx, dsty, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return new TraceBlit(this);
|
||||
}
|
||||
|
||||
private static class TraceBlit extends Blit {
|
||||
Blit target;
|
||||
|
||||
public TraceBlit(Blit target) {
|
||||
super(target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int srcx, int srcy, int dstx, int dsty,
|
||||
int width, int height)
|
||||
{
|
||||
tracePrimitive(target);
|
||||
target.Blit(src, dst, comp, clip,
|
||||
srcx, srcy, dstx, dsty, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
217
jdkSrc/jdk8/sun/java2d/loops/BlitBg.java
Normal file
217
jdkSrc/jdk8/sun/java2d/loops/BlitBg.java
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.awt.image.BufferedImage;
|
||||
import sun.awt.image.BufImgSurfaceData;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.pipe.Region;
|
||||
|
||||
/**
|
||||
* BlitBg
|
||||
* 1) copies rectangle of pixels from one surface to another
|
||||
* 2) performs compositing of colors based upon a Composite
|
||||
* parameter
|
||||
* 3) assumes that non-opaque pixels are to be blended with
|
||||
* the indicated Bg color before compositing with the
|
||||
* destination
|
||||
*
|
||||
* precise behavior is undefined if the source surface
|
||||
* and the destination surface are the same surface
|
||||
* with overlapping regions of pixels
|
||||
*/
|
||||
public class BlitBg extends GraphicsPrimitive
|
||||
{
|
||||
public static final String methodSignature = "BlitBg(...)".toString();
|
||||
|
||||
public static final int primTypeID = makePrimTypeID();
|
||||
|
||||
private static RenderCache blitcache = new RenderCache(20);
|
||||
|
||||
public static BlitBg locate(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return (BlitBg)
|
||||
GraphicsPrimitiveMgr.locate(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public static BlitBg getFromCache(SurfaceType src,
|
||||
CompositeType comp,
|
||||
SurfaceType dst)
|
||||
{
|
||||
Object o = blitcache.get(src, comp, dst);
|
||||
if (o != null) {
|
||||
return (BlitBg) o;
|
||||
}
|
||||
BlitBg blit = locate(src, comp, dst);
|
||||
if (blit == null) {
|
||||
System.out.println("blitbg loop not found for:");
|
||||
System.out.println("src: "+src);
|
||||
System.out.println("comp: "+comp);
|
||||
System.out.println("dst: "+dst);
|
||||
} else {
|
||||
blitcache.put(src, comp, dst, blit);
|
||||
}
|
||||
return blit;
|
||||
}
|
||||
|
||||
protected BlitBg(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public BlitBg(long pNativePrim,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(pNativePrim, methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
/**
|
||||
* All BlitBg implementors must have this invoker method
|
||||
*/
|
||||
public native void BlitBg(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int bgColor,
|
||||
int srcx, int srcy,
|
||||
int dstx, int dsty,
|
||||
int width, int height);
|
||||
|
||||
static {
|
||||
GraphicsPrimitiveMgr.registerGeneral(new BlitBg(null, null, null));
|
||||
}
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
/*
|
||||
System.out.println("Constructing general blitbg for:");
|
||||
System.out.println("src: "+srctype);
|
||||
System.out.println("comp: "+comptype);
|
||||
System.out.println("dst: "+dsttype);
|
||||
*/
|
||||
return new General(srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
private static class General extends BlitBg {
|
||||
CompositeType compositeType;
|
||||
|
||||
public General(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(srctype, comptype, dsttype);
|
||||
compositeType = comptype;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void BlitBg(SurfaceData srcData,
|
||||
SurfaceData dstData,
|
||||
Composite comp,
|
||||
Region clip,
|
||||
int bgArgb,
|
||||
int srcx, int srcy,
|
||||
int dstx, int dsty,
|
||||
int width, int height)
|
||||
{
|
||||
ColorModel dstModel = dstData.getColorModel();
|
||||
boolean bgHasAlpha = (bgArgb >>> 24) != 0xff;
|
||||
if (!dstModel.hasAlpha() && bgHasAlpha) {
|
||||
dstModel = ColorModel.getRGBdefault();
|
||||
}
|
||||
WritableRaster wr =
|
||||
dstModel.createCompatibleWritableRaster(width, height);
|
||||
boolean isPremult = dstModel.isAlphaPremultiplied();
|
||||
BufferedImage bimg =
|
||||
new BufferedImage(dstModel, wr, isPremult, null);
|
||||
SurfaceData tmpData = BufImgSurfaceData.createData(bimg);
|
||||
Color bgColor = new Color(bgArgb, bgHasAlpha);
|
||||
SunGraphics2D sg2d = new SunGraphics2D(tmpData, bgColor, bgColor,
|
||||
defaultFont);
|
||||
FillRect fillop = FillRect.locate(SurfaceType.AnyColor,
|
||||
CompositeType.SrcNoEa,
|
||||
tmpData.getSurfaceType());
|
||||
Blit combineop = Blit.getFromCache(srcData.getSurfaceType(),
|
||||
CompositeType.SrcOverNoEa,
|
||||
tmpData.getSurfaceType());
|
||||
Blit blitop = Blit.getFromCache(tmpData.getSurfaceType(), compositeType,
|
||||
dstData.getSurfaceType());
|
||||
fillop.FillRect(sg2d, tmpData, 0, 0, width, height);
|
||||
combineop.Blit(srcData, tmpData, AlphaComposite.SrcOver, null,
|
||||
srcx, srcy, 0, 0, width, height);
|
||||
blitop.Blit(tmpData, dstData, comp, clip,
|
||||
0, 0, dstx, dsty, width, height);
|
||||
}
|
||||
|
||||
private static Font defaultFont = new Font("Dialog", Font.PLAIN, 12);
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return new TraceBlitBg(this);
|
||||
}
|
||||
|
||||
private static class TraceBlitBg extends BlitBg {
|
||||
BlitBg target;
|
||||
|
||||
public TraceBlitBg(BlitBg target) {
|
||||
super(target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void BlitBg(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int bgColor,
|
||||
int srcx, int srcy, int dstx, int dsty,
|
||||
int width, int height)
|
||||
{
|
||||
tracePrimitive(target);
|
||||
target.BlitBg(src, dst, comp, clip, bgColor,
|
||||
srcx, srcy, dstx, dsty, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
295
jdkSrc/jdk8/sun/java2d/loops/CompositeType.java
Normal file
295
jdkSrc/jdk8/sun/java2d/loops/CompositeType.java
Normal file
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* A CompositeType object provides a chained description of a type of
|
||||
* algorithm for color compositing. The object will provide a single
|
||||
* String constant descriptor which is one way of describing a particular
|
||||
* compositing algorithm as well as a pointer to another CompositeType
|
||||
* which describes a more general algorithm for achieving the same result.
|
||||
* <p>
|
||||
* A description of a more specific algorithm is considered a "subtype"
|
||||
* and a description of a more general algorithm is considered a "supertype".
|
||||
* Thus, the deriveSubType method provides a way to create a new CompositeType
|
||||
* that is related to but more specific than an existing CompositeType and
|
||||
* the getSuperType method provides a way to ask a given CompositeType
|
||||
* for a more general algorithm to achieve the same result.
|
||||
* <p>
|
||||
* Note that you cannot construct a brand new root for a chain since
|
||||
* the constructor is private. Every chain of types must at some point
|
||||
* derive from the Any node provided here using the deriveSubType()
|
||||
* method. The presence of this common Any node on every chain
|
||||
* ensures that all chains end with the DESC_ANY descriptor so that
|
||||
* a suitable General GraphicsPrimitive object can be obtained for
|
||||
* the indicated algorithm if all of the more specific searches fail.
|
||||
*/
|
||||
public final class CompositeType {
|
||||
|
||||
private static int unusedUID = 1;
|
||||
private static final HashMap<String,Integer> compositeUIDMap =
|
||||
new HashMap<String,Integer>(100);
|
||||
|
||||
/*
|
||||
* CONSTANTS USED BY ALL PRIMITIVES TO DESCRIBE THE COMPOSITING
|
||||
* ALGORITHMS THEY CAN PERFORM
|
||||
*/
|
||||
|
||||
/**
|
||||
* algorithm is a general algorithm that uses a CompositeContext
|
||||
* to do the rendering.
|
||||
*/
|
||||
public static final String DESC_ANY = "Any CompositeContext";
|
||||
|
||||
/**
|
||||
* constant used to describe the Graphics.setXORMode() algorithm
|
||||
*/
|
||||
public static final String DESC_XOR = "XOR mode";
|
||||
|
||||
/**
|
||||
* constants used to describe the various AlphaComposite
|
||||
* algorithms.
|
||||
*/
|
||||
public static final String DESC_CLEAR = "Porter-Duff Clear";
|
||||
public static final String DESC_SRC = "Porter-Duff Src";
|
||||
public static final String DESC_DST = "Porter-Duff Dst";
|
||||
public static final String DESC_SRC_OVER = "Porter-Duff Src Over Dst";
|
||||
public static final String DESC_DST_OVER = "Porter-Duff Dst Over Src";
|
||||
public static final String DESC_SRC_IN = "Porter-Duff Src In Dst";
|
||||
public static final String DESC_DST_IN = "Porter-Duff Dst In Src";
|
||||
public static final String DESC_SRC_OUT = "Porter-Duff Src HeldOutBy Dst";
|
||||
public static final String DESC_DST_OUT = "Porter-Duff Dst HeldOutBy Src";
|
||||
public static final String DESC_SRC_ATOP = "Porter-Duff Src Atop Dst";
|
||||
public static final String DESC_DST_ATOP = "Porter-Duff Dst Atop Src";
|
||||
public static final String DESC_ALPHA_XOR = "Porter-Duff Xor";
|
||||
|
||||
/**
|
||||
* constants used to describe the two common cases of
|
||||
* AlphaComposite algorithms that are simpler if there
|
||||
* is not extraAlpha.
|
||||
*/
|
||||
public static final String
|
||||
DESC_SRC_NO_EA = "Porter-Duff Src, No Extra Alpha";
|
||||
public static final String
|
||||
DESC_SRC_OVER_NO_EA = "Porter-Duff SrcOverDst, No Extra Alpha";
|
||||
|
||||
/**
|
||||
* constant used to describe an algorithm that implements all 8 of
|
||||
* the Porter-Duff rules in one Primitive.
|
||||
*/
|
||||
public static final String DESC_ANY_ALPHA = "Any AlphaComposite Rule";
|
||||
|
||||
/*
|
||||
* END OF COMPOSITE ALGORITHM TYPE CONSTANTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* The root CompositeType object for all chains of algorithm descriptions.
|
||||
*/
|
||||
public static final CompositeType
|
||||
Any = new CompositeType(null, DESC_ANY);
|
||||
|
||||
/*
|
||||
* START OF CompositeeType OBJECTS FOR THE VARIOUS CONSTANTS
|
||||
*/
|
||||
|
||||
public static final CompositeType
|
||||
General = Any;
|
||||
|
||||
public static final CompositeType
|
||||
AnyAlpha = General.deriveSubType(DESC_ANY_ALPHA);
|
||||
public static final CompositeType
|
||||
Xor = General.deriveSubType(DESC_XOR);
|
||||
|
||||
public static final CompositeType
|
||||
Clear = AnyAlpha.deriveSubType(DESC_CLEAR);
|
||||
public static final CompositeType
|
||||
Src = AnyAlpha.deriveSubType(DESC_SRC);
|
||||
public static final CompositeType
|
||||
Dst = AnyAlpha.deriveSubType(DESC_DST);
|
||||
public static final CompositeType
|
||||
SrcOver = AnyAlpha.deriveSubType(DESC_SRC_OVER);
|
||||
public static final CompositeType
|
||||
DstOver = AnyAlpha.deriveSubType(DESC_DST_OVER);
|
||||
public static final CompositeType
|
||||
SrcIn = AnyAlpha.deriveSubType(DESC_SRC_IN);
|
||||
public static final CompositeType
|
||||
DstIn = AnyAlpha.deriveSubType(DESC_DST_IN);
|
||||
public static final CompositeType
|
||||
SrcOut = AnyAlpha.deriveSubType(DESC_SRC_OUT);
|
||||
public static final CompositeType
|
||||
DstOut = AnyAlpha.deriveSubType(DESC_DST_OUT);
|
||||
public static final CompositeType
|
||||
SrcAtop = AnyAlpha.deriveSubType(DESC_SRC_ATOP);
|
||||
public static final CompositeType
|
||||
DstAtop = AnyAlpha.deriveSubType(DESC_DST_ATOP);
|
||||
public static final CompositeType
|
||||
AlphaXor = AnyAlpha.deriveSubType(DESC_ALPHA_XOR);
|
||||
|
||||
public static final CompositeType
|
||||
SrcNoEa = Src.deriveSubType(DESC_SRC_NO_EA);
|
||||
public static final CompositeType
|
||||
SrcOverNoEa = SrcOver.deriveSubType(DESC_SRC_OVER_NO_EA);
|
||||
|
||||
/*
|
||||
* A special CompositeType for the case where we are filling in
|
||||
* SrcOverNoEa mode with an opaque color. In that case then the
|
||||
* best loop for us to use would be a SrcNoEa loop, but what if
|
||||
* there is no such loop? In that case then we would end up
|
||||
* backing off to a Src loop (which should still be fine) or an
|
||||
* AnyAlpha loop which would be slower than a SrcOver loop in
|
||||
* most cases.
|
||||
* The fix is to use the following chain which looks for loops
|
||||
* in the following order:
|
||||
* SrcNoEa, Src, SrcOverNoEa, SrcOver, AnyAlpha
|
||||
*/
|
||||
public static final CompositeType
|
||||
OpaqueSrcOverNoEa = SrcOverNoEa.deriveSubType(DESC_SRC)
|
||||
.deriveSubType(DESC_SRC_NO_EA);
|
||||
|
||||
/*
|
||||
* END OF CompositeType OBJECTS FOR THE VARIOUS CONSTANTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* Return a new CompositeType object which uses this object as its
|
||||
* more general "supertype" descriptor. If no operation can be
|
||||
* found that implements the algorithm described more exactly
|
||||
* by desc, then this object will define the more general
|
||||
* compositing algorithm that can be used instead.
|
||||
*/
|
||||
public CompositeType deriveSubType(String desc) {
|
||||
return new CompositeType(this, desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a CompositeType object for the specified AlphaComposite
|
||||
* rule.
|
||||
*/
|
||||
public static CompositeType forAlphaComposite(AlphaComposite ac) {
|
||||
switch (ac.getRule()) {
|
||||
case AlphaComposite.CLEAR:
|
||||
return Clear;
|
||||
case AlphaComposite.SRC:
|
||||
if (ac.getAlpha() >= 1.0f) {
|
||||
return SrcNoEa;
|
||||
} else {
|
||||
return Src;
|
||||
}
|
||||
case AlphaComposite.DST:
|
||||
return Dst;
|
||||
case AlphaComposite.SRC_OVER:
|
||||
if (ac.getAlpha() >= 1.0f) {
|
||||
return SrcOverNoEa;
|
||||
} else {
|
||||
return SrcOver;
|
||||
}
|
||||
case AlphaComposite.DST_OVER:
|
||||
return DstOver;
|
||||
case AlphaComposite.SRC_IN:
|
||||
return SrcIn;
|
||||
case AlphaComposite.DST_IN:
|
||||
return DstIn;
|
||||
case AlphaComposite.SRC_OUT:
|
||||
return SrcOut;
|
||||
case AlphaComposite.DST_OUT:
|
||||
return DstOut;
|
||||
case AlphaComposite.SRC_ATOP:
|
||||
return SrcAtop;
|
||||
case AlphaComposite.DST_ATOP:
|
||||
return DstAtop;
|
||||
case AlphaComposite.XOR:
|
||||
return AlphaXor;
|
||||
default:
|
||||
throw new InternalError("Unrecognized alpha rule");
|
||||
}
|
||||
}
|
||||
|
||||
private int uniqueID;
|
||||
private String desc;
|
||||
private CompositeType next;
|
||||
|
||||
private CompositeType(CompositeType parent, String desc) {
|
||||
next = parent;
|
||||
this.desc = desc;
|
||||
this.uniqueID = makeUniqueID(desc);
|
||||
}
|
||||
|
||||
public synchronized static final int makeUniqueID(String desc) {
|
||||
Integer i = compositeUIDMap.get(desc);
|
||||
|
||||
if (i == null) {
|
||||
if (unusedUID > 255) {
|
||||
throw new InternalError("composite type id overflow");
|
||||
}
|
||||
i = unusedUID++;
|
||||
compositeUIDMap.put(desc, i);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public int getUniqueID() {
|
||||
return uniqueID;
|
||||
}
|
||||
|
||||
public String getDescriptor() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public CompositeType getSuperType() {
|
||||
return next;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return desc.hashCode();
|
||||
}
|
||||
|
||||
public boolean isDerivedFrom(CompositeType other) {
|
||||
CompositeType comptype = this;
|
||||
do {
|
||||
if (comptype.desc == other.desc) {
|
||||
return true;
|
||||
}
|
||||
comptype = comptype.next;
|
||||
} while (comptype != null);
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof CompositeType) {
|
||||
return (((CompositeType) o).uniqueID == this.uniqueID);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
329
jdkSrc/jdk8/sun/java2d/loops/CustomComponent.java
Normal file
329
jdkSrc/jdk8/sun/java2d/loops/CustomComponent.java
Normal file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Charlton Innovations, Inc.
|
||||
* @author Jim Graham
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import java.awt.Composite;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import sun.awt.image.IntegerComponentRaster;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.java2d.pipe.SpanIterator;
|
||||
|
||||
/**
|
||||
* CustomComponent, collection of GraphicsPrimitive
|
||||
* Basically, this collection of components performs conversion from
|
||||
* ANY to ANY via opaque copy
|
||||
*/
|
||||
public final class CustomComponent {
|
||||
public static void register() {
|
||||
// REMIND: This does not work for all destinations yet since
|
||||
// the screen SurfaceData objects do not implement getRaster
|
||||
Class owner = CustomComponent.class;
|
||||
GraphicsPrimitive[] primitives = {
|
||||
new GraphicsPrimitiveProxy(owner, "OpaqueCopyAnyToArgb",
|
||||
Blit.methodSignature,
|
||||
Blit.primTypeID,
|
||||
SurfaceType.Any,
|
||||
CompositeType.SrcNoEa,
|
||||
SurfaceType.IntArgb),
|
||||
new GraphicsPrimitiveProxy(owner, "OpaqueCopyArgbToAny",
|
||||
Blit.methodSignature,
|
||||
Blit.primTypeID,
|
||||
SurfaceType.IntArgb,
|
||||
CompositeType.SrcNoEa,
|
||||
SurfaceType.Any),
|
||||
new GraphicsPrimitiveProxy(owner, "XorCopyArgbToAny",
|
||||
Blit.methodSignature,
|
||||
Blit.primTypeID,
|
||||
SurfaceType.IntArgb,
|
||||
CompositeType.Xor,
|
||||
SurfaceType.Any),
|
||||
};
|
||||
GraphicsPrimitiveMgr.register(primitives);
|
||||
}
|
||||
|
||||
public static Region getRegionOfInterest(SurfaceData src, SurfaceData dst,
|
||||
Region clip,
|
||||
int srcx, int srcy,
|
||||
int dstx, int dsty,
|
||||
int w, int h)
|
||||
{
|
||||
/*
|
||||
* Intersect all of:
|
||||
* - operation area (dstx, dsty, w, h)
|
||||
* - destination bounds
|
||||
* - (translated) src bounds
|
||||
* - supplied clip (may be non-rectangular)
|
||||
* Intersect the rectangular regions first since those are
|
||||
* simpler operations.
|
||||
*/
|
||||
Region ret = Region.getInstanceXYWH(dstx, dsty, w, h);
|
||||
ret = ret.getIntersection(dst.getBounds());
|
||||
Rectangle r = src.getBounds();
|
||||
// srcxy in src space maps to dstxy in dst space
|
||||
r.translate(dstx - srcx, dsty - srcy);
|
||||
ret = ret.getIntersection(r);
|
||||
if (clip != null) {
|
||||
// Intersect with clip last since it may be non-rectangular
|
||||
ret = ret.getIntersection(clip);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ANY format to ARGB format Blit
|
||||
*/
|
||||
class OpaqueCopyAnyToArgb extends Blit {
|
||||
OpaqueCopyAnyToArgb() {
|
||||
super(SurfaceType.Any,
|
||||
CompositeType.SrcNoEa,
|
||||
SurfaceType.IntArgb);
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int srcx, int srcy, int dstx, int dsty, int w, int h)
|
||||
{
|
||||
Raster srcRast = src.getRaster(srcx, srcy, w, h);
|
||||
ColorModel srcCM = src.getColorModel();
|
||||
|
||||
Raster dstRast = dst.getRaster(dstx, dsty, w, h);
|
||||
IntegerComponentRaster icr = (IntegerComponentRaster) dstRast;
|
||||
int[] dstPix = icr.getDataStorage();
|
||||
|
||||
Region roi = CustomComponent.getRegionOfInterest(src, dst, clip,
|
||||
srcx, srcy,
|
||||
dstx, dsty, w, h);
|
||||
SpanIterator si = roi.getSpanIterator();
|
||||
|
||||
Object srcPix = null;
|
||||
|
||||
int dstScan = icr.getScanlineStride();
|
||||
// assert(icr.getPixelStride() == 1);
|
||||
srcx -= dstx;
|
||||
srcy -= dsty;
|
||||
int span[] = new int[4];
|
||||
while (si.nextSpan(span)) {
|
||||
int rowoff = icr.getDataOffset(0) + span[1] * dstScan + span[0];
|
||||
for (int y = span[1]; y < span[3]; y++) {
|
||||
int off = rowoff;
|
||||
for (int x = span[0]; x < span[2]; x++) {
|
||||
srcPix = srcRast.getDataElements(x+srcx, y+srcy, srcPix);
|
||||
dstPix[off++] = srcCM.getRGB(srcPix);
|
||||
}
|
||||
rowoff += dstScan;
|
||||
}
|
||||
}
|
||||
// Pixels in the dest were modified directly, we must
|
||||
// manually notify the raster that it was modified
|
||||
icr.markDirty();
|
||||
// REMIND: We need to do something to make sure that dstRast
|
||||
// is put back to the destination (as in the native Release
|
||||
// function)
|
||||
// src.releaseRaster(srcRast); // NOP?
|
||||
// dst.releaseRaster(dstRast);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ARGB format to ANY format Blit
|
||||
*/
|
||||
class OpaqueCopyArgbToAny extends Blit {
|
||||
OpaqueCopyArgbToAny() {
|
||||
super(SurfaceType.IntArgb,
|
||||
CompositeType.SrcNoEa,
|
||||
SurfaceType.Any);
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int srcx, int srcy, int dstx, int dsty, int w, int h)
|
||||
{
|
||||
Raster srcRast = src.getRaster(srcx, srcy, w, h);
|
||||
IntegerComponentRaster icr = (IntegerComponentRaster) srcRast;
|
||||
int[] srcPix = icr.getDataStorage();
|
||||
|
||||
WritableRaster dstRast =
|
||||
(WritableRaster) dst.getRaster(dstx, dsty, w, h);
|
||||
ColorModel dstCM = dst.getColorModel();
|
||||
|
||||
Region roi = CustomComponent.getRegionOfInterest(src, dst, clip,
|
||||
srcx, srcy,
|
||||
dstx, dsty, w, h);
|
||||
SpanIterator si = roi.getSpanIterator();
|
||||
|
||||
Object dstPix = null;
|
||||
|
||||
int srcScan = icr.getScanlineStride();
|
||||
// assert(icr.getPixelStride() == 1);
|
||||
srcx -= dstx;
|
||||
srcy -= dsty;
|
||||
int span[] = new int[4];
|
||||
while (si.nextSpan(span)) {
|
||||
int rowoff = (icr.getDataOffset(0) +
|
||||
(srcy + span[1]) * srcScan +
|
||||
(srcx + span[0]));
|
||||
for (int y = span[1]; y < span[3]; y++) {
|
||||
int off = rowoff;
|
||||
for (int x = span[0]; x < span[2]; x++) {
|
||||
dstPix = dstCM.getDataElements(srcPix[off++], dstPix);
|
||||
dstRast.setDataElements(x, y, dstPix);
|
||||
}
|
||||
rowoff += srcScan;
|
||||
}
|
||||
}
|
||||
// REMIND: We need to do something to make sure that dstRast
|
||||
// is put back to the destination (as in the native Release
|
||||
// function)
|
||||
// src.releaseRaster(srcRast); // NOP?
|
||||
// dst.releaseRaster(dstRast);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ARGB format to ANY format Blit (pixels are XORed together with XOR pixel)
|
||||
*/
|
||||
class XorCopyArgbToAny extends Blit {
|
||||
XorCopyArgbToAny() {
|
||||
super(SurfaceType.IntArgb,
|
||||
CompositeType.Xor,
|
||||
SurfaceType.Any);
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int srcx, int srcy, int dstx, int dsty, int w, int h)
|
||||
{
|
||||
Raster srcRast = src.getRaster(srcx, srcy, w, h);
|
||||
IntegerComponentRaster icr = (IntegerComponentRaster) srcRast;
|
||||
int[] srcPix = icr.getDataStorage();
|
||||
|
||||
WritableRaster dstRast =
|
||||
(WritableRaster) dst.getRaster(dstx, dsty, w, h);
|
||||
ColorModel dstCM = dst.getColorModel();
|
||||
|
||||
Region roi = CustomComponent.getRegionOfInterest(src, dst, clip,
|
||||
srcx, srcy,
|
||||
dstx, dsty, w, h);
|
||||
SpanIterator si = roi.getSpanIterator();
|
||||
|
||||
int xorrgb = ((XORComposite)comp).getXorColor().getRGB();
|
||||
Object xorPixel = dstCM.getDataElements(xorrgb, null);
|
||||
|
||||
Object srcPixel = null;
|
||||
Object dstPixel = null;
|
||||
|
||||
int srcScan = icr.getScanlineStride();
|
||||
// assert(icr.getPixelStride() == 1);
|
||||
srcx -= dstx;
|
||||
srcy -= dsty;
|
||||
int span[] = new int[4];
|
||||
while (si.nextSpan(span)) {
|
||||
int rowoff = (icr.getDataOffset(0) +
|
||||
(srcy + span[1]) * srcScan +
|
||||
(srcx + span[0]));
|
||||
for (int y = span[1]; y < span[3]; y++) {
|
||||
int off = rowoff;
|
||||
for (int x = span[0]; x < span[2]; x++) {
|
||||
// REMIND: alpha bits of the destination pixel are
|
||||
// currently altered by the XOR operation, but
|
||||
// should be left untouched
|
||||
srcPixel = dstCM.getDataElements(srcPix[off++], srcPixel);
|
||||
dstPixel = dstRast.getDataElements(x, y, dstPixel);
|
||||
|
||||
switch (dstCM.getTransferType()) {
|
||||
case DataBuffer.TYPE_BYTE:
|
||||
byte[] bytesrcarr = (byte[]) srcPixel;
|
||||
byte[] bytedstarr = (byte[]) dstPixel;
|
||||
byte[] bytexorarr = (byte[]) xorPixel;
|
||||
for (int i = 0; i < bytedstarr.length; i++) {
|
||||
bytedstarr[i] ^= bytesrcarr[i] ^ bytexorarr[i];
|
||||
}
|
||||
break;
|
||||
case DataBuffer.TYPE_SHORT:
|
||||
case DataBuffer.TYPE_USHORT:
|
||||
short[] shortsrcarr = (short[]) srcPixel;
|
||||
short[] shortdstarr = (short[]) dstPixel;
|
||||
short[] shortxorarr = (short[]) xorPixel;
|
||||
for (int i = 0; i < shortdstarr.length; i++) {
|
||||
shortdstarr[i] ^= shortsrcarr[i] ^ shortxorarr[i];
|
||||
}
|
||||
break;
|
||||
case DataBuffer.TYPE_INT:
|
||||
int[] intsrcarr = (int[]) srcPixel;
|
||||
int[] intdstarr = (int[]) dstPixel;
|
||||
int[] intxorarr = (int[]) xorPixel;
|
||||
for (int i = 0; i < intdstarr.length; i++) {
|
||||
intdstarr[i] ^= intsrcarr[i] ^ intxorarr[i];
|
||||
}
|
||||
break;
|
||||
case DataBuffer.TYPE_FLOAT:
|
||||
float[] floatsrcarr = (float[]) srcPixel;
|
||||
float[] floatdstarr = (float[]) dstPixel;
|
||||
float[] floatxorarr = (float[]) xorPixel;
|
||||
for (int i = 0; i < floatdstarr.length; i++) {
|
||||
int v = (Float.floatToIntBits(floatdstarr[i]) ^
|
||||
Float.floatToIntBits(floatsrcarr[i]) ^
|
||||
Float.floatToIntBits(floatxorarr[i]));
|
||||
floatdstarr[i] = Float.intBitsToFloat(v);
|
||||
}
|
||||
break;
|
||||
case DataBuffer.TYPE_DOUBLE:
|
||||
double[] doublesrcarr = (double[]) srcPixel;
|
||||
double[] doubledstarr = (double[]) dstPixel;
|
||||
double[] doublexorarr = (double[]) xorPixel;
|
||||
for (int i = 0; i < doubledstarr.length; i++) {
|
||||
long v = (Double.doubleToLongBits(doubledstarr[i]) ^
|
||||
Double.doubleToLongBits(doublesrcarr[i]) ^
|
||||
Double.doubleToLongBits(doublexorarr[i]));
|
||||
doubledstarr[i] = Double.longBitsToDouble(v);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new InternalError("Unsupported XOR pixel type");
|
||||
}
|
||||
dstRast.setDataElements(x, y, dstPixel);
|
||||
}
|
||||
rowoff += srcScan;
|
||||
}
|
||||
}
|
||||
// REMIND: We need to do something to make sure that dstRast
|
||||
// is put back to the destination (as in the native Release
|
||||
// function)
|
||||
// src.releaseRaster(srcRast); // NOP?
|
||||
// dst.releaseRaster(dstRast);
|
||||
}
|
||||
}
|
||||
161
jdkSrc/jdk8/sun/java2d/loops/DrawGlyphList.java
Normal file
161
jdkSrc/jdk8/sun/java2d/loops/DrawGlyphList.java
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.font.GlyphList;
|
||||
|
||||
/**
|
||||
* DrawGlyphList - loops for SolidTextRenderer pipe.
|
||||
* 1) draw solid color text onto destination surface
|
||||
* 2) must accept output area [x, y, dx, dy]
|
||||
* from within the surface description data for clip rect
|
||||
*/
|
||||
public class DrawGlyphList extends GraphicsPrimitive {
|
||||
|
||||
public final static String methodSignature = "DrawGlyphList(...)".toString();
|
||||
|
||||
public final static int primTypeID = makePrimTypeID();
|
||||
|
||||
public static DrawGlyphList locate(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return (DrawGlyphList)
|
||||
GraphicsPrimitiveMgr.locate(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
protected DrawGlyphList(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public DrawGlyphList(long pNativePrim,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(pNativePrim, methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
|
||||
public native void DrawGlyphList(SunGraphics2D sg2d, SurfaceData dest,
|
||||
GlyphList srcData);
|
||||
|
||||
// This instance is used only for lookup.
|
||||
static {
|
||||
GraphicsPrimitiveMgr.registerGeneral(
|
||||
new DrawGlyphList(null, null, null));
|
||||
}
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype) {
|
||||
return new General(srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
private static class General extends DrawGlyphList {
|
||||
MaskFill maskop;
|
||||
|
||||
public General(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(srctype, comptype, dsttype);
|
||||
maskop = MaskFill.locate(srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public void DrawGlyphList(SunGraphics2D sg2d, SurfaceData dest,
|
||||
GlyphList gl) {
|
||||
|
||||
int strbounds[] = gl.getBounds(); // Don't delete, bug 4895493
|
||||
int num = gl.getNumGlyphs();
|
||||
Region clip = sg2d.getCompClip();
|
||||
int cx1 = clip.getLoX();
|
||||
int cy1 = clip.getLoY();
|
||||
int cx2 = clip.getHiX();
|
||||
int cy2 = clip.getHiY();
|
||||
for (int i = 0; i < num; i++) {
|
||||
gl.setGlyphIndex(i);
|
||||
int metrics[] = gl.getMetrics();
|
||||
int gx1 = metrics[0];
|
||||
int gy1 = metrics[1];
|
||||
int w = metrics[2];
|
||||
int gx2 = gx1 + w;
|
||||
int gy2 = gy1 + metrics[3];
|
||||
int off = 0;
|
||||
if (gx1 < cx1) {
|
||||
off = cx1 - gx1;
|
||||
gx1 = cx1;
|
||||
}
|
||||
if (gy1 < cy1) {
|
||||
off += (cy1 - gy1) * w;
|
||||
gy1 = cy1;
|
||||
}
|
||||
if (gx2 > cx2) gx2 = cx2;
|
||||
if (gy2 > cy2) gy2 = cy2;
|
||||
if (gx2 > gx1 && gy2 > gy1) {
|
||||
byte alpha[] = gl.getGrayBits();
|
||||
maskop.MaskFill(sg2d, dest, sg2d.composite,
|
||||
gx1, gy1, gx2 - gx1, gy2 - gy1,
|
||||
alpha, off, w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return new TraceDrawGlyphList(this);
|
||||
}
|
||||
|
||||
private static class TraceDrawGlyphList extends DrawGlyphList {
|
||||
DrawGlyphList target;
|
||||
|
||||
public TraceDrawGlyphList(DrawGlyphList target) {
|
||||
super(target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void DrawGlyphList(SunGraphics2D sg2d, SurfaceData dest,
|
||||
GlyphList glyphs)
|
||||
{
|
||||
tracePrimitive(target);
|
||||
target.DrawGlyphList(sg2d, dest, glyphs);
|
||||
}
|
||||
}
|
||||
}
|
||||
159
jdkSrc/jdk8/sun/java2d/loops/DrawGlyphListAA.java
Normal file
159
jdkSrc/jdk8/sun/java2d/loops/DrawGlyphListAA.java
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.font.GlyphList;
|
||||
|
||||
/**
|
||||
* DrawGlyphListAA - loops for AATextRenderer pipe
|
||||
* 1) draw anti-aliased text onto destination surface
|
||||
* 2) must accept output area [x, y, dx, dy]
|
||||
* from within the surface description data for clip rect
|
||||
*/
|
||||
public class DrawGlyphListAA extends GraphicsPrimitive {
|
||||
|
||||
public final static String methodSignature = "DrawGlyphListAA(...)".toString();
|
||||
|
||||
public final static int primTypeID = makePrimTypeID();
|
||||
|
||||
public static DrawGlyphListAA locate(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return (DrawGlyphListAA)
|
||||
GraphicsPrimitiveMgr.locate(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
protected DrawGlyphListAA(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public DrawGlyphListAA(long pNativePrim,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(pNativePrim, methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public native void DrawGlyphListAA(SunGraphics2D sg2d, SurfaceData dest,
|
||||
GlyphList srcData);
|
||||
|
||||
static {
|
||||
GraphicsPrimitiveMgr.registerGeneral(
|
||||
new DrawGlyphListAA(null, null, null));
|
||||
}
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype) {
|
||||
return new General(srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public static class General extends DrawGlyphListAA {
|
||||
MaskFill maskop;
|
||||
|
||||
public General(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(srctype, comptype, dsttype);
|
||||
maskop = MaskFill.locate(srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public void DrawGlyphListAA(SunGraphics2D sg2d, SurfaceData dest,
|
||||
GlyphList gl)
|
||||
{
|
||||
gl.getBounds(); // Don't delete, bug 4895493
|
||||
int num = gl.getNumGlyphs();
|
||||
Region clip = sg2d.getCompClip();
|
||||
int cx1 = clip.getLoX();
|
||||
int cy1 = clip.getLoY();
|
||||
int cx2 = clip.getHiX();
|
||||
int cy2 = clip.getHiY();
|
||||
for (int i = 0; i < num; i++) {
|
||||
gl.setGlyphIndex(i);
|
||||
int metrics[] = gl.getMetrics();
|
||||
int gx1 = metrics[0];
|
||||
int gy1 = metrics[1];
|
||||
int w = metrics[2];
|
||||
int gx2 = gx1 + w;
|
||||
int gy2 = gy1 + metrics[3];
|
||||
int off = 0;
|
||||
if (gx1 < cx1) {
|
||||
off = cx1 - gx1;
|
||||
gx1 = cx1;
|
||||
}
|
||||
if (gy1 < cy1) {
|
||||
off += (cy1 - gy1) * w;
|
||||
gy1 = cy1;
|
||||
}
|
||||
if (gx2 > cx2) gx2 = cx2;
|
||||
if (gy2 > cy2) gy2 = cy2;
|
||||
if (gx2 > gx1 && gy2 > gy1) {
|
||||
byte alpha[] = gl.getGrayBits();
|
||||
maskop.MaskFill(sg2d, dest, sg2d.composite,
|
||||
gx1, gy1, gx2 - gx1, gy2 - gy1,
|
||||
alpha, off, w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return new TraceDrawGlyphListAA(this);
|
||||
}
|
||||
|
||||
private static class TraceDrawGlyphListAA extends DrawGlyphListAA {
|
||||
DrawGlyphListAA target;
|
||||
|
||||
public TraceDrawGlyphListAA(DrawGlyphListAA target) {
|
||||
super(target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void DrawGlyphListAA(SunGraphics2D sg2d, SurfaceData dest,
|
||||
GlyphList glyphs)
|
||||
{
|
||||
tracePrimitive(target);
|
||||
target.DrawGlyphListAA(sg2d, dest, glyphs);
|
||||
}
|
||||
}
|
||||
}
|
||||
117
jdkSrc/jdk8/sun/java2d/loops/DrawGlyphListLCD.java
Normal file
117
jdkSrc/jdk8/sun/java2d/loops/DrawGlyphListLCD.java
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.font.GlyphList;
|
||||
|
||||
/**
|
||||
* DrawGlyphListLCD- loops for LCDTextRenderer pipe
|
||||
* 1) draw LCD anti-aliased text onto destination surface
|
||||
* 2) must accept output area [x, y, dx, dy]
|
||||
* from within the surface description data for clip rect
|
||||
*/
|
||||
public class DrawGlyphListLCD extends GraphicsPrimitive {
|
||||
|
||||
public final static String
|
||||
methodSignature = "DrawGlyphListLCD(...)".toString();
|
||||
|
||||
public final static int primTypeID = makePrimTypeID();
|
||||
|
||||
public static DrawGlyphListLCD locate(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return (DrawGlyphListLCD)
|
||||
GraphicsPrimitiveMgr.locate(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
protected DrawGlyphListLCD(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public DrawGlyphListLCD(long pNativePrim,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(pNativePrim, methodSignature, primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public native void DrawGlyphListLCD(SunGraphics2D sg2d, SurfaceData dest,
|
||||
GlyphList srcData);
|
||||
|
||||
static {
|
||||
GraphicsPrimitiveMgr.registerGeneral(
|
||||
new DrawGlyphListLCD(null, null, null));
|
||||
}
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype) {
|
||||
/* Do not return a General loop. SunGraphics2D determines whether
|
||||
* to use LCD or standard AA text based on whether there is an
|
||||
* installed loop.
|
||||
* This can be uncommented once there is a General loop which can
|
||||
* handle one byte per colour component masks properly.
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return new TraceDrawGlyphListLCD(this);
|
||||
}
|
||||
|
||||
private static class TraceDrawGlyphListLCD extends DrawGlyphListLCD {
|
||||
DrawGlyphListLCD target;
|
||||
|
||||
public TraceDrawGlyphListLCD(DrawGlyphListLCD target) {
|
||||
super(target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void DrawGlyphListLCD(SunGraphics2D sg2d, SurfaceData dest,
|
||||
GlyphList glyphs)
|
||||
{
|
||||
tracePrimitive(target);
|
||||
target.DrawGlyphListLCD(sg2d, dest, glyphs);
|
||||
}
|
||||
}
|
||||
}
|
||||
114
jdkSrc/jdk8/sun/java2d/loops/DrawLine.java
Normal file
114
jdkSrc/jdk8/sun/java2d/loops/DrawLine.java
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2002, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Charlton Innovations, Inc.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import java.awt.Color;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.Raster;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
|
||||
/**
|
||||
* DrawLine
|
||||
* 1) draw solid color single width line onto destination surface
|
||||
* 2) must accept output area [x, y, dx, dy]
|
||||
* from within the surface description data for clip rect
|
||||
*/
|
||||
public class DrawLine extends GraphicsPrimitive
|
||||
{
|
||||
public final static String methodSignature = "DrawLine(...)".toString();
|
||||
|
||||
public final static int primTypeID = makePrimTypeID();
|
||||
|
||||
public static DrawLine locate(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return (DrawLine) GraphicsPrimitiveMgr.locate(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
protected DrawLine(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public DrawLine(long pNativePrim,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(pNativePrim, methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
/**
|
||||
* All DrawLine implementors must have this invoker method
|
||||
*/
|
||||
public native void DrawLine(SunGraphics2D sg2d, SurfaceData dest,
|
||||
int x1, int y1, int x2, int y2);
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
// REMIND: use FillSpans or converter object?
|
||||
throw new InternalError("DrawLine not implemented for "+
|
||||
srctype+" with "+comptype);
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return new TraceDrawLine(this);
|
||||
}
|
||||
|
||||
private static class TraceDrawLine extends DrawLine {
|
||||
DrawLine target;
|
||||
|
||||
public TraceDrawLine(DrawLine target) {
|
||||
super(target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void DrawLine(SunGraphics2D sg2d, SurfaceData dest,
|
||||
int x1, int y1, int x2, int y2)
|
||||
{
|
||||
tracePrimitive(target);
|
||||
target.DrawLine(sg2d, dest, x1, y1, x2, y2);
|
||||
}
|
||||
}
|
||||
}
|
||||
123
jdkSrc/jdk8/sun/java2d/loops/DrawParallelogram.java
Normal file
123
jdkSrc/jdk8/sun/java2d/loops/DrawParallelogram.java
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Jim Graham
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
|
||||
/**
|
||||
* DrawParallelogram
|
||||
* 1) fill the area between the 4 edges of an outer parallelogram
|
||||
* (as specified by an origin and 2 delta vectors)
|
||||
* but also outside the 4 edges of an inner parallelogram
|
||||
* (as specified by proportional amounts of the outer delta vectors)
|
||||
*/
|
||||
public class DrawParallelogram extends GraphicsPrimitive
|
||||
{
|
||||
public final static String methodSignature =
|
||||
"DrawParallelogram(...)".toString();
|
||||
|
||||
public final static int primTypeID = makePrimTypeID();
|
||||
|
||||
public static DrawParallelogram locate(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return (DrawParallelogram)
|
||||
GraphicsPrimitiveMgr.locate(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
protected DrawParallelogram(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(methodSignature, primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public DrawParallelogram(long pNativePrim,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(pNativePrim, methodSignature, primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
/**
|
||||
* All DrawParallelogram implementors must have this invoker method
|
||||
*/
|
||||
public native void DrawParallelogram(SunGraphics2D sg, SurfaceData dest,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double lw1, double lw2);
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
// REMIND: iterate with a FillRect primitive?
|
||||
throw new InternalError("DrawParallelogram not implemented for "+
|
||||
srctype+" with "+comptype);
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return new TraceDrawParallelogram(this);
|
||||
}
|
||||
|
||||
private static class TraceDrawParallelogram extends DrawParallelogram {
|
||||
DrawParallelogram target;
|
||||
|
||||
public TraceDrawParallelogram(DrawParallelogram target) {
|
||||
super(target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void DrawParallelogram(SunGraphics2D sg2d, SurfaceData dest,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double lw1, double lw2)
|
||||
{
|
||||
tracePrimitive(target);
|
||||
target.DrawParallelogram(sg2d, dest,
|
||||
x, y, dx1, dy1, dx2, dy2, lw1, lw2);
|
||||
}
|
||||
}
|
||||
}
|
||||
114
jdkSrc/jdk8/sun/java2d/loops/DrawPath.java
Normal file
114
jdkSrc/jdk8/sun/java2d/loops/DrawPath.java
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import java.awt.geom.Path2D;
|
||||
|
||||
/**
|
||||
* DrawPath
|
||||
* 1. draw single-width line path onto destination surface
|
||||
* 2. must accept output area [x, y, dx, dy]
|
||||
* from within the surface description data for clip rect
|
||||
*/
|
||||
public class DrawPath extends GraphicsPrimitive {
|
||||
|
||||
public final static String methodSignature =
|
||||
"DrawPath(...)".toString();
|
||||
|
||||
public final static int primTypeID = makePrimTypeID();
|
||||
|
||||
public static DrawPath locate(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return (DrawPath)
|
||||
GraphicsPrimitiveMgr.locate(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
protected DrawPath(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(methodSignature, primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public DrawPath(long pNativePrim,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(pNativePrim, methodSignature, primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* All DrawPath implementors must have this invoker method
|
||||
*/
|
||||
public native void DrawPath(SunGraphics2D sg2d, SurfaceData sData,
|
||||
int transX, int transY,
|
||||
Path2D.Float p2df);
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
throw new InternalError("DrawPath not implemented for "+
|
||||
srctype+" with "+comptype);
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return new TraceDrawPath(this);
|
||||
}
|
||||
|
||||
private static class TraceDrawPath extends DrawPath {
|
||||
DrawPath target;
|
||||
|
||||
public TraceDrawPath(DrawPath target) {
|
||||
super(target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void DrawPath(SunGraphics2D sg2d, SurfaceData sData,
|
||||
int transX, int transY,
|
||||
Path2D.Float p2df)
|
||||
{
|
||||
tracePrimitive(target);
|
||||
target.DrawPath(sg2d, sData, transX, transY, p2df);
|
||||
}
|
||||
}
|
||||
}
|
||||
120
jdkSrc/jdk8/sun/java2d/loops/DrawPolygons.java
Normal file
120
jdkSrc/jdk8/sun/java2d/loops/DrawPolygons.java
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2002, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Charlton Innovations, Inc.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
|
||||
/**
|
||||
* DrawPolygons
|
||||
* 1) draw single-width line polygons onto destination surface
|
||||
* 2) must accept output area [x, y, dx, dy]
|
||||
* from within the surface description data for clip rect
|
||||
*/
|
||||
public class DrawPolygons extends GraphicsPrimitive
|
||||
{
|
||||
public final static String methodSignature = "DrawPolygons(...)".toString();
|
||||
|
||||
public final static int primTypeID = makePrimTypeID();
|
||||
|
||||
public static DrawPolygons locate(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return (DrawPolygons)
|
||||
GraphicsPrimitiveMgr.locate(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
protected DrawPolygons(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public DrawPolygons(long pNativePrim,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(pNativePrim, methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
/**
|
||||
* All DrawPolygon implementors must have this invoker method
|
||||
*/
|
||||
public native void DrawPolygons(SunGraphics2D sg2d, SurfaceData sData,
|
||||
int xPoints[], int yPoints[],
|
||||
int nPoints[], int numPolys,
|
||||
int transX, int transY,
|
||||
boolean close);
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
// REMIND: use FillSpans or converter object?
|
||||
throw new InternalError("DrawPolygons not implemented for "+
|
||||
srctype+" with "+comptype);
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return new TraceDrawPolygons(this);
|
||||
}
|
||||
|
||||
private static class TraceDrawPolygons extends DrawPolygons {
|
||||
DrawPolygons target;
|
||||
|
||||
public TraceDrawPolygons(DrawPolygons target) {
|
||||
super(target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void DrawPolygons(SunGraphics2D sg2d, SurfaceData sData,
|
||||
int xPoints[], int yPoints[],
|
||||
int nPoints[], int numPolys,
|
||||
int transX, int transY,
|
||||
boolean close)
|
||||
{
|
||||
tracePrimitive(target);
|
||||
target.DrawPolygons(sg2d, sData,
|
||||
xPoints, yPoints, nPoints, numPolys,
|
||||
transX, transY, close);
|
||||
}
|
||||
}
|
||||
}
|
||||
115
jdkSrc/jdk8/sun/java2d/loops/DrawRect.java
Normal file
115
jdkSrc/jdk8/sun/java2d/loops/DrawRect.java
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2002, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Charlton Innovations, Inc.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import java.awt.Color;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.Raster;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
|
||||
/**
|
||||
* DrawRect
|
||||
* 1) draw single-width line rectangle onto destination surface
|
||||
* 2) must accept output area [x, y, dx, dy]
|
||||
* from within the surface description data for clip rect
|
||||
*/
|
||||
public class DrawRect extends GraphicsPrimitive
|
||||
{
|
||||
public final static String methodSignature = "DrawRect(...)".toString();
|
||||
|
||||
public final static int primTypeID = makePrimTypeID();
|
||||
|
||||
public static DrawRect locate(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return (DrawRect)
|
||||
GraphicsPrimitiveMgr.locate(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
protected DrawRect(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public DrawRect(long pNativePrim,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(pNativePrim, methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
/**
|
||||
* All DrawRect implementors must have this invoker method
|
||||
*/
|
||||
public native void DrawRect(SunGraphics2D sg2d, SurfaceData dest,
|
||||
int x1, int y1, int w, int h);
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
// REMIND: use FillSpans or converter object?
|
||||
throw new InternalError("DrawRect not implemented for "+
|
||||
srctype+" with "+comptype);
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return new TraceDrawRect(this);
|
||||
}
|
||||
|
||||
private static class TraceDrawRect extends DrawRect {
|
||||
DrawRect target;
|
||||
|
||||
public TraceDrawRect(DrawRect target) {
|
||||
super(target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void DrawRect(SunGraphics2D sg2d, SurfaceData dest,
|
||||
int x1, int y1, int w, int h)
|
||||
{
|
||||
tracePrimitive(target);
|
||||
target.DrawRect(sg2d, dest, x1, y1, w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
118
jdkSrc/jdk8/sun/java2d/loops/FillParallelogram.java
Normal file
118
jdkSrc/jdk8/sun/java2d/loops/FillParallelogram.java
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Jim Graham
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
|
||||
/**
|
||||
* FillParallelogram
|
||||
* 1) fill the area between the 4 edges of a parallelogram
|
||||
* (as specified by an origin and 2 delta vectors)
|
||||
*/
|
||||
public class FillParallelogram extends GraphicsPrimitive
|
||||
{
|
||||
public final static String methodSignature =
|
||||
"FillParallelogram(...)".toString();
|
||||
|
||||
public final static int primTypeID = makePrimTypeID();
|
||||
|
||||
public static FillParallelogram locate(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return (FillParallelogram)
|
||||
GraphicsPrimitiveMgr.locate(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
protected FillParallelogram(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(methodSignature, primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public FillParallelogram(long pNativePrim,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(pNativePrim, methodSignature, primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
/**
|
||||
* All FillParallelogram implementors must have this invoker method
|
||||
*/
|
||||
public native void FillParallelogram(SunGraphics2D sg2d, SurfaceData dest,
|
||||
double x0, double y0,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2);
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
// REMIND: iterate with a FillRect primitive?
|
||||
throw new InternalError("FillParallelogram not implemented for "+
|
||||
srctype+" with "+comptype);
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return new TraceFillParallelogram(this);
|
||||
}
|
||||
|
||||
private static class TraceFillParallelogram extends FillParallelogram {
|
||||
FillParallelogram target;
|
||||
|
||||
public TraceFillParallelogram(FillParallelogram target) {
|
||||
super(target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void FillParallelogram(SunGraphics2D sg2d, SurfaceData dest,
|
||||
double x0, double y0,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
tracePrimitive(target);
|
||||
target.FillParallelogram(sg2d, dest, x0, y0, dx1, dy1, dx2, dy2);
|
||||
}
|
||||
}
|
||||
}
|
||||
114
jdkSrc/jdk8/sun/java2d/loops/FillPath.java
Normal file
114
jdkSrc/jdk8/sun/java2d/loops/FillPath.java
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import java.awt.geom.Path2D;
|
||||
|
||||
/**
|
||||
* FillPath
|
||||
* 1. fill path onto destination surface
|
||||
* 2. must accept output area [x, y, dx, dy]
|
||||
* from within the surface description data for clip rect
|
||||
*/
|
||||
public class FillPath extends GraphicsPrimitive {
|
||||
|
||||
public final static String methodSignature =
|
||||
"FillPath(...)".toString();
|
||||
|
||||
public final static int primTypeID = makePrimTypeID();
|
||||
|
||||
public static FillPath locate(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return (FillPath)
|
||||
GraphicsPrimitiveMgr.locate(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
protected FillPath(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(methodSignature, primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public FillPath(long pNativePrim,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(pNativePrim, methodSignature, primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* All FillPath implementors must have this invoker method
|
||||
*/
|
||||
public native void FillPath(SunGraphics2D sg2d, SurfaceData sData,
|
||||
int transX, int transY,
|
||||
Path2D.Float p2df);
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
throw new InternalError("FillPath not implemented for "+
|
||||
srctype+" with "+comptype);
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return new TraceFillPath(this);
|
||||
}
|
||||
|
||||
private static class TraceFillPath extends FillPath {
|
||||
FillPath target;
|
||||
|
||||
public TraceFillPath(FillPath target) {
|
||||
super(target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void FillPath(SunGraphics2D sg2d, SurfaceData sData,
|
||||
int transX, int transY,
|
||||
Path2D.Float p2df)
|
||||
{
|
||||
tracePrimitive(target);
|
||||
target.FillPath(sg2d, sData, transX, transY, p2df);
|
||||
}
|
||||
}
|
||||
}
|
||||
135
jdkSrc/jdk8/sun/java2d/loops/FillRect.java
Normal file
135
jdkSrc/jdk8/sun/java2d/loops/FillRect.java
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2002, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Charlton Innovations, Inc.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import java.awt.Color;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.Raster;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
|
||||
/**
|
||||
* FillRect
|
||||
* 1) draw solid color rectangle onto destination surface
|
||||
* 2) must accept output area [x, y, dx, dy]
|
||||
* from within the surface description data for clip rect
|
||||
*/
|
||||
public class FillRect extends GraphicsPrimitive
|
||||
{
|
||||
public final static String methodSignature = "FillRect(...)".toString();
|
||||
|
||||
public final static int primTypeID = makePrimTypeID();
|
||||
|
||||
public static FillRect locate(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return (FillRect)
|
||||
GraphicsPrimitiveMgr.locate(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
protected FillRect(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public FillRect(long pNativePrim,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(pNativePrim, methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
/**
|
||||
* All FillRect implementors must have this invoker method
|
||||
*/
|
||||
public native void FillRect(SunGraphics2D sg2d, SurfaceData dest,
|
||||
int x, int y, int w, int h);
|
||||
|
||||
static {
|
||||
GraphicsPrimitiveMgr.registerGeneral(new FillRect(null, null, null));
|
||||
}
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return new General(srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public static class General extends FillRect {
|
||||
public MaskFill fillop;
|
||||
|
||||
public General(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(srctype, comptype, dsttype);
|
||||
fillop = MaskFill.locate(srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public void FillRect(SunGraphics2D sg2d, SurfaceData dest,
|
||||
int x, int y, int w, int h)
|
||||
{
|
||||
fillop.MaskFill(sg2d, dest, sg2d.composite, x, y, w, h, null, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return new TraceFillRect(this);
|
||||
}
|
||||
|
||||
private static class TraceFillRect extends FillRect {
|
||||
FillRect target;
|
||||
|
||||
public TraceFillRect(FillRect target) {
|
||||
super(target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void FillRect(SunGraphics2D sg2d, SurfaceData dest,
|
||||
int x, int y, int w, int h)
|
||||
{
|
||||
tracePrimitive(target);
|
||||
target.FillRect(sg2d, dest, x, y, w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
122
jdkSrc/jdk8/sun/java2d/loops/FillSpans.java
Normal file
122
jdkSrc/jdk8/sun/java2d/loops/FillSpans.java
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2002, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Jim Graham
|
||||
* @author Charlton Innovations, Inc.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.pipe.SpanIterator;
|
||||
import java.awt.Color;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.Raster;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
|
||||
/**
|
||||
* FillSpans
|
||||
* 1) draw solid color onto destination surface
|
||||
* 2) rectangular areas to fill come from SpanIterator
|
||||
*/
|
||||
public class FillSpans extends GraphicsPrimitive
|
||||
{
|
||||
public final static String methodSignature = "FillSpans(...)".toString();
|
||||
|
||||
public final static int primTypeID = makePrimTypeID();
|
||||
|
||||
public static FillSpans locate(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return (FillSpans)
|
||||
GraphicsPrimitiveMgr.locate(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
protected FillSpans(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public FillSpans(long pNativePrim,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(pNativePrim, methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
private native void FillSpans(SunGraphics2D sg2d, SurfaceData dest,
|
||||
int pixel, long pIterator, SpanIterator si);
|
||||
|
||||
/**
|
||||
* All FillSpan implementors must have this invoker method
|
||||
*/
|
||||
public void FillSpans(SunGraphics2D sg2d, SurfaceData dest,
|
||||
SpanIterator si)
|
||||
{
|
||||
FillSpans(sg2d, dest, sg2d.pixel, si.getNativeIterator(), si);
|
||||
}
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
// REMIND: iterate with a FillRect primitive?
|
||||
throw new InternalError("FillSpans not implemented for "+
|
||||
srctype+" with "+comptype);
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return new TraceFillSpans(this);
|
||||
}
|
||||
|
||||
private static class TraceFillSpans extends FillSpans {
|
||||
FillSpans target;
|
||||
|
||||
public TraceFillSpans(FillSpans target) {
|
||||
super(target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void FillSpans(SunGraphics2D sg2d, SurfaceData dest,
|
||||
SpanIterator si)
|
||||
{
|
||||
tracePrimitive(target);
|
||||
target.FillSpans(sg2d, dest, si);
|
||||
}
|
||||
}
|
||||
}
|
||||
89
jdkSrc/jdk8/sun/java2d/loops/FontInfo.java
Normal file
89
jdkSrc/jdk8/sun/java2d/loops/FontInfo.java
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.geom.AffineTransform;
|
||||
|
||||
import sun.font.Font2D;
|
||||
import sun.font.FontStrike;
|
||||
import sun.font.FontStrikeDesc;
|
||||
|
||||
/*
|
||||
* A FontInfo object holds all calculated or derived data needed
|
||||
* to handle rendering operations based on a particular set of
|
||||
* Graphics2D rendering attributes.
|
||||
* Note that this does not use a Font2DHandle, and also has a reference
|
||||
* to the strike which also references the Font2D.
|
||||
* So presently, until SG2D objects no longer reference this FontInfo,
|
||||
* there is still some potential for a bad Font2D to be used for a short
|
||||
* time. I am reluctant to add the overhead of that machinery here without
|
||||
* a proven benefit.
|
||||
*/
|
||||
public class FontInfo implements Cloneable {
|
||||
public Font font;
|
||||
public Font2D font2D;
|
||||
public FontStrike fontStrike;
|
||||
public double[] devTx;
|
||||
public double[] glyphTx;
|
||||
public int pixelHeight;
|
||||
public float originX;
|
||||
public float originY;
|
||||
public int aaHint;
|
||||
public boolean lcdRGBOrder;
|
||||
/* lcdSubPixPos is used if FM is ON for HRGB/HBGR LCD text mode */
|
||||
public boolean lcdSubPixPos;
|
||||
|
||||
public String mtx(double[] matrix) {
|
||||
return ("["+
|
||||
matrix[0]+", "+
|
||||
matrix[1]+", "+
|
||||
matrix[2]+", "+
|
||||
matrix[3]+
|
||||
"]");
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
try {
|
||||
return super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return ("FontInfo["+
|
||||
"font="+font+", "+
|
||||
"devTx="+mtx(devTx)+", "+
|
||||
"glyphTx="+mtx(glyphTx)+", "+
|
||||
"pixelHeight="+pixelHeight+", "+
|
||||
"origin=("+originX+","+originY+"), "+
|
||||
"aaHint="+aaHint+", "+
|
||||
"lcdRGBOrder="+(lcdRGBOrder ? "RGB" : "BGR")+
|
||||
"lcdSubPixPos="+lcdSubPixPos+
|
||||
"]");
|
||||
}
|
||||
}
|
||||
1125
jdkSrc/jdk8/sun/java2d/loops/GeneralRenderer.java
Normal file
1125
jdkSrc/jdk8/sun/java2d/loops/GeneralRenderer.java
Normal file
File diff suppressed because it is too large
Load Diff
623
jdkSrc/jdk8/sun/java2d/loops/GraphicsPrimitive.java
Normal file
623
jdkSrc/jdk8/sun/java2d/loops/GraphicsPrimitive.java
Normal file
@@ -0,0 +1,623 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Charlton Innovations, Inc.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Rectangle;
|
||||
import sun.awt.image.BufImgSurfaceData;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.pipe.Region;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.Iterator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.io.PrintStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
* defines interface for primitives which can be placed into
|
||||
* the graphic component manager framework
|
||||
*/
|
||||
public abstract class GraphicsPrimitive {
|
||||
|
||||
protected static interface GeneralBinaryOp {
|
||||
/**
|
||||
* This method allows the setupGeneralBinaryOp method to set
|
||||
* the converters into the General version of the Primitive.
|
||||
*/
|
||||
public void setPrimitives(Blit srcconverter,
|
||||
Blit dstconverter,
|
||||
GraphicsPrimitive genericop,
|
||||
Blit resconverter);
|
||||
|
||||
/**
|
||||
* These 4 methods are implemented automatically for any
|
||||
* GraphicsPrimitive. They are used by setupGeneralBinaryOp
|
||||
* to retrieve the information needed to find the right
|
||||
* converter primitives.
|
||||
*/
|
||||
public SurfaceType getSourceType();
|
||||
public CompositeType getCompositeType();
|
||||
public SurfaceType getDestType();
|
||||
public String getSignature();
|
||||
public int getPrimTypeID();
|
||||
}
|
||||
|
||||
protected static interface GeneralUnaryOp {
|
||||
/**
|
||||
* This method allows the setupGeneralUnaryOp method to set
|
||||
* the converters into the General version of the Primitive.
|
||||
*/
|
||||
public void setPrimitives(Blit dstconverter,
|
||||
GraphicsPrimitive genericop,
|
||||
Blit resconverter);
|
||||
|
||||
/**
|
||||
* These 3 methods are implemented automatically for any
|
||||
* GraphicsPrimitive. They are used by setupGeneralUnaryOp
|
||||
* to retrieve the information needed to find the right
|
||||
* converter primitives.
|
||||
*/
|
||||
public CompositeType getCompositeType();
|
||||
public SurfaceType getDestType();
|
||||
public String getSignature();
|
||||
public int getPrimTypeID();
|
||||
}
|
||||
|
||||
/**
|
||||
* INSTANCE DATA MEMBERS DESCRIBING CHARACTERISTICS OF THIS PRIMITIVE
|
||||
**/
|
||||
|
||||
// Making these be instance data members (instead of virtual methods
|
||||
// overridden by subclasses) is actually cheaper, since each class
|
||||
// is a singleton. As instance data members with final accessors,
|
||||
// accesses can be inlined.
|
||||
private String methodSignature;
|
||||
private int uniqueID;
|
||||
private static int unusedPrimID = 1;
|
||||
|
||||
private SurfaceType sourceType;
|
||||
private CompositeType compositeType;
|
||||
private SurfaceType destType;
|
||||
|
||||
private long pNativePrim; // Native blit loop info
|
||||
|
||||
public synchronized static final int makePrimTypeID() {
|
||||
if (unusedPrimID > 255) {
|
||||
throw new InternalError("primitive id overflow");
|
||||
}
|
||||
return unusedPrimID++;
|
||||
}
|
||||
|
||||
public synchronized static final int makeUniqueID(int primTypeID,
|
||||
SurfaceType src,
|
||||
CompositeType cmp,
|
||||
SurfaceType dst)
|
||||
{
|
||||
return (primTypeID << 24) |
|
||||
(dst.getUniqueID() << 16) |
|
||||
(cmp.getUniqueID() << 8) |
|
||||
(src.getUniqueID());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new GraphicsPrimitive with all of the required
|
||||
* descriptive information.
|
||||
*/
|
||||
protected GraphicsPrimitive(String methodSignature,
|
||||
int primTypeID,
|
||||
SurfaceType sourceType,
|
||||
CompositeType compositeType,
|
||||
SurfaceType destType)
|
||||
{
|
||||
this.methodSignature = methodSignature;
|
||||
this.sourceType = sourceType;
|
||||
this.compositeType = compositeType;
|
||||
this.destType = destType;
|
||||
|
||||
if(sourceType == null || compositeType == null || destType == null) {
|
||||
this.uniqueID = primTypeID << 24;
|
||||
} else {
|
||||
this.uniqueID = GraphicsPrimitive.makeUniqueID(primTypeID,
|
||||
sourceType,
|
||||
compositeType,
|
||||
destType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new GraphicsPrimitive for native invocation
|
||||
* with all of the required descriptive information.
|
||||
*/
|
||||
protected GraphicsPrimitive(long pNativePrim,
|
||||
String methodSignature,
|
||||
int primTypeID,
|
||||
SurfaceType sourceType,
|
||||
CompositeType compositeType,
|
||||
SurfaceType destType)
|
||||
{
|
||||
this.pNativePrim = pNativePrim;
|
||||
this.methodSignature = methodSignature;
|
||||
this.sourceType = sourceType;
|
||||
this.compositeType = compositeType;
|
||||
this.destType = destType;
|
||||
|
||||
if(sourceType == null || compositeType == null || destType == null) {
|
||||
this.uniqueID = primTypeID << 24;
|
||||
} else {
|
||||
this.uniqueID = GraphicsPrimitive.makeUniqueID(primTypeID,
|
||||
sourceType,
|
||||
compositeType,
|
||||
destType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* METHODS TO DESCRIBE THE SURFACES PRIMITIVES
|
||||
* CAN OPERATE ON AND THE FUNCTIONALITY THEY IMPLEMENT
|
||||
**/
|
||||
|
||||
/**
|
||||
* Gets instance ID of this graphics primitive.
|
||||
*
|
||||
* Instance ID is comprised of four distinct ids (ORed together)
|
||||
* that uniquely identify each instance of a GraphicsPrimitive
|
||||
* object. The four ids making up instance ID are:
|
||||
* 1. primitive id - identifier shared by all primitives of the
|
||||
* same type (eg. all Blits have the same primitive id)
|
||||
* 2. sourcetype id - identifies source surface type
|
||||
* 3. desttype id - identifies destination surface type
|
||||
* 4. compositetype id - identifies composite used
|
||||
*
|
||||
* @return instance ID
|
||||
*/
|
||||
public final int getUniqueID() {
|
||||
return uniqueID;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public final String getSignature() {
|
||||
return methodSignature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets unique id for this GraphicsPrimitive type.
|
||||
*
|
||||
* This id is used to identify the TYPE of primitive (Blit vs. BlitBg)
|
||||
* as opposed to INSTANCE of primitive.
|
||||
*
|
||||
* @return primitive ID
|
||||
*/
|
||||
public final int getPrimTypeID() {
|
||||
return uniqueID >>> 24;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public final long getNativePrim() {
|
||||
return pNativePrim;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public final SurfaceType getSourceType() {
|
||||
return sourceType;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public final CompositeType getCompositeType() {
|
||||
return compositeType;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public final SurfaceType getDestType() {
|
||||
return destType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this primitive can be used for the given signature
|
||||
* surfaces, and composite.
|
||||
*
|
||||
* @param signature The signature of the given operation. Must be
|
||||
* == (not just .equals) the signature string given by the
|
||||
* abstract class that declares the operation.
|
||||
* @param srctype The surface type for the source of the operation
|
||||
* @param comptype The composite type for the operation
|
||||
* @param dsttype The surface type for the destination of the operation
|
||||
*/
|
||||
public final boolean satisfies(String signature,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
if (signature != methodSignature) {
|
||||
return false;
|
||||
}
|
||||
while (true) {
|
||||
if (srctype == null) {
|
||||
return false;
|
||||
}
|
||||
if (srctype.equals(sourceType)) {
|
||||
break;
|
||||
}
|
||||
srctype = srctype.getSuperType();
|
||||
}
|
||||
while (true) {
|
||||
if (comptype == null) {
|
||||
return false;
|
||||
}
|
||||
if (comptype.equals(compositeType)) {
|
||||
break;
|
||||
}
|
||||
comptype = comptype.getSuperType();
|
||||
}
|
||||
while (true) {
|
||||
if (dsttype == null) {
|
||||
return false;
|
||||
}
|
||||
if (dsttype.equals(destType)) {
|
||||
break;
|
||||
}
|
||||
dsttype = dsttype.getSuperType();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// A version of satisfies used for regression testing
|
||||
//
|
||||
final boolean satisfiesSameAs(GraphicsPrimitive other) {
|
||||
return (methodSignature == other.methodSignature &&
|
||||
sourceType.equals(other.sourceType) &&
|
||||
compositeType.equals(other.compositeType) &&
|
||||
destType.equals(other.destType));
|
||||
}
|
||||
|
||||
public abstract GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype);
|
||||
|
||||
public abstract GraphicsPrimitive traceWrap();
|
||||
|
||||
static HashMap traceMap;
|
||||
|
||||
public static int traceflags;
|
||||
public static String tracefile;
|
||||
public static PrintStream traceout;
|
||||
|
||||
public static final int TRACELOG = 1;
|
||||
public static final int TRACETIMESTAMP = 2;
|
||||
public static final int TRACECOUNTS = 4;
|
||||
|
||||
static {
|
||||
GetPropertyAction gpa = new GetPropertyAction("sun.java2d.trace");
|
||||
String trace = AccessController.doPrivileged(gpa);
|
||||
if (trace != null) {
|
||||
boolean verbose = false;
|
||||
int traceflags = 0;
|
||||
StringTokenizer st = new StringTokenizer(trace, ",");
|
||||
while (st.hasMoreTokens()) {
|
||||
String tok = st.nextToken();
|
||||
if (tok.equalsIgnoreCase("count")) {
|
||||
traceflags |= GraphicsPrimitive.TRACECOUNTS;
|
||||
} else if (tok.equalsIgnoreCase("log")) {
|
||||
traceflags |= GraphicsPrimitive.TRACELOG;
|
||||
} else if (tok.equalsIgnoreCase("timestamp")) {
|
||||
traceflags |= GraphicsPrimitive.TRACETIMESTAMP;
|
||||
} else if (tok.equalsIgnoreCase("verbose")) {
|
||||
verbose = true;
|
||||
} else if (tok.regionMatches(true, 0, "out:", 0, 4)) {
|
||||
tracefile = tok.substring(4);
|
||||
} else {
|
||||
if (!tok.equalsIgnoreCase("help")) {
|
||||
System.err.println("unrecognized token: "+tok);
|
||||
}
|
||||
System.err.println("usage: -Dsun.java2d.trace="+
|
||||
"[log[,timestamp]],[count],"+
|
||||
"[out:<filename>],[help],[verbose]");
|
||||
}
|
||||
}
|
||||
if (verbose) {
|
||||
System.err.print("GraphicsPrimitive logging ");
|
||||
if ((traceflags & GraphicsPrimitive.TRACELOG) != 0) {
|
||||
System.err.println("enabled");
|
||||
System.err.print("GraphicsPrimitive timetamps ");
|
||||
if ((traceflags & GraphicsPrimitive.TRACETIMESTAMP) != 0) {
|
||||
System.err.println("enabled");
|
||||
} else {
|
||||
System.err.println("disabled");
|
||||
}
|
||||
} else {
|
||||
System.err.println("[and timestamps] disabled");
|
||||
}
|
||||
System.err.print("GraphicsPrimitive invocation counts ");
|
||||
if ((traceflags & GraphicsPrimitive.TRACECOUNTS) != 0) {
|
||||
System.err.println("enabled");
|
||||
} else {
|
||||
System.err.println("disabled");
|
||||
}
|
||||
System.err.print("GraphicsPrimitive trace output to ");
|
||||
if (tracefile == null) {
|
||||
System.err.println("System.err");
|
||||
} else {
|
||||
System.err.println("file '"+tracefile+"'");
|
||||
}
|
||||
}
|
||||
GraphicsPrimitive.traceflags = traceflags;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean tracingEnabled() {
|
||||
return (traceflags != 0);
|
||||
}
|
||||
|
||||
private static PrintStream getTraceOutputFile() {
|
||||
if (traceout == null) {
|
||||
if (tracefile != null) {
|
||||
FileOutputStream o = AccessController.doPrivileged(
|
||||
new PrivilegedAction<FileOutputStream>() {
|
||||
public FileOutputStream run() {
|
||||
try {
|
||||
return new FileOutputStream(tracefile);
|
||||
} catch (FileNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (o != null) {
|
||||
traceout = new PrintStream(o);
|
||||
} else {
|
||||
traceout = System.err;
|
||||
}
|
||||
} else {
|
||||
traceout = System.err;
|
||||
}
|
||||
}
|
||||
return traceout;
|
||||
}
|
||||
|
||||
public static class TraceReporter extends Thread {
|
||||
public static void setShutdownHook() {
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
TraceReporter t = new TraceReporter();
|
||||
t.setContextClassLoader(null);
|
||||
Runtime.getRuntime().addShutdownHook(t);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void run() {
|
||||
PrintStream ps = getTraceOutputFile();
|
||||
Iterator iterator = traceMap.entrySet().iterator();
|
||||
long total = 0;
|
||||
int numprims = 0;
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry me = (Map.Entry) iterator.next();
|
||||
Object prim = me.getKey();
|
||||
int[] count = (int[]) me.getValue();
|
||||
if (count[0] == 1) {
|
||||
ps.print("1 call to ");
|
||||
} else {
|
||||
ps.print(count[0]+" calls to ");
|
||||
}
|
||||
ps.println(prim);
|
||||
numprims++;
|
||||
total += count[0];
|
||||
}
|
||||
if (numprims == 0) {
|
||||
ps.println("No graphics primitives executed");
|
||||
} else if (numprims > 1) {
|
||||
ps.println(total+" total calls to "+
|
||||
numprims+" different primitives");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized static void tracePrimitive(Object prim) {
|
||||
if ((traceflags & TRACECOUNTS) != 0) {
|
||||
if (traceMap == null) {
|
||||
traceMap = new HashMap();
|
||||
TraceReporter.setShutdownHook();
|
||||
}
|
||||
Object o = traceMap.get(prim);
|
||||
if (o == null) {
|
||||
o = new int[1];
|
||||
traceMap.put(prim, o);
|
||||
}
|
||||
((int[]) o)[0]++;
|
||||
}
|
||||
if ((traceflags & TRACELOG) != 0) {
|
||||
PrintStream ps = getTraceOutputFile();
|
||||
if ((traceflags & TRACETIMESTAMP) != 0) {
|
||||
ps.print(System.currentTimeMillis()+": ");
|
||||
}
|
||||
ps.println(prim);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setupGeneralBinaryOp(GeneralBinaryOp gbo) {
|
||||
int primID = gbo.getPrimTypeID();
|
||||
String methodSignature = gbo.getSignature();
|
||||
SurfaceType srctype = gbo.getSourceType();
|
||||
CompositeType comptype = gbo.getCompositeType();
|
||||
SurfaceType dsttype = gbo.getDestType();
|
||||
Blit convertsrc, convertdst, convertres;
|
||||
GraphicsPrimitive performop;
|
||||
|
||||
convertsrc = createConverter(srctype, SurfaceType.IntArgb);
|
||||
performop = GraphicsPrimitiveMgr.locatePrim(primID,
|
||||
SurfaceType.IntArgb,
|
||||
comptype, dsttype);
|
||||
if (performop != null) {
|
||||
convertdst = null;
|
||||
convertres = null;
|
||||
} else {
|
||||
performop = getGeneralOp(primID, comptype);
|
||||
if (performop == null) {
|
||||
throw new InternalError("Cannot construct general op for "+
|
||||
methodSignature+" "+comptype);
|
||||
}
|
||||
convertdst = createConverter(dsttype, SurfaceType.IntArgb);
|
||||
convertres = createConverter(SurfaceType.IntArgb, dsttype);
|
||||
}
|
||||
|
||||
gbo.setPrimitives(convertsrc, convertdst, performop, convertres);
|
||||
}
|
||||
|
||||
protected void setupGeneralUnaryOp(GeneralUnaryOp guo) {
|
||||
int primID = guo.getPrimTypeID();
|
||||
String methodSignature = guo.getSignature();
|
||||
CompositeType comptype = guo.getCompositeType();
|
||||
SurfaceType dsttype = guo.getDestType();
|
||||
|
||||
Blit convertdst = createConverter(dsttype, SurfaceType.IntArgb);
|
||||
GraphicsPrimitive performop = getGeneralOp(primID, comptype);
|
||||
Blit convertres = createConverter(SurfaceType.IntArgb, dsttype);
|
||||
if (convertdst == null || performop == null || convertres == null) {
|
||||
throw new InternalError("Cannot construct binary op for "+
|
||||
comptype+" "+dsttype);
|
||||
}
|
||||
|
||||
guo.setPrimitives(convertdst, performop, convertres);
|
||||
}
|
||||
|
||||
protected static Blit createConverter(SurfaceType srctype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
if (srctype.equals(dsttype)) {
|
||||
return null;
|
||||
}
|
||||
Blit cv = Blit.getFromCache(srctype, CompositeType.SrcNoEa, dsttype);
|
||||
if (cv == null) {
|
||||
throw new InternalError("Cannot construct converter for "+
|
||||
srctype+"=>"+dsttype);
|
||||
}
|
||||
return cv;
|
||||
}
|
||||
|
||||
protected static SurfaceData convertFrom(Blit ob, SurfaceData srcData,
|
||||
int srcX, int srcY, int w, int h,
|
||||
SurfaceData dstData)
|
||||
{
|
||||
return convertFrom(ob, srcData,
|
||||
srcX, srcY, w, h, dstData,
|
||||
BufferedImage.TYPE_INT_ARGB);
|
||||
}
|
||||
|
||||
protected static SurfaceData convertFrom(Blit ob, SurfaceData srcData,
|
||||
int srcX, int srcY, int w, int h,
|
||||
SurfaceData dstData, int type)
|
||||
{
|
||||
if (dstData != null) {
|
||||
Rectangle r = dstData.getBounds();
|
||||
if (w > r.width || h > r.height) {
|
||||
dstData = null;
|
||||
}
|
||||
}
|
||||
if (dstData == null) {
|
||||
BufferedImage dstBI = new BufferedImage(w, h, type);
|
||||
dstData = BufImgSurfaceData.createData(dstBI);
|
||||
}
|
||||
ob.Blit(srcData, dstData, AlphaComposite.Src, null,
|
||||
srcX, srcY, 0, 0, w, h);
|
||||
return dstData;
|
||||
}
|
||||
|
||||
protected static void convertTo(Blit ob,
|
||||
SurfaceData srcImg, SurfaceData dstImg,
|
||||
Region clip,
|
||||
int dstX, int dstY, int w, int h)
|
||||
{
|
||||
if (ob != null) {
|
||||
ob.Blit(srcImg, dstImg, AlphaComposite.Src, clip,
|
||||
0, 0, dstX, dstY, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
protected static GraphicsPrimitive getGeneralOp(int primID,
|
||||
CompositeType comptype)
|
||||
{
|
||||
return GraphicsPrimitiveMgr.locatePrim(primID,
|
||||
SurfaceType.IntArgb,
|
||||
comptype,
|
||||
SurfaceType.IntArgb);
|
||||
}
|
||||
|
||||
public static String simplename(Field[] fields, Object o) {
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
Field f = fields[i];
|
||||
try {
|
||||
if (o == f.get(null)) {
|
||||
return f.getName();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
return "\""+o.toString()+"\"";
|
||||
}
|
||||
|
||||
public static String simplename(SurfaceType st) {
|
||||
return simplename(SurfaceType.class.getDeclaredFields(), st);
|
||||
}
|
||||
|
||||
public static String simplename(CompositeType ct) {
|
||||
return simplename(CompositeType.class.getDeclaredFields(), ct);
|
||||
}
|
||||
|
||||
private String cachedname;
|
||||
|
||||
public String toString() {
|
||||
if (cachedname == null) {
|
||||
String sig = methodSignature;
|
||||
int index = sig.indexOf('(');
|
||||
if (index >= 0) {
|
||||
sig = sig.substring(0, index);
|
||||
}
|
||||
cachedname = (getClass().getName()+"::"+
|
||||
sig+"("+
|
||||
simplename(sourceType)+", "+
|
||||
simplename(compositeType)+", "+
|
||||
simplename(destType)+")");
|
||||
}
|
||||
return cachedname;
|
||||
}
|
||||
}
|
||||
330
jdkSrc/jdk8/sun/java2d/loops/GraphicsPrimitiveMgr.java
Normal file
330
jdkSrc/jdk8/sun/java2d/loops/GraphicsPrimitiveMgr.java
Normal file
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Charlton Innovations, Inc.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Arrays;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
|
||||
/**
|
||||
* GraphicsComponentMgr provides services to
|
||||
* 1. register primitives for later use
|
||||
* 2. locate an instance of a primitve based on characteristics
|
||||
*/
|
||||
public final class GraphicsPrimitiveMgr {
|
||||
|
||||
private static final boolean debugTrace = false;
|
||||
private static GraphicsPrimitive primitives[];
|
||||
private static GraphicsPrimitive generalPrimitives[];
|
||||
private static boolean needssort = true;
|
||||
|
||||
private static native void initIDs(Class GP, Class ST, Class CT,
|
||||
Class SG2D, Class Color, Class AT,
|
||||
Class XORComp, Class AlphaComp,
|
||||
Class Path2D, Class Path2DFloat,
|
||||
Class SHints);
|
||||
private static native void registerNativeLoops();
|
||||
|
||||
static {
|
||||
initIDs(GraphicsPrimitive.class,
|
||||
SurfaceType.class,
|
||||
CompositeType.class,
|
||||
SunGraphics2D.class,
|
||||
java.awt.Color.class,
|
||||
java.awt.geom.AffineTransform.class,
|
||||
XORComposite.class,
|
||||
java.awt.AlphaComposite.class,
|
||||
java.awt.geom.Path2D.class,
|
||||
java.awt.geom.Path2D.Float.class,
|
||||
sun.awt.SunHints.class);
|
||||
CustomComponent.register();
|
||||
GeneralRenderer.register();
|
||||
registerNativeLoops();
|
||||
}
|
||||
|
||||
private static class PrimitiveSpec {
|
||||
public int uniqueID;
|
||||
}
|
||||
|
||||
private static Comparator primSorter = new Comparator() {
|
||||
public int compare(Object o1, Object o2) {
|
||||
int id1 = ((GraphicsPrimitive) o1).getUniqueID();
|
||||
int id2 = ((GraphicsPrimitive) o2).getUniqueID();
|
||||
|
||||
return (id1 == id2 ? 0 : (id1 < id2 ? -1 : 1));
|
||||
}
|
||||
};
|
||||
|
||||
private static Comparator primFinder = new Comparator() {
|
||||
public int compare(Object o1, Object o2) {
|
||||
int id1 = ((GraphicsPrimitive) o1).getUniqueID();
|
||||
int id2 = ((PrimitiveSpec) o2).uniqueID;
|
||||
|
||||
return (id1 == id2 ? 0 : (id1 < id2 ? -1 : 1));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Ensure that noone can instantiate this class.
|
||||
*/
|
||||
private GraphicsPrimitiveMgr() {
|
||||
}
|
||||
|
||||
public synchronized static void register(GraphicsPrimitive[] newPrimitives)
|
||||
{
|
||||
GraphicsPrimitive[] devCollection = primitives;
|
||||
int oldSize = 0;
|
||||
int newSize = newPrimitives.length;
|
||||
if (debugTrace) {
|
||||
writeLog("Registering " + newSize + " primitives");
|
||||
for (int i = 0; i < newSize; i++) {
|
||||
writeLog(newPrimitives[i].toString());
|
||||
}
|
||||
}
|
||||
if (devCollection != null) {
|
||||
oldSize = devCollection.length;
|
||||
}
|
||||
GraphicsPrimitive[] temp = new GraphicsPrimitive[oldSize + newSize];
|
||||
if (devCollection != null) {
|
||||
System.arraycopy(devCollection, 0, temp, 0, oldSize);
|
||||
}
|
||||
System.arraycopy(newPrimitives, 0, temp, oldSize, newSize);
|
||||
needssort = true;
|
||||
primitives = temp;
|
||||
}
|
||||
|
||||
public synchronized static void registerGeneral(GraphicsPrimitive gen) {
|
||||
if (generalPrimitives == null) {
|
||||
generalPrimitives = new GraphicsPrimitive[] {gen};
|
||||
return;
|
||||
}
|
||||
int len = generalPrimitives.length;
|
||||
GraphicsPrimitive[] newGen = new GraphicsPrimitive[len + 1];
|
||||
System.arraycopy(generalPrimitives, 0, newGen, 0, len);
|
||||
newGen[len] = gen;
|
||||
generalPrimitives = newGen;
|
||||
}
|
||||
|
||||
public synchronized static GraphicsPrimitive locate(int primTypeID,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return locate(primTypeID,
|
||||
SurfaceType.OpaqueColor,
|
||||
CompositeType.Src,
|
||||
dsttype);
|
||||
}
|
||||
|
||||
public synchronized static GraphicsPrimitive locate(int primTypeID,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
/*
|
||||
System.out.println("Looking for:");
|
||||
System.out.println(" method: "+signature);
|
||||
System.out.println(" from: "+srctype);
|
||||
System.out.println(" by: "+comptype);
|
||||
System.out.println(" to: "+dsttype);
|
||||
*/
|
||||
GraphicsPrimitive prim = locatePrim(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
|
||||
if (prim == null) {
|
||||
//System.out.println("Trying general loop");
|
||||
prim = locateGeneral(primTypeID);
|
||||
if (prim != null) {
|
||||
prim = prim.makePrimitive(srctype, comptype, dsttype);
|
||||
if (prim != null && GraphicsPrimitive.traceflags != 0) {
|
||||
prim = prim.traceWrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
return prim;
|
||||
}
|
||||
|
||||
public synchronized static GraphicsPrimitive
|
||||
locatePrim(int primTypeID,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
/*
|
||||
System.out.println("Looking for:");
|
||||
System.out.println(" method: "+signature);
|
||||
System.out.println(" from: "+srctype);
|
||||
System.out.println(" by: "+comptype);
|
||||
System.out.println(" to: "+dsttype);
|
||||
*/
|
||||
SurfaceType src, dst;
|
||||
CompositeType cmp;
|
||||
GraphicsPrimitive prim;
|
||||
PrimitiveSpec spec = new PrimitiveSpec();
|
||||
|
||||
for (dst = dsttype; dst != null; dst = dst.getSuperType()) {
|
||||
for (src = srctype; src != null; src = src.getSuperType()) {
|
||||
for (cmp = comptype; cmp != null; cmp = cmp.getSuperType()) {
|
||||
/*
|
||||
System.out.println("Trying:");
|
||||
System.out.println(" method: "+spec.methodSignature);
|
||||
System.out.println(" from: "+spec.sourceType);
|
||||
System.out.println(" by: "+spec.compType);
|
||||
System.out.println(" to: "+spec.destType);
|
||||
*/
|
||||
|
||||
spec.uniqueID =
|
||||
GraphicsPrimitive.makeUniqueID(primTypeID, src, cmp, dst);
|
||||
prim = locate(spec);
|
||||
if (prim != null) {
|
||||
//System.out.println("<GPMgr> Found: " + prim + " in " + i + " steps");
|
||||
return prim;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static GraphicsPrimitive locateGeneral(int primTypeID) {
|
||||
if (generalPrimitives == null) {
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < generalPrimitives.length; i++) {
|
||||
GraphicsPrimitive prim = generalPrimitives[i];
|
||||
if (prim.getPrimTypeID() == primTypeID) {
|
||||
return prim;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
//throw new InternalError("No general handler registered for"+signature);
|
||||
}
|
||||
|
||||
private static GraphicsPrimitive locate(PrimitiveSpec spec) {
|
||||
if (needssort) {
|
||||
if (GraphicsPrimitive.traceflags != 0) {
|
||||
for (int i = 0; i < primitives.length; i++) {
|
||||
primitives[i] = primitives[i].traceWrap();
|
||||
}
|
||||
}
|
||||
Arrays.sort(primitives, primSorter);
|
||||
needssort = false;
|
||||
}
|
||||
GraphicsPrimitive[] devCollection = primitives;
|
||||
if (devCollection == null) {
|
||||
return null;
|
||||
}
|
||||
int index = Arrays.binarySearch(devCollection, spec, primFinder);
|
||||
if (index >= 0) {
|
||||
GraphicsPrimitive prim = devCollection[index];
|
||||
if (prim instanceof GraphicsPrimitiveProxy) {
|
||||
prim = ((GraphicsPrimitiveProxy) prim).instantiate();
|
||||
devCollection[index] = prim;
|
||||
if (debugTrace) {
|
||||
writeLog("Instantiated graphics primitive " + prim);
|
||||
}
|
||||
}
|
||||
if (debugTrace) {
|
||||
writeLog("Lookup found[" + index + "]["+ prim + "]");
|
||||
}
|
||||
return prim;
|
||||
}
|
||||
if (debugTrace) {
|
||||
writeLog("Lookup found nothing for:");
|
||||
writeLog(" " + spec.uniqueID);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void writeLog(String str) {
|
||||
if (debugTrace) {
|
||||
System.err.println(str);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that all of the GraphicsPrimitiveProxy objects actually
|
||||
* resolve to something. Throws a RuntimeException if anything
|
||||
* is wrong, an has no effect if all is well.
|
||||
*/
|
||||
// This is only really meant to be called from GraphicsPrimitiveProxyTest
|
||||
// in the regression tests directory, but it has to be here because
|
||||
// it needs access to a private data structure. It is not very
|
||||
// big, though.
|
||||
public static void testPrimitiveInstantiation() {
|
||||
testPrimitiveInstantiation(false);
|
||||
}
|
||||
|
||||
public static void testPrimitiveInstantiation(boolean verbose) {
|
||||
int resolved = 0;
|
||||
int unresolved = 0;
|
||||
GraphicsPrimitive[] prims = primitives;
|
||||
for (int j = 0; j < prims.length; j++) {
|
||||
GraphicsPrimitive p = prims[j];
|
||||
if (p instanceof GraphicsPrimitiveProxy) {
|
||||
GraphicsPrimitive r = ((GraphicsPrimitiveProxy) p).instantiate();
|
||||
if (!r.getSignature().equals(p.getSignature()) ||
|
||||
r.getUniqueID() != p.getUniqueID()) {
|
||||
System.out.println("r.getSignature == "+r.getSignature());
|
||||
System.out.println("r.getUniqueID == " + r.getUniqueID());
|
||||
System.out.println("p.getSignature == "+p.getSignature());
|
||||
System.out.println("p.getUniqueID == " + p.getUniqueID());
|
||||
throw new RuntimeException("Primitive " + p
|
||||
+ " returns wrong signature for "
|
||||
+ r.getClass());
|
||||
}
|
||||
// instantiate checks that p.satisfiesSameAs(r)
|
||||
unresolved++;
|
||||
p = r;
|
||||
if (verbose) {
|
||||
System.out.println(p);
|
||||
}
|
||||
} else {
|
||||
if (verbose) {
|
||||
System.out.println(p + " (not proxied).");
|
||||
}
|
||||
resolved++;
|
||||
}
|
||||
}
|
||||
System.out.println(resolved+
|
||||
" graphics primitives were not proxied.");
|
||||
System.out.println(unresolved+
|
||||
" proxied graphics primitives resolved correctly.");
|
||||
System.out.println(resolved+unresolved+
|
||||
" total graphics primitives");
|
||||
}
|
||||
|
||||
public static void main(String argv[]) {
|
||||
// REMIND: Should trigger loading of platform primitives somehow...
|
||||
if (needssort) {
|
||||
Arrays.sort(primitives, primSorter);
|
||||
needssort = false;
|
||||
}
|
||||
testPrimitiveInstantiation(argv.length > 0);
|
||||
}
|
||||
}
|
||||
114
jdkSrc/jdk8/sun/java2d/loops/GraphicsPrimitiveProxy.java
Normal file
114
jdkSrc/jdk8/sun/java2d/loops/GraphicsPrimitiveProxy.java
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
/**
|
||||
* GraphicsPrimitiveProxy
|
||||
*
|
||||
* Acts as a proxy for instances of GraphicsPrimitive, enabling lazy
|
||||
* classloading of these primitives. This leads to a substantial
|
||||
* savings in start-up time and footprint. In the typical case,
|
||||
* it has been found that a small number of GraphicsPrimitive instance
|
||||
* actually end up getting instantiated.
|
||||
* <p>
|
||||
* Note that the makePrimitive method should never be invoked on
|
||||
* a GraphicsPrimitiveProxy object since they are instantiated as
|
||||
* soon as they are found in the primitive list and never returned
|
||||
* to the caller.
|
||||
*/
|
||||
public class GraphicsPrimitiveProxy extends GraphicsPrimitive {
|
||||
|
||||
private Class owner;
|
||||
private String relativeClassName;
|
||||
|
||||
/**
|
||||
* Create a GraphicsPrimitiveProxy for a primitive with a no-argument
|
||||
* constructor.
|
||||
*
|
||||
* @param owner The owner class for this primitive. The primitive
|
||||
* must be in the same package as this owner.
|
||||
* @param relativeClassName The name of the class this is a proxy for.
|
||||
* This should not include the package.
|
||||
*/
|
||||
public GraphicsPrimitiveProxy(Class owner, String relativeClassName,
|
||||
String methodSignature,
|
||||
int primID,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(methodSignature, primID, srctype, comptype, dsttype);
|
||||
this.owner = owner;
|
||||
this.relativeClassName = relativeClassName;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype) {
|
||||
// This should never happen.
|
||||
throw new InternalError("makePrimitive called on a Proxy!");
|
||||
}
|
||||
|
||||
//
|
||||
// Come up with the real instance. Called from
|
||||
// GraphicsPrimitiveMgr.locate()
|
||||
//
|
||||
GraphicsPrimitive instantiate() {
|
||||
String name = getPackageName(owner.getName()) + "."
|
||||
+ relativeClassName;
|
||||
try {
|
||||
Class clazz = Class.forName(name);
|
||||
GraphicsPrimitive p = (GraphicsPrimitive) clazz.newInstance();
|
||||
if (!satisfiesSameAs(p)) {
|
||||
throw new RuntimeException("Primitive " + p
|
||||
+ " incompatible with proxy for "
|
||||
+ name);
|
||||
}
|
||||
return p;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
throw new RuntimeException(ex.toString());
|
||||
} catch (InstantiationException ex) {
|
||||
throw new RuntimeException(ex.toString());
|
||||
} catch (IllegalAccessException ex) {
|
||||
throw new RuntimeException(ex.toString());
|
||||
}
|
||||
// A RuntimeException should never happen in a deployed JDK, because
|
||||
// the regression test GraphicsPrimitiveProxyTest will catch any
|
||||
// of these errors.
|
||||
}
|
||||
|
||||
private static String getPackageName(String className) {
|
||||
int lastDotIdx = className.lastIndexOf('.');
|
||||
if (lastDotIdx < 0) {
|
||||
return className;
|
||||
}
|
||||
return className.substring(0, lastDotIdx);
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return instantiate().traceWrap();
|
||||
}
|
||||
}
|
||||
264
jdkSrc/jdk8/sun/java2d/loops/MaskBlit.java
Normal file
264
jdkSrc/jdk8/sun/java2d/loops/MaskBlit.java
Normal file
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import java.awt.Composite;
|
||||
import java.lang.ref.WeakReference;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.pipe.Region;
|
||||
|
||||
/**
|
||||
* MaskBlit
|
||||
* 1) copies rectangle of pixels from one surface to another
|
||||
* 2) performs compositing of colors based upon a Composite
|
||||
* parameter
|
||||
* 3) blends result of composite with destination using an
|
||||
* alpha coverage mask
|
||||
* 4) the mask may be null in which case it should be treated
|
||||
* as if it were an array of all opaque values (0xff)
|
||||
*
|
||||
* precise behavior is undefined if the source surface
|
||||
* and the destination surface are the same surface
|
||||
* with overlapping regions of pixels
|
||||
*/
|
||||
|
||||
public class MaskBlit extends GraphicsPrimitive
|
||||
{
|
||||
public static final String methodSignature = "MaskBlit(...)".toString();
|
||||
|
||||
public static final int primTypeID = makePrimTypeID();
|
||||
|
||||
private static RenderCache blitcache = new RenderCache(20);
|
||||
|
||||
public static MaskBlit locate(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return (MaskBlit)
|
||||
GraphicsPrimitiveMgr.locate(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public static MaskBlit getFromCache(SurfaceType src,
|
||||
CompositeType comp,
|
||||
SurfaceType dst)
|
||||
{
|
||||
Object o = blitcache.get(src, comp, dst);
|
||||
if (o != null) {
|
||||
return (MaskBlit) o;
|
||||
}
|
||||
MaskBlit blit = locate(src, comp, dst);
|
||||
if (blit == null) {
|
||||
System.out.println("mask blit loop not found for:");
|
||||
System.out.println("src: "+src);
|
||||
System.out.println("comp: "+comp);
|
||||
System.out.println("dst: "+dst);
|
||||
} else {
|
||||
blitcache.put(src, comp, dst, blit);
|
||||
}
|
||||
return blit;
|
||||
}
|
||||
|
||||
protected MaskBlit(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public MaskBlit(long pNativePrim,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(pNativePrim, methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
/**
|
||||
* All MaskBlit implementors must have this invoker method
|
||||
*/
|
||||
public native void MaskBlit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int srcx, int srcy,
|
||||
int dstx, int dsty,
|
||||
int width, int height,
|
||||
byte[] mask, int maskoff, int maskscan);
|
||||
|
||||
static {
|
||||
GraphicsPrimitiveMgr.registerGeneral(new MaskBlit(null, null, null));
|
||||
}
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
/*
|
||||
new Throwable().printStackTrace();
|
||||
System.out.println("Constructing general maskblit for:");
|
||||
System.out.println("src: "+srctype);
|
||||
System.out.println("comp: "+comptype);
|
||||
System.out.println("dst: "+dsttype);
|
||||
*/
|
||||
|
||||
if (CompositeType.Xor.equals(comptype)) {
|
||||
throw new InternalError("Cannot construct MaskBlit for " +
|
||||
"XOR mode");
|
||||
}
|
||||
|
||||
General ob = new General(srctype, comptype, dsttype);
|
||||
setupGeneralBinaryOp(ob);
|
||||
return ob;
|
||||
}
|
||||
|
||||
private static class General
|
||||
extends MaskBlit
|
||||
implements GeneralBinaryOp
|
||||
{
|
||||
Blit convertsrc;
|
||||
Blit convertdst;
|
||||
MaskBlit performop;
|
||||
Blit convertresult;
|
||||
|
||||
WeakReference srcTmp;
|
||||
WeakReference dstTmp;
|
||||
|
||||
public General(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public void setPrimitives(Blit srcconverter,
|
||||
Blit dstconverter,
|
||||
GraphicsPrimitive genericop,
|
||||
Blit resconverter)
|
||||
{
|
||||
this.convertsrc = srcconverter;
|
||||
this.convertdst = dstconverter;
|
||||
this.performop = (MaskBlit) genericop;
|
||||
this.convertresult = resconverter;
|
||||
}
|
||||
|
||||
public synchronized void MaskBlit(SurfaceData srcData,
|
||||
SurfaceData dstData,
|
||||
Composite comp,
|
||||
Region clip,
|
||||
int srcx, int srcy,
|
||||
int dstx, int dsty,
|
||||
int width, int height,
|
||||
byte mask[], int offset, int scan)
|
||||
{
|
||||
SurfaceData src, dst;
|
||||
Region opclip;
|
||||
int sx, sy, dx, dy;
|
||||
|
||||
if (convertsrc == null) {
|
||||
src = srcData;
|
||||
sx = srcx;
|
||||
sy = srcy;
|
||||
} else {
|
||||
SurfaceData cachedSrc = null;
|
||||
if (srcTmp != null) {
|
||||
cachedSrc = (SurfaceData) srcTmp.get();
|
||||
}
|
||||
src = convertFrom(convertsrc, srcData, srcx, srcy,
|
||||
width, height, cachedSrc);
|
||||
sx = 0;
|
||||
sy = 0;
|
||||
if (src != cachedSrc) {
|
||||
srcTmp = new WeakReference(src);
|
||||
}
|
||||
}
|
||||
|
||||
if (convertdst == null) {
|
||||
dst = dstData;
|
||||
dx = dstx;
|
||||
dy = dsty;
|
||||
opclip = clip;
|
||||
} else {
|
||||
// assert: convertresult != null
|
||||
SurfaceData cachedDst = null;
|
||||
if (dstTmp != null) {
|
||||
cachedDst = (SurfaceData) dstTmp.get();
|
||||
}
|
||||
dst = convertFrom(convertdst, dstData, dstx, dsty,
|
||||
width, height, cachedDst);
|
||||
dx = 0;
|
||||
dy = 0;
|
||||
opclip = null;
|
||||
if (dst != cachedDst) {
|
||||
dstTmp = new WeakReference(dst);
|
||||
}
|
||||
}
|
||||
|
||||
performop.MaskBlit(src, dst, comp, opclip,
|
||||
sx, sy, dx, dy, width, height,
|
||||
mask, offset, scan);
|
||||
|
||||
if (convertresult != null) {
|
||||
// assert: convertdst != null
|
||||
convertTo(convertresult, dst, dstData, clip,
|
||||
dstx, dsty, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return new TraceMaskBlit(this);
|
||||
}
|
||||
|
||||
private static class TraceMaskBlit extends MaskBlit {
|
||||
MaskBlit target;
|
||||
|
||||
public TraceMaskBlit(MaskBlit target) {
|
||||
// We need to have the same NativePrim as our
|
||||
// target in case we are used with a TransformHelper
|
||||
super(target.getNativePrim(),
|
||||
target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void MaskBlit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int srcx, int srcy, int dstx, int dsty,
|
||||
int width, int height,
|
||||
byte[] mask, int maskoff, int maskscan)
|
||||
{
|
||||
tracePrimitive(target);
|
||||
target.MaskBlit(src, dst, comp, clip,
|
||||
srcx, srcy, dstx, dsty, width, height,
|
||||
mask, maskoff, maskscan);
|
||||
}
|
||||
}
|
||||
}
|
||||
277
jdkSrc/jdk8/sun/java2d/loops/MaskFill.java
Normal file
277
jdkSrc/jdk8/sun/java2d/loops/MaskFill.java
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import java.awt.Paint;
|
||||
import java.awt.PaintContext;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.WritableRaster;
|
||||
import sun.awt.image.BufImgSurfaceData;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.pipe.Region;
|
||||
|
||||
/**
|
||||
* MaskFill
|
||||
* 1) fills rectangles of pixels on a surface
|
||||
* 2) performs compositing of colors based upon a Composite
|
||||
* parameter
|
||||
* 3) blends result of composite with destination using an
|
||||
* alpha coverage mask
|
||||
* 4) the mask may be null in which case it should be treated
|
||||
* as if it were an array of all opaque values (0xff)
|
||||
*/
|
||||
public class MaskFill extends GraphicsPrimitive
|
||||
{
|
||||
public static final String methodSignature = "MaskFill(...)".toString();
|
||||
public static final String fillPgramSignature =
|
||||
"FillAAPgram(...)".toString();
|
||||
public static final String drawPgramSignature =
|
||||
"DrawAAPgram(...)".toString();
|
||||
|
||||
public static final int primTypeID = makePrimTypeID();
|
||||
|
||||
private static RenderCache fillcache = new RenderCache(10);
|
||||
|
||||
public static MaskFill locate(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return (MaskFill)
|
||||
GraphicsPrimitiveMgr.locate(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public static MaskFill locatePrim(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return (MaskFill)
|
||||
GraphicsPrimitiveMgr.locatePrim(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that this uses locatePrim, not locate, so it can return
|
||||
* null if there is no specific loop to handle this op...
|
||||
*/
|
||||
public static MaskFill getFromCache(SurfaceType src,
|
||||
CompositeType comp,
|
||||
SurfaceType dst)
|
||||
{
|
||||
Object o = fillcache.get(src, comp, dst);
|
||||
if (o != null) {
|
||||
return (MaskFill) o;
|
||||
}
|
||||
MaskFill fill = locatePrim(src, comp, dst);
|
||||
if (fill != null) {
|
||||
fillcache.put(src, comp, dst, fill);
|
||||
}
|
||||
return fill;
|
||||
}
|
||||
|
||||
protected MaskFill(String alternateSignature,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(alternateSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
protected MaskFill(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public MaskFill(long pNativePrim,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(pNativePrim, methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
/**
|
||||
* All MaskFill implementors must have this invoker method
|
||||
*/
|
||||
public native void MaskFill(SunGraphics2D sg2d, SurfaceData sData,
|
||||
Composite comp,
|
||||
int x, int y, int w, int h,
|
||||
byte[] mask, int maskoff, int maskscan);
|
||||
|
||||
public native void FillAAPgram(SunGraphics2D sg2d, SurfaceData sData,
|
||||
Composite comp,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2);
|
||||
|
||||
public native void DrawAAPgram(SunGraphics2D sg2d, SurfaceData sData,
|
||||
Composite comp,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double lw1, double lw2);
|
||||
|
||||
public boolean canDoParallelograms() {
|
||||
return (getNativePrim() != 0);
|
||||
}
|
||||
|
||||
static {
|
||||
GraphicsPrimitiveMgr.registerGeneral(new MaskFill(null, null, null));
|
||||
}
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
if (SurfaceType.OpaqueColor.equals(srctype) ||
|
||||
SurfaceType.AnyColor.equals(srctype))
|
||||
{
|
||||
if (CompositeType.Xor.equals(comptype)) {
|
||||
throw new InternalError("Cannot construct MaskFill for " +
|
||||
"XOR mode");
|
||||
} else {
|
||||
return new General(srctype, comptype, dsttype);
|
||||
}
|
||||
} else {
|
||||
throw new InternalError("MaskFill can only fill with colors");
|
||||
}
|
||||
}
|
||||
|
||||
private static class General extends MaskFill {
|
||||
FillRect fillop;
|
||||
MaskBlit maskop;
|
||||
|
||||
public General(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(srctype, comptype, dsttype);
|
||||
fillop = FillRect.locate(srctype,
|
||||
CompositeType.SrcNoEa,
|
||||
SurfaceType.IntArgb);
|
||||
maskop = MaskBlit.locate(SurfaceType.IntArgb, comptype, dsttype);
|
||||
}
|
||||
|
||||
public void MaskFill(SunGraphics2D sg2d,
|
||||
SurfaceData sData,
|
||||
Composite comp,
|
||||
int x, int y, int w, int h,
|
||||
byte mask[], int offset, int scan)
|
||||
{
|
||||
BufferedImage dstBI =
|
||||
new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
|
||||
SurfaceData tmpData = BufImgSurfaceData.createData(dstBI);
|
||||
|
||||
// REMIND: This is not pretty. It would be nicer if we
|
||||
// passed a "FillData" object to the Pixel loops, instead
|
||||
// of a SunGraphics2D parameter...
|
||||
Region clip = sg2d.clipRegion;
|
||||
sg2d.clipRegion = null;
|
||||
int pixel = sg2d.pixel;
|
||||
sg2d.pixel = tmpData.pixelFor(sg2d.getColor());
|
||||
fillop.FillRect(sg2d, tmpData, 0, 0, w, h);
|
||||
sg2d.pixel = pixel;
|
||||
sg2d.clipRegion = clip;
|
||||
|
||||
maskop.MaskBlit(tmpData, sData, comp, null,
|
||||
0, 0, x, y, w, h,
|
||||
mask, offset, scan);
|
||||
}
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return new TraceMaskFill(this);
|
||||
}
|
||||
|
||||
private static class TraceMaskFill extends MaskFill {
|
||||
MaskFill target;
|
||||
MaskFill fillPgramTarget;
|
||||
MaskFill drawPgramTarget;
|
||||
|
||||
public TraceMaskFill(MaskFill target) {
|
||||
super(target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
this.target = target;
|
||||
this.fillPgramTarget = new MaskFill(fillPgramSignature,
|
||||
target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
this.drawPgramTarget = new MaskFill(drawPgramSignature,
|
||||
target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void MaskFill(SunGraphics2D sg2d, SurfaceData sData,
|
||||
Composite comp,
|
||||
int x, int y, int w, int h,
|
||||
byte[] mask, int maskoff, int maskscan)
|
||||
{
|
||||
tracePrimitive(target);
|
||||
target.MaskFill(sg2d, sData, comp, x, y, w, h,
|
||||
mask, maskoff, maskscan);
|
||||
}
|
||||
|
||||
public void FillAAPgram(SunGraphics2D sg2d, SurfaceData sData,
|
||||
Composite comp,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
tracePrimitive(fillPgramTarget);
|
||||
target.FillAAPgram(sg2d, sData, comp,
|
||||
x, y, dx1, dy1, dx2, dy2);
|
||||
}
|
||||
|
||||
public void DrawAAPgram(SunGraphics2D sg2d, SurfaceData sData,
|
||||
Composite comp,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double lw1, double lw2)
|
||||
{
|
||||
tracePrimitive(drawPgramTarget);
|
||||
target.DrawAAPgram(sg2d, sData, comp,
|
||||
x, y, dx1, dy1, dx2, dy2, lw1, lw2);
|
||||
}
|
||||
|
||||
public boolean canDoParallelograms() {
|
||||
return target.canDoParallelograms();
|
||||
}
|
||||
}
|
||||
}
|
||||
2128
jdkSrc/jdk8/sun/java2d/loops/ProcessPath.java
Normal file
2128
jdkSrc/jdk8/sun/java2d/loops/ProcessPath.java
Normal file
File diff suppressed because it is too large
Load Diff
103
jdkSrc/jdk8/sun/java2d/loops/RenderCache.java
Normal file
103
jdkSrc/jdk8/sun/java2d/loops/RenderCache.java
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
public final class RenderCache {
|
||||
final class Entry {
|
||||
private SurfaceType src;
|
||||
private CompositeType comp;
|
||||
private SurfaceType dst;
|
||||
private Object value;
|
||||
|
||||
public Entry(SurfaceType src,
|
||||
CompositeType comp,
|
||||
SurfaceType dst,
|
||||
Object value)
|
||||
{
|
||||
this.src = src;
|
||||
this.comp = comp;
|
||||
this.dst = dst;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean matches(SurfaceType src,
|
||||
CompositeType comp,
|
||||
SurfaceType dst)
|
||||
{
|
||||
// bug 4725045: using equals() causes different SurfaceType
|
||||
// objects with the same strings to match in the cache, which is
|
||||
// not the behavior we want. Constrain the match to succeed only
|
||||
// on object matches instead.
|
||||
return ((this.src == src) &&
|
||||
(this.comp == comp) &&
|
||||
(this.dst == dst));
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
private Entry entries[];
|
||||
|
||||
public RenderCache(int size) {
|
||||
entries = new Entry[size];
|
||||
}
|
||||
|
||||
public synchronized Object get(SurfaceType src,
|
||||
CompositeType comp,
|
||||
SurfaceType dst)
|
||||
{
|
||||
int max = entries.length - 1;
|
||||
for (int i = max; i >= 0; i--) {
|
||||
Entry e = entries[i];
|
||||
if (e == null) {
|
||||
break;
|
||||
}
|
||||
if (e.matches(src, comp, dst)) {
|
||||
if (i < max - 4) {
|
||||
System.arraycopy(entries, i+1, entries, i, max - i);
|
||||
entries[max] = e;
|
||||
}
|
||||
return e.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public synchronized void put(SurfaceType src,
|
||||
CompositeType comp,
|
||||
SurfaceType dst,
|
||||
Object value)
|
||||
{
|
||||
Entry e = new Entry(src, comp, dst, value);
|
||||
|
||||
int num = entries.length;
|
||||
System.arraycopy(entries, 1, entries, 0, num - 1);
|
||||
entries[num - 1] = e;
|
||||
}
|
||||
}
|
||||
55
jdkSrc/jdk8/sun/java2d/loops/RenderLoops.java
Normal file
55
jdkSrc/jdk8/sun/java2d/loops/RenderLoops.java
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
/*
|
||||
* This class stores the various loops that are used by the
|
||||
* standard rendering pipelines. The loops for a given instance
|
||||
* of this class will all share the same destination type and the
|
||||
* same supported paint and composite operation.
|
||||
* Each instance of this class should be shared by all graphics
|
||||
* objects that render onto the same type of destination with the
|
||||
* same paint and composite combination to reduce the amount of
|
||||
* time spent looking up loops appropriate for the current fill
|
||||
* technique.
|
||||
*/
|
||||
public class RenderLoops {
|
||||
|
||||
public static final int primTypeID = GraphicsPrimitive.makePrimTypeID();
|
||||
|
||||
public DrawLine drawLineLoop;
|
||||
public FillRect fillRectLoop;
|
||||
public DrawRect drawRectLoop;
|
||||
public DrawPolygons drawPolygonsLoop;
|
||||
public DrawPath drawPathLoop;
|
||||
public FillPath fillPathLoop;
|
||||
public FillSpans fillSpansLoop;
|
||||
public FillParallelogram fillParallelogramLoop;
|
||||
public DrawParallelogram drawParallelogramLoop;
|
||||
public DrawGlyphList drawGlyphListLoop;
|
||||
public DrawGlyphListAA drawGlyphListAALoop;
|
||||
public DrawGlyphListLCD drawGlyphListLCDLoop;
|
||||
}
|
||||
156
jdkSrc/jdk8/sun/java2d/loops/ScaledBlit.java
Normal file
156
jdkSrc/jdk8/sun/java2d/loops/ScaledBlit.java
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import java.awt.Composite;
|
||||
import java.lang.ref.WeakReference;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.pipe.Region;
|
||||
|
||||
/**
|
||||
* ScaledBlit
|
||||
* 1) copies rectangle of pixels from one surface to another
|
||||
* while scaling the pixels to meet the sizes specified
|
||||
* 2) performs compositing of colors based upon a Composite
|
||||
* parameter
|
||||
*
|
||||
* precise behavior is undefined if the source surface
|
||||
* and the destination surface are the same surface
|
||||
* with overlapping regions of pixels
|
||||
*/
|
||||
|
||||
public class ScaledBlit extends GraphicsPrimitive
|
||||
{
|
||||
public static final String methodSignature = "ScaledBlit(...)".toString();
|
||||
|
||||
public static final int primTypeID = makePrimTypeID();
|
||||
|
||||
private static RenderCache blitcache = new RenderCache(20);
|
||||
|
||||
public static ScaledBlit locate(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return (ScaledBlit)
|
||||
GraphicsPrimitiveMgr.locate(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public static ScaledBlit getFromCache(SurfaceType src,
|
||||
CompositeType comp,
|
||||
SurfaceType dst)
|
||||
{
|
||||
Object o = blitcache.get(src, comp, dst);
|
||||
if (o != null) {
|
||||
return (ScaledBlit) o;
|
||||
}
|
||||
ScaledBlit blit = locate(src, comp, dst);
|
||||
if (blit == null) {
|
||||
/*
|
||||
System.out.println("blit loop not found for:");
|
||||
System.out.println("src: "+src);
|
||||
System.out.println("comp: "+comp);
|
||||
System.out.println("dst: "+dst);
|
||||
*/
|
||||
} else {
|
||||
blitcache.put(src, comp, dst, blit);
|
||||
}
|
||||
return blit;
|
||||
}
|
||||
|
||||
protected ScaledBlit(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public ScaledBlit(long pNativePrim,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(pNativePrim, methodSignature, primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public native void Scale(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2);
|
||||
|
||||
static {
|
||||
GraphicsPrimitiveMgr.registerGeneral(new ScaledBlit(null, null, null));
|
||||
}
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
/*
|
||||
System.out.println("Constructing general blit for:");
|
||||
System.out.println("src: "+srctype);
|
||||
System.out.println("comp: "+comptype);
|
||||
System.out.println("dst: "+dsttype);
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return new TraceScaledBlit(this);
|
||||
}
|
||||
|
||||
private static class TraceScaledBlit extends ScaledBlit {
|
||||
ScaledBlit target;
|
||||
|
||||
public TraceScaledBlit(ScaledBlit target) {
|
||||
super(target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Scale(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
tracePrimitive(target);
|
||||
target.Scale(src, dst, comp, clip,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2);
|
||||
}
|
||||
}
|
||||
}
|
||||
460
jdkSrc/jdk8/sun/java2d/loops/SurfaceType.java
Normal file
460
jdkSrc/jdk8/sun/java2d/loops/SurfaceType.java
Normal file
@@ -0,0 +1,460 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
import sun.awt.image.PixelConverter;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* A SurfaceType object provides a chained description of a type of
|
||||
* drawing surface. The object will provide a single String constant
|
||||
* descriptor which is one way of viewing or accessing a particular
|
||||
* drawing surface as well as a pointer to another SurfaceType which
|
||||
* describes the same drawing surface in a different (typically more
|
||||
* generalized) way.
|
||||
* <p>
|
||||
* A more specific description of a surface is considered a "subtype"
|
||||
* and a more general description is considered a "supertype". Thus,
|
||||
* the deriveSubType method provides a way to create a new SurfaceType
|
||||
* that is related to but more specific than an existing SurfaceType and
|
||||
* the getSuperType method provides a way to ask a given SurfaceType
|
||||
* for a more general way to describe the same surface.
|
||||
* <p>
|
||||
* Note that you cannot construct a brand new root for a chain since
|
||||
* the constructor is private. Every chain of types must at some point
|
||||
* derive from the Any node provided here using the deriveSubType()
|
||||
* method. The presence of this common Any node on every chain
|
||||
* ensures that all chains end with the DESC_ANY descriptor so that
|
||||
* a suitable General GraphicsPrimitive object can be obtained for
|
||||
* the indicated surface if all of the more specific searches fail.
|
||||
*/
|
||||
public final class SurfaceType {
|
||||
|
||||
private static int unusedUID = 1;
|
||||
private static HashMap<String, Integer> surfaceUIDMap = new HashMap<>(100);
|
||||
|
||||
/*
|
||||
* CONSTANTS USED BY ALL PRIMITIVES TO DESCRIBE THE SURFACES
|
||||
* THEY CAN OPERATE ON
|
||||
*/
|
||||
|
||||
/**
|
||||
* surface is unknown color model or sample model.
|
||||
*/
|
||||
public static final String
|
||||
DESC_ANY = "Any Surface";
|
||||
|
||||
/**
|
||||
* common surface formats defined in BufferedImage
|
||||
*/
|
||||
public static final String
|
||||
DESC_INT_RGB = "Integer RGB";
|
||||
public static final String
|
||||
DESC_INT_ARGB = "Integer ARGB";
|
||||
public static final String
|
||||
DESC_INT_ARGB_PRE = "Integer ARGB Premultiplied";
|
||||
public static final String
|
||||
DESC_INT_BGR = "Integer BGR";
|
||||
public static final String
|
||||
DESC_3BYTE_BGR = "3 Byte BGR";
|
||||
public static final String
|
||||
DESC_4BYTE_ABGR = "4 Byte ABGR";
|
||||
public static final String
|
||||
DESC_4BYTE_ABGR_PRE = "4 Byte ABGR Premultiplied";
|
||||
public static final String
|
||||
DESC_USHORT_565_RGB = "Short 565 RGB";
|
||||
public static final String
|
||||
DESC_USHORT_555_RGB = "Short 555 RGB";
|
||||
public static final String
|
||||
DESC_USHORT_555_RGBx= "Short 555 RGBx";
|
||||
public static final String
|
||||
DESC_USHORT_4444_ARGB= "Short 4444 ARGB";
|
||||
public static final String
|
||||
DESC_BYTE_GRAY = "8-bit Gray";
|
||||
public static final String
|
||||
DESC_USHORT_INDEXED = "16-bit Indexed";
|
||||
public static final String
|
||||
DESC_USHORT_GRAY = "16-bit Gray";
|
||||
public static final String
|
||||
DESC_BYTE_BINARY = "Packed Binary Bitmap";
|
||||
public static final String
|
||||
DESC_BYTE_INDEXED = "8-bit Indexed";
|
||||
|
||||
/**
|
||||
* wildcard format which indicates that the GraphicsPrimitive
|
||||
* is independent of the color model on an IntegerComponent
|
||||
* sample model surface
|
||||
*/
|
||||
public static final String DESC_ANY_INT = "Any Discrete Integer";
|
||||
|
||||
/**
|
||||
* wildcard format which indicates that the GraphicsPrimitive
|
||||
* is independent of the color model on a ShortComponent
|
||||
* sample model surface
|
||||
*/
|
||||
public static final String DESC_ANY_SHORT = "Any Discrete Short";
|
||||
|
||||
/**
|
||||
* wildcard format which indicates that the GraphicsPrimitive
|
||||
* is independent of the color model on a ByteComponent
|
||||
* sample model surface
|
||||
*/
|
||||
public static final String DESC_ANY_BYTE = "Any Discrete Byte";
|
||||
|
||||
/**
|
||||
* wildcard format which indicates that the GraphicsPrimitive
|
||||
* operates on a surface with 3 component interleaved Raster and
|
||||
* sample model and a ComponentColorModel with an arbitrary ordering
|
||||
* of the RGB channels
|
||||
*/
|
||||
public static final String DESC_ANY_3BYTE = "Any 3 Byte Component";
|
||||
|
||||
/**
|
||||
* wildcard format which indicates that the GraphicsPrimitive
|
||||
* operates on a surface with 4 component interleaved Raster and
|
||||
* sample model and a ComponentColorModel with an arbitrary ordering
|
||||
* of the ARGB channels
|
||||
*/
|
||||
public static final String DESC_ANY_4BYTE = "Any 4 Byte Component";
|
||||
|
||||
/**
|
||||
* wildcard format which indicates that the GraphicsPrimitive
|
||||
* operates on a surface with a single component IntegerComponent
|
||||
* sample model and a DirectColorModel with an arbitrary ordering
|
||||
* of the RGB channels
|
||||
*/
|
||||
public static final String DESC_ANY_INT_DCM = "Any Integer DCM";
|
||||
|
||||
/**
|
||||
* additional IntegerComponent types common on Windows
|
||||
*/
|
||||
public static final String DESC_INT_RGBx = "Integer RGBx";
|
||||
public static final String DESC_INT_BGRx = "Integer BGRx";
|
||||
|
||||
/**
|
||||
* additional 3 byte format common on Windows
|
||||
*/
|
||||
public static final String DESC_3BYTE_RGB = "3 Byte RGB";
|
||||
|
||||
/**
|
||||
* common formats for BITMASK transparency.
|
||||
*/
|
||||
public static final String DESC_INT_ARGB_BM = "Int ARGB (Bitmask)";
|
||||
public static final String DESC_BYTE_INDEXED_BM = "8-bit Indexed (Bitmask)";
|
||||
|
||||
/**
|
||||
* Opaque 8-bit indexed images
|
||||
*/
|
||||
public static final String
|
||||
DESC_BYTE_INDEXED_OPAQUE = "8-bit Indexed (Opaque)";
|
||||
|
||||
/**
|
||||
* Special Gray Scale types for rendering loops. Really indexed
|
||||
* types, but colormap has all gray values.
|
||||
*/
|
||||
public static final String DESC_INDEX8_GRAY = "8-bit Palettized Gray";
|
||||
public static final String DESC_INDEX12_GRAY = "12-bit Palettized Gray";
|
||||
|
||||
public static final String
|
||||
DESC_BYTE_BINARY_1BIT = "Packed Binary 1-bit Bitmap";
|
||||
public static final String
|
||||
DESC_BYTE_BINARY_2BIT = "Packed Binary 2-bit Bitmap";
|
||||
public static final String
|
||||
DESC_BYTE_BINARY_4BIT = "Packed Binary 4-bit Bitmap";
|
||||
|
||||
/**
|
||||
* Special type for describing the sources of loops that render the
|
||||
* current foreground color or paint instead of copying colors from
|
||||
* a source surface.
|
||||
*/
|
||||
public static final String DESC_ANY_PAINT = "Paint Object";
|
||||
public static final String DESC_ANY_COLOR = "Single Color";
|
||||
public static final String DESC_OPAQUE_COLOR = "Opaque Color";
|
||||
public static final String
|
||||
DESC_GRADIENT_PAINT = "Gradient Paint";
|
||||
public static final String
|
||||
DESC_OPAQUE_GRADIENT_PAINT = "Opaque Gradient Paint";
|
||||
public static final String
|
||||
DESC_TEXTURE_PAINT = "Texture Paint";
|
||||
public static final String
|
||||
DESC_OPAQUE_TEXTURE_PAINT = "Opaque Texture Paint";
|
||||
public static final String
|
||||
DESC_LINEAR_GRADIENT_PAINT = "Linear Gradient Paint";
|
||||
public static final String
|
||||
DESC_OPAQUE_LINEAR_GRADIENT_PAINT = "Opaque Linear Gradient Paint";
|
||||
public static final String
|
||||
DESC_RADIAL_GRADIENT_PAINT = "Radial Gradient Paint";
|
||||
public static final String
|
||||
DESC_OPAQUE_RADIAL_GRADIENT_PAINT = "Opaque Radial Gradient Paint";
|
||||
|
||||
/*
|
||||
* END OF SURFACE TYPE CONSTANTS
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The root SurfaceType object for all chains of surface descriptions.
|
||||
* The root uses the default PixelConverter object, which uses a given
|
||||
* ColorModel object to calculate its pixelFor() values when asked.
|
||||
* Any SurfaceType objects that are not created with a specific
|
||||
* PixelConverter object will inherit this behavior from the root.
|
||||
*/
|
||||
public static final SurfaceType Any =
|
||||
new SurfaceType(null, DESC_ANY, PixelConverter.instance);
|
||||
|
||||
/*
|
||||
* START OF SurfaceType OBJECTS FOR THE VARIOUS CONSTANTS
|
||||
*/
|
||||
|
||||
public static final SurfaceType
|
||||
AnyInt = Any.deriveSubType(DESC_ANY_INT);
|
||||
public static final SurfaceType
|
||||
AnyShort = Any.deriveSubType(DESC_ANY_SHORT);
|
||||
public static final SurfaceType
|
||||
AnyByte = Any.deriveSubType(DESC_ANY_BYTE);
|
||||
public static final SurfaceType
|
||||
AnyByteBinary = Any.deriveSubType(DESC_BYTE_BINARY);
|
||||
public static final SurfaceType
|
||||
Any3Byte = Any.deriveSubType(DESC_ANY_3BYTE);
|
||||
public static final SurfaceType
|
||||
Any4Byte = Any.deriveSubType(DESC_ANY_4BYTE);
|
||||
public static final SurfaceType
|
||||
AnyDcm = AnyInt.deriveSubType(DESC_ANY_INT_DCM);
|
||||
|
||||
public static final SurfaceType
|
||||
Custom = Any;
|
||||
public static final SurfaceType IntRgb =
|
||||
AnyDcm.deriveSubType(DESC_INT_RGB, PixelConverter.Xrgb.instance);
|
||||
|
||||
public static final SurfaceType IntArgb =
|
||||
AnyDcm.deriveSubType(DESC_INT_ARGB, PixelConverter.Argb.instance);
|
||||
|
||||
public static final SurfaceType IntArgbPre =
|
||||
AnyDcm.deriveSubType(DESC_INT_ARGB_PRE,
|
||||
PixelConverter.ArgbPre.instance);
|
||||
|
||||
public static final SurfaceType IntBgr =
|
||||
AnyDcm.deriveSubType(DESC_INT_BGR, PixelConverter.Xbgr.instance);
|
||||
|
||||
public static final SurfaceType ThreeByteBgr =
|
||||
Any3Byte.deriveSubType(DESC_3BYTE_BGR, PixelConverter.Xrgb.instance);
|
||||
|
||||
public static final SurfaceType FourByteAbgr =
|
||||
Any4Byte.deriveSubType(DESC_4BYTE_ABGR, PixelConverter.Rgba.instance);
|
||||
|
||||
public static final SurfaceType FourByteAbgrPre =
|
||||
Any4Byte.deriveSubType(DESC_4BYTE_ABGR_PRE,
|
||||
PixelConverter.RgbaPre.instance);
|
||||
|
||||
public static final SurfaceType Ushort565Rgb =
|
||||
AnyShort.deriveSubType(DESC_USHORT_565_RGB,
|
||||
PixelConverter.Ushort565Rgb.instance);
|
||||
|
||||
public static final SurfaceType Ushort555Rgb =
|
||||
AnyShort.deriveSubType(DESC_USHORT_555_RGB,
|
||||
PixelConverter.Ushort555Rgb.instance);
|
||||
|
||||
public static final SurfaceType Ushort555Rgbx =
|
||||
AnyShort.deriveSubType(DESC_USHORT_555_RGBx,
|
||||
PixelConverter.Ushort555Rgbx.instance);
|
||||
|
||||
public static final SurfaceType Ushort4444Argb =
|
||||
AnyShort.deriveSubType(DESC_USHORT_4444_ARGB,
|
||||
PixelConverter.Ushort4444Argb.instance);
|
||||
|
||||
public static final SurfaceType UshortIndexed =
|
||||
AnyShort.deriveSubType(DESC_USHORT_INDEXED);
|
||||
|
||||
public static final SurfaceType ByteGray =
|
||||
AnyByte.deriveSubType(DESC_BYTE_GRAY,
|
||||
PixelConverter.ByteGray.instance);
|
||||
|
||||
public static final SurfaceType UshortGray =
|
||||
AnyShort.deriveSubType(DESC_USHORT_GRAY,
|
||||
PixelConverter.UshortGray.instance);
|
||||
|
||||
public static final SurfaceType ByteBinary1Bit =
|
||||
AnyByteBinary.deriveSubType(DESC_BYTE_BINARY_1BIT);
|
||||
public static final SurfaceType ByteBinary2Bit =
|
||||
AnyByteBinary.deriveSubType(DESC_BYTE_BINARY_2BIT);
|
||||
public static final SurfaceType ByteBinary4Bit =
|
||||
AnyByteBinary.deriveSubType(DESC_BYTE_BINARY_4BIT);
|
||||
|
||||
public static final SurfaceType ByteIndexed =
|
||||
AnyByte.deriveSubType(DESC_BYTE_INDEXED);
|
||||
|
||||
public static final SurfaceType IntRgbx =
|
||||
AnyDcm.deriveSubType(DESC_INT_RGBx, PixelConverter.Rgbx.instance);
|
||||
|
||||
public static final SurfaceType IntBgrx =
|
||||
AnyDcm.deriveSubType(DESC_INT_BGRx, PixelConverter.Bgrx.instance);
|
||||
|
||||
public static final SurfaceType ThreeByteRgb =
|
||||
Any3Byte.deriveSubType(DESC_3BYTE_RGB, PixelConverter.Xbgr.instance);
|
||||
|
||||
public static final SurfaceType IntArgbBm =
|
||||
AnyDcm.deriveSubType(DESC_INT_ARGB_BM, PixelConverter.ArgbBm.instance);
|
||||
|
||||
public static final SurfaceType ByteIndexedBm =
|
||||
ByteIndexed.deriveSubType(DESC_BYTE_INDEXED_BM);
|
||||
|
||||
public static final SurfaceType ByteIndexedOpaque =
|
||||
ByteIndexedBm.deriveSubType(DESC_BYTE_INDEXED_OPAQUE);
|
||||
|
||||
public static final SurfaceType Index8Gray =
|
||||
ByteIndexedOpaque.deriveSubType(DESC_INDEX8_GRAY);
|
||||
|
||||
public static final SurfaceType Index12Gray =
|
||||
Any.deriveSubType(DESC_INDEX12_GRAY);
|
||||
|
||||
public static final SurfaceType AnyPaint =
|
||||
Any.deriveSubType(DESC_ANY_PAINT);
|
||||
|
||||
public static final SurfaceType AnyColor =
|
||||
AnyPaint.deriveSubType(DESC_ANY_COLOR);
|
||||
|
||||
public static final SurfaceType OpaqueColor =
|
||||
AnyColor.deriveSubType(DESC_OPAQUE_COLOR);
|
||||
|
||||
public static final SurfaceType GradientPaint =
|
||||
AnyPaint.deriveSubType(DESC_GRADIENT_PAINT);
|
||||
public static final SurfaceType OpaqueGradientPaint =
|
||||
GradientPaint.deriveSubType(DESC_OPAQUE_GRADIENT_PAINT);
|
||||
|
||||
public static final SurfaceType LinearGradientPaint =
|
||||
AnyPaint.deriveSubType(DESC_LINEAR_GRADIENT_PAINT);
|
||||
public static final SurfaceType OpaqueLinearGradientPaint =
|
||||
LinearGradientPaint.deriveSubType(DESC_OPAQUE_LINEAR_GRADIENT_PAINT);
|
||||
|
||||
public static final SurfaceType RadialGradientPaint =
|
||||
AnyPaint.deriveSubType(DESC_RADIAL_GRADIENT_PAINT);
|
||||
public static final SurfaceType OpaqueRadialGradientPaint =
|
||||
RadialGradientPaint.deriveSubType(DESC_OPAQUE_RADIAL_GRADIENT_PAINT);
|
||||
|
||||
public static final SurfaceType TexturePaint =
|
||||
AnyPaint.deriveSubType(DESC_TEXTURE_PAINT);
|
||||
public static final SurfaceType OpaqueTexturePaint =
|
||||
TexturePaint.deriveSubType(DESC_OPAQUE_TEXTURE_PAINT);
|
||||
|
||||
/*
|
||||
* END OF SurfaceType OBJECTS FOR THE VARIOUS CONSTANTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* Return a new SurfaceType object which uses this object as its
|
||||
* more general "supertype" descriptor. If no operation can be
|
||||
* found that manipulates the type of surface described more exactly
|
||||
* by desc, then this object will define the more relaxed specification
|
||||
* of the surface that can be used to find a more general operator.
|
||||
*/
|
||||
public SurfaceType deriveSubType(String desc) {
|
||||
return new SurfaceType(this, desc);
|
||||
}
|
||||
|
||||
public SurfaceType deriveSubType(String desc,
|
||||
PixelConverter pixelConverter) {
|
||||
return new SurfaceType(this, desc, pixelConverter);
|
||||
}
|
||||
|
||||
private int uniqueID;
|
||||
private String desc;
|
||||
private SurfaceType next;
|
||||
protected PixelConverter pixelConverter;
|
||||
|
||||
private SurfaceType(SurfaceType parent, String desc,
|
||||
PixelConverter pixelConverter) {
|
||||
next = parent;
|
||||
this.desc = desc;
|
||||
this.uniqueID = makeUniqueID(desc);
|
||||
this.pixelConverter = pixelConverter;
|
||||
}
|
||||
|
||||
private SurfaceType(SurfaceType parent, String desc) {
|
||||
next = parent;
|
||||
this.desc = desc;
|
||||
this.uniqueID = makeUniqueID(desc);
|
||||
this.pixelConverter = parent.pixelConverter;
|
||||
}
|
||||
|
||||
public synchronized static final int makeUniqueID(String desc) {
|
||||
Integer i = surfaceUIDMap.get(desc);
|
||||
|
||||
if (i == null) {
|
||||
if (unusedUID > 255) {
|
||||
throw new InternalError("surface type id overflow");
|
||||
}
|
||||
i = Integer.valueOf(unusedUID++);
|
||||
surfaceUIDMap.put(desc, i);
|
||||
}
|
||||
return i.intValue();
|
||||
}
|
||||
|
||||
public int getUniqueID() {
|
||||
return uniqueID;
|
||||
}
|
||||
|
||||
public String getDescriptor() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public SurfaceType getSuperType() {
|
||||
return next;
|
||||
}
|
||||
|
||||
public PixelConverter getPixelConverter() {
|
||||
return pixelConverter;
|
||||
}
|
||||
|
||||
public int pixelFor(int rgb, ColorModel cm) {
|
||||
return pixelConverter.rgbToPixel(rgb, cm);
|
||||
}
|
||||
|
||||
public int rgbFor(int pixel, ColorModel cm) {
|
||||
return pixelConverter.pixelToRgb(pixel, cm);
|
||||
}
|
||||
|
||||
public int getAlphaMask() {
|
||||
return pixelConverter.getAlphaMask();
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return desc.hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof SurfaceType) {
|
||||
return (((SurfaceType) o).uniqueID == this.uniqueID);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
}
|
||||
157
jdkSrc/jdk8/sun/java2d/loops/TransformBlit.java
Normal file
157
jdkSrc/jdk8/sun/java2d/loops/TransformBlit.java
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import java.awt.Composite;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.lang.ref.WeakReference;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.pipe.Region;
|
||||
|
||||
/**
|
||||
* TransformBlit
|
||||
* 1) applies an AffineTransform to a rectangle of pixels while copying
|
||||
* from one surface to another
|
||||
* 2) performs compositing of colors based upon a Composite
|
||||
* parameter
|
||||
*
|
||||
* precise behavior is undefined if the source surface
|
||||
* and the destination surface are the same surface
|
||||
* with overlapping regions of pixels
|
||||
*/
|
||||
|
||||
public class TransformBlit extends GraphicsPrimitive
|
||||
{
|
||||
public static final String methodSignature =
|
||||
"TransformBlit(...)".toString();
|
||||
|
||||
public static final int primTypeID = makePrimTypeID();
|
||||
|
||||
private static RenderCache blitcache = new RenderCache(10);
|
||||
|
||||
public static TransformBlit locate(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return (TransformBlit)
|
||||
GraphicsPrimitiveMgr.locate(primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public static TransformBlit getFromCache(SurfaceType src,
|
||||
CompositeType comp,
|
||||
SurfaceType dst)
|
||||
{
|
||||
Object o = blitcache.get(src, comp, dst);
|
||||
if (o != null) {
|
||||
return (TransformBlit) o;
|
||||
}
|
||||
TransformBlit blit = locate(src, comp, dst);
|
||||
if (blit == null) {
|
||||
/*
|
||||
System.out.println("blit loop not found for:");
|
||||
System.out.println("src: "+src);
|
||||
System.out.println("comp: "+comp);
|
||||
System.out.println("dst: "+dst);
|
||||
*/
|
||||
} else {
|
||||
blitcache.put(src, comp, dst, blit);
|
||||
}
|
||||
return blit;
|
||||
}
|
||||
|
||||
protected TransformBlit(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(methodSignature, primTypeID, srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public TransformBlit(long pNativePrim,
|
||||
SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(pNativePrim, methodSignature, primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public native void Transform(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform at, int hint,
|
||||
int srcx, int srcy, int dstx, int dsty,
|
||||
int width, int height);
|
||||
|
||||
// REMIND: do we have a general loop?
|
||||
static {
|
||||
GraphicsPrimitiveMgr.registerGeneral(new TransformBlit(null, null,
|
||||
null));
|
||||
}
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
/*
|
||||
System.out.println("Constructing general blit for:");
|
||||
System.out.println("src: "+srctype);
|
||||
System.out.println("comp: "+comptype);
|
||||
System.out.println("dst: "+dsttype);
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return new TraceTransformBlit(this);
|
||||
}
|
||||
|
||||
private static class TraceTransformBlit extends TransformBlit {
|
||||
TransformBlit target;
|
||||
|
||||
public TraceTransformBlit(TransformBlit target) {
|
||||
super(target.getSourceType(),
|
||||
target.getCompositeType(),
|
||||
target.getDestType());
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Transform(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform at, int hint,
|
||||
int srcx, int srcy, int dstx, int dsty,
|
||||
int width, int height)
|
||||
{
|
||||
tracePrimitive(target);
|
||||
target.Transform(src, dst, comp, clip, at, hint,
|
||||
srcx, srcy, dstx, dsty, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
140
jdkSrc/jdk8/sun/java2d/loops/TransformHelper.java
Normal file
140
jdkSrc/jdk8/sun/java2d/loops/TransformHelper.java
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import java.awt.Composite;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.lang.ref.WeakReference;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.pipe.Region;
|
||||
|
||||
/**
|
||||
* TransformHelper
|
||||
* 1) applies an AffineTransform to a rectangle of pixels while copying
|
||||
* from one surface to another
|
||||
* 2) performs compositing of colors based upon a Composite
|
||||
* parameter
|
||||
*
|
||||
* precise behavior is undefined if the source surface
|
||||
* and the destination surface are the same surface
|
||||
* with overlapping regions of pixels
|
||||
*/
|
||||
public class TransformHelper extends GraphicsPrimitive
|
||||
{
|
||||
public static final String methodSignature =
|
||||
"TransformHelper(...)".toString();
|
||||
|
||||
public static final int primTypeID = makePrimTypeID();
|
||||
|
||||
private static RenderCache helpercache = new RenderCache(10);
|
||||
|
||||
public static TransformHelper locate(SurfaceType srctype) {
|
||||
return (TransformHelper)
|
||||
GraphicsPrimitiveMgr.locate(primTypeID,
|
||||
srctype,
|
||||
CompositeType.SrcNoEa,
|
||||
SurfaceType.IntArgbPre);
|
||||
}
|
||||
|
||||
public static synchronized TransformHelper getFromCache(SurfaceType src) {
|
||||
Object o = helpercache.get(src, null, null);
|
||||
if (o != null) {
|
||||
return (TransformHelper) o;
|
||||
}
|
||||
TransformHelper helper = locate(src);
|
||||
if (helper == null) {
|
||||
/*
|
||||
System.out.println("helper loop not found for:");
|
||||
System.out.println("src: "+src);
|
||||
*/
|
||||
} else {
|
||||
helpercache.put(src, null, null, helper);
|
||||
}
|
||||
return helper;
|
||||
}
|
||||
|
||||
protected TransformHelper(SurfaceType srctype) {
|
||||
super(methodSignature, primTypeID, srctype,
|
||||
CompositeType.SrcNoEa,
|
||||
SurfaceType.IntArgbPre);
|
||||
}
|
||||
|
||||
public TransformHelper(long pNativePrim, SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
super(pNativePrim, methodSignature, primTypeID,
|
||||
srctype, comptype, dsttype);
|
||||
}
|
||||
|
||||
public native void Transform(MaskBlit output,
|
||||
SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform itx, int txtype,
|
||||
int sx1, int sy1, int sx2, int sy2,
|
||||
int dx1, int dy1, int dx2, int dy2,
|
||||
int edges[], int dxoff, int dyoff);
|
||||
|
||||
public GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
CompositeType comptype,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return new TraceTransformHelper(this);
|
||||
}
|
||||
|
||||
private static class TraceTransformHelper extends TransformHelper {
|
||||
TransformHelper target;
|
||||
|
||||
public TraceTransformHelper(TransformHelper target) {
|
||||
super(target.getSourceType());
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public GraphicsPrimitive traceWrap() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Transform(MaskBlit output,
|
||||
SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform itx, int txtype,
|
||||
int sx1, int sy1, int sx2, int sy2,
|
||||
int dx1, int dy1, int dx2, int dy2,
|
||||
int edges[], int dxoff, int dyoff)
|
||||
{
|
||||
tracePrimitive(target);
|
||||
target.Transform(output, src, dst, comp, clip, itx, txtype,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2,
|
||||
edges, dxoff, dyoff);
|
||||
}
|
||||
}
|
||||
}
|
||||
72
jdkSrc/jdk8/sun/java2d/loops/XORComposite.java
Normal file
72
jdkSrc/jdk8/sun/java2d/loops/XORComposite.java
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2002, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.loops;
|
||||
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
import java.awt.CompositeContext;
|
||||
import java.awt.RenderingHints;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.SunCompositeContext;
|
||||
|
||||
/**
|
||||
* Bitwise XOR Composite class.
|
||||
*/
|
||||
|
||||
public final class XORComposite implements Composite {
|
||||
|
||||
Color xorColor;
|
||||
int xorPixel;
|
||||
int alphaMask;
|
||||
|
||||
public XORComposite(Color xorColor, SurfaceData sd) {
|
||||
this.xorColor = xorColor;
|
||||
|
||||
SurfaceType sType = sd.getSurfaceType();
|
||||
|
||||
this.xorPixel = sd.pixelFor(xorColor.getRGB());
|
||||
this.alphaMask = sType.getAlphaMask();
|
||||
}
|
||||
|
||||
public Color getXorColor() {
|
||||
return xorColor;
|
||||
}
|
||||
|
||||
public int getXorPixel() {
|
||||
return xorPixel;
|
||||
}
|
||||
|
||||
public int getAlphaMask() {
|
||||
return alphaMask;
|
||||
}
|
||||
|
||||
public CompositeContext createContext(ColorModel srcColorModel,
|
||||
ColorModel dstColorModel,
|
||||
RenderingHints hints) {
|
||||
return new SunCompositeContext(this, srcColorModel, dstColorModel);
|
||||
}
|
||||
}
|
||||
232
jdkSrc/jdk8/sun/java2d/marlin/ArrayCache.java
Normal file
232
jdkSrc/jdk8/sun/java2d/marlin/ArrayCache.java
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.marlin;
|
||||
|
||||
import java.util.Arrays;
|
||||
import static sun.java2d.marlin.MarlinUtils.logInfo;
|
||||
|
||||
public final class ArrayCache implements MarlinConst {
|
||||
|
||||
static final int BUCKETS = 4;
|
||||
static final int MIN_ARRAY_SIZE = 4096;
|
||||
static final int MAX_ARRAY_SIZE;
|
||||
static final int MASK_CLR_1 = ~1;
|
||||
// threshold to grow arrays only by (3/2) instead of 2
|
||||
static final int THRESHOLD_ARRAY_SIZE;
|
||||
static final int[] ARRAY_SIZES = new int[BUCKETS];
|
||||
// dirty byte array sizes
|
||||
static final int MIN_DIRTY_BYTE_ARRAY_SIZE = 32 * 2048; // 32px x 2048px
|
||||
static final int MAX_DIRTY_BYTE_ARRAY_SIZE;
|
||||
static final int[] DIRTY_BYTE_ARRAY_SIZES = new int[BUCKETS];
|
||||
// large array thresholds:
|
||||
static final long THRESHOLD_LARGE_ARRAY_SIZE;
|
||||
static final long THRESHOLD_HUGE_ARRAY_SIZE;
|
||||
// stats
|
||||
private static int resizeInt = 0;
|
||||
private static int resizeDirtyInt = 0;
|
||||
private static int resizeDirtyFloat = 0;
|
||||
private static int resizeDirtyByte = 0;
|
||||
private static int oversize = 0;
|
||||
|
||||
static {
|
||||
// initialize buckets for int/float arrays
|
||||
int arraySize = MIN_ARRAY_SIZE;
|
||||
|
||||
for (int i = 0; i < BUCKETS; i++, arraySize <<= 2) {
|
||||
ARRAY_SIZES[i] = arraySize;
|
||||
|
||||
if (doTrace) {
|
||||
logInfo("arraySize[" + i + "]: " + arraySize);
|
||||
}
|
||||
}
|
||||
MAX_ARRAY_SIZE = arraySize >> 2;
|
||||
|
||||
/* initialize buckets for dirty byte arrays
|
||||
(large AA chunk = 32 x 2048 pixels) */
|
||||
arraySize = MIN_DIRTY_BYTE_ARRAY_SIZE;
|
||||
|
||||
for (int i = 0; i < BUCKETS; i++, arraySize <<= 1) {
|
||||
DIRTY_BYTE_ARRAY_SIZES[i] = arraySize;
|
||||
|
||||
if (doTrace) {
|
||||
logInfo("dirty arraySize[" + i + "]: " + arraySize);
|
||||
}
|
||||
}
|
||||
MAX_DIRTY_BYTE_ARRAY_SIZE = arraySize >> 1;
|
||||
|
||||
// threshold to grow arrays only by (3/2) instead of 2
|
||||
THRESHOLD_ARRAY_SIZE = Math.max(2 * 1024 * 1024, MAX_ARRAY_SIZE); // 2M
|
||||
|
||||
THRESHOLD_LARGE_ARRAY_SIZE = 8L * THRESHOLD_ARRAY_SIZE; // 16M
|
||||
THRESHOLD_HUGE_ARRAY_SIZE = 8L * THRESHOLD_LARGE_ARRAY_SIZE; // 128M
|
||||
|
||||
if (doStats || doMonitors) {
|
||||
logInfo("ArrayCache.BUCKETS = " + BUCKETS);
|
||||
logInfo("ArrayCache.MIN_ARRAY_SIZE = " + MIN_ARRAY_SIZE);
|
||||
logInfo("ArrayCache.MAX_ARRAY_SIZE = " + MAX_ARRAY_SIZE);
|
||||
logInfo("ArrayCache.ARRAY_SIZES = "
|
||||
+ Arrays.toString(ARRAY_SIZES));
|
||||
logInfo("ArrayCache.MIN_DIRTY_BYTE_ARRAY_SIZE = "
|
||||
+ MIN_DIRTY_BYTE_ARRAY_SIZE);
|
||||
logInfo("ArrayCache.MAX_DIRTY_BYTE_ARRAY_SIZE = "
|
||||
+ MAX_DIRTY_BYTE_ARRAY_SIZE);
|
||||
logInfo("ArrayCache.ARRAY_SIZES = "
|
||||
+ Arrays.toString(DIRTY_BYTE_ARRAY_SIZES));
|
||||
logInfo("ArrayCache.THRESHOLD_ARRAY_SIZE = "
|
||||
+ THRESHOLD_ARRAY_SIZE);
|
||||
logInfo("ArrayCache.THRESHOLD_LARGE_ARRAY_SIZE = "
|
||||
+ THRESHOLD_LARGE_ARRAY_SIZE);
|
||||
logInfo("ArrayCache.THRESHOLD_HUGE_ARRAY_SIZE = "
|
||||
+ THRESHOLD_HUGE_ARRAY_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayCache() {
|
||||
// Utility class
|
||||
}
|
||||
|
||||
static synchronized void incResizeInt() {
|
||||
resizeInt++;
|
||||
}
|
||||
|
||||
static synchronized void incResizeDirtyInt() {
|
||||
resizeDirtyInt++;
|
||||
}
|
||||
|
||||
static synchronized void incResizeDirtyFloat() {
|
||||
resizeDirtyFloat++;
|
||||
}
|
||||
|
||||
static synchronized void incResizeDirtyByte() {
|
||||
resizeDirtyByte++;
|
||||
}
|
||||
|
||||
static synchronized void incOversize() {
|
||||
oversize++;
|
||||
}
|
||||
|
||||
static void dumpStats() {
|
||||
if (resizeInt != 0 || resizeDirtyInt != 0 || resizeDirtyFloat != 0
|
||||
|| resizeDirtyByte != 0 || oversize != 0) {
|
||||
logInfo("ArrayCache: int resize: " + resizeInt
|
||||
+ " - dirty int resize: " + resizeDirtyInt
|
||||
+ " - dirty float resize: " + resizeDirtyFloat
|
||||
+ " - dirty byte resize: " + resizeDirtyByte
|
||||
+ " - oversize: " + oversize);
|
||||
}
|
||||
}
|
||||
|
||||
// small methods used a lot (to be inlined / optimized by hotspot)
|
||||
|
||||
static int getBucket(final int length) {
|
||||
for (int i = 0; i < ARRAY_SIZES.length; i++) {
|
||||
if (length <= ARRAY_SIZES[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int getBucketDirtyBytes(final int length) {
|
||||
for (int i = 0; i < DIRTY_BYTE_ARRAY_SIZES.length; i++) {
|
||||
if (length <= DIRTY_BYTE_ARRAY_SIZES[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the new array size (~ x2)
|
||||
* @param curSize current used size
|
||||
* @param needSize needed size
|
||||
* @return new array size
|
||||
*/
|
||||
public static int getNewSize(final int curSize, final int needSize) {
|
||||
// check if needSize is negative or integer overflow:
|
||||
if (needSize < 0) {
|
||||
// hard overflow failure - we can't even accommodate
|
||||
// new items without overflowing
|
||||
throw new ArrayIndexOutOfBoundsException(
|
||||
"array exceeds maximum capacity !");
|
||||
}
|
||||
assert curSize >= 0;
|
||||
final int initial = (curSize & MASK_CLR_1);
|
||||
int size;
|
||||
if (initial > THRESHOLD_ARRAY_SIZE) {
|
||||
size = initial + (initial >> 1); // x(3/2)
|
||||
} else {
|
||||
size = (initial << 1); // x2
|
||||
}
|
||||
// ensure the new size is >= needed size:
|
||||
if (size < needSize) {
|
||||
// align to 4096 (may overflow):
|
||||
size = ((needSize >> 12) + 1) << 12;
|
||||
}
|
||||
// check integer overflow:
|
||||
if (size < 0) {
|
||||
// resize to maximum capacity:
|
||||
size = Integer.MAX_VALUE;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the new array size (~ x2)
|
||||
* @param curSize current used size
|
||||
* @param needSize needed size
|
||||
* @return new array size
|
||||
*/
|
||||
public static long getNewLargeSize(final long curSize, final long needSize) {
|
||||
// check if needSize is negative or integer overflow:
|
||||
if ((needSize >> 31L) != 0L) {
|
||||
// hard overflow failure - we can't even accommodate
|
||||
// new items without overflowing
|
||||
throw new ArrayIndexOutOfBoundsException(
|
||||
"array exceeds maximum capacity !");
|
||||
}
|
||||
assert curSize >= 0L;
|
||||
long size;
|
||||
if (curSize > THRESHOLD_HUGE_ARRAY_SIZE) {
|
||||
size = curSize + (curSize >> 2L); // x(5/4)
|
||||
} else if (curSize > THRESHOLD_LARGE_ARRAY_SIZE) {
|
||||
size = curSize + (curSize >> 1L); // x(3/2)
|
||||
} else {
|
||||
size = (curSize << 1L); // x2
|
||||
}
|
||||
// ensure the new size is >= needed size:
|
||||
if (size < needSize) {
|
||||
// align to 4096:
|
||||
size = ((needSize >> 12L) + 1L) << 12L;
|
||||
}
|
||||
// check integer overflow:
|
||||
if (size > Integer.MAX_VALUE) {
|
||||
// resize to maximum capacity:
|
||||
size = Integer.MAX_VALUE;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
||||
152
jdkSrc/jdk8/sun/java2d/marlin/ByteArrayCache.java
Normal file
152
jdkSrc/jdk8/sun/java2d/marlin/ByteArrayCache.java
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.marlin;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Arrays;
|
||||
import static sun.java2d.marlin.MarlinUtils.logException;
|
||||
import static sun.java2d.marlin.MarlinUtils.logInfo;
|
||||
|
||||
final class ByteArrayCache implements MarlinConst {
|
||||
|
||||
private final int arraySize;
|
||||
private final ArrayDeque<byte[]> byteArrays;
|
||||
// stats
|
||||
private int getOp = 0;
|
||||
private int createOp = 0;
|
||||
private int returnOp = 0;
|
||||
|
||||
void dumpStats() {
|
||||
if (getOp > 0) {
|
||||
logInfo("ByteArrayCache[" + arraySize + "]: get: " + getOp
|
||||
+ " created: " + createOp + " - returned: " + returnOp
|
||||
+ " :: cache size: " + byteArrays.size());
|
||||
}
|
||||
}
|
||||
|
||||
ByteArrayCache(final int arraySize) {
|
||||
this.arraySize = arraySize;
|
||||
// small but enough: almost 1 cache line
|
||||
this.byteArrays = new ArrayDeque<byte[]>(6);
|
||||
}
|
||||
|
||||
byte[] getArray() {
|
||||
if (doStats) {
|
||||
getOp++;
|
||||
}
|
||||
|
||||
// use cache:
|
||||
final byte[] array = byteArrays.pollLast();
|
||||
if (array != null) {
|
||||
return array;
|
||||
}
|
||||
|
||||
if (doStats) {
|
||||
createOp++;
|
||||
}
|
||||
|
||||
return new byte[arraySize];
|
||||
}
|
||||
|
||||
void putDirtyArray(final byte[] array, final int length) {
|
||||
if (length != arraySize) {
|
||||
if (doChecks) {
|
||||
MarlinUtils.logInfo("ArrayCache: bad length = " + length);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (doStats) {
|
||||
returnOp++;
|
||||
}
|
||||
|
||||
// NO clean-up of array data = DIRTY ARRAY
|
||||
|
||||
if (doCleanDirty) {
|
||||
// Force zero-fill dirty arrays:
|
||||
Arrays.fill(array, 0, array.length, BYTE_0);
|
||||
}
|
||||
|
||||
// fill cache:
|
||||
byteArrays.addLast(array);
|
||||
}
|
||||
|
||||
void putArray(final byte[] array, final int length,
|
||||
final int fromIndex, final int toIndex)
|
||||
{
|
||||
if (length != arraySize) {
|
||||
if (doChecks) {
|
||||
MarlinUtils.logInfo("ArrayCache: bad length = " + length);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (doStats) {
|
||||
returnOp++;
|
||||
}
|
||||
|
||||
// clean-up array of dirty part[fromIndex; toIndex[
|
||||
fill(array, fromIndex, toIndex, BYTE_0);
|
||||
|
||||
// fill cache:
|
||||
byteArrays.addLast(array);
|
||||
}
|
||||
|
||||
static void fill(final byte[] array, final int fromIndex,
|
||||
final int toIndex, final byte value)
|
||||
{
|
||||
// clear array data:
|
||||
/*
|
||||
* Arrays.fill is faster than System.arraycopy(empty array)
|
||||
* or Unsafe.setMemory(byte 0)
|
||||
*/
|
||||
if (toIndex != 0) {
|
||||
Arrays.fill(array, fromIndex, toIndex, value);
|
||||
}
|
||||
|
||||
if (doChecks) {
|
||||
check(array, fromIndex, toIndex, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void check(final byte[] array, final int fromIndex,
|
||||
final int toIndex, final byte value)
|
||||
{
|
||||
if (doChecks) {
|
||||
// check zero on full array:
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
if (array[i] != value) {
|
||||
logException("Invalid value at: " + i + " = " + array[i]
|
||||
+ " from: " + fromIndex + " to: " + toIndex + "\n"
|
||||
+ Arrays.toString(array), new Throwable());
|
||||
|
||||
// ensure array is correctly filled:
|
||||
Arrays.fill(array, value);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
155
jdkSrc/jdk8/sun/java2d/marlin/CollinearSimplifier.java
Normal file
155
jdkSrc/jdk8/sun/java2d/marlin/CollinearSimplifier.java
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.marlin;
|
||||
|
||||
import sun.awt.geom.PathConsumer2D;
|
||||
|
||||
final class CollinearSimplifier implements PathConsumer2D {
|
||||
|
||||
enum SimplifierState {
|
||||
|
||||
Empty, PreviousPoint, PreviousLine
|
||||
};
|
||||
// slope precision threshold
|
||||
static final float EPS = 1e-4f; // aaime proposed 1e-3f
|
||||
|
||||
PathConsumer2D delegate;
|
||||
SimplifierState state;
|
||||
float px1, py1, px2, py2;
|
||||
float pslope;
|
||||
|
||||
CollinearSimplifier() {
|
||||
}
|
||||
|
||||
public CollinearSimplifier init(PathConsumer2D delegate) {
|
||||
this.delegate = delegate;
|
||||
this.state = SimplifierState.Empty;
|
||||
|
||||
return this; // fluent API
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pathDone() {
|
||||
emitStashedLine();
|
||||
state = SimplifierState.Empty;
|
||||
delegate.pathDone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closePath() {
|
||||
emitStashedLine();
|
||||
state = SimplifierState.Empty;
|
||||
delegate.closePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getNativeConsumer() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void quadTo(float x1, float y1, float x2, float y2) {
|
||||
emitStashedLine();
|
||||
delegate.quadTo(x1, y1, x2, y2);
|
||||
// final end point:
|
||||
state = SimplifierState.PreviousPoint;
|
||||
px1 = x2;
|
||||
py1 = y2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void curveTo(float x1, float y1, float x2, float y2,
|
||||
float x3, float y3) {
|
||||
emitStashedLine();
|
||||
delegate.curveTo(x1, y1, x2, y2, x3, y3);
|
||||
// final end point:
|
||||
state = SimplifierState.PreviousPoint;
|
||||
px1 = x3;
|
||||
py1 = y3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveTo(float x, float y) {
|
||||
emitStashedLine();
|
||||
delegate.moveTo(x, y);
|
||||
state = SimplifierState.PreviousPoint;
|
||||
px1 = x;
|
||||
py1 = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lineTo(final float x, final float y) {
|
||||
switch (state) {
|
||||
case Empty:
|
||||
delegate.lineTo(x, y);
|
||||
state = SimplifierState.PreviousPoint;
|
||||
px1 = x;
|
||||
py1 = y;
|
||||
return;
|
||||
|
||||
case PreviousPoint:
|
||||
state = SimplifierState.PreviousLine;
|
||||
px2 = x;
|
||||
py2 = y;
|
||||
pslope = getSlope(px1, py1, x, y);
|
||||
return;
|
||||
|
||||
case PreviousLine:
|
||||
final float slope = getSlope(px2, py2, x, y);
|
||||
// test for collinearity
|
||||
if ((slope == pslope) || (Math.abs(pslope - slope) < EPS)) {
|
||||
// merge segments
|
||||
px2 = x;
|
||||
py2 = y;
|
||||
return;
|
||||
}
|
||||
// emit previous segment
|
||||
delegate.lineTo(px2, py2);
|
||||
px1 = px2;
|
||||
py1 = py2;
|
||||
px2 = x;
|
||||
py2 = y;
|
||||
pslope = slope;
|
||||
return;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
private void emitStashedLine() {
|
||||
if (state == SimplifierState.PreviousLine) {
|
||||
delegate.lineTo(px2, py2);
|
||||
}
|
||||
}
|
||||
|
||||
private static float getSlope(float x1, float y1, float x2, float y2) {
|
||||
float dy = y2 - y1;
|
||||
if (dy == 0f) {
|
||||
return (x2 > x1) ? Float.POSITIVE_INFINITY
|
||||
: Float.NEGATIVE_INFINITY;
|
||||
}
|
||||
return (x2 - x1) / dy;
|
||||
}
|
||||
}
|
||||
306
jdkSrc/jdk8/sun/java2d/marlin/Curve.java
Normal file
306
jdkSrc/jdk8/sun/java2d/marlin/Curve.java
Normal file
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.marlin;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
final class Curve {
|
||||
|
||||
float ax, ay, bx, by, cx, cy, dx, dy;
|
||||
float dax, day, dbx, dby;
|
||||
// shared iterator instance
|
||||
private final BreakPtrIterator iterator = new BreakPtrIterator();
|
||||
|
||||
Curve() {
|
||||
}
|
||||
|
||||
void set(float[] points, int type) {
|
||||
switch(type) {
|
||||
case 8:
|
||||
set(points[0], points[1],
|
||||
points[2], points[3],
|
||||
points[4], points[5],
|
||||
points[6], points[7]);
|
||||
return;
|
||||
case 6:
|
||||
set(points[0], points[1],
|
||||
points[2], points[3],
|
||||
points[4], points[5]);
|
||||
return;
|
||||
default:
|
||||
throw new InternalError("Curves can only be cubic or quadratic");
|
||||
}
|
||||
}
|
||||
|
||||
void set(float x1, float y1,
|
||||
float x2, float y2,
|
||||
float x3, float y3,
|
||||
float x4, float y4)
|
||||
{
|
||||
ax = 3f * (x2 - x3) + x4 - x1;
|
||||
ay = 3f * (y2 - y3) + y4 - y1;
|
||||
bx = 3f * (x1 - 2f * x2 + x3);
|
||||
by = 3f * (y1 - 2f * y2 + y3);
|
||||
cx = 3f * (x2 - x1);
|
||||
cy = 3f * (y2 - y1);
|
||||
dx = x1;
|
||||
dy = y1;
|
||||
dax = 3f * ax; day = 3f * ay;
|
||||
dbx = 2f * bx; dby = 2f * by;
|
||||
}
|
||||
|
||||
void set(float x1, float y1,
|
||||
float x2, float y2,
|
||||
float x3, float y3)
|
||||
{
|
||||
ax = 0f; ay = 0f;
|
||||
bx = x1 - 2f * x2 + x3;
|
||||
by = y1 - 2f * y2 + y3;
|
||||
cx = 2f * (x2 - x1);
|
||||
cy = 2f * (y2 - y1);
|
||||
dx = x1;
|
||||
dy = y1;
|
||||
dax = 0f; day = 0f;
|
||||
dbx = 2f * bx; dby = 2f * by;
|
||||
}
|
||||
|
||||
float xat(float t) {
|
||||
return t * (t * (t * ax + bx) + cx) + dx;
|
||||
}
|
||||
float yat(float t) {
|
||||
return t * (t * (t * ay + by) + cy) + dy;
|
||||
}
|
||||
|
||||
float dxat(float t) {
|
||||
return t * (t * dax + dbx) + cx;
|
||||
}
|
||||
|
||||
float dyat(float t) {
|
||||
return t * (t * day + dby) + cy;
|
||||
}
|
||||
|
||||
int dxRoots(float[] roots, int off) {
|
||||
return Helpers.quadraticRoots(dax, dbx, cx, roots, off);
|
||||
}
|
||||
|
||||
int dyRoots(float[] roots, int off) {
|
||||
return Helpers.quadraticRoots(day, dby, cy, roots, off);
|
||||
}
|
||||
|
||||
int infPoints(float[] pts, int off) {
|
||||
// inflection point at t if -f'(t)x*f''(t)y + f'(t)y*f''(t)x == 0
|
||||
// Fortunately, this turns out to be quadratic, so there are at
|
||||
// most 2 inflection points.
|
||||
final float a = dax * dby - dbx * day;
|
||||
final float b = 2f * (cy * dax - day * cx);
|
||||
final float c = cy * dbx - cx * dby;
|
||||
|
||||
return Helpers.quadraticRoots(a, b, c, pts, off);
|
||||
}
|
||||
|
||||
// finds points where the first and second derivative are
|
||||
// perpendicular. This happens when g(t) = f'(t)*f''(t) == 0 (where
|
||||
// * is a dot product). Unfortunately, we have to solve a cubic.
|
||||
private int perpendiculardfddf(float[] pts, int off) {
|
||||
assert pts.length >= off + 4;
|
||||
|
||||
// these are the coefficients of some multiple of g(t) (not g(t),
|
||||
// because the roots of a polynomial are not changed after multiplication
|
||||
// by a constant, and this way we save a few multiplications).
|
||||
final float a = 2f * (dax*dax + day*day);
|
||||
final float b = 3f * (dax*dbx + day*dby);
|
||||
final float c = 2f * (dax*cx + day*cy) + dbx*dbx + dby*dby;
|
||||
final float d = dbx*cx + dby*cy;
|
||||
return Helpers.cubicRootsInAB(a, b, c, d, pts, off, 0f, 1f);
|
||||
}
|
||||
|
||||
// Tries to find the roots of the function ROC(t)-w in [0, 1). It uses
|
||||
// a variant of the false position algorithm to find the roots. False
|
||||
// position requires that 2 initial values x0,x1 be given, and that the
|
||||
// function must have opposite signs at those values. To find such
|
||||
// values, we need the local extrema of the ROC function, for which we
|
||||
// need the roots of its derivative; however, it's harder to find the
|
||||
// roots of the derivative in this case than it is to find the roots
|
||||
// of the original function. So, we find all points where this curve's
|
||||
// first and second derivative are perpendicular, and we pretend these
|
||||
// are our local extrema. There are at most 3 of these, so we will check
|
||||
// at most 4 sub-intervals of (0,1). ROC has asymptotes at inflection
|
||||
// points, so roc-w can have at least 6 roots. This shouldn't be a
|
||||
// problem for what we're trying to do (draw a nice looking curve).
|
||||
int rootsOfROCMinusW(float[] roots, int off, final float w, final float err) {
|
||||
// no OOB exception, because by now off<=6, and roots.length >= 10
|
||||
assert off <= 6 && roots.length >= 10;
|
||||
int ret = off;
|
||||
int numPerpdfddf = perpendiculardfddf(roots, off);
|
||||
float t0 = 0, ft0 = ROCsq(t0) - w*w;
|
||||
roots[off + numPerpdfddf] = 1f; // always check interval end points
|
||||
numPerpdfddf++;
|
||||
for (int i = off; i < off + numPerpdfddf; i++) {
|
||||
float t1 = roots[i], ft1 = ROCsq(t1) - w*w;
|
||||
if (ft0 == 0f) {
|
||||
roots[ret++] = t0;
|
||||
} else if (ft1 * ft0 < 0f) { // have opposite signs
|
||||
// (ROC(t)^2 == w^2) == (ROC(t) == w) is true because
|
||||
// ROC(t) >= 0 for all t.
|
||||
roots[ret++] = falsePositionROCsqMinusX(t0, t1, w*w, err);
|
||||
}
|
||||
t0 = t1;
|
||||
ft0 = ft1;
|
||||
}
|
||||
|
||||
return ret - off;
|
||||
}
|
||||
|
||||
private static float eliminateInf(float x) {
|
||||
return (x == Float.POSITIVE_INFINITY ? Float.MAX_VALUE :
|
||||
(x == Float.NEGATIVE_INFINITY ? Float.MIN_VALUE : x));
|
||||
}
|
||||
|
||||
// A slight modification of the false position algorithm on wikipedia.
|
||||
// This only works for the ROCsq-x functions. It might be nice to have
|
||||
// the function as an argument, but that would be awkward in java6.
|
||||
// TODO: It is something to consider for java8 (or whenever lambda
|
||||
// expressions make it into the language), depending on how closures
|
||||
// and turn out. Same goes for the newton's method
|
||||
// algorithm in Helpers.java
|
||||
private float falsePositionROCsqMinusX(float x0, float x1,
|
||||
final float x, final float err)
|
||||
{
|
||||
final int iterLimit = 100;
|
||||
int side = 0;
|
||||
float t = x1, ft = eliminateInf(ROCsq(t) - x);
|
||||
float s = x0, fs = eliminateInf(ROCsq(s) - x);
|
||||
float r = s, fr;
|
||||
for (int i = 0; i < iterLimit && Math.abs(t - s) > err * Math.abs(t + s); i++) {
|
||||
r = (fs * t - ft * s) / (fs - ft);
|
||||
fr = ROCsq(r) - x;
|
||||
if (sameSign(fr, ft)) {
|
||||
ft = fr; t = r;
|
||||
if (side < 0) {
|
||||
fs /= (1 << (-side));
|
||||
side--;
|
||||
} else {
|
||||
side = -1;
|
||||
}
|
||||
} else if (fr * fs > 0) {
|
||||
fs = fr; s = r;
|
||||
if (side > 0) {
|
||||
ft /= (1 << side);
|
||||
side++;
|
||||
} else {
|
||||
side = 1;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
private static boolean sameSign(float x, float y) {
|
||||
// another way is to test if x*y > 0. This is bad for small x, y.
|
||||
return (x < 0f && y < 0f) || (x > 0f && y > 0f);
|
||||
}
|
||||
|
||||
// returns the radius of curvature squared at t of this curve
|
||||
// see http://en.wikipedia.org/wiki/Radius_of_curvature_(applications)
|
||||
private float ROCsq(final float t) {
|
||||
// dx=xat(t) and dy=yat(t). These calls have been inlined for efficiency
|
||||
final float dx = t * (t * dax + dbx) + cx;
|
||||
final float dy = t * (t * day + dby) + cy;
|
||||
final float ddx = 2f * dax * t + dbx;
|
||||
final float ddy = 2f * day * t + dby;
|
||||
final float dx2dy2 = dx*dx + dy*dy;
|
||||
final float ddx2ddy2 = ddx*ddx + ddy*ddy;
|
||||
final float ddxdxddydy = ddx*dx + ddy*dy;
|
||||
return dx2dy2*((dx2dy2*dx2dy2) / (dx2dy2 * ddx2ddy2 - ddxdxddydy*ddxdxddydy));
|
||||
}
|
||||
|
||||
// curve to be broken should be in pts
|
||||
// this will change the contents of pts but not Ts
|
||||
// TODO: There's no reason for Ts to be an array. All we need is a sequence
|
||||
// of t values at which to subdivide. An array statisfies this condition,
|
||||
// but is unnecessarily restrictive. Ts should be an Iterator<Float> instead.
|
||||
// Doing this will also make dashing easier, since we could easily make
|
||||
// LengthIterator an Iterator<Float> and feed it to this function to simplify
|
||||
// the loop in Dasher.somethingTo.
|
||||
BreakPtrIterator breakPtsAtTs(final float[] pts, final int type,
|
||||
final float[] Ts, final int numTs)
|
||||
{
|
||||
assert pts.length >= 2*type && numTs <= Ts.length;
|
||||
|
||||
// initialize shared iterator:
|
||||
iterator.init(pts, type, Ts, numTs);
|
||||
|
||||
return iterator;
|
||||
}
|
||||
|
||||
static final class BreakPtrIterator {
|
||||
private int nextCurveIdx;
|
||||
private int curCurveOff;
|
||||
private float prevT;
|
||||
private float[] pts;
|
||||
private int type;
|
||||
private float[] ts;
|
||||
private int numTs;
|
||||
|
||||
void init(final float[] pts, final int type,
|
||||
final float[] ts, final int numTs) {
|
||||
this.pts = pts;
|
||||
this.type = type;
|
||||
this.ts = ts;
|
||||
this.numTs = numTs;
|
||||
|
||||
nextCurveIdx = 0;
|
||||
curCurveOff = 0;
|
||||
prevT = 0f;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return nextCurveIdx <= numTs;
|
||||
}
|
||||
|
||||
public int next() {
|
||||
int ret;
|
||||
if (nextCurveIdx < numTs) {
|
||||
float curT = ts[nextCurveIdx];
|
||||
float splitT = (curT - prevT) / (1f - prevT);
|
||||
Helpers.subdivideAt(splitT,
|
||||
pts, curCurveOff,
|
||||
pts, 0,
|
||||
pts, type, type);
|
||||
prevT = curT;
|
||||
ret = 0;
|
||||
curCurveOff = type;
|
||||
} else {
|
||||
ret = curCurveOff;
|
||||
}
|
||||
nextCurveIdx++;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
702
jdkSrc/jdk8/sun/java2d/marlin/Dasher.java
Normal file
702
jdkSrc/jdk8/sun/java2d/marlin/Dasher.java
Normal file
@@ -0,0 +1,702 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.marlin;
|
||||
|
||||
import java.util.Arrays;
|
||||
import sun.awt.geom.PathConsumer2D;
|
||||
|
||||
/**
|
||||
* The <code>Dasher</code> class takes a series of linear commands
|
||||
* (<code>moveTo</code>, <code>lineTo</code>, <code>close</code> and
|
||||
* <code>end</code>) and breaks them into smaller segments according to a
|
||||
* dash pattern array and a starting dash phase.
|
||||
*
|
||||
* <p> Issues: in J2Se, a zero length dash segment as drawn as a very
|
||||
* short dash, whereas Pisces does not draw anything. The PostScript
|
||||
* semantics are unclear.
|
||||
*
|
||||
*/
|
||||
final class Dasher implements sun.awt.geom.PathConsumer2D, MarlinConst {
|
||||
|
||||
static final int recLimit = 4;
|
||||
static final float ERR = 0.01f;
|
||||
static final float minTincrement = 1f / (1 << recLimit);
|
||||
|
||||
private PathConsumer2D out;
|
||||
private float[] dash;
|
||||
private int dashLen;
|
||||
private float startPhase;
|
||||
private boolean startDashOn;
|
||||
private int startIdx;
|
||||
|
||||
private boolean starting;
|
||||
private boolean needsMoveTo;
|
||||
|
||||
private int idx;
|
||||
private boolean dashOn;
|
||||
private float phase;
|
||||
|
||||
private float sx, sy;
|
||||
private float x0, y0;
|
||||
|
||||
// temporary storage for the current curve
|
||||
private final float[] curCurvepts;
|
||||
|
||||
// per-thread renderer context
|
||||
final RendererContext rdrCtx;
|
||||
|
||||
// dashes array (dirty)
|
||||
final float[] dashes_initial = new float[INITIAL_ARRAY];
|
||||
|
||||
// flag to recycle dash array copy
|
||||
boolean recycleDashes;
|
||||
|
||||
// per-thread initial arrays (large enough to satisfy most usages
|
||||
// +1 to avoid recycling in Helpers.widenArray()
|
||||
private final float[] firstSegmentsBuffer_initial = new float[INITIAL_ARRAY + 1];
|
||||
|
||||
/**
|
||||
* Constructs a <code>Dasher</code>.
|
||||
* @param rdrCtx per-thread renderer context
|
||||
*/
|
||||
Dasher(final RendererContext rdrCtx) {
|
||||
this.rdrCtx = rdrCtx;
|
||||
|
||||
firstSegmentsBuffer = firstSegmentsBuffer_initial;
|
||||
|
||||
// we need curCurvepts to be able to contain 2 curves because when
|
||||
// dashing curves, we need to subdivide it
|
||||
curCurvepts = new float[8 * 2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the <code>Dasher</code>.
|
||||
*
|
||||
* @param out an output <code>PathConsumer2D</code>.
|
||||
* @param dash an array of <code>float</code>s containing the dash pattern
|
||||
* @param dashLen length of the given dash array
|
||||
* @param phase a <code>float</code> containing the dash phase
|
||||
* @param recycleDashes true to indicate to recycle the given dash array
|
||||
* @return this instance
|
||||
*/
|
||||
Dasher init(final PathConsumer2D out, float[] dash, int dashLen,
|
||||
float phase, boolean recycleDashes)
|
||||
{
|
||||
if (phase < 0f) {
|
||||
throw new IllegalArgumentException("phase < 0 !");
|
||||
}
|
||||
this.out = out;
|
||||
|
||||
// Normalize so 0 <= phase < dash[0]
|
||||
int idx = 0;
|
||||
dashOn = true;
|
||||
float d;
|
||||
while (phase >= (d = dash[idx])) {
|
||||
phase -= d;
|
||||
idx = (idx + 1) % dashLen;
|
||||
dashOn = !dashOn;
|
||||
}
|
||||
|
||||
this.dash = dash;
|
||||
this.dashLen = dashLen;
|
||||
this.startPhase = this.phase = phase;
|
||||
this.startDashOn = dashOn;
|
||||
this.startIdx = idx;
|
||||
this.starting = true;
|
||||
needsMoveTo = false;
|
||||
firstSegidx = 0;
|
||||
|
||||
this.recycleDashes = recycleDashes;
|
||||
|
||||
return this; // fluent API
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes this dasher:
|
||||
* clean up before reusing this instance
|
||||
*/
|
||||
void dispose() {
|
||||
if (doCleanDirty) {
|
||||
// Force zero-fill dirty arrays:
|
||||
Arrays.fill(curCurvepts, 0f);
|
||||
Arrays.fill(firstSegmentsBuffer, 0f);
|
||||
}
|
||||
// Return arrays:
|
||||
if (recycleDashes && dash != dashes_initial) {
|
||||
rdrCtx.putDirtyFloatArray(dash);
|
||||
dash = null;
|
||||
}
|
||||
|
||||
if (firstSegmentsBuffer != firstSegmentsBuffer_initial) {
|
||||
rdrCtx.putDirtyFloatArray(firstSegmentsBuffer);
|
||||
firstSegmentsBuffer = firstSegmentsBuffer_initial;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveTo(float x0, float y0) {
|
||||
if (firstSegidx > 0) {
|
||||
out.moveTo(sx, sy);
|
||||
emitFirstSegments();
|
||||
}
|
||||
needsMoveTo = true;
|
||||
this.idx = startIdx;
|
||||
this.dashOn = this.startDashOn;
|
||||
this.phase = this.startPhase;
|
||||
this.sx = this.x0 = x0;
|
||||
this.sy = this.y0 = y0;
|
||||
this.starting = true;
|
||||
}
|
||||
|
||||
private void emitSeg(float[] buf, int off, int type) {
|
||||
switch (type) {
|
||||
case 8:
|
||||
out.curveTo(buf[off+0], buf[off+1],
|
||||
buf[off+2], buf[off+3],
|
||||
buf[off+4], buf[off+5]);
|
||||
return;
|
||||
case 6:
|
||||
out.quadTo(buf[off+0], buf[off+1],
|
||||
buf[off+2], buf[off+3]);
|
||||
return;
|
||||
case 4:
|
||||
out.lineTo(buf[off], buf[off+1]);
|
||||
return;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
private void emitFirstSegments() {
|
||||
final float[] fSegBuf = firstSegmentsBuffer;
|
||||
|
||||
for (int i = 0; i < firstSegidx; ) {
|
||||
int type = (int)fSegBuf[i];
|
||||
emitSeg(fSegBuf, i + 1, type);
|
||||
i += (type - 1);
|
||||
}
|
||||
firstSegidx = 0;
|
||||
}
|
||||
// We don't emit the first dash right away. If we did, caps would be
|
||||
// drawn on it, but we need joins to be drawn if there's a closePath()
|
||||
// So, we store the path elements that make up the first dash in the
|
||||
// buffer below.
|
||||
private float[] firstSegmentsBuffer; // dynamic array
|
||||
private int firstSegidx;
|
||||
|
||||
// precondition: pts must be in relative coordinates (relative to x0,y0)
|
||||
// fullCurve is true iff the curve in pts has not been split.
|
||||
private void goTo(float[] pts, int off, final int type) {
|
||||
float x = pts[off + type - 4];
|
||||
float y = pts[off + type - 3];
|
||||
if (dashOn) {
|
||||
if (starting) {
|
||||
int len = type - 2 + 1;
|
||||
int segIdx = firstSegidx;
|
||||
float[] buf = firstSegmentsBuffer;
|
||||
if (segIdx + len > buf.length) {
|
||||
if (doStats) {
|
||||
RendererContext.stats.stat_array_dasher_firstSegmentsBuffer
|
||||
.add(segIdx + len);
|
||||
}
|
||||
firstSegmentsBuffer = buf
|
||||
= rdrCtx.widenDirtyFloatArray(buf, segIdx, segIdx + len);
|
||||
}
|
||||
buf[segIdx++] = type;
|
||||
len--;
|
||||
// small arraycopy (2, 4 or 6) but with offset:
|
||||
System.arraycopy(pts, off, buf, segIdx, len);
|
||||
segIdx += len;
|
||||
firstSegidx = segIdx;
|
||||
} else {
|
||||
if (needsMoveTo) {
|
||||
out.moveTo(x0, y0);
|
||||
needsMoveTo = false;
|
||||
}
|
||||
emitSeg(pts, off, type);
|
||||
}
|
||||
} else {
|
||||
starting = false;
|
||||
needsMoveTo = true;
|
||||
}
|
||||
this.x0 = x;
|
||||
this.y0 = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lineTo(float x1, float y1) {
|
||||
float dx = x1 - x0;
|
||||
float dy = y1 - y0;
|
||||
|
||||
float len = dx*dx + dy*dy;
|
||||
if (len == 0f) {
|
||||
return;
|
||||
}
|
||||
len = (float) Math.sqrt(len);
|
||||
|
||||
// The scaling factors needed to get the dx and dy of the
|
||||
// transformed dash segments.
|
||||
final float cx = dx / len;
|
||||
final float cy = dy / len;
|
||||
|
||||
final float[] _curCurvepts = curCurvepts;
|
||||
final float[] _dash = dash;
|
||||
|
||||
float leftInThisDashSegment;
|
||||
float dashdx, dashdy, p;
|
||||
|
||||
while (true) {
|
||||
leftInThisDashSegment = _dash[idx] - phase;
|
||||
|
||||
if (len <= leftInThisDashSegment) {
|
||||
_curCurvepts[0] = x1;
|
||||
_curCurvepts[1] = y1;
|
||||
goTo(_curCurvepts, 0, 4);
|
||||
|
||||
// Advance phase within current dash segment
|
||||
phase += len;
|
||||
// TODO: compare float values using epsilon:
|
||||
if (len == leftInThisDashSegment) {
|
||||
phase = 0f;
|
||||
idx = (idx + 1) % dashLen;
|
||||
dashOn = !dashOn;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
dashdx = _dash[idx] * cx;
|
||||
dashdy = _dash[idx] * cy;
|
||||
|
||||
if (phase == 0f) {
|
||||
_curCurvepts[0] = x0 + dashdx;
|
||||
_curCurvepts[1] = y0 + dashdy;
|
||||
} else {
|
||||
p = leftInThisDashSegment / _dash[idx];
|
||||
_curCurvepts[0] = x0 + p * dashdx;
|
||||
_curCurvepts[1] = y0 + p * dashdy;
|
||||
}
|
||||
|
||||
goTo(_curCurvepts, 0, 4);
|
||||
|
||||
len -= leftInThisDashSegment;
|
||||
// Advance to next dash segment
|
||||
idx = (idx + 1) % dashLen;
|
||||
dashOn = !dashOn;
|
||||
phase = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
// shared instance in Dasher
|
||||
private final LengthIterator li = new LengthIterator();
|
||||
|
||||
// preconditions: curCurvepts must be an array of length at least 2 * type,
|
||||
// that contains the curve we want to dash in the first type elements
|
||||
private void somethingTo(int type) {
|
||||
if (pointCurve(curCurvepts, type)) {
|
||||
return;
|
||||
}
|
||||
li.initializeIterationOnCurve(curCurvepts, type);
|
||||
|
||||
// initially the current curve is at curCurvepts[0...type]
|
||||
int curCurveoff = 0;
|
||||
float lastSplitT = 0f;
|
||||
float t;
|
||||
float leftInThisDashSegment = dash[idx] - phase;
|
||||
|
||||
while ((t = li.next(leftInThisDashSegment)) < 1f) {
|
||||
if (t != 0f) {
|
||||
Helpers.subdivideAt((t - lastSplitT) / (1f - lastSplitT),
|
||||
curCurvepts, curCurveoff,
|
||||
curCurvepts, 0,
|
||||
curCurvepts, type, type);
|
||||
lastSplitT = t;
|
||||
goTo(curCurvepts, 2, type);
|
||||
curCurveoff = type;
|
||||
}
|
||||
// Advance to next dash segment
|
||||
idx = (idx + 1) % dashLen;
|
||||
dashOn = !dashOn;
|
||||
phase = 0f;
|
||||
leftInThisDashSegment = dash[idx];
|
||||
}
|
||||
goTo(curCurvepts, curCurveoff+2, type);
|
||||
phase += li.lastSegLen();
|
||||
if (phase >= dash[idx]) {
|
||||
phase = 0f;
|
||||
idx = (idx + 1) % dashLen;
|
||||
dashOn = !dashOn;
|
||||
}
|
||||
// reset LengthIterator:
|
||||
li.reset();
|
||||
}
|
||||
|
||||
private static boolean pointCurve(float[] curve, int type) {
|
||||
for (int i = 2; i < type; i++) {
|
||||
if (curve[i] != curve[i-2]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Objects of this class are used to iterate through curves. They return
|
||||
// t values where the left side of the curve has a specified length.
|
||||
// It does this by subdividing the input curve until a certain error
|
||||
// condition has been met. A recursive subdivision procedure would
|
||||
// return as many as 1<<limit curves, but this is an iterator and we
|
||||
// don't need all the curves all at once, so what we carry out a
|
||||
// lazy inorder traversal of the recursion tree (meaning we only move
|
||||
// through the tree when we need the next subdivided curve). This saves
|
||||
// us a lot of memory because at any one time we only need to store
|
||||
// limit+1 curves - one for each level of the tree + 1.
|
||||
// NOTE: the way we do things here is not enough to traverse a general
|
||||
// tree; however, the trees we are interested in have the property that
|
||||
// every non leaf node has exactly 2 children
|
||||
static final class LengthIterator {
|
||||
private enum Side {LEFT, RIGHT};
|
||||
// Holds the curves at various levels of the recursion. The root
|
||||
// (i.e. the original curve) is at recCurveStack[0] (but then it
|
||||
// gets subdivided, the left half is put at 1, so most of the time
|
||||
// only the right half of the original curve is at 0)
|
||||
private final float[][] recCurveStack; // dirty
|
||||
// sides[i] indicates whether the node at level i+1 in the path from
|
||||
// the root to the current leaf is a left or right child of its parent.
|
||||
private final Side[] sides; // dirty
|
||||
private int curveType;
|
||||
// lastT and nextT delimit the current leaf.
|
||||
private float nextT;
|
||||
private float lenAtNextT;
|
||||
private float lastT;
|
||||
private float lenAtLastT;
|
||||
private float lenAtLastSplit;
|
||||
private float lastSegLen;
|
||||
// the current level in the recursion tree. 0 is the root. limit
|
||||
// is the deepest possible leaf.
|
||||
private int recLevel;
|
||||
private boolean done;
|
||||
|
||||
// the lengths of the lines of the control polygon. Only its first
|
||||
// curveType/2 - 1 elements are valid. This is an optimization. See
|
||||
// next(float) for more detail.
|
||||
private final float[] curLeafCtrlPolyLengths = new float[3];
|
||||
|
||||
LengthIterator() {
|
||||
this.recCurveStack = new float[recLimit + 1][8];
|
||||
this.sides = new Side[recLimit];
|
||||
// if any methods are called without first initializing this object
|
||||
// on a curve, we want it to fail ASAP.
|
||||
this.nextT = Float.MAX_VALUE;
|
||||
this.lenAtNextT = Float.MAX_VALUE;
|
||||
this.lenAtLastSplit = Float.MIN_VALUE;
|
||||
this.recLevel = Integer.MIN_VALUE;
|
||||
this.lastSegLen = Float.MAX_VALUE;
|
||||
this.done = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset this LengthIterator.
|
||||
*/
|
||||
void reset() {
|
||||
// keep data dirty
|
||||
// as it appears not useful to reset data:
|
||||
if (doCleanDirty) {
|
||||
final int recLimit = recCurveStack.length - 1;
|
||||
for (int i = recLimit; i >= 0; i--) {
|
||||
Arrays.fill(recCurveStack[i], 0f);
|
||||
}
|
||||
Arrays.fill(sides, Side.LEFT);
|
||||
Arrays.fill(curLeafCtrlPolyLengths, 0f);
|
||||
Arrays.fill(nextRoots, 0f);
|
||||
Arrays.fill(flatLeafCoefCache, 0f);
|
||||
flatLeafCoefCache[2] = -1f;
|
||||
}
|
||||
}
|
||||
|
||||
void initializeIterationOnCurve(float[] pts, int type) {
|
||||
// optimize arraycopy (8 values faster than 6 = type):
|
||||
System.arraycopy(pts, 0, recCurveStack[0], 0, 8);
|
||||
this.curveType = type;
|
||||
this.recLevel = 0;
|
||||
this.lastT = 0f;
|
||||
this.lenAtLastT = 0f;
|
||||
this.nextT = 0f;
|
||||
this.lenAtNextT = 0f;
|
||||
goLeft(); // initializes nextT and lenAtNextT properly
|
||||
this.lenAtLastSplit = 0f;
|
||||
if (recLevel > 0) {
|
||||
this.sides[0] = Side.LEFT;
|
||||
this.done = false;
|
||||
} else {
|
||||
// the root of the tree is a leaf so we're done.
|
||||
this.sides[0] = Side.RIGHT;
|
||||
this.done = true;
|
||||
}
|
||||
this.lastSegLen = 0f;
|
||||
}
|
||||
|
||||
// 0 == false, 1 == true, -1 == invalid cached value.
|
||||
private int cachedHaveLowAcceleration = -1;
|
||||
|
||||
private boolean haveLowAcceleration(float err) {
|
||||
if (cachedHaveLowAcceleration == -1) {
|
||||
final float len1 = curLeafCtrlPolyLengths[0];
|
||||
final float len2 = curLeafCtrlPolyLengths[1];
|
||||
// the test below is equivalent to !within(len1/len2, 1, err).
|
||||
// It is using a multiplication instead of a division, so it
|
||||
// should be a bit faster.
|
||||
if (!Helpers.within(len1, len2, err*len2)) {
|
||||
cachedHaveLowAcceleration = 0;
|
||||
return false;
|
||||
}
|
||||
if (curveType == 8) {
|
||||
final float len3 = curLeafCtrlPolyLengths[2];
|
||||
// if len1 is close to 2 and 2 is close to 3, that probably
|
||||
// means 1 is close to 3 so the second part of this test might
|
||||
// not be needed, but it doesn't hurt to include it.
|
||||
final float errLen3 = err * len3;
|
||||
if (!(Helpers.within(len2, len3, errLen3) &&
|
||||
Helpers.within(len1, len3, errLen3))) {
|
||||
cachedHaveLowAcceleration = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
cachedHaveLowAcceleration = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
return (cachedHaveLowAcceleration == 1);
|
||||
}
|
||||
|
||||
// we want to avoid allocations/gc so we keep this array so we
|
||||
// can put roots in it,
|
||||
private final float[] nextRoots = new float[4];
|
||||
|
||||
// caches the coefficients of the current leaf in its flattened
|
||||
// form (see inside next() for what that means). The cache is
|
||||
// invalid when it's third element is negative, since in any
|
||||
// valid flattened curve, this would be >= 0.
|
||||
private final float[] flatLeafCoefCache = new float[]{0f, 0f, -1f, 0f};
|
||||
|
||||
// returns the t value where the remaining curve should be split in
|
||||
// order for the left subdivided curve to have length len. If len
|
||||
// is >= than the length of the uniterated curve, it returns 1.
|
||||
float next(final float len) {
|
||||
final float targetLength = lenAtLastSplit + len;
|
||||
while (lenAtNextT < targetLength) {
|
||||
if (done) {
|
||||
lastSegLen = lenAtNextT - lenAtLastSplit;
|
||||
return 1f;
|
||||
}
|
||||
goToNextLeaf();
|
||||
}
|
||||
lenAtLastSplit = targetLength;
|
||||
final float leaflen = lenAtNextT - lenAtLastT;
|
||||
float t = (targetLength - lenAtLastT) / leaflen;
|
||||
|
||||
// cubicRootsInAB is a fairly expensive call, so we just don't do it
|
||||
// if the acceleration in this section of the curve is small enough.
|
||||
if (!haveLowAcceleration(0.05f)) {
|
||||
// We flatten the current leaf along the x axis, so that we're
|
||||
// left with a, b, c which define a 1D Bezier curve. We then
|
||||
// solve this to get the parameter of the original leaf that
|
||||
// gives us the desired length.
|
||||
final float[] _flatLeafCoefCache = flatLeafCoefCache;
|
||||
|
||||
if (_flatLeafCoefCache[2] < 0) {
|
||||
float x = 0f + curLeafCtrlPolyLengths[0],
|
||||
y = x + curLeafCtrlPolyLengths[1];
|
||||
if (curveType == 8) {
|
||||
float z = y + curLeafCtrlPolyLengths[2];
|
||||
_flatLeafCoefCache[0] = 3f * (x - y) + z;
|
||||
_flatLeafCoefCache[1] = 3f * (y - 2f * x);
|
||||
_flatLeafCoefCache[2] = 3f * x;
|
||||
_flatLeafCoefCache[3] = -z;
|
||||
} else if (curveType == 6) {
|
||||
_flatLeafCoefCache[0] = 0f;
|
||||
_flatLeafCoefCache[1] = y - 2f * x;
|
||||
_flatLeafCoefCache[2] = 2f * x;
|
||||
_flatLeafCoefCache[3] = -y;
|
||||
}
|
||||
}
|
||||
float a = _flatLeafCoefCache[0];
|
||||
float b = _flatLeafCoefCache[1];
|
||||
float c = _flatLeafCoefCache[2];
|
||||
float d = t * _flatLeafCoefCache[3];
|
||||
|
||||
// we use cubicRootsInAB here, because we want only roots in 0, 1,
|
||||
// and our quadratic root finder doesn't filter, so it's just a
|
||||
// matter of convenience.
|
||||
int n = Helpers.cubicRootsInAB(a, b, c, d, nextRoots, 0, 0, 1);
|
||||
if (n == 1 && !Float.isNaN(nextRoots[0])) {
|
||||
t = nextRoots[0];
|
||||
}
|
||||
}
|
||||
// t is relative to the current leaf, so we must make it a valid parameter
|
||||
// of the original curve.
|
||||
t = t * (nextT - lastT) + lastT;
|
||||
if (t >= 1f) {
|
||||
t = 1f;
|
||||
done = true;
|
||||
}
|
||||
// even if done = true, if we're here, that means targetLength
|
||||
// is equal to, or very, very close to the total length of the
|
||||
// curve, so lastSegLen won't be too high. In cases where len
|
||||
// overshoots the curve, this method will exit in the while
|
||||
// loop, and lastSegLen will still be set to the right value.
|
||||
lastSegLen = len;
|
||||
return t;
|
||||
}
|
||||
|
||||
float lastSegLen() {
|
||||
return lastSegLen;
|
||||
}
|
||||
|
||||
// go to the next leaf (in an inorder traversal) in the recursion tree
|
||||
// preconditions: must be on a leaf, and that leaf must not be the root.
|
||||
private void goToNextLeaf() {
|
||||
// We must go to the first ancestor node that has an unvisited
|
||||
// right child.
|
||||
int _recLevel = recLevel;
|
||||
final Side[] _sides = sides;
|
||||
|
||||
_recLevel--;
|
||||
while(_sides[_recLevel] == Side.RIGHT) {
|
||||
if (_recLevel == 0) {
|
||||
recLevel = 0;
|
||||
done = true;
|
||||
return;
|
||||
}
|
||||
_recLevel--;
|
||||
}
|
||||
|
||||
_sides[_recLevel] = Side.RIGHT;
|
||||
// optimize arraycopy (8 values faster than 6 = type):
|
||||
System.arraycopy(recCurveStack[_recLevel], 0,
|
||||
recCurveStack[_recLevel+1], 0, 8);
|
||||
_recLevel++;
|
||||
|
||||
recLevel = _recLevel;
|
||||
goLeft();
|
||||
}
|
||||
|
||||
// go to the leftmost node from the current node. Return its length.
|
||||
private void goLeft() {
|
||||
float len = onLeaf();
|
||||
if (len >= 0f) {
|
||||
lastT = nextT;
|
||||
lenAtLastT = lenAtNextT;
|
||||
nextT += (1 << (recLimit - recLevel)) * minTincrement;
|
||||
lenAtNextT += len;
|
||||
// invalidate caches
|
||||
flatLeafCoefCache[2] = -1f;
|
||||
cachedHaveLowAcceleration = -1;
|
||||
} else {
|
||||
Helpers.subdivide(recCurveStack[recLevel], 0,
|
||||
recCurveStack[recLevel+1], 0,
|
||||
recCurveStack[recLevel], 0, curveType);
|
||||
sides[recLevel] = Side.LEFT;
|
||||
recLevel++;
|
||||
goLeft();
|
||||
}
|
||||
}
|
||||
|
||||
// this is a bit of a hack. It returns -1 if we're not on a leaf, and
|
||||
// the length of the leaf if we are on a leaf.
|
||||
private float onLeaf() {
|
||||
float[] curve = recCurveStack[recLevel];
|
||||
float polyLen = 0f;
|
||||
|
||||
float x0 = curve[0], y0 = curve[1];
|
||||
for (int i = 2; i < curveType; i += 2) {
|
||||
final float x1 = curve[i], y1 = curve[i+1];
|
||||
final float len = Helpers.linelen(x0, y0, x1, y1);
|
||||
polyLen += len;
|
||||
curLeafCtrlPolyLengths[i/2 - 1] = len;
|
||||
x0 = x1;
|
||||
y0 = y1;
|
||||
}
|
||||
|
||||
final float lineLen = Helpers.linelen(curve[0], curve[1],
|
||||
curve[curveType-2],
|
||||
curve[curveType-1]);
|
||||
if ((polyLen - lineLen) < ERR || recLevel == recLimit) {
|
||||
return (polyLen + lineLen) / 2f;
|
||||
}
|
||||
return -1f;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void curveTo(float x1, float y1,
|
||||
float x2, float y2,
|
||||
float x3, float y3)
|
||||
{
|
||||
final float[] _curCurvepts = curCurvepts;
|
||||
_curCurvepts[0] = x0; _curCurvepts[1] = y0;
|
||||
_curCurvepts[2] = x1; _curCurvepts[3] = y1;
|
||||
_curCurvepts[4] = x2; _curCurvepts[5] = y2;
|
||||
_curCurvepts[6] = x3; _curCurvepts[7] = y3;
|
||||
somethingTo(8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void quadTo(float x1, float y1, float x2, float y2) {
|
||||
final float[] _curCurvepts = curCurvepts;
|
||||
_curCurvepts[0] = x0; _curCurvepts[1] = y0;
|
||||
_curCurvepts[2] = x1; _curCurvepts[3] = y1;
|
||||
_curCurvepts[4] = x2; _curCurvepts[5] = y2;
|
||||
somethingTo(6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closePath() {
|
||||
lineTo(sx, sy);
|
||||
if (firstSegidx > 0) {
|
||||
if (!dashOn || needsMoveTo) {
|
||||
out.moveTo(sx, sy);
|
||||
}
|
||||
emitFirstSegments();
|
||||
}
|
||||
moveTo(sx, sy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pathDone() {
|
||||
if (firstSegidx > 0) {
|
||||
out.moveTo(sx, sy);
|
||||
emitFirstSegments();
|
||||
}
|
||||
out.pathDone();
|
||||
|
||||
// Dispose this instance:
|
||||
dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getNativeConsumer() {
|
||||
throw new InternalError("Dasher does not use a native consumer");
|
||||
}
|
||||
}
|
||||
|
||||
153
jdkSrc/jdk8/sun/java2d/marlin/FloatArrayCache.java
Normal file
153
jdkSrc/jdk8/sun/java2d/marlin/FloatArrayCache.java
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.marlin;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Arrays;
|
||||
import static sun.java2d.marlin.MarlinUtils.logException;
|
||||
import static sun.java2d.marlin.MarlinUtils.logInfo;
|
||||
|
||||
final class FloatArrayCache implements MarlinConst {
|
||||
|
||||
private final int arraySize;
|
||||
private final ArrayDeque<float[]> floatArrays;
|
||||
// stats
|
||||
private int getOp = 0;
|
||||
private int createOp = 0;
|
||||
private int returnOp = 0;
|
||||
|
||||
void dumpStats() {
|
||||
if (getOp > 0) {
|
||||
logInfo("FloatArrayCache[" + arraySize + "]: get: " + getOp
|
||||
+ " created: " + createOp + " - returned: " + returnOp
|
||||
+ " :: cache size: " + floatArrays.size());
|
||||
}
|
||||
}
|
||||
|
||||
FloatArrayCache(final int arraySize) {
|
||||
this.arraySize = arraySize;
|
||||
// small but enough: almost 1 cache line
|
||||
this.floatArrays = new ArrayDeque<float[]>(6);
|
||||
}
|
||||
|
||||
float[] getArray() {
|
||||
if (doStats) {
|
||||
getOp++;
|
||||
}
|
||||
|
||||
// use cache
|
||||
final float[] array = floatArrays.pollLast();
|
||||
|
||||
if (array != null) {
|
||||
return array;
|
||||
}
|
||||
|
||||
if (doStats) {
|
||||
createOp++;
|
||||
}
|
||||
|
||||
return new float[arraySize];
|
||||
}
|
||||
|
||||
void putDirtyArray(final float[] array, final int length) {
|
||||
if (length != arraySize) {
|
||||
if (doChecks) {
|
||||
MarlinUtils.logInfo("ArrayCache: bad length = " + length);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (doStats) {
|
||||
returnOp++;
|
||||
}
|
||||
|
||||
// NO clean-up of array data = DIRTY ARRAY
|
||||
|
||||
if (doCleanDirty) {
|
||||
// Force zero-fill dirty arrays:
|
||||
Arrays.fill(array, 0, array.length, 0f);
|
||||
}
|
||||
|
||||
// fill cache:
|
||||
floatArrays.addLast(array);
|
||||
}
|
||||
|
||||
void putArray(final float[] array, final int length,
|
||||
final int fromIndex, final int toIndex)
|
||||
{
|
||||
if (length != arraySize) {
|
||||
if (doChecks) {
|
||||
MarlinUtils.logInfo("ArrayCache: bad length = " + length);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (doStats) {
|
||||
returnOp++;
|
||||
}
|
||||
|
||||
// clean-up array of dirty part[fromIndex; toIndex[
|
||||
fill(array, fromIndex, toIndex, 0f);
|
||||
|
||||
// fill cache:
|
||||
floatArrays.addLast(array);
|
||||
}
|
||||
|
||||
static void fill(final float[] array, final int fromIndex,
|
||||
final int toIndex, final float value)
|
||||
{
|
||||
// clear array data:
|
||||
/*
|
||||
* Arrays.fill is faster than System.arraycopy(empty array)
|
||||
* or Unsafe.setMemory(byte 0)
|
||||
*/
|
||||
if (toIndex != 0) {
|
||||
Arrays.fill(array, fromIndex, toIndex, value);
|
||||
}
|
||||
|
||||
if (doChecks) {
|
||||
check(array, fromIndex, toIndex, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void check(final float[] array, final int fromIndex,
|
||||
final int toIndex, final float value)
|
||||
{
|
||||
if (doChecks) {
|
||||
// check zero on full array:
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
if (array[i] != value) {
|
||||
logException("Invalid value at: " + i + " = " + array[i]
|
||||
+ " from: " + fromIndex + " to: " + toIndex + "\n"
|
||||
+ Arrays.toString(array), new Throwable());
|
||||
|
||||
// ensure array is correctly filled:
|
||||
Arrays.fill(array, value);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
213
jdkSrc/jdk8/sun/java2d/marlin/FloatMath.java
Normal file
213
jdkSrc/jdk8/sun/java2d/marlin/FloatMath.java
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package sun.java2d.marlin;
|
||||
|
||||
import sun.misc.DoubleConsts;
|
||||
import sun.misc.FloatConsts;
|
||||
|
||||
/**
|
||||
* Faster Math ceil / floor routines derived from StrictMath
|
||||
*/
|
||||
public final class FloatMath implements MarlinConst {
|
||||
|
||||
// overflow / NaN handling enabled:
|
||||
static final boolean CHECK_OVERFLOW = true;
|
||||
static final boolean CHECK_NAN = true;
|
||||
|
||||
private FloatMath() {
|
||||
// utility class
|
||||
}
|
||||
|
||||
// faster inlined min/max functions in the branch prediction is high
|
||||
static float max(final float a, final float b) {
|
||||
// no NaN handling
|
||||
return (a >= b) ? a : b;
|
||||
}
|
||||
|
||||
static int max(final int a, final int b) {
|
||||
return (a >= b) ? a : b;
|
||||
}
|
||||
|
||||
static int min(final int a, final int b) {
|
||||
return (a <= b) ? a : b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the smallest (closest to negative infinity) {@code float} value
|
||||
* that is greater than or equal to the argument and is equal to a
|
||||
* mathematical integer. Special cases:
|
||||
* <ul><li>If the argument value is already equal to a mathematical integer,
|
||||
* then the result is the same as the argument. <li>If the argument is NaN
|
||||
* or an infinity or positive zero or negative zero, then the result is the
|
||||
* same as the argument. <li>If the argument value is less than zero but
|
||||
* greater than -1.0, then the result is negative zero.</ul> Note that the
|
||||
* value of {@code StrictMath.ceil(x)} is exactly the value of
|
||||
* {@code -StrictMath.floor(-x)}.
|
||||
*
|
||||
* @param a a value.
|
||||
* @return the smallest (closest to negative infinity) floating-point value
|
||||
* that is greater than or equal to the argument and is equal to a
|
||||
* mathematical integer.
|
||||
*/
|
||||
public static float ceil_f(final float a) {
|
||||
// Derived from StrictMath.ceil(double):
|
||||
|
||||
// Inline call to Math.getExponent(a) to
|
||||
// compute only once Float.floatToRawIntBits(a)
|
||||
final int doppel = Float.floatToRawIntBits(a);
|
||||
|
||||
final int exponent = ((doppel & FloatConsts.EXP_BIT_MASK)
|
||||
>> (FloatConsts.SIGNIFICAND_WIDTH - 1))
|
||||
- FloatConsts.EXP_BIAS;
|
||||
|
||||
if (exponent < 0) {
|
||||
/*
|
||||
* Absolute value of argument is less than 1.
|
||||
* floorOrceil(-0.0) => -0.0
|
||||
* floorOrceil(+0.0) => +0.0
|
||||
*/
|
||||
return ((a == 0) ? a :
|
||||
( (a < 0f) ? -0f : 1f) );
|
||||
}
|
||||
if (CHECK_OVERFLOW && (exponent >= 23)) { // 52 for double
|
||||
/*
|
||||
* Infinity, NaN, or a value so large it must be integral.
|
||||
*/
|
||||
return a;
|
||||
}
|
||||
// Else the argument is either an integral value already XOR it
|
||||
// has to be rounded to one.
|
||||
assert exponent >= 0 && exponent <= 22; // 51 for double
|
||||
|
||||
final int intpart = doppel
|
||||
& (~(FloatConsts.SIGNIF_BIT_MASK >> exponent));
|
||||
|
||||
if (intpart == doppel) {
|
||||
return a; // integral value (including 0)
|
||||
}
|
||||
|
||||
// 0 handled above as an integer
|
||||
// sign: 1 for negative, 0 for positive numbers
|
||||
// add : 0 for negative and 1 for positive numbers
|
||||
return Float.intBitsToFloat(intpart) + ((~intpart) >>> 31);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the largest (closest to positive infinity) {@code float} value
|
||||
* that is less than or equal to the argument and is equal to a mathematical
|
||||
* integer. Special cases:
|
||||
* <ul><li>If the argument value is already equal to a mathematical integer,
|
||||
* then the result is the same as the argument. <li>If the argument is NaN
|
||||
* or an infinity or positive zero or negative zero, then the result is the
|
||||
* same as the argument.</ul>
|
||||
*
|
||||
* @param a a value.
|
||||
* @return the largest (closest to positive infinity) floating-point value
|
||||
* that less than or equal to the argument and is equal to a mathematical
|
||||
* integer.
|
||||
*/
|
||||
public static float floor_f(final float a) {
|
||||
// Derived from StrictMath.floor(double):
|
||||
|
||||
// Inline call to Math.getExponent(a) to
|
||||
// compute only once Float.floatToRawIntBits(a)
|
||||
final int doppel = Float.floatToRawIntBits(a);
|
||||
|
||||
final int exponent = ((doppel & FloatConsts.EXP_BIT_MASK)
|
||||
>> (FloatConsts.SIGNIFICAND_WIDTH - 1))
|
||||
- FloatConsts.EXP_BIAS;
|
||||
|
||||
if (exponent < 0) {
|
||||
/*
|
||||
* Absolute value of argument is less than 1.
|
||||
* floorOrceil(-0.0) => -0.0
|
||||
* floorOrceil(+0.0) => +0.0
|
||||
*/
|
||||
return ((a == 0) ? a :
|
||||
( (a < 0f) ? -1f : 0f) );
|
||||
}
|
||||
if (CHECK_OVERFLOW && (exponent >= 23)) { // 52 for double
|
||||
/*
|
||||
* Infinity, NaN, or a value so large it must be integral.
|
||||
*/
|
||||
return a;
|
||||
}
|
||||
// Else the argument is either an integral value already XOR it
|
||||
// has to be rounded to one.
|
||||
assert exponent >= 0 && exponent <= 22; // 51 for double
|
||||
|
||||
final int intpart = doppel
|
||||
& (~(FloatConsts.SIGNIF_BIT_MASK >> exponent));
|
||||
|
||||
if (intpart == doppel) {
|
||||
return a; // integral value (including 0)
|
||||
}
|
||||
|
||||
// 0 handled above as an integer
|
||||
// sign: 1 for negative, 0 for positive numbers
|
||||
// add : -1 for negative and 0 for positive numbers
|
||||
return Float.intBitsToFloat(intpart) + (intpart >> 31);
|
||||
}
|
||||
|
||||
/**
|
||||
* Faster alternative to ceil(float) optimized for the integer domain
|
||||
* and supporting NaN and +/-Infinity.
|
||||
*
|
||||
* @param a a value.
|
||||
* @return the largest (closest to positive infinity) integer value
|
||||
* that less than or equal to the argument and is equal to a mathematical
|
||||
* integer.
|
||||
*/
|
||||
public static int ceil_int(final float a) {
|
||||
final int intpart = (int) a;
|
||||
|
||||
if (a <= intpart
|
||||
|| (CHECK_OVERFLOW && intpart == Integer.MAX_VALUE)
|
||||
|| CHECK_NAN && Float.isNaN(a)) {
|
||||
return intpart;
|
||||
}
|
||||
return intpart + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Faster alternative to floor(float) optimized for the integer domain
|
||||
* and supporting NaN and +/-Infinity.
|
||||
*
|
||||
* @param a a value.
|
||||
* @return the largest (closest to positive infinity) floating-point value
|
||||
* that less than or equal to the argument and is equal to a mathematical
|
||||
* integer.
|
||||
*/
|
||||
public static int floor_int(final float a) {
|
||||
final int intpart = (int) a;
|
||||
|
||||
if (a >= intpart
|
||||
|| (CHECK_OVERFLOW && intpart == Integer.MIN_VALUE)
|
||||
|| CHECK_NAN && Float.isNaN(a)) {
|
||||
return intpart;
|
||||
}
|
||||
return intpart - 1;
|
||||
}
|
||||
}
|
||||
441
jdkSrc/jdk8/sun/java2d/marlin/Helpers.java
Normal file
441
jdkSrc/jdk8/sun/java2d/marlin/Helpers.java
Normal file
@@ -0,0 +1,441 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.marlin;
|
||||
|
||||
import static java.lang.Math.PI;
|
||||
import static java.lang.Math.cos;
|
||||
import static java.lang.Math.sqrt;
|
||||
import static java.lang.Math.cbrt;
|
||||
import static java.lang.Math.acos;
|
||||
|
||||
final class Helpers implements MarlinConst {
|
||||
|
||||
private Helpers() {
|
||||
throw new Error("This is a non instantiable class");
|
||||
}
|
||||
|
||||
static boolean within(final float x, final float y, final float err) {
|
||||
final float d = y - x;
|
||||
return (d <= err && d >= -err);
|
||||
}
|
||||
|
||||
static boolean within(final double x, final double y, final double err) {
|
||||
final double d = y - x;
|
||||
return (d <= err && d >= -err);
|
||||
}
|
||||
|
||||
static int quadraticRoots(final float a, final float b,
|
||||
final float c, float[] zeroes, final int off)
|
||||
{
|
||||
int ret = off;
|
||||
float t;
|
||||
if (a != 0f) {
|
||||
final float dis = b*b - 4*a*c;
|
||||
if (dis > 0f) {
|
||||
final float sqrtDis = (float)Math.sqrt(dis);
|
||||
// depending on the sign of b we use a slightly different
|
||||
// algorithm than the traditional one to find one of the roots
|
||||
// so we can avoid adding numbers of different signs (which
|
||||
// might result in loss of precision).
|
||||
if (b >= 0f) {
|
||||
zeroes[ret++] = (2f * c) / (-b - sqrtDis);
|
||||
zeroes[ret++] = (-b - sqrtDis) / (2f * a);
|
||||
} else {
|
||||
zeroes[ret++] = (-b + sqrtDis) / (2f * a);
|
||||
zeroes[ret++] = (2f * c) / (-b + sqrtDis);
|
||||
}
|
||||
} else if (dis == 0f) {
|
||||
t = (-b) / (2f * a);
|
||||
zeroes[ret++] = t;
|
||||
}
|
||||
} else {
|
||||
if (b != 0f) {
|
||||
t = (-c) / b;
|
||||
zeroes[ret++] = t;
|
||||
}
|
||||
}
|
||||
return ret - off;
|
||||
}
|
||||
|
||||
// find the roots of g(t) = d*t^3 + a*t^2 + b*t + c in [A,B)
|
||||
static int cubicRootsInAB(float d, float a, float b, float c,
|
||||
float[] pts, final int off,
|
||||
final float A, final float B)
|
||||
{
|
||||
if (d == 0f) {
|
||||
int num = quadraticRoots(a, b, c, pts, off);
|
||||
return filterOutNotInAB(pts, off, num, A, B) - off;
|
||||
}
|
||||
// From Graphics Gems:
|
||||
// http://tog.acm.org/resources/GraphicsGems/gems/Roots3And4.c
|
||||
// (also from awt.geom.CubicCurve2D. But here we don't need as
|
||||
// much accuracy and we don't want to create arrays so we use
|
||||
// our own customized version).
|
||||
|
||||
// normal form: x^3 + ax^2 + bx + c = 0
|
||||
a /= d;
|
||||
b /= d;
|
||||
c /= d;
|
||||
|
||||
// substitute x = y - A/3 to eliminate quadratic term:
|
||||
// x^3 +Px + Q = 0
|
||||
//
|
||||
// Since we actually need P/3 and Q/2 for all of the
|
||||
// calculations that follow, we will calculate
|
||||
// p = P/3
|
||||
// q = Q/2
|
||||
// instead and use those values for simplicity of the code.
|
||||
double sq_A = a * a;
|
||||
double p = (1.0/3.0) * ((-1.0/3.0) * sq_A + b);
|
||||
double q = (1.0/2.0) * ((2.0/27.0) * a * sq_A - (1.0/3.0) * a * b + c);
|
||||
|
||||
// use Cardano's formula
|
||||
|
||||
double cb_p = p * p * p;
|
||||
double D = q * q + cb_p;
|
||||
|
||||
int num;
|
||||
if (D < 0.0) {
|
||||
// see: http://en.wikipedia.org/wiki/Cubic_function#Trigonometric_.28and_hyperbolic.29_method
|
||||
final double phi = (1.0/3.0) * acos(-q / sqrt(-cb_p));
|
||||
final double t = 2.0 * sqrt(-p);
|
||||
|
||||
pts[ off+0 ] = (float)( t * cos(phi));
|
||||
pts[ off+1 ] = (float)(-t * cos(phi + (PI / 3.0)));
|
||||
pts[ off+2 ] = (float)(-t * cos(phi - (PI / 3.0)));
|
||||
num = 3;
|
||||
} else {
|
||||
final double sqrt_D = sqrt(D);
|
||||
final double u = cbrt(sqrt_D - q);
|
||||
final double v = - cbrt(sqrt_D + q);
|
||||
|
||||
pts[ off ] = (float)(u + v);
|
||||
num = 1;
|
||||
|
||||
if (within(D, 0.0, 1e-8)) {
|
||||
pts[off+1] = -(pts[off] / 2f);
|
||||
num = 2;
|
||||
}
|
||||
}
|
||||
|
||||
final float sub = (1f/3f) * a;
|
||||
|
||||
for (int i = 0; i < num; ++i) {
|
||||
pts[ off+i ] -= sub;
|
||||
}
|
||||
|
||||
return filterOutNotInAB(pts, off, num, A, B) - off;
|
||||
}
|
||||
|
||||
static float evalCubic(final float a, final float b,
|
||||
final float c, final float d,
|
||||
final float t)
|
||||
{
|
||||
return t * (t * (t * a + b) + c) + d;
|
||||
}
|
||||
|
||||
static float evalQuad(final float a, final float b,
|
||||
final float c, final float t)
|
||||
{
|
||||
return t * (t * a + b) + c;
|
||||
}
|
||||
|
||||
// returns the index 1 past the last valid element remaining after filtering
|
||||
static int filterOutNotInAB(float[] nums, final int off, final int len,
|
||||
final float a, final float b)
|
||||
{
|
||||
int ret = off;
|
||||
for (int i = off, end = off + len; i < end; i++) {
|
||||
if (nums[i] >= a && nums[i] < b) {
|
||||
nums[ret++] = nums[i];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static float polyLineLength(float[] poly, final int off, final int nCoords) {
|
||||
assert nCoords % 2 == 0 && poly.length >= off + nCoords : "";
|
||||
float acc = 0;
|
||||
for (int i = off + 2; i < off + nCoords; i += 2) {
|
||||
acc += linelen(poly[i], poly[i+1], poly[i-2], poly[i-1]);
|
||||
}
|
||||
return acc;
|
||||
}
|
||||
|
||||
static float linelen(float x1, float y1, float x2, float y2) {
|
||||
final float dx = x2 - x1;
|
||||
final float dy = y2 - y1;
|
||||
return (float)Math.sqrt(dx*dx + dy*dy);
|
||||
}
|
||||
|
||||
static void subdivide(float[] src, int srcoff, float[] left, int leftoff,
|
||||
float[] right, int rightoff, int type)
|
||||
{
|
||||
switch(type) {
|
||||
case 6:
|
||||
Helpers.subdivideQuad(src, srcoff, left, leftoff, right, rightoff);
|
||||
return;
|
||||
case 8:
|
||||
Helpers.subdivideCubic(src, srcoff, left, leftoff, right, rightoff);
|
||||
return;
|
||||
default:
|
||||
throw new InternalError("Unsupported curve type");
|
||||
}
|
||||
}
|
||||
|
||||
static void isort(float[] a, int off, int len) {
|
||||
for (int i = off + 1, end = off + len; i < end; i++) {
|
||||
float ai = a[i];
|
||||
int j = i - 1;
|
||||
for (; j >= off && a[j] > ai; j--) {
|
||||
a[j+1] = a[j];
|
||||
}
|
||||
a[j+1] = ai;
|
||||
}
|
||||
}
|
||||
|
||||
// Most of these are copied from classes in java.awt.geom because we need
|
||||
// float versions of these functions, and Line2D, CubicCurve2D,
|
||||
// QuadCurve2D don't provide them.
|
||||
/**
|
||||
* Subdivides the cubic curve specified by the coordinates
|
||||
* stored in the <code>src</code> array at indices <code>srcoff</code>
|
||||
* through (<code>srcoff</code> + 7) and stores the
|
||||
* resulting two subdivided curves into the two result arrays at the
|
||||
* corresponding indices.
|
||||
* Either or both of the <code>left</code> and <code>right</code>
|
||||
* arrays may be <code>null</code> or a reference to the same array
|
||||
* as the <code>src</code> array.
|
||||
* Note that the last point in the first subdivided curve is the
|
||||
* same as the first point in the second subdivided curve. Thus,
|
||||
* it is possible to pass the same array for <code>left</code>
|
||||
* and <code>right</code> and to use offsets, such as <code>rightoff</code>
|
||||
* equals (<code>leftoff</code> + 6), in order
|
||||
* to avoid allocating extra storage for this common point.
|
||||
* @param src the array holding the coordinates for the source curve
|
||||
* @param srcoff the offset into the array of the beginning of the
|
||||
* the 6 source coordinates
|
||||
* @param left the array for storing the coordinates for the first
|
||||
* half of the subdivided curve
|
||||
* @param leftoff the offset into the array of the beginning of the
|
||||
* the 6 left coordinates
|
||||
* @param right the array for storing the coordinates for the second
|
||||
* half of the subdivided curve
|
||||
* @param rightoff the offset into the array of the beginning of the
|
||||
* the 6 right coordinates
|
||||
* @since 1.7
|
||||
*/
|
||||
static void subdivideCubic(float src[], int srcoff,
|
||||
float left[], int leftoff,
|
||||
float right[], int rightoff)
|
||||
{
|
||||
float x1 = src[srcoff + 0];
|
||||
float y1 = src[srcoff + 1];
|
||||
float ctrlx1 = src[srcoff + 2];
|
||||
float ctrly1 = src[srcoff + 3];
|
||||
float ctrlx2 = src[srcoff + 4];
|
||||
float ctrly2 = src[srcoff + 5];
|
||||
float x2 = src[srcoff + 6];
|
||||
float y2 = src[srcoff + 7];
|
||||
if (left != null) {
|
||||
left[leftoff + 0] = x1;
|
||||
left[leftoff + 1] = y1;
|
||||
}
|
||||
if (right != null) {
|
||||
right[rightoff + 6] = x2;
|
||||
right[rightoff + 7] = y2;
|
||||
}
|
||||
x1 = (x1 + ctrlx1) / 2f;
|
||||
y1 = (y1 + ctrly1) / 2f;
|
||||
x2 = (x2 + ctrlx2) / 2f;
|
||||
y2 = (y2 + ctrly2) / 2f;
|
||||
float centerx = (ctrlx1 + ctrlx2) / 2f;
|
||||
float centery = (ctrly1 + ctrly2) / 2f;
|
||||
ctrlx1 = (x1 + centerx) / 2f;
|
||||
ctrly1 = (y1 + centery) / 2f;
|
||||
ctrlx2 = (x2 + centerx) / 2f;
|
||||
ctrly2 = (y2 + centery) / 2f;
|
||||
centerx = (ctrlx1 + ctrlx2) / 2f;
|
||||
centery = (ctrly1 + ctrly2) / 2f;
|
||||
if (left != null) {
|
||||
left[leftoff + 2] = x1;
|
||||
left[leftoff + 3] = y1;
|
||||
left[leftoff + 4] = ctrlx1;
|
||||
left[leftoff + 5] = ctrly1;
|
||||
left[leftoff + 6] = centerx;
|
||||
left[leftoff + 7] = centery;
|
||||
}
|
||||
if (right != null) {
|
||||
right[rightoff + 0] = centerx;
|
||||
right[rightoff + 1] = centery;
|
||||
right[rightoff + 2] = ctrlx2;
|
||||
right[rightoff + 3] = ctrly2;
|
||||
right[rightoff + 4] = x2;
|
||||
right[rightoff + 5] = y2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void subdivideCubicAt(float t, float src[], int srcoff,
|
||||
float left[], int leftoff,
|
||||
float right[], int rightoff)
|
||||
{
|
||||
float x1 = src[srcoff + 0];
|
||||
float y1 = src[srcoff + 1];
|
||||
float ctrlx1 = src[srcoff + 2];
|
||||
float ctrly1 = src[srcoff + 3];
|
||||
float ctrlx2 = src[srcoff + 4];
|
||||
float ctrly2 = src[srcoff + 5];
|
||||
float x2 = src[srcoff + 6];
|
||||
float y2 = src[srcoff + 7];
|
||||
if (left != null) {
|
||||
left[leftoff + 0] = x1;
|
||||
left[leftoff + 1] = y1;
|
||||
}
|
||||
if (right != null) {
|
||||
right[rightoff + 6] = x2;
|
||||
right[rightoff + 7] = y2;
|
||||
}
|
||||
x1 = x1 + t * (ctrlx1 - x1);
|
||||
y1 = y1 + t * (ctrly1 - y1);
|
||||
x2 = ctrlx2 + t * (x2 - ctrlx2);
|
||||
y2 = ctrly2 + t * (y2 - ctrly2);
|
||||
float centerx = ctrlx1 + t * (ctrlx2 - ctrlx1);
|
||||
float centery = ctrly1 + t * (ctrly2 - ctrly1);
|
||||
ctrlx1 = x1 + t * (centerx - x1);
|
||||
ctrly1 = y1 + t * (centery - y1);
|
||||
ctrlx2 = centerx + t * (x2 - centerx);
|
||||
ctrly2 = centery + t * (y2 - centery);
|
||||
centerx = ctrlx1 + t * (ctrlx2 - ctrlx1);
|
||||
centery = ctrly1 + t * (ctrly2 - ctrly1);
|
||||
if (left != null) {
|
||||
left[leftoff + 2] = x1;
|
||||
left[leftoff + 3] = y1;
|
||||
left[leftoff + 4] = ctrlx1;
|
||||
left[leftoff + 5] = ctrly1;
|
||||
left[leftoff + 6] = centerx;
|
||||
left[leftoff + 7] = centery;
|
||||
}
|
||||
if (right != null) {
|
||||
right[rightoff + 0] = centerx;
|
||||
right[rightoff + 1] = centery;
|
||||
right[rightoff + 2] = ctrlx2;
|
||||
right[rightoff + 3] = ctrly2;
|
||||
right[rightoff + 4] = x2;
|
||||
right[rightoff + 5] = y2;
|
||||
}
|
||||
}
|
||||
|
||||
static void subdivideQuad(float src[], int srcoff,
|
||||
float left[], int leftoff,
|
||||
float right[], int rightoff)
|
||||
{
|
||||
float x1 = src[srcoff + 0];
|
||||
float y1 = src[srcoff + 1];
|
||||
float ctrlx = src[srcoff + 2];
|
||||
float ctrly = src[srcoff + 3];
|
||||
float x2 = src[srcoff + 4];
|
||||
float y2 = src[srcoff + 5];
|
||||
if (left != null) {
|
||||
left[leftoff + 0] = x1;
|
||||
left[leftoff + 1] = y1;
|
||||
}
|
||||
if (right != null) {
|
||||
right[rightoff + 4] = x2;
|
||||
right[rightoff + 5] = y2;
|
||||
}
|
||||
x1 = (x1 + ctrlx) / 2f;
|
||||
y1 = (y1 + ctrly) / 2f;
|
||||
x2 = (x2 + ctrlx) / 2f;
|
||||
y2 = (y2 + ctrly) / 2f;
|
||||
ctrlx = (x1 + x2) / 2f;
|
||||
ctrly = (y1 + y2) / 2f;
|
||||
if (left != null) {
|
||||
left[leftoff + 2] = x1;
|
||||
left[leftoff + 3] = y1;
|
||||
left[leftoff + 4] = ctrlx;
|
||||
left[leftoff + 5] = ctrly;
|
||||
}
|
||||
if (right != null) {
|
||||
right[rightoff + 0] = ctrlx;
|
||||
right[rightoff + 1] = ctrly;
|
||||
right[rightoff + 2] = x2;
|
||||
right[rightoff + 3] = y2;
|
||||
}
|
||||
}
|
||||
|
||||
static void subdivideQuadAt(float t, float src[], int srcoff,
|
||||
float left[], int leftoff,
|
||||
float right[], int rightoff)
|
||||
{
|
||||
float x1 = src[srcoff + 0];
|
||||
float y1 = src[srcoff + 1];
|
||||
float ctrlx = src[srcoff + 2];
|
||||
float ctrly = src[srcoff + 3];
|
||||
float x2 = src[srcoff + 4];
|
||||
float y2 = src[srcoff + 5];
|
||||
if (left != null) {
|
||||
left[leftoff + 0] = x1;
|
||||
left[leftoff + 1] = y1;
|
||||
}
|
||||
if (right != null) {
|
||||
right[rightoff + 4] = x2;
|
||||
right[rightoff + 5] = y2;
|
||||
}
|
||||
x1 = x1 + t * (ctrlx - x1);
|
||||
y1 = y1 + t * (ctrly - y1);
|
||||
x2 = ctrlx + t * (x2 - ctrlx);
|
||||
y2 = ctrly + t * (y2 - ctrly);
|
||||
ctrlx = x1 + t * (x2 - x1);
|
||||
ctrly = y1 + t * (y2 - y1);
|
||||
if (left != null) {
|
||||
left[leftoff + 2] = x1;
|
||||
left[leftoff + 3] = y1;
|
||||
left[leftoff + 4] = ctrlx;
|
||||
left[leftoff + 5] = ctrly;
|
||||
}
|
||||
if (right != null) {
|
||||
right[rightoff + 0] = ctrlx;
|
||||
right[rightoff + 1] = ctrly;
|
||||
right[rightoff + 2] = x2;
|
||||
right[rightoff + 3] = y2;
|
||||
}
|
||||
}
|
||||
|
||||
static void subdivideAt(float t, float src[], int srcoff,
|
||||
float left[], int leftoff,
|
||||
float right[], int rightoff, int size)
|
||||
{
|
||||
switch(size) {
|
||||
case 8:
|
||||
subdivideCubicAt(t, src, srcoff, left, leftoff, right, rightoff);
|
||||
return;
|
||||
case 6:
|
||||
subdivideQuadAt(t, src, srcoff, left, leftoff, right, rightoff);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
152
jdkSrc/jdk8/sun/java2d/marlin/IntArrayCache.java
Normal file
152
jdkSrc/jdk8/sun/java2d/marlin/IntArrayCache.java
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.marlin;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Arrays;
|
||||
import static sun.java2d.marlin.MarlinUtils.logException;
|
||||
import static sun.java2d.marlin.MarlinUtils.logInfo;
|
||||
|
||||
final class IntArrayCache implements MarlinConst {
|
||||
|
||||
private final int arraySize;
|
||||
private final ArrayDeque<int[]> intArrays;
|
||||
// stats
|
||||
private int getOp = 0;
|
||||
private int createOp = 0;
|
||||
private int returnOp = 0;
|
||||
|
||||
void dumpStats() {
|
||||
if (getOp > 0) {
|
||||
logInfo("IntArrayCache[" + arraySize + "]: get: " + getOp
|
||||
+ " created: " + createOp + " - returned: " + returnOp
|
||||
+ " :: cache size: " + intArrays.size());
|
||||
}
|
||||
}
|
||||
|
||||
IntArrayCache(final int arraySize) {
|
||||
this.arraySize = arraySize;
|
||||
// small but enough: almost 1 cache line
|
||||
this.intArrays = new ArrayDeque<int[]>(6);
|
||||
}
|
||||
|
||||
int[] getArray() {
|
||||
if (doStats) {
|
||||
getOp++;
|
||||
}
|
||||
|
||||
// use cache:
|
||||
final int[] array = intArrays.pollLast();
|
||||
if (array != null) {
|
||||
return array;
|
||||
}
|
||||
|
||||
if (doStats) {
|
||||
createOp++;
|
||||
}
|
||||
|
||||
return new int[arraySize];
|
||||
}
|
||||
|
||||
void putDirtyArray(final int[] array, final int length) {
|
||||
if (length != arraySize) {
|
||||
if (doChecks) {
|
||||
MarlinUtils.logInfo("ArrayCache: bad length = " + length);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (doStats) {
|
||||
returnOp++;
|
||||
}
|
||||
|
||||
// NO clean-up of array data = DIRTY ARRAY
|
||||
|
||||
if (doCleanDirty) {
|
||||
// Force zero-fill dirty arrays:
|
||||
Arrays.fill(array, 0, array.length, 0);
|
||||
}
|
||||
|
||||
// fill cache:
|
||||
intArrays.addLast(array);
|
||||
}
|
||||
|
||||
void putArray(final int[] array, final int length,
|
||||
final int fromIndex, final int toIndex)
|
||||
{
|
||||
if (length != arraySize) {
|
||||
if (doChecks) {
|
||||
MarlinUtils.logInfo("ArrayCache: bad length = " + length);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (doStats) {
|
||||
returnOp++;
|
||||
}
|
||||
|
||||
// clean-up array of dirty part[fromIndex; toIndex[
|
||||
fill(array, fromIndex, toIndex, 0);
|
||||
|
||||
// fill cache:
|
||||
intArrays.addLast(array);
|
||||
}
|
||||
|
||||
static void fill(final int[] array, final int fromIndex,
|
||||
final int toIndex, final int value)
|
||||
{
|
||||
// clear array data:
|
||||
/*
|
||||
* Arrays.fill is faster than System.arraycopy(empty array)
|
||||
* or Unsafe.setMemory(byte 0)
|
||||
*/
|
||||
if (toIndex != 0) {
|
||||
Arrays.fill(array, fromIndex, toIndex, value);
|
||||
}
|
||||
|
||||
if (doChecks) {
|
||||
check(array, fromIndex, toIndex, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void check(final int[] array, final int fromIndex,
|
||||
final int toIndex, final int value)
|
||||
{
|
||||
if (doChecks) {
|
||||
// check zero on full array:
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
if (array[i] != value) {
|
||||
logException("Invalid value at: " + i + " = " + array[i]
|
||||
+ " from: " + fromIndex + " to: " + toIndex + "\n"
|
||||
+ Arrays.toString(array), new Throwable());
|
||||
|
||||
// ensure array is correctly filled:
|
||||
Arrays.fill(array, value);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
689
jdkSrc/jdk8/sun/java2d/marlin/MarlinCache.java
Normal file
689
jdkSrc/jdk8/sun/java2d/marlin/MarlinCache.java
Normal file
@@ -0,0 +1,689 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.marlin;
|
||||
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
/**
|
||||
* An object used to cache pre-rendered complex paths.
|
||||
*
|
||||
* @see Renderer
|
||||
*/
|
||||
public final class MarlinCache implements MarlinConst {
|
||||
|
||||
static final boolean FORCE_RLE = MarlinProperties.isForceRLE();
|
||||
static final boolean FORCE_NO_RLE = MarlinProperties.isForceNoRLE();
|
||||
// minimum width to try using RLE encoding:
|
||||
static final int RLE_MIN_WIDTH
|
||||
= Math.max(BLOCK_SIZE, MarlinProperties.getRLEMinWidth());
|
||||
// maximum width for RLE encoding:
|
||||
// values are stored as int [x|alpha] where alpha is 8 bits
|
||||
static final int RLE_MAX_WIDTH = 1 << (24 - 1);
|
||||
|
||||
// 2048 (pixelSize) alpha values (width) x 32 rows (tile) = 64K bytes
|
||||
// x1 instead of 4 bytes (RLE) ie 1/4 capacity or average good RLE compression
|
||||
static final long INITIAL_CHUNK_ARRAY = TILE_SIZE * INITIAL_PIXEL_DIM; // 64K
|
||||
|
||||
// The alpha map used by this object (taken out of our map cache) to convert
|
||||
// pixel coverage counts gotten from MarlinCache (which are in the range
|
||||
// [0, maxalpha]) into alpha values, which are in [0,256).
|
||||
static final byte[] ALPHA_MAP;
|
||||
|
||||
static final OffHeapArray ALPHA_MAP_UNSAFE;
|
||||
|
||||
static {
|
||||
final byte[] _ALPHA_MAP = buildAlphaMap(MAX_AA_ALPHA);
|
||||
|
||||
ALPHA_MAP_UNSAFE = new OffHeapArray(_ALPHA_MAP, _ALPHA_MAP.length); // 1K
|
||||
ALPHA_MAP =_ALPHA_MAP;
|
||||
|
||||
final Unsafe _unsafe = OffHeapArray.unsafe;
|
||||
final long addr = ALPHA_MAP_UNSAFE.address;
|
||||
|
||||
for (int i = 0; i < _ALPHA_MAP.length; i++) {
|
||||
_unsafe.putByte(addr + i, _ALPHA_MAP[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int bboxX0, bboxY0, bboxX1, bboxY1;
|
||||
|
||||
// 1D dirty arrays
|
||||
// row index in rowAAChunk[]
|
||||
final long[] rowAAChunkIndex = new long[TILE_SIZE];
|
||||
// first pixel (inclusive) for each row
|
||||
final int[] rowAAx0 = new int[TILE_SIZE];
|
||||
// last pixel (exclusive) for each row
|
||||
final int[] rowAAx1 = new int[TILE_SIZE];
|
||||
// encoding mode (0=raw, 1=RLE encoding) for each row
|
||||
final int[] rowAAEnc = new int[TILE_SIZE];
|
||||
// coded length (RLE encoding) for each row
|
||||
final long[] rowAALen = new long[TILE_SIZE];
|
||||
// last position in RLE decoding for each row (getAlpha):
|
||||
final long[] rowAAPos = new long[TILE_SIZE];
|
||||
|
||||
// dirty off-heap array containing pixel coverages for (32) rows (packed)
|
||||
// if encoding=raw, it contains alpha coverage values (val) as integer
|
||||
// if encoding=RLE, it contains tuples (val, last x-coordinate exclusive)
|
||||
// use rowAAx0/rowAAx1 to get row indices within this chunk
|
||||
final OffHeapArray rowAAChunk;
|
||||
|
||||
// current position in rowAAChunk array
|
||||
long rowAAChunkPos;
|
||||
|
||||
// touchedTile[i] is the sum of all the alphas in the tile with
|
||||
// x=j*TILE_SIZE+bboxX0.
|
||||
int[] touchedTile;
|
||||
|
||||
// per-thread renderer context
|
||||
final RendererContext rdrCtx;
|
||||
|
||||
// large cached touchedTile (dirty)
|
||||
final int[] touchedTile_initial = new int[INITIAL_ARRAY]; // 1 tile line
|
||||
|
||||
int tileMin, tileMax;
|
||||
|
||||
boolean useRLE = false;
|
||||
|
||||
MarlinCache(final RendererContext rdrCtx) {
|
||||
this.rdrCtx = rdrCtx;
|
||||
|
||||
rowAAChunk = new OffHeapArray(rdrCtx, INITIAL_CHUNK_ARRAY);
|
||||
|
||||
touchedTile = touchedTile_initial;
|
||||
|
||||
// tile used marks:
|
||||
tileMin = Integer.MAX_VALUE;
|
||||
tileMax = Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
void init(int minx, int miny, int maxx, int maxy, int edgeSumDeltaY)
|
||||
{
|
||||
// assert maxy >= miny && maxx >= minx;
|
||||
bboxX0 = minx;
|
||||
bboxY0 = miny;
|
||||
bboxX1 = maxx;
|
||||
bboxY1 = maxy;
|
||||
|
||||
final int width = (maxx - minx);
|
||||
|
||||
if (FORCE_NO_RLE) {
|
||||
useRLE = false;
|
||||
} else if (FORCE_RLE) {
|
||||
useRLE = true;
|
||||
} else {
|
||||
// heuristics: use both bbox area and complexity
|
||||
// ie number of primitives:
|
||||
|
||||
// fast check min and max width (maxx < 23bits):
|
||||
if (width <= RLE_MIN_WIDTH || width >= RLE_MAX_WIDTH) {
|
||||
useRLE = false;
|
||||
} else {
|
||||
// perimeter approach: how fit the total length into given height:
|
||||
|
||||
// if stroking: meanCrossings /= 2 => divide edgeSumDeltaY by 2
|
||||
final int heightSubPixel
|
||||
= (((maxy - miny) << SUBPIXEL_LG_POSITIONS_Y) << rdrCtx.stroking);
|
||||
|
||||
// check meanDist > block size:
|
||||
// check width / (meanCrossings - 1) >= RLE_THRESHOLD
|
||||
|
||||
// fast case: (meanCrossingPerPixel <= 2) means 1 span only
|
||||
useRLE = (edgeSumDeltaY <= (heightSubPixel << 1))
|
||||
// note: already checked (meanCrossingPerPixel <= 2)
|
||||
// rewritten to avoid division:
|
||||
|| (width * heightSubPixel) >
|
||||
((edgeSumDeltaY - heightSubPixel) << BLOCK_SIZE_LG);
|
||||
|
||||
if (doTrace && !useRLE) {
|
||||
final float meanCrossings
|
||||
= ((float) edgeSumDeltaY) / heightSubPixel;
|
||||
final float meanDist = width / (meanCrossings - 1);
|
||||
|
||||
System.out.println("High complexity: "
|
||||
+ " for bbox[width = " + width
|
||||
+ " height = " + (maxy - miny)
|
||||
+ "] edgeSumDeltaY = " + edgeSumDeltaY
|
||||
+ " heightSubPixel = " + heightSubPixel
|
||||
+ " meanCrossings = "+ meanCrossings
|
||||
+ " meanDist = " + meanDist
|
||||
+ " width = " + (width * heightSubPixel)
|
||||
+ " <= criteria: " + ((edgeSumDeltaY - heightSubPixel) << BLOCK_SIZE_LG)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the ceiling of (maxy - miny + 1) / TILE_SIZE;
|
||||
final int nxTiles = (width + TILE_SIZE) >> TILE_SIZE_LG;
|
||||
|
||||
if (nxTiles > INITIAL_ARRAY) {
|
||||
if (doStats) {
|
||||
RendererContext.stats.stat_array_marlincache_touchedTile
|
||||
.add(nxTiles);
|
||||
}
|
||||
touchedTile = rdrCtx.getIntArray(nxTiles);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes this cache:
|
||||
* clean up before reusing this instance
|
||||
*/
|
||||
void dispose() {
|
||||
// Reset touchedTile if needed:
|
||||
resetTileLine(0);
|
||||
|
||||
// Return arrays:
|
||||
if (touchedTile != touchedTile_initial) {
|
||||
rdrCtx.putIntArray(touchedTile, 0, 0); // already zero filled
|
||||
touchedTile = touchedTile_initial;
|
||||
}
|
||||
// At last: resize back off-heap rowAA to initial size
|
||||
if (rowAAChunk.length != INITIAL_CHUNK_ARRAY) {
|
||||
// note: may throw OOME:
|
||||
rowAAChunk.resize(INITIAL_CHUNK_ARRAY);
|
||||
}
|
||||
if (doCleanDirty) {
|
||||
// Force zero-fill dirty arrays:
|
||||
rowAAChunk.fill(BYTE_0);
|
||||
}
|
||||
}
|
||||
|
||||
void resetTileLine(final int pminY) {
|
||||
// update bboxY0 to process a complete tile line [0 - 32]
|
||||
bboxY0 = pminY;
|
||||
|
||||
// reset current pos
|
||||
if (doStats) {
|
||||
RendererContext.stats.stat_cache_rowAAChunk.add(rowAAChunkPos);
|
||||
}
|
||||
rowAAChunkPos = 0L;
|
||||
|
||||
// Reset touchedTile:
|
||||
if (tileMin != Integer.MAX_VALUE) {
|
||||
if (doStats) {
|
||||
RendererContext.stats.stat_cache_tiles.add(tileMax - tileMin);
|
||||
}
|
||||
// clean only dirty touchedTile:
|
||||
if (tileMax == 1) {
|
||||
touchedTile[0] = 0;
|
||||
} else {
|
||||
IntArrayCache.fill(touchedTile, tileMin, tileMax, 0);
|
||||
}
|
||||
// reset tile used marks:
|
||||
tileMin = Integer.MAX_VALUE;
|
||||
tileMax = Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
if (doCleanDirty) {
|
||||
// Force zero-fill dirty arrays:
|
||||
rowAAChunk.fill(BYTE_0);
|
||||
}
|
||||
}
|
||||
|
||||
void clearAARow(final int y) {
|
||||
// process tile line [0 - 32]
|
||||
final int row = y - bboxY0;
|
||||
|
||||
// update pixel range:
|
||||
rowAAx0[row] = 0; // first pixel inclusive
|
||||
rowAAx1[row] = 0; // last pixel exclusive
|
||||
rowAAEnc[row] = 0; // raw encoding
|
||||
|
||||
// note: leave rowAAChunkIndex[row] undefined
|
||||
// and rowAALen[row] & rowAAPos[row] (RLE)
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the given alpha data into the rowAA cache
|
||||
* @param alphaRow alpha data to copy from
|
||||
* @param y y pixel coordinate
|
||||
* @param px0 first pixel inclusive x0
|
||||
* @param px1 last pixel exclusive x1
|
||||
*/
|
||||
void copyAARowNoRLE(final int[] alphaRow, final int y,
|
||||
final int px0, final int px1)
|
||||
{
|
||||
if (doMonitors) {
|
||||
RendererContext.stats.mon_rdr_copyAARow.start();
|
||||
}
|
||||
|
||||
// skip useless pixels above boundary
|
||||
final int px_bbox1 = FloatMath.min(px1, bboxX1);
|
||||
|
||||
if (doLogBounds) {
|
||||
MarlinUtils.logInfo("row = [" + px0 + " ... " + px_bbox1
|
||||
+ " (" + px1 + ") [ for y=" + y);
|
||||
}
|
||||
|
||||
final int row = y - bboxY0;
|
||||
|
||||
// update pixel range:
|
||||
rowAAx0[row] = px0; // first pixel inclusive
|
||||
rowAAx1[row] = px_bbox1; // last pixel exclusive
|
||||
rowAAEnc[row] = 0; // raw encoding
|
||||
|
||||
// get current position (bytes):
|
||||
final long pos = rowAAChunkPos;
|
||||
// update row index to current position:
|
||||
rowAAChunkIndex[row] = pos;
|
||||
|
||||
// determine need array size:
|
||||
// for RLE encoding, position must be aligned to 4 bytes (int):
|
||||
// align - 1 = 3 so add +3 and round-off by mask ~3 = -4
|
||||
final long needSize = pos + ((px_bbox1 - px0 + 3) & -4);
|
||||
|
||||
// update next position (bytes):
|
||||
rowAAChunkPos = needSize;
|
||||
|
||||
// update row data:
|
||||
final OffHeapArray _rowAAChunk = rowAAChunk;
|
||||
// ensure rowAAChunk capacity:
|
||||
if (_rowAAChunk.length < needSize) {
|
||||
expandRowAAChunk(needSize);
|
||||
}
|
||||
if (doStats) {
|
||||
RendererContext.stats.stat_cache_rowAA.add(px_bbox1 - px0);
|
||||
}
|
||||
|
||||
// rowAA contains only alpha values for range[x0; x1[
|
||||
final int[] _touchedTile = touchedTile;
|
||||
final int _TILE_SIZE_LG = TILE_SIZE_LG;
|
||||
|
||||
final int from = px0 - bboxX0; // first pixel inclusive
|
||||
final int to = px_bbox1 - bboxX0; // last pixel exclusive
|
||||
|
||||
final Unsafe _unsafe = OffHeapArray.unsafe;
|
||||
final long SIZE_BYTE = 1L;
|
||||
final long addr_alpha = ALPHA_MAP_UNSAFE.address;
|
||||
long addr_off = _rowAAChunk.address + pos;
|
||||
|
||||
// compute alpha sum into rowAA:
|
||||
for (int x = from, val = 0; x < to; x++) {
|
||||
// alphaRow is in [0; MAX_COVERAGE]
|
||||
val += alphaRow[x]; // [from; to[
|
||||
|
||||
// ensure values are in [0; MAX_AA_ALPHA] range
|
||||
if (DO_AA_RANGE_CHECK) {
|
||||
if (val < 0) {
|
||||
System.out.println("Invalid coverage = " + val);
|
||||
val = 0;
|
||||
}
|
||||
if (val > MAX_AA_ALPHA) {
|
||||
System.out.println("Invalid coverage = " + val);
|
||||
val = MAX_AA_ALPHA;
|
||||
}
|
||||
}
|
||||
|
||||
// store alpha sum (as byte):
|
||||
if (val == 0) {
|
||||
_unsafe.putByte(addr_off, (byte)0); // [0..255]
|
||||
} else {
|
||||
_unsafe.putByte(addr_off, _unsafe.getByte(addr_alpha + val)); // [0..255]
|
||||
|
||||
// update touchedTile
|
||||
_touchedTile[x >> _TILE_SIZE_LG] += val;
|
||||
}
|
||||
addr_off += SIZE_BYTE;
|
||||
}
|
||||
|
||||
// update tile used marks:
|
||||
int tx = from >> _TILE_SIZE_LG; // inclusive
|
||||
if (tx < tileMin) {
|
||||
tileMin = tx;
|
||||
}
|
||||
|
||||
tx = ((to - 1) >> _TILE_SIZE_LG) + 1; // exclusive (+1 to be sure)
|
||||
if (tx > tileMax) {
|
||||
tileMax = tx;
|
||||
}
|
||||
|
||||
if (doLogBounds) {
|
||||
MarlinUtils.logInfo("clear = [" + from + " ... " + to + "[");
|
||||
}
|
||||
|
||||
// Clear alpha row for reuse:
|
||||
IntArrayCache.fill(alphaRow, from, px1 - bboxX0, 0);
|
||||
|
||||
if (doMonitors) {
|
||||
RendererContext.stats.mon_rdr_copyAARow.stop();
|
||||
}
|
||||
}
|
||||
|
||||
void copyAARowRLE_WithBlockFlags(final int[] blkFlags, final int[] alphaRow,
|
||||
final int y, final int px0, final int px1)
|
||||
{
|
||||
if (doMonitors) {
|
||||
RendererContext.stats.mon_rdr_copyAARow.start();
|
||||
}
|
||||
|
||||
// Copy rowAA data into the piscesCache if one is present
|
||||
final int _bboxX0 = bboxX0;
|
||||
|
||||
// process tile line [0 - 32]
|
||||
final int row = y - bboxY0;
|
||||
final int from = px0 - _bboxX0; // first pixel inclusive
|
||||
|
||||
// skip useless pixels above boundary
|
||||
final int px_bbox1 = FloatMath.min(px1, bboxX1);
|
||||
final int to = px_bbox1 - _bboxX0; // last pixel exclusive
|
||||
|
||||
if (doLogBounds) {
|
||||
MarlinUtils.logInfo("row = [" + px0 + " ... " + px_bbox1
|
||||
+ " (" + px1 + ") [ for y=" + y);
|
||||
}
|
||||
|
||||
// get current position:
|
||||
final long initialPos = startRLERow(row, px0, px_bbox1);
|
||||
|
||||
// determine need array size:
|
||||
// pessimistic: max needed size = deltaX x 4 (1 int)
|
||||
final long needSize = initialPos + ((to - from) << 2);
|
||||
|
||||
// update row data:
|
||||
OffHeapArray _rowAAChunk = rowAAChunk;
|
||||
// ensure rowAAChunk capacity:
|
||||
if (_rowAAChunk.length < needSize) {
|
||||
expandRowAAChunk(needSize);
|
||||
}
|
||||
|
||||
final Unsafe _unsafe = OffHeapArray.unsafe;
|
||||
final long SIZE_INT = 4L;
|
||||
final long addr_alpha = ALPHA_MAP_UNSAFE.address;
|
||||
long addr_off = _rowAAChunk.address + initialPos;
|
||||
|
||||
final int[] _touchedTile = touchedTile;
|
||||
final int _TILE_SIZE_LG = TILE_SIZE_LG;
|
||||
final int _BLK_SIZE_LG = BLOCK_SIZE_LG;
|
||||
|
||||
// traverse flagged blocks:
|
||||
final int blkW = (from >> _BLK_SIZE_LG);
|
||||
final int blkE = (to >> _BLK_SIZE_LG) + 1;
|
||||
|
||||
// Perform run-length encoding and store results in the piscesCache
|
||||
int val = 0;
|
||||
int cx0 = from;
|
||||
int runLen;
|
||||
|
||||
final int _MAX_VALUE = Integer.MAX_VALUE;
|
||||
int last_t0 = _MAX_VALUE;
|
||||
|
||||
int skip = 0;
|
||||
|
||||
for (int t = blkW, blk_x0, blk_x1, cx, delta; t <= blkE; t++) {
|
||||
if (blkFlags[t] != 0) {
|
||||
blkFlags[t] = 0;
|
||||
|
||||
if (last_t0 == _MAX_VALUE) {
|
||||
last_t0 = t;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (last_t0 != _MAX_VALUE) {
|
||||
// emit blocks:
|
||||
blk_x0 = FloatMath.max(last_t0 << _BLK_SIZE_LG, from);
|
||||
last_t0 = _MAX_VALUE;
|
||||
|
||||
// (last block pixel+1) inclusive => +1
|
||||
blk_x1 = FloatMath.min((t << _BLK_SIZE_LG) + 1, to);
|
||||
|
||||
for (cx = blk_x0; cx < blk_x1; cx++) {
|
||||
if ((delta = alphaRow[cx]) != 0) {
|
||||
alphaRow[cx] = 0;
|
||||
|
||||
// not first rle entry:
|
||||
if (cx != cx0) {
|
||||
runLen = cx - cx0;
|
||||
|
||||
// store alpha coverage (ensure within bounds):
|
||||
// as [absX|val] where:
|
||||
// absX is the absolute x-coordinate:
|
||||
// note: last pixel exclusive (>= 0)
|
||||
// note: it should check X is smaller than 23bits (overflow)!
|
||||
|
||||
// check address alignment to 4 bytes:
|
||||
if (doCheckUnsafe) {
|
||||
if ((addr_off & 3) != 0) {
|
||||
MarlinUtils.logInfo("Misaligned Unsafe address: " + addr_off);
|
||||
}
|
||||
}
|
||||
|
||||
// special case to encode entries into a single int:
|
||||
if (val == 0) {
|
||||
_unsafe.putInt(addr_off,
|
||||
((_bboxX0 + cx) << 8)
|
||||
);
|
||||
} else {
|
||||
_unsafe.putInt(addr_off,
|
||||
((_bboxX0 + cx) << 8)
|
||||
| (((int) _unsafe.getByte(addr_alpha + val)) & 0xFF) // [0..255]
|
||||
);
|
||||
|
||||
if (runLen == 1) {
|
||||
_touchedTile[cx0 >> _TILE_SIZE_LG] += val;
|
||||
} else {
|
||||
touchTile(cx0, val, cx, runLen, _touchedTile);
|
||||
}
|
||||
}
|
||||
addr_off += SIZE_INT;
|
||||
|
||||
if (doStats) {
|
||||
RendererContext.stats.hist_tile_generator_encoding_runLen
|
||||
.add(runLen);
|
||||
}
|
||||
cx0 = cx;
|
||||
}
|
||||
|
||||
// alpha value = running sum of coverage delta:
|
||||
val += delta;
|
||||
|
||||
// ensure values are in [0; MAX_AA_ALPHA] range
|
||||
if (DO_AA_RANGE_CHECK) {
|
||||
if (val < 0) {
|
||||
System.out.println("Invalid coverage = " + val);
|
||||
val = 0;
|
||||
}
|
||||
if (val > MAX_AA_ALPHA) {
|
||||
System.out.println("Invalid coverage = " + val);
|
||||
val = MAX_AA_ALPHA;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (doStats) {
|
||||
skip++;
|
||||
}
|
||||
}
|
||||
|
||||
// Process remaining RLE run:
|
||||
runLen = to - cx0;
|
||||
|
||||
// store alpha coverage (ensure within bounds):
|
||||
// as (int)[absX|val] where:
|
||||
// absX is the absolute x-coordinate in bits 31 to 8 and val in bits 0..7
|
||||
// note: last pixel exclusive (>= 0)
|
||||
// note: it should check X is smaller than 23bits (overflow)!
|
||||
|
||||
// check address alignment to 4 bytes:
|
||||
if (doCheckUnsafe) {
|
||||
if ((addr_off & 3) != 0) {
|
||||
MarlinUtils.logInfo("Misaligned Unsafe address: " + addr_off);
|
||||
}
|
||||
}
|
||||
|
||||
// special case to encode entries into a single int:
|
||||
if (val == 0) {
|
||||
_unsafe.putInt(addr_off,
|
||||
((_bboxX0 + to) << 8)
|
||||
);
|
||||
} else {
|
||||
_unsafe.putInt(addr_off,
|
||||
((_bboxX0 + to) << 8)
|
||||
| (((int) _unsafe.getByte(addr_alpha + val)) & 0xFF) // [0..255]
|
||||
);
|
||||
|
||||
if (runLen == 1) {
|
||||
_touchedTile[cx0 >> _TILE_SIZE_LG] += val;
|
||||
} else {
|
||||
touchTile(cx0, val, to, runLen, _touchedTile);
|
||||
}
|
||||
}
|
||||
addr_off += SIZE_INT;
|
||||
|
||||
if (doStats) {
|
||||
RendererContext.stats.hist_tile_generator_encoding_runLen
|
||||
.add(runLen);
|
||||
}
|
||||
|
||||
long len = (addr_off - _rowAAChunk.address);
|
||||
|
||||
// update coded length as bytes:
|
||||
rowAALen[row] = (len - initialPos);
|
||||
|
||||
// update current position:
|
||||
rowAAChunkPos = len;
|
||||
|
||||
if (doStats) {
|
||||
RendererContext.stats.stat_cache_rowAA.add(rowAALen[row]);
|
||||
RendererContext.stats.hist_tile_generator_encoding_ratio.add(
|
||||
(100 * skip) / (blkE - blkW)
|
||||
);
|
||||
}
|
||||
|
||||
// update tile used marks:
|
||||
int tx = from >> _TILE_SIZE_LG; // inclusive
|
||||
if (tx < tileMin) {
|
||||
tileMin = tx;
|
||||
}
|
||||
|
||||
tx = ((to - 1) >> _TILE_SIZE_LG) + 1; // exclusive (+1 to be sure)
|
||||
if (tx > tileMax) {
|
||||
tileMax = tx;
|
||||
}
|
||||
|
||||
// Clear alpha row for reuse:
|
||||
if (px1 > bboxX1) {
|
||||
alphaRow[to ] = 0;
|
||||
alphaRow[to + 1] = 0;
|
||||
}
|
||||
if (doChecks) {
|
||||
IntArrayCache.check(blkFlags, blkW, blkE, 0);
|
||||
IntArrayCache.check(alphaRow, from, px1 - bboxX0, 0);
|
||||
}
|
||||
|
||||
if (doMonitors) {
|
||||
RendererContext.stats.mon_rdr_copyAARow.stop();
|
||||
}
|
||||
}
|
||||
|
||||
long startRLERow(final int row, final int x0, final int x1) {
|
||||
// rows are supposed to be added by increasing y.
|
||||
rowAAx0[row] = x0; // first pixel inclusive
|
||||
rowAAx1[row] = x1; // last pixel exclusive
|
||||
rowAAEnc[row] = 1; // RLE encoding
|
||||
rowAAPos[row] = 0L; // position = 0
|
||||
|
||||
// update row index to current position:
|
||||
return (rowAAChunkIndex[row] = rowAAChunkPos);
|
||||
}
|
||||
|
||||
private void expandRowAAChunk(final long needSize) {
|
||||
if (doStats) {
|
||||
RendererContext.stats.stat_array_marlincache_rowAAChunk
|
||||
.add(needSize);
|
||||
}
|
||||
|
||||
// note: throw IOOB if neededSize > 2Gb:
|
||||
final long newSize = ArrayCache.getNewLargeSize(rowAAChunk.length, needSize);
|
||||
|
||||
rowAAChunk.resize(newSize);
|
||||
}
|
||||
|
||||
private void touchTile(final int x0, final int val, final int x1,
|
||||
final int runLen,
|
||||
final int[] _touchedTile)
|
||||
{
|
||||
// the x and y of the current row, minus bboxX0, bboxY0
|
||||
// process tile line [0 - 32]
|
||||
final int _TILE_SIZE_LG = TILE_SIZE_LG;
|
||||
|
||||
// update touchedTile
|
||||
int tx = (x0 >> _TILE_SIZE_LG);
|
||||
|
||||
// handle trivial case: same tile (x0, x0+runLen)
|
||||
if (tx == (x1 >> _TILE_SIZE_LG)) {
|
||||
// same tile:
|
||||
_touchedTile[tx] += val * runLen;
|
||||
return;
|
||||
}
|
||||
|
||||
final int tx1 = (x1 - 1) >> _TILE_SIZE_LG;
|
||||
|
||||
if (tx <= tx1) {
|
||||
final int nextTileXCoord = (tx + 1) << _TILE_SIZE_LG;
|
||||
_touchedTile[tx++] += val * (nextTileXCoord - x0);
|
||||
}
|
||||
if (tx < tx1) {
|
||||
// don't go all the way to tx1 - we need to handle the last
|
||||
// tile as a special case (just like we did with the first
|
||||
final int tileVal = (val << _TILE_SIZE_LG);
|
||||
for (; tx < tx1; tx++) {
|
||||
_touchedTile[tx] += tileVal;
|
||||
}
|
||||
}
|
||||
// they will be equal unless x0 >> TILE_SIZE_LG == tx1
|
||||
if (tx == tx1) {
|
||||
final int txXCoord = tx << _TILE_SIZE_LG;
|
||||
final int nextTileXCoord = (tx + 1) << _TILE_SIZE_LG;
|
||||
|
||||
final int lastXCoord = (nextTileXCoord <= x1) ? nextTileXCoord : x1;
|
||||
_touchedTile[tx] += val * (lastXCoord - txXCoord);
|
||||
}
|
||||
}
|
||||
|
||||
int alphaSumInTile(final int x) {
|
||||
return touchedTile[(x - bboxX0) >> TILE_SIZE_LG];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "bbox = ["
|
||||
+ bboxX0 + ", " + bboxY0 + " => "
|
||||
+ bboxX1 + ", " + bboxY1 + "]\n";
|
||||
}
|
||||
|
||||
private static byte[] buildAlphaMap(final int maxalpha) {
|
||||
// double size !
|
||||
final byte[] alMap = new byte[maxalpha << 1];
|
||||
final int halfmaxalpha = maxalpha >> 2;
|
||||
for (int i = 0; i <= maxalpha; i++) {
|
||||
alMap[i] = (byte) ((i * 255 + halfmaxalpha) / maxalpha);
|
||||
// System.out.println("alphaMap[" + i + "] = "
|
||||
// + Byte.toUnsignedInt(alMap[i]));
|
||||
}
|
||||
return alMap;
|
||||
}
|
||||
}
|
||||
124
jdkSrc/jdk8/sun/java2d/marlin/MarlinConst.java
Normal file
124
jdkSrc/jdk8/sun/java2d/marlin/MarlinConst.java
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.marlin;
|
||||
|
||||
/**
|
||||
* Marlin constant holder using System properties
|
||||
*/
|
||||
interface MarlinConst {
|
||||
// enable Logs (logger or stdout)
|
||||
static final boolean enableLogs = MarlinProperties.isLoggingEnabled();
|
||||
// use Logger instead of stdout
|
||||
static final boolean useLogger = enableLogs && MarlinProperties.isUseLogger();
|
||||
|
||||
// log new RendererContext
|
||||
static final boolean logCreateContext = enableLogs
|
||||
&& MarlinProperties.isLogCreateContext();
|
||||
// log misc.Unsafe alloc/realloc/free
|
||||
static final boolean logUnsafeMalloc = enableLogs
|
||||
&& MarlinProperties.isLogUnsafeMalloc();
|
||||
// do check unsafe alignment:
|
||||
static final boolean doCheckUnsafe = false;
|
||||
|
||||
// do statistics
|
||||
static final boolean doStats = enableLogs && MarlinProperties.isDoStats();
|
||||
// do monitors
|
||||
// disabled to reduce byte-code size a bit...
|
||||
static final boolean doMonitors = false;
|
||||
// static final boolean doMonitors = enableLogs && MarlinProperties.isDoMonitors();
|
||||
// do checks
|
||||
static final boolean doChecks = enableLogs && MarlinProperties.isDoChecks();
|
||||
|
||||
// do AA range checks: disable when algorithm / code is stable
|
||||
static final boolean DO_AA_RANGE_CHECK = false;
|
||||
|
||||
// enable logs
|
||||
static final boolean doLogWidenArray = enableLogs && false;
|
||||
// enable oversize logs
|
||||
static final boolean doLogOverSize = enableLogs && false;
|
||||
// enable traces
|
||||
static final boolean doTrace = enableLogs && false;
|
||||
// do flush monitors
|
||||
static final boolean doFlushMonitors = true;
|
||||
// use one polling thread to dump statistics/monitors
|
||||
static final boolean useDumpThread = false;
|
||||
// thread dump interval (ms)
|
||||
static final long statDump = 5000L;
|
||||
|
||||
// do clean dirty array
|
||||
static final boolean doCleanDirty = false;
|
||||
|
||||
// flag to use line simplifier
|
||||
static final boolean useSimplifier = MarlinProperties.isUseSimplifier();
|
||||
|
||||
// flag to enable logs related bounds checks
|
||||
static final boolean doLogBounds = enableLogs && false;
|
||||
|
||||
// Initial Array sizing (initial context capacity) ~ 512K
|
||||
|
||||
// 2048 pixel (width x height) for initial capacity
|
||||
static final int INITIAL_PIXEL_DIM
|
||||
= MarlinProperties.getInitialImageSize();
|
||||
|
||||
// typical array sizes: only odd numbers allowed below
|
||||
static final int INITIAL_ARRAY = 256;
|
||||
static final int INITIAL_SMALL_ARRAY = 1024;
|
||||
static final int INITIAL_MEDIUM_ARRAY = 4096;
|
||||
static final int INITIAL_LARGE_ARRAY = 8192;
|
||||
static final int INITIAL_ARRAY_16K = 16384;
|
||||
static final int INITIAL_ARRAY_32K = 32768;
|
||||
// alpha row dimension
|
||||
static final int INITIAL_AA_ARRAY = INITIAL_PIXEL_DIM;
|
||||
|
||||
// initial edges (24 bytes) = 24K [ints] = 96K
|
||||
static final int INITIAL_EDGES_CAPACITY = 4096 * 24; // 6 ints per edges
|
||||
|
||||
// zero value as byte
|
||||
static final byte BYTE_0 = (byte) 0;
|
||||
|
||||
// subpixels expressed as log2
|
||||
public static final int SUBPIXEL_LG_POSITIONS_X
|
||||
= MarlinProperties.getSubPixel_Log2_X();
|
||||
public static final int SUBPIXEL_LG_POSITIONS_Y
|
||||
= MarlinProperties.getSubPixel_Log2_Y();
|
||||
|
||||
// number of subpixels
|
||||
public static final int SUBPIXEL_POSITIONS_X = 1 << (SUBPIXEL_LG_POSITIONS_X);
|
||||
public static final int SUBPIXEL_POSITIONS_Y = 1 << (SUBPIXEL_LG_POSITIONS_Y);
|
||||
|
||||
public static final float NORM_SUBPIXELS
|
||||
= (float)Math.sqrt(( SUBPIXEL_POSITIONS_X * SUBPIXEL_POSITIONS_X
|
||||
+ SUBPIXEL_POSITIONS_Y * SUBPIXEL_POSITIONS_Y)/2.0);
|
||||
|
||||
public static final int MAX_AA_ALPHA
|
||||
= SUBPIXEL_POSITIONS_X * SUBPIXEL_POSITIONS_Y;
|
||||
|
||||
public static final int TILE_SIZE_LG = MarlinProperties.getTileSize_Log2();
|
||||
public static final int TILE_SIZE = 1 << TILE_SIZE_LG; // 32 by default
|
||||
|
||||
public static final int BLOCK_SIZE_LG = MarlinProperties.getBlockSize_Log2();
|
||||
public static final int BLOCK_SIZE = 1 << BLOCK_SIZE_LG;
|
||||
}
|
||||
185
jdkSrc/jdk8/sun/java2d/marlin/MarlinProperties.java
Normal file
185
jdkSrc/jdk8/sun/java2d/marlin/MarlinProperties.java
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.marlin;
|
||||
|
||||
import java.security.AccessController;
|
||||
import static sun.java2d.marlin.MarlinUtils.logInfo;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
public final class MarlinProperties {
|
||||
|
||||
private MarlinProperties() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
// marlin system properties
|
||||
|
||||
public static boolean isUseThreadLocal() {
|
||||
return getBoolean("sun.java2d.renderer.useThreadLocal", "true");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the initial pixel size used to define initial arrays
|
||||
* (tile AA chunk, alpha line, buckets)
|
||||
*
|
||||
* @return 64 < initial pixel size < 32768 (2048 by default)
|
||||
*/
|
||||
public static int getInitialImageSize() {
|
||||
return getInteger("sun.java2d.renderer.pixelsize", 2048, 64, 32 * 1024);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the log(2) corresponding to subpixel on x-axis (
|
||||
*
|
||||
* @return 1 (2 subpixels) < initial pixel size < 4 (256 subpixels)
|
||||
* (3 by default ie 8 subpixels)
|
||||
*/
|
||||
public static int getSubPixel_Log2_X() {
|
||||
return getInteger("sun.java2d.renderer.subPixel_log2_X", 3, 1, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the log(2) corresponding to subpixel on y-axis (
|
||||
*
|
||||
* @return 1 (2 subpixels) < initial pixel size < 8 (256 subpixels)
|
||||
* (3 by default ie 8 subpixels)
|
||||
*/
|
||||
public static int getSubPixel_Log2_Y() {
|
||||
return getInteger("sun.java2d.renderer.subPixel_log2_Y", 3, 1, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the log(2) corresponding to the square tile size in pixels
|
||||
*
|
||||
* @return 3 (8x8 pixels) < tile size < 8 (256x256 pixels)
|
||||
* (5 by default ie 32x32 pixels)
|
||||
*/
|
||||
public static int getTileSize_Log2() {
|
||||
return getInteger("sun.java2d.renderer.tileSize_log2", 5, 3, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the log(2) corresponding to the block size in pixels
|
||||
*
|
||||
* @return 3 (8 pixels) < block size < 8 (256 pixels)
|
||||
* (5 by default ie 32 pixels)
|
||||
*/
|
||||
public static int getBlockSize_Log2() {
|
||||
return getInteger("sun.java2d.renderer.blockSize_log2", 5, 3, 8);
|
||||
}
|
||||
|
||||
// RLE / blockFlags settings
|
||||
|
||||
public static boolean isForceRLE() {
|
||||
return getBoolean("sun.java2d.renderer.forceRLE", "false");
|
||||
}
|
||||
|
||||
public static boolean isForceNoRLE() {
|
||||
return getBoolean("sun.java2d.renderer.forceNoRLE", "false");
|
||||
}
|
||||
|
||||
public static boolean isUseTileFlags() {
|
||||
return getBoolean("sun.java2d.renderer.useTileFlags", "true");
|
||||
}
|
||||
|
||||
public static boolean isUseTileFlagsWithHeuristics() {
|
||||
return isUseTileFlags()
|
||||
&& getBoolean("sun.java2d.renderer.useTileFlags.useHeuristics", "true");
|
||||
}
|
||||
|
||||
public static int getRLEMinWidth() {
|
||||
return getInteger("sun.java2d.renderer.rleMinWidth", 64, 0, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
// optimisation parameters
|
||||
|
||||
public static boolean isUseSimplifier() {
|
||||
return getBoolean("sun.java2d.renderer.useSimplifier", "false");
|
||||
}
|
||||
|
||||
// debugging parameters
|
||||
|
||||
public static boolean isDoStats() {
|
||||
return getBoolean("sun.java2d.renderer.doStats", "false");
|
||||
}
|
||||
|
||||
public static boolean isDoMonitors() {
|
||||
return getBoolean("sun.java2d.renderer.doMonitors", "false");
|
||||
}
|
||||
|
||||
public static boolean isDoChecks() {
|
||||
return getBoolean("sun.java2d.renderer.doChecks", "false");
|
||||
}
|
||||
|
||||
// logging parameters
|
||||
|
||||
public static boolean isLoggingEnabled() {
|
||||
return getBoolean("sun.java2d.renderer.log", "false");
|
||||
}
|
||||
|
||||
public static boolean isUseLogger() {
|
||||
return getBoolean("sun.java2d.renderer.useLogger", "false");
|
||||
}
|
||||
|
||||
public static boolean isLogCreateContext() {
|
||||
return getBoolean("sun.java2d.renderer.logCreateContext", "false");
|
||||
}
|
||||
|
||||
public static boolean isLogUnsafeMalloc() {
|
||||
return getBoolean("sun.java2d.renderer.logUnsafeMalloc", "false");
|
||||
}
|
||||
|
||||
// system property utilities
|
||||
static boolean getBoolean(final String key, final String def) {
|
||||
return Boolean.valueOf(AccessController.doPrivileged(
|
||||
new GetPropertyAction(key, def)));
|
||||
}
|
||||
|
||||
static int getInteger(final String key, final int def,
|
||||
final int min, final int max)
|
||||
{
|
||||
final String property = AccessController.doPrivileged(
|
||||
new GetPropertyAction(key));
|
||||
|
||||
int value = def;
|
||||
if (property != null) {
|
||||
try {
|
||||
value = Integer.decode(property);
|
||||
} catch (NumberFormatException e) {
|
||||
logInfo("Invalid integer value for " + key + " = " + property);
|
||||
}
|
||||
}
|
||||
|
||||
// check for invalid values
|
||||
if ((value < min) || (value > max)) {
|
||||
logInfo("Invalid value for " + key + " = " + value
|
||||
+ "; expected value in range[" + min + ", " + max + "] !");
|
||||
value = def;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
1052
jdkSrc/jdk8/sun/java2d/marlin/MarlinRenderingEngine.java
Normal file
1052
jdkSrc/jdk8/sun/java2d/marlin/MarlinRenderingEngine.java
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user