org.apache.batik.bridge.CursorManager Maven / Gradle / Ivy
The newest version!
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package org.apache.batik.bridge;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.util.HashMap;
import java.util.Map;
import org.apache.batik.css.engine.SVGCSSEngine;
import org.apache.batik.css.engine.value.Value;
import org.apache.batik.dom.AbstractNode;
import org.apache.batik.dom.util.XLinkSupport;
import org.apache.batik.ext.awt.image.PadMode;
import org.apache.batik.ext.awt.image.renderable.AffineRable8Bit;
import org.apache.batik.ext.awt.image.renderable.Filter;
import org.apache.batik.ext.awt.image.renderable.PadRable8Bit;
import org.apache.batik.ext.awt.image.spi.BrokenLinkProvider;
import org.apache.batik.ext.awt.image.spi.ImageTagRegistry;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.util.ParsedURL;
import org.apache.batik.util.Platform;
import org.apache.batik.util.SVGConstants;
import org.apache.batik.util.SoftReferenceCache;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.css.CSSPrimitiveValue;
import org.w3c.dom.css.CSSValue;
import org.w3c.dom.svg.SVGDocument;
import org.w3c.dom.svg.SVGPreserveAspectRatio;
/**
* The CursorManager class is a helper class which preloads the cursors
* corresponding to the SVG built in cursors.
*
* @author Vincent Hardy
* @version $Id$
*/
public class CursorManager implements SVGConstants, ErrorConstants {
/**
* Maps SVG Cursor Values to Java Cursors
*/
protected static Map cursorMap;
/**
* Default cursor when value is not found
*/
public static final Cursor DEFAULT_CURSOR
= Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
/**
* Cursor used over anchors
*/
public static final Cursor ANCHOR_CURSOR
= Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
/**
* Cursor used over text
*/
public static final Cursor TEXT_CURSOR
= Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR);
/**
* Default preferred cursor size, used for SVG images
*/
public static final int DEFAULT_PREFERRED_WIDTH = 32;
public static final int DEFAULT_PREFERRED_HEIGHT = 32;
/**
* Static initialization of the cursorMap
*/
static {
Toolkit toolkit = Toolkit.getDefaultToolkit();
cursorMap = new HashMap();
cursorMap.put(SVG_CROSSHAIR_VALUE,
Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
cursorMap.put(SVG_DEFAULT_VALUE,
Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
cursorMap.put(SVG_POINTER_VALUE,
Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
cursorMap.put(SVG_E_RESIZE_VALUE,
Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
cursorMap.put(SVG_NE_RESIZE_VALUE,
Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR));
cursorMap.put(SVG_NW_RESIZE_VALUE,
Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR));
cursorMap.put(SVG_N_RESIZE_VALUE,
Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR));
cursorMap.put(SVG_SE_RESIZE_VALUE,
Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
cursorMap.put(SVG_SW_RESIZE_VALUE,
Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR));
cursorMap.put(SVG_S_RESIZE_VALUE,
Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR));
cursorMap.put(SVG_W_RESIZE_VALUE,
Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
cursorMap.put(SVG_TEXT_VALUE,
Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
cursorMap.put(SVG_WAIT_VALUE,
Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
Cursor moveCursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
if (Platform.isOSX) {
try {
Image img = toolkit.createImage
(CursorManager.class.getResource("resources/move.gif"));
moveCursor = toolkit.createCustomCursor
(img, new Point(11, 11), "move");
} catch (Exception ex) {
}
}
cursorMap.put(SVG_MOVE_VALUE, moveCursor);
Cursor helpCursor;
try {
Image img = toolkit.createImage
(CursorManager.class.getResource("resources/help.gif"));
helpCursor = toolkit.createCustomCursor
(img, new Point(1, 3), "help");
} catch (Exception ex) {
helpCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
}
cursorMap.put(SVG_HELP_VALUE, helpCursor);
}
/**
* BridgeContext associated with this CursorManager
*/
protected BridgeContext ctx;
/**
* Cache used to hold references to cursors
*/
protected CursorCache cursorCache = new CursorCache();
/**
* Creates a new CursorManager object.
*
* @param ctx the BridgeContext associated to this CursorManager
*/
public CursorManager(BridgeContext ctx) {
this.ctx = ctx;
}
/**
* Returns a Cursor object for a given cursor value. This initial
* implementation does not handle user-defined cursors, so it
* always uses the cursor at the end of the list
*/
public static Cursor getPredefinedCursor(String cursorName){
return (Cursor)cursorMap.get(cursorName);
}
/**
* Returns the Cursor corresponding to the input element's cursor property
*
* @param e the element on which the cursor property is set
*/
public Cursor convertCursor(Element e) {
Value cursorValue = CSSUtilities.getComputedStyle
(e, SVGCSSEngine.CURSOR_INDEX);
String cursorStr = SVGConstants.SVG_AUTO_VALUE;
if (cursorValue != null) {
if (cursorValue.getCssValueType() == CSSValue.CSS_PRIMITIVE_VALUE
&&
cursorValue.getPrimitiveType() == CSSPrimitiveValue.CSS_IDENT) {
// Single Value : should be one of the predefined cursors or
// 'inherit'
cursorStr = cursorValue.getStringValue();
return convertBuiltInCursor(e, cursorStr);
} else if (cursorValue.getCssValueType() ==
CSSValue.CSS_VALUE_LIST) {
int nValues = cursorValue.getLength();
if (nValues == 1) {
cursorValue = cursorValue.item(0);
if (cursorValue.getPrimitiveType() ==
CSSPrimitiveValue.CSS_IDENT) {
cursorStr = cursorValue.getStringValue();
return convertBuiltInCursor(e, cursorStr);
}
} else if (nValues > 1) {
//
// Look for the first cursor url we can handle.
// That would be a reference to a element.
//
return convertSVGCursor(e, cursorValue);
}
}
}
return convertBuiltInCursor(e, cursorStr);
}
public Cursor convertBuiltInCursor(Element e, String cursorStr) {
Cursor cursor = null;
// The CSS engine guarantees an non null, non empty string
// as the computed value for cursor. Therefore, the following
// test is safe.
if (cursorStr.charAt(0) == 'a') {
//
// Handle 'auto' value.
//
// - The following sets the cursor for element
// enclosing text nodes. Setting the proper cursor (i.e.,
// depending on the children's 'cursor' property, is
// handled in the SVGAElementBridge so as to avoid going
// up the tree on mouseover events (looking for an anchor
// ancestor.
//
// - The following does not change the cursor if
// the element's cursor property is set to
// 'auto'. Otherwise, it takes precedence over any child
// (in case of SVG content) cursor setting. This means
// that for images referencing SVG content, a cursor
// property set to 'auto' on the element will not
// override the cursor settings inside the SVG image. Any
// other cursor property will take precedence.
//
// -
© 2015 - 2024 Weber Informatics LLC | Privacy Policy