Java Code Examples for java.awt.geom.AffineTransform#preConcatenate()

The following examples show how to use java.awt.geom.AffineTransform#preConcatenate() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: AttributeValues.java    From openjdk-jdk8u with GNU General Public License v2.0 6 votes vote down vote up
private static AffineTransform extractRotation(Point2D.Double pt,
    AffineTransform tx, boolean andTranslation) {

    tx.deltaTransform(pt, pt);
    AffineTransform rtx = AffineTransform.getRotateInstance(pt.x, pt.y);

    try {
        AffineTransform rtxi = rtx.createInverse();
        double dx = tx.getTranslateX();
        double dy = tx.getTranslateY();
        tx.preConcatenate(rtxi);
        if (andTranslation) {
            if (dx != 0 || dy != 0) {
                tx.setTransform(tx.getScaleX(), tx.getShearY(),
                                tx.getShearX(), tx.getScaleY(), 0, 0);
                rtx.setTransform(rtx.getScaleX(), rtx.getShearY(),
                                 rtx.getShearX(), rtx.getScaleY(), dx, dy);
            }
        }
    }
    catch (NoninvertibleTransformException e) {
        return null;
    }
    return rtx;
}
 
Example 2
Source File: AttributeValues.java    From jdk8u-dev-jdk with GNU General Public License v2.0 6 votes vote down vote up
private static AffineTransform extractRotation(Point2D.Double pt,
    AffineTransform tx, boolean andTranslation) {

    tx.deltaTransform(pt, pt);
    AffineTransform rtx = AffineTransform.getRotateInstance(pt.x, pt.y);

    try {
        AffineTransform rtxi = rtx.createInverse();
        double dx = tx.getTranslateX();
        double dy = tx.getTranslateY();
        tx.preConcatenate(rtxi);
        if (andTranslation) {
            if (dx != 0 || dy != 0) {
                tx.setTransform(tx.getScaleX(), tx.getShearY(),
                                tx.getShearX(), tx.getScaleY(), 0, 0);
                rtx.setTransform(rtx.getScaleX(), rtx.getShearY(),
                                 rtx.getShearX(), rtx.getScaleY(), dx, dy);
            }
        }
    }
    catch (NoninvertibleTransformException e) {
        return null;
    }
    return rtx;
}
 
Example 3
Source File: Util.java    From TrakEM2 with GNU General Public License v3.0 6 votes vote down vote up
final static public void applyLayerTransformToPatch( final Patch patch, final CoordinateTransform ct ) throws Exception
{
	final Rectangle pbox = patch.getCoordinateTransformBoundingBox();
	final AffineTransform pat = new AffineTransform();
	pat.translate( -pbox.x, -pbox.y );
	pat.preConcatenate( patch.getAffineTransform() );
	
	final AffineModel2D toWorld = new AffineModel2D();
	toWorld.set( pat );
	
	final CoordinateTransformList< CoordinateTransform > ctl = new CoordinateTransformList< CoordinateTransform >();
	ctl.add( toWorld );
	ctl.add( ct );
	ctl.add( toWorld.createInverse() );
	
	patch.appendCoordinateTransform( ctl );
}
 
Example 4
Source File: ExportImageAction.java    From snap-desktop with GNU General Public License v3.0 6 votes vote down vote up
private static BufferedImageRendering createRendering(ProductSceneView view, boolean fullScene,
                                                      boolean geoReferenced, BufferedImage bufferedImage) {
    final Viewport vp1 = view.getLayerCanvas().getViewport();
    final Viewport vp2 = new DefaultViewport(new Rectangle(bufferedImage.getWidth(), bufferedImage.getHeight()),
                                             vp1.isModelYAxisDown());
    if (fullScene) {
        vp2.zoom(view.getBaseImageLayer().getModelBounds());
    } else {
        setTransform(vp1, vp2);
    }

    final BufferedImageRendering imageRendering = new BufferedImageRendering(bufferedImage, vp2);
    if (geoReferenced) {
        // because image to model transform is stored with the exported image we have to invert
        // image to view transformation
        final AffineTransform m2iTransform = view.getBaseImageLayer().getModelToImageTransform(0);
        final AffineTransform v2mTransform = vp2.getViewToModelTransform();
        v2mTransform.preConcatenate(m2iTransform);
        final AffineTransform v2iTransform = new AffineTransform(v2mTransform);

        final Graphics2D graphics2D = imageRendering.getGraphics();
        v2iTransform.concatenate(graphics2D.getTransform());
        graphics2D.setTransform(v2iTransform);
    }
    return imageRendering;
}
 
Example 5
Source File: AttributeValues.java    From openjdk-jdk9 with GNU General Public License v2.0 6 votes vote down vote up
private static AffineTransform extractRotation(Point2D.Double pt,
    AffineTransform tx, boolean andTranslation) {

    tx.deltaTransform(pt, pt);
    AffineTransform rtx = AffineTransform.getRotateInstance(pt.x, pt.y);

    try {
        AffineTransform rtxi = rtx.createInverse();
        double dx = tx.getTranslateX();
        double dy = tx.getTranslateY();
        tx.preConcatenate(rtxi);
        if (andTranslation) {
            if (dx != 0 || dy != 0) {
                tx.setTransform(tx.getScaleX(), tx.getShearY(),
                                tx.getShearX(), tx.getScaleY(), 0, 0);
                rtx.setTransform(rtx.getScaleX(), rtx.getShearY(),
                                 rtx.getShearX(), rtx.getScaleY(), dx, dy);
            }
        }
    }
    catch (NoninvertibleTransformException e) {
        return null;
    }
    return rtx;
}
 
Example 6
Source File: AreaWrapper.java    From TrakEM2 with GNU General Public License v3.0 5 votes vote down vote up
/** Add an area that needs to be transformed by tmp first to bring it to world coordinates;
 *  will MODIFY the to_world AffineTransform object. */
public void add(final Area a, final AffineTransform to_world) {
	try {
		to_world.preConcatenate(source.getAffineTransform().createInverse());
		this.area.add(a.createTransformedArea(to_world));
	} catch (NoninvertibleTransformException nite) { IJError.print(nite); }
}
 
Example 7
Source File: Displayable.java    From TrakEM2 with GNU General Public License v3.0 5 votes vote down vote up
/** Will crop second dimension of the given array at the given length. */
final protected double[][] transformPoints(final double[][] p, final int length, final AffineTransform additional) {
	if (null == additional) return transformPoints(this.at, p, length);
	final AffineTransform aff = new AffineTransform(this.at);
	aff.preConcatenate(additional);
	return transformPoints(aff, p, length);
}
 
Example 8
Source File: BitmapExporter.java    From jpexs-decompiler with GNU General Public License v3.0 5 votes vote down vote up
private void exportTo(SerializableImage image, Matrix transformation, Matrix strokeTransformation) {
    this.image = image;
    this.strokeTransformation = strokeTransformation.clone();
    this.strokeTransformation.scaleX /= SWF.unitDivisor;
    this.strokeTransformation.scaleY /= SWF.unitDivisor;

    graphics = (Graphics2D) image.getGraphics();
    AffineTransform at = transformation.toTransform();
    at.preConcatenate(AffineTransform.getScaleInstance(1 / SWF.unitDivisor, 1 / SWF.unitDivisor));
    graphics.setTransform(at);
    defaultStroke = graphics.getStroke();
    super.export();
}
 
Example 9
Source File: NeuroML.java    From TrakEM2 with GNU General Public License v3.0 4 votes vote down vote up
/** Without headers, just the cell block for a single Treeline.
 * If pre is null, then synapses are not collected. */
static private final void exportMorphMLCell(final Writer w, final Treeline t,
		final Set<Tree<?>> trees, final List<HalfSynapse> pre, final List<HalfSynapse> post,
		final AffineTransform scale2d, final double zScale) throws IOException
{	
	final float[] fp = new float[4]; // x, y, z, r

	// Prepare transform
	final AffineTransform aff = new AffineTransform(t.getAffineTransform());
	aff.preConcatenate(scale2d);

	writeCellHeader(w, t);

	// Map of Node vs id of the node
	// These ids are used to express parent-child relationships between segments
	final HashMap<Node<Float>,Long> nodeIds = new HashMap<Node<Float>,Long>();

	// Map of coords for branch or end nodes
	// so that the start of a cable can write the proximal coords
	final HashMap<Node<Float>,float[]> nodeCoords = new HashMap<Node<Float>,float[]>();

	// Root gets ID of 0:
	long nextSegmentId = 0;
	long cableId = 0;
	final Node<Float> root = t.getRoot();

	toPoint(root, fp, aff, zScale);
	writeSomaSegment(w, fp); // a dummy segment that has no length, and with a cableId of 0.
	if (null != pre) collectConnectors(root, t, fp, 0, pre, post);

	// Prepare
	nodeIds.put(root, nextSegmentId);
	nodeCoords.put(root, fp.clone());
	nextSegmentId += 1;
	cableId += 1;

	// All cables that come out of the Soma (the root) require a special tag:
	final HashSet<Long> somaCables = new HashSet<Long>();

	// Iterate all cables (all slabs; here a slab is synonym with cable, even if in NeuroML it doesn't have to be)
	for (final Node<Float> node : t.getRoot().getBranchAndEndNodes()) {
		// Gather the list of nodes all the way up to the previous branch node or root,
		// that last one not included.
		final List<Node<Float>> slab = cable(node);
		final String sCableId = Long.toString(cableId);
		// The id of the parent already exists, given that the Collection
		// is iterated depth-first from the root.
		final Node<Float> parent = slab.get(slab.size()-1).getParent();
		long parentId = nodeIds.get(parent);
		// Use the parent coords for the proximal coords of the first segment of the cable
		float[] parentCoords = nodeCoords.get(parent);
		// Is it a cable coming out of the root node (the soma) ?
		if (0 == parentId) somaCables.add(cableId);
		// For every node starting from the closest to the root (the last),
		// write a segment of the cable
		for (final ListIterator<Node<Float>> it = slab.listIterator(slab.size()); it.hasPrevious(); ) {
			// Assign an id to the node of the slab
			final Node<Float> seg = it.previous();
			// Write the segment
			toPoint(seg, fp, aff, zScale);
			writeCableSegment(w, fp, nextSegmentId, parentId, parentCoords, sCableId);
			// Inspect and collect synapses originating at this node
			if (null != pre) collectConnectors(seg, t, fp, nextSegmentId, pre, post);
			// Prepare next segment in the cable
			parentId = nextSegmentId;
			nextSegmentId += 1;
			parentCoords = null; // is used only for the first node
		}
		// Record the branch node, to be used for filling in "distal" fields
		if (node.getChildrenCount() > 1) {
			nodeIds.put(node, parentId); // parentId is the last used nextId, which is the id of node
			final float[] fpCopy = new float[4];
			toPoint(node, fpCopy, aff, zScale);
			nodeCoords.put(node, fpCopy);
		}

		// Prepare next slab or cable
		cableId += 1;
	}

	w.write(" </segments>\n");

	// Define the nature of each cable
	// Each cable requires a unique name
	w.write(" <cables xmlns=\"http://morphml.org/morphml/schema\">\n");
	w.write("  <cable id=\"0\" name=\"Soma\">\n   <meta:group>soma_group</meta:group>\n  </cable>\n");
	for (long i=1; i<cableId; i++) {
		final String sid = Long.toString(i);
		w.write("  <cable id=\""); w.write(sid);
		w.write("\" name=\""); w.write(sid);
		if (somaCables.contains(i)) w.write("\" fract_along_parent=\"0.5");
		else w.write("\" fract_along_parent=\"1.0"); // child segments start at the end of the segment
		w.write("\">\n   <meta:group>arbor_group</meta:group>\n  </cable>\n");
	}

	w.write(" </cables>\n</cell>\n");
}
 
Example 10
Source File: Font.java    From hottub with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Returns a copy of the transform associated with this
 * <code>Font</code>.  This transform is not necessarily the one
 * used to construct the font.  If the font has algorithmic
 * superscripting or width adjustment, this will be incorporated
 * into the returned <code>AffineTransform</code>.
 * <p>
 * Typically, fonts will not be transformed.  Clients generally
 * should call {@link #isTransformed} first, and only call this
 * method if <code>isTransformed</code> returns true.
 *
 * @return an {@link AffineTransform} object representing the
 *          transform attribute of this <code>Font</code> object.
 */
public AffineTransform getTransform() {
    /* The most common case is the identity transform.  Most callers
     * should call isTransformed() first, to decide if they need to
     * get the transform, but some may not.  Here we check to see
     * if we have a nonidentity transform, and only do the work to
     * fetch and/or compute it if so, otherwise we return a new
     * identity transform.
     *
     * Note that the transform is _not_ necessarily the same as
     * the transform passed in as an Attribute in a Map, as the
     * transform returned will also reflect the effects of WIDTH and
     * SUPERSCRIPT attributes.  Clients who want the actual transform
     * need to call getRequestedAttributes.
     */
    if (nonIdentityTx) {
        AttributeValues values = getAttributeValues();

        AffineTransform at = values.isNonDefault(ETRANSFORM)
            ? new AffineTransform(values.getTransform())
            : new AffineTransform();

        if (values.getSuperscript() != 0) {
            // can't get ascent and descent here, recursive call to this fn,
            // so use pointsize
            // let users combine super- and sub-scripting

            int superscript = values.getSuperscript();

            double trans = 0;
            int n = 0;
            boolean up = superscript > 0;
            int sign = up ? -1 : 1;
            int ss = up ? superscript : -superscript;

            while ((ss & 7) > n) {
                int newn = ss & 7;
                trans += sign * (ssinfo[newn] - ssinfo[n]);
                ss >>= 3;
                sign = -sign;
                n = newn;
            }
            trans *= pointSize;
            double scale = Math.pow(2./3., n);

            at.preConcatenate(AffineTransform.getTranslateInstance(0, trans));
            at.scale(scale, scale);

            // note on placement and italics
            // We preconcatenate the transform because we don't want to translate along
            // the italic angle, but purely perpendicular to the baseline.  While this
            // looks ok for superscripts, it can lead subscripts to stack on each other
            // and bring the following text too close.  The way we deal with potential
            // collisions that can occur in the case of italics is by adjusting the
            // horizontal spacing of the adjacent glyphvectors.  Examine the italic
            // angle of both vectors, if one is non-zero, compute the minimum ascent
            // and descent, and then the x position at each for each vector along its
            // italic angle starting from its (offset) baseline.  Compute the difference
            // between the x positions and use the maximum difference to adjust the
            // position of the right gv.
        }

        if (values.isNonDefault(EWIDTH)) {
            at.scale(values.getWidth(), 1f);
        }

        return at;
    }

    return new AffineTransform();
}
 
Example 11
Source File: ShapeTag.java    From jpexs-decompiler with GNU General Public License v3.0 4 votes vote down vote up
@Override
public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, ColorTransform colorTransform) {
    BitmapExporter.export(swf, getShapes(), null, image, transformation, strokeTransformation, colorTransform);
    if (Configuration._debugMode.get()) { // show control points
        List<GeneralPath> paths = PathExporter.export(swf, getShapes());
        double[] coords = new double[6];
        AffineTransform at = transformation.toTransform();
        at.preConcatenate(AffineTransform.getScaleInstance(1 / SWF.unitDivisor, 1 / SWF.unitDivisor));

        // get the graphics from the inner image object, because it creates a new Graphics object
        Graphics2D graphics = (Graphics2D) image.getBufferedImage().getGraphics();
        graphics.setPaint(Color.black);
        for (GeneralPath path : paths) {
            PathIterator iterator = path.getPathIterator(at);
            while (!iterator.isDone()) {
                int type = iterator.currentSegment(coords);
                double x = coords[0];
                double y = coords[1];
                switch (type) {
                    case PathIterator.SEG_MOVETO:
                        graphics.drawRect((int) (x - markerSize / 2), (int) (y - markerSize / 2), markerSize, markerSize);
                        break;
                    case PathIterator.SEG_LINETO:
                        graphics.drawRect((int) (x - markerSize / 2), (int) (y - markerSize / 2), markerSize, markerSize);
                        break;
                    case PathIterator.SEG_QUADTO:
                        graphics.drawRect((int) (x - markerSize / 2), (int) (y - markerSize / 2), markerSize, markerSize);
                        x = coords[2];
                        y = coords[3];
                        graphics.drawRect((int) (x - markerSize / 2), (int) (y - markerSize / 2), markerSize, markerSize);
                        break;
                    case PathIterator.SEG_CUBICTO:
                        System.out.print("CUBICTO NOT SUPPORTED. ");
                        break;
                    case PathIterator.SEG_CLOSE:
                        System.out.print("CLOSE NOT SUPPORTED. ");
                        break;
                }
                iterator.next();
            }
        }
    }
}
 
Example 12
Source File: Font.java    From jdk8u_jdk with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Returns a copy of the transform associated with this
 * <code>Font</code>.  This transform is not necessarily the one
 * used to construct the font.  If the font has algorithmic
 * superscripting or width adjustment, this will be incorporated
 * into the returned <code>AffineTransform</code>.
 * <p>
 * Typically, fonts will not be transformed.  Clients generally
 * should call {@link #isTransformed} first, and only call this
 * method if <code>isTransformed</code> returns true.
 *
 * @return an {@link AffineTransform} object representing the
 *          transform attribute of this <code>Font</code> object.
 */
public AffineTransform getTransform() {
    /* The most common case is the identity transform.  Most callers
     * should call isTransformed() first, to decide if they need to
     * get the transform, but some may not.  Here we check to see
     * if we have a nonidentity transform, and only do the work to
     * fetch and/or compute it if so, otherwise we return a new
     * identity transform.
     *
     * Note that the transform is _not_ necessarily the same as
     * the transform passed in as an Attribute in a Map, as the
     * transform returned will also reflect the effects of WIDTH and
     * SUPERSCRIPT attributes.  Clients who want the actual transform
     * need to call getRequestedAttributes.
     */
    if (nonIdentityTx) {
        AttributeValues values = getAttributeValues();

        AffineTransform at = values.isNonDefault(ETRANSFORM)
            ? new AffineTransform(values.getTransform())
            : new AffineTransform();

        if (values.getSuperscript() != 0) {
            // can't get ascent and descent here, recursive call to this fn,
            // so use pointsize
            // let users combine super- and sub-scripting

            int superscript = values.getSuperscript();

            double trans = 0;
            int n = 0;
            boolean up = superscript > 0;
            int sign = up ? -1 : 1;
            int ss = up ? superscript : -superscript;

            while ((ss & 7) > n) {
                int newn = ss & 7;
                trans += sign * (ssinfo[newn] - ssinfo[n]);
                ss >>= 3;
                sign = -sign;
                n = newn;
            }
            trans *= pointSize;
            double scale = Math.pow(2./3., n);

            at.preConcatenate(AffineTransform.getTranslateInstance(0, trans));
            at.scale(scale, scale);

            // note on placement and italics
            // We preconcatenate the transform because we don't want to translate along
            // the italic angle, but purely perpendicular to the baseline.  While this
            // looks ok for superscripts, it can lead subscripts to stack on each other
            // and bring the following text too close.  The way we deal with potential
            // collisions that can occur in the case of italics is by adjusting the
            // horizontal spacing of the adjacent glyphvectors.  Examine the italic
            // angle of both vectors, if one is non-zero, compute the minimum ascent
            // and descent, and then the x position at each for each vector along its
            // italic angle starting from its (offset) baseline.  Compute the difference
            // between the x positions and use the maximum difference to adjust the
            // position of the right gv.
        }

        if (values.isNonDefault(EWIDTH)) {
            at.scale(values.getWidth(), 1f);
        }

        return at;
    }

    return new AffineTransform();
}
 
Example 13
Source File: BufferedPaints.java    From openjdk-8-source with GNU General Public License v2.0 4 votes vote down vote up
/**
 * This method calculates six m** values and a focusX value that
 * are used by the native fragment shader.  These techniques are
 * based on a whitepaper by Daniel Rice on radial gradient performance
 * (attached to the bug report for 6521533).  One can refer to that
 * document for the complete set of formulas and calculations, but
 * the basic goal is to compose a transform that will convert an
 * (x,y) position in device space into a "u" value that represents
 * the relative distance to the gradient focus point.  The resulting
 * value can be used to look up the appropriate color by linearly
 * interpolating between the two nearest colors in the gradient.
 */
private static void setRadialGradientPaint(RenderQueue rq,
                                           SunGraphics2D sg2d,
                                           RadialGradientPaint paint,
                                           boolean useMask)
{
    boolean linear =
        (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
    int cycleMethod = paint.getCycleMethod().ordinal();
    float[] fractions = paint.getFractions();
    Color[] colors = paint.getColors();
    int numStops = colors.length;
    int[] pixels = convertToIntArgbPrePixels(colors, linear);
    Point2D center = paint.getCenterPoint();
    Point2D focus = paint.getFocusPoint();
    float radius = paint.getRadius();

    // save original (untransformed) center and focus points
    double cx = center.getX();
    double cy = center.getY();
    double fx = focus.getX();
    double fy = focus.getY();

    // transform from gradient coords to device coords
    AffineTransform at = paint.getTransform();
    at.preConcatenate(sg2d.transform);
    focus = at.transform(focus, focus);

    // transform unit circle to gradient coords; we start with the
    // unit circle (center=(0,0), focus on positive x-axis, radius=1)
    // and then transform into gradient space
    at.translate(cx, cy);
    at.rotate(fx - cx, fy - cy);
    at.scale(radius, radius);

    // invert to get mapping from device coords to unit circle
    try {
        at.invert();
    } catch (Exception e) {
        at.setToScale(0.0, 0.0);
    }
    focus = at.transform(focus, focus);

    // clamp the focus point so that it does not rest on, or outside
    // of, the circumference of the gradient circle
    fx = Math.min(focus.getX(), 0.99);

    // assert rq.lock.isHeldByCurrentThread();
    rq.ensureCapacity(20 + 28 + (numStops*4*2));
    RenderBuffer buf = rq.getBuffer();
    buf.putInt(SET_RADIAL_GRADIENT_PAINT);
    buf.putInt(useMask ? 1 : 0);
    buf.putInt(linear  ? 1 : 0);
    buf.putInt(numStops);
    buf.putInt(cycleMethod);
    buf.putFloat((float)at.getScaleX());
    buf.putFloat((float)at.getShearX());
    buf.putFloat((float)at.getTranslateX());
    buf.putFloat((float)at.getShearY());
    buf.putFloat((float)at.getScaleY());
    buf.putFloat((float)at.getTranslateY());
    buf.putFloat((float)fx);
    buf.put(fractions);
    buf.put(pixels);
}
 
Example 14
Source File: BufferedPaints.java    From jdk8u60 with GNU General Public License v2.0 4 votes vote down vote up
/**
 * This method calculates six m** values and a focusX value that
 * are used by the native fragment shader.  These techniques are
 * based on a whitepaper by Daniel Rice on radial gradient performance
 * (attached to the bug report for 6521533).  One can refer to that
 * document for the complete set of formulas and calculations, but
 * the basic goal is to compose a transform that will convert an
 * (x,y) position in device space into a "u" value that represents
 * the relative distance to the gradient focus point.  The resulting
 * value can be used to look up the appropriate color by linearly
 * interpolating between the two nearest colors in the gradient.
 */
private static void setRadialGradientPaint(RenderQueue rq,
                                           SunGraphics2D sg2d,
                                           RadialGradientPaint paint,
                                           boolean useMask)
{
    boolean linear =
        (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
    int cycleMethod = paint.getCycleMethod().ordinal();
    float[] fractions = paint.getFractions();
    Color[] colors = paint.getColors();
    int numStops = colors.length;
    int[] pixels = convertToIntArgbPrePixels(colors, linear);
    Point2D center = paint.getCenterPoint();
    Point2D focus = paint.getFocusPoint();
    float radius = paint.getRadius();

    // save original (untransformed) center and focus points
    double cx = center.getX();
    double cy = center.getY();
    double fx = focus.getX();
    double fy = focus.getY();

    // transform from gradient coords to device coords
    AffineTransform at = paint.getTransform();
    at.preConcatenate(sg2d.transform);
    focus = at.transform(focus, focus);

    // transform unit circle to gradient coords; we start with the
    // unit circle (center=(0,0), focus on positive x-axis, radius=1)
    // and then transform into gradient space
    at.translate(cx, cy);
    at.rotate(fx - cx, fy - cy);
    at.scale(radius, radius);

    // invert to get mapping from device coords to unit circle
    try {
        at.invert();
    } catch (Exception e) {
        at.setToScale(0.0, 0.0);
    }
    focus = at.transform(focus, focus);

    // clamp the focus point so that it does not rest on, or outside
    // of, the circumference of the gradient circle
    fx = Math.min(focus.getX(), 0.99);

    // assert rq.lock.isHeldByCurrentThread();
    rq.ensureCapacity(20 + 28 + (numStops*4*2));
    RenderBuffer buf = rq.getBuffer();
    buf.putInt(SET_RADIAL_GRADIENT_PAINT);
    buf.putInt(useMask ? 1 : 0);
    buf.putInt(linear  ? 1 : 0);
    buf.putInt(numStops);
    buf.putInt(cycleMethod);
    buf.putFloat((float)at.getScaleX());
    buf.putFloat((float)at.getShearX());
    buf.putFloat((float)at.getTranslateX());
    buf.putFloat((float)at.getShearY());
    buf.putFloat((float)at.getScaleY());
    buf.putFloat((float)at.getTranslateY());
    buf.putFloat((float)fx);
    buf.put(fractions);
    buf.put(pixels);
}
 
Example 15
Source File: Font.java    From jdk1.8-source-analysis with Apache License 2.0 4 votes vote down vote up
/**
 * Returns a copy of the transform associated with this
 * <code>Font</code>.  This transform is not necessarily the one
 * used to construct the font.  If the font has algorithmic
 * superscripting or width adjustment, this will be incorporated
 * into the returned <code>AffineTransform</code>.
 * <p>
 * Typically, fonts will not be transformed.  Clients generally
 * should call {@link #isTransformed} first, and only call this
 * method if <code>isTransformed</code> returns true.
 *
 * @return an {@link AffineTransform} object representing the
 *          transform attribute of this <code>Font</code> object.
 */
public AffineTransform getTransform() {
    /* The most common case is the identity transform.  Most callers
     * should call isTransformed() first, to decide if they need to
     * get the transform, but some may not.  Here we check to see
     * if we have a nonidentity transform, and only do the work to
     * fetch and/or compute it if so, otherwise we return a new
     * identity transform.
     *
     * Note that the transform is _not_ necessarily the same as
     * the transform passed in as an Attribute in a Map, as the
     * transform returned will also reflect the effects of WIDTH and
     * SUPERSCRIPT attributes.  Clients who want the actual transform
     * need to call getRequestedAttributes.
     */
    if (nonIdentityTx) {
        AttributeValues values = getAttributeValues();

        AffineTransform at = values.isNonDefault(ETRANSFORM)
            ? new AffineTransform(values.getTransform())
            : new AffineTransform();

        if (values.getSuperscript() != 0) {
            // can't get ascent and descent here, recursive call to this fn,
            // so use pointsize
            // let users combine super- and sub-scripting

            int superscript = values.getSuperscript();

            double trans = 0;
            int n = 0;
            boolean up = superscript > 0;
            int sign = up ? -1 : 1;
            int ss = up ? superscript : -superscript;

            while ((ss & 7) > n) {
                int newn = ss & 7;
                trans += sign * (ssinfo[newn] - ssinfo[n]);
                ss >>= 3;
                sign = -sign;
                n = newn;
            }
            trans *= pointSize;
            double scale = Math.pow(2./3., n);

            at.preConcatenate(AffineTransform.getTranslateInstance(0, trans));
            at.scale(scale, scale);

            // note on placement and italics
            // We preconcatenate the transform because we don't want to translate along
            // the italic angle, but purely perpendicular to the baseline.  While this
            // looks ok for superscripts, it can lead subscripts to stack on each other
            // and bring the following text too close.  The way we deal with potential
            // collisions that can occur in the case of italics is by adjusting the
            // horizontal spacing of the adjacent glyphvectors.  Examine the italic
            // angle of both vectors, if one is non-zero, compute the minimum ascent
            // and descent, and then the x position at each for each vector along its
            // italic angle starting from its (offset) baseline.  Compute the difference
            // between the x positions and use the maximum difference to adjust the
            // position of the right gv.
        }

        if (values.isNonDefault(EWIDTH)) {
            at.scale(values.getWidth(), 1f);
        }

        return at;
    }

    return new AffineTransform();
}
 
Example 16
Source File: BufferedPaints.java    From hottub with GNU General Public License v2.0 4 votes vote down vote up
/**
 * This method calculates six m** values and a focusX value that
 * are used by the native fragment shader.  These techniques are
 * based on a whitepaper by Daniel Rice on radial gradient performance
 * (attached to the bug report for 6521533).  One can refer to that
 * document for the complete set of formulas and calculations, but
 * the basic goal is to compose a transform that will convert an
 * (x,y) position in device space into a "u" value that represents
 * the relative distance to the gradient focus point.  The resulting
 * value can be used to look up the appropriate color by linearly
 * interpolating between the two nearest colors in the gradient.
 */
private static void setRadialGradientPaint(RenderQueue rq,
                                           SunGraphics2D sg2d,
                                           RadialGradientPaint paint,
                                           boolean useMask)
{
    boolean linear =
        (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
    int cycleMethod = paint.getCycleMethod().ordinal();
    float[] fractions = paint.getFractions();
    Color[] colors = paint.getColors();
    int numStops = colors.length;
    int[] pixels = convertToIntArgbPrePixels(colors, linear);
    Point2D center = paint.getCenterPoint();
    Point2D focus = paint.getFocusPoint();
    float radius = paint.getRadius();

    // save original (untransformed) center and focus points
    double cx = center.getX();
    double cy = center.getY();
    double fx = focus.getX();
    double fy = focus.getY();

    // transform from gradient coords to device coords
    AffineTransform at = paint.getTransform();
    at.preConcatenate(sg2d.transform);
    focus = at.transform(focus, focus);

    // transform unit circle to gradient coords; we start with the
    // unit circle (center=(0,0), focus on positive x-axis, radius=1)
    // and then transform into gradient space
    at.translate(cx, cy);
    at.rotate(fx - cx, fy - cy);
    at.scale(radius, radius);

    // invert to get mapping from device coords to unit circle
    try {
        at.invert();
    } catch (Exception e) {
        at.setToScale(0.0, 0.0);
    }
    focus = at.transform(focus, focus);

    // clamp the focus point so that it does not rest on, or outside
    // of, the circumference of the gradient circle
    fx = Math.min(focus.getX(), 0.99);

    // assert rq.lock.isHeldByCurrentThread();
    rq.ensureCapacity(20 + 28 + (numStops*4*2));
    RenderBuffer buf = rq.getBuffer();
    buf.putInt(SET_RADIAL_GRADIENT_PAINT);
    buf.putInt(useMask ? 1 : 0);
    buf.putInt(linear  ? 1 : 0);
    buf.putInt(numStops);
    buf.putInt(cycleMethod);
    buf.putFloat((float)at.getScaleX());
    buf.putFloat((float)at.getShearX());
    buf.putFloat((float)at.getTranslateX());
    buf.putFloat((float)at.getShearY());
    buf.putFloat((float)at.getScaleY());
    buf.putFloat((float)at.getTranslateY());
    buf.putFloat((float)fx);
    buf.put(fractions);
    buf.put(pixels);
}
 
Example 17
Source File: BufferedPaints.java    From openjdk-8 with GNU General Public License v2.0 4 votes vote down vote up
/**
 * This method uses techniques that are nearly identical to those
 * employed in setGradientPaint() above.  The primary difference
 * is that at the native level we use a fragment shader to manually
 * apply the plane equation constants to the current fragment position
 * to calculate the gradient position in the range [0,1] (the native
 * code for GradientPaint does the same, except that it uses OpenGL's
 * automatic texture coordinate generation facilities).
 *
 * One other minor difference worth mentioning is that
 * setGradientPaint() calculates the plane equation constants
 * such that the gradient end points are positioned at 0.25 and 0.75
 * (for reasons discussed in the comments for that method).  In
 * contrast, for LinearGradientPaint we setup the equation constants
 * such that the gradient end points fall at 0.0 and 1.0.  The
 * reason for this difference is that in the fragment shader we
 * have more control over how the gradient values are interpreted
 * (depending on the paint's CycleMethod).
 */
private static void setLinearGradientPaint(RenderQueue rq,
                                           SunGraphics2D sg2d,
                                           LinearGradientPaint paint,
                                           boolean useMask)
{
    boolean linear =
        (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
    Color[] colors = paint.getColors();
    int numStops = colors.length;
    Point2D pt1 = paint.getStartPoint();
    Point2D pt2 = paint.getEndPoint();
    AffineTransform at = paint.getTransform();
    at.preConcatenate(sg2d.transform);

    if (!linear && numStops == 2 &&
        paint.getCycleMethod() != CycleMethod.REPEAT)
    {
        // delegate to the optimized two-color gradient codepath
        boolean isCyclic =
            (paint.getCycleMethod() != CycleMethod.NO_CYCLE);
        setGradientPaint(rq, at,
                         colors[0], colors[1],
                         pt1, pt2,
                         isCyclic, useMask);
        return;
    }

    int cycleMethod = paint.getCycleMethod().ordinal();
    float[] fractions = paint.getFractions();
    int[] pixels = convertToIntArgbPrePixels(colors, linear);

    // calculate plane equation constants
    double x = pt1.getX();
    double y = pt1.getY();
    at.translate(x, y);
    // now gradient point 1 is at the origin
    x = pt2.getX() - x;
    y = pt2.getY() - y;
    double len = Math.sqrt(x * x + y * y);
    at.rotate(x, y);
    // now gradient point 2 is on the positive x-axis
    at.scale(len, 1);
    // now gradient point 1 is at (0.0, 0), point 2 is at (1.0, 0)

    float p0, p1, p3;
    try {
        at.invert();
        p0 = (float)at.getScaleX();
        p1 = (float)at.getShearX();
        p3 = (float)at.getTranslateX();
    } catch (java.awt.geom.NoninvertibleTransformException e) {
        p0 = p1 = p3 = 0.0f;
    }

    // assert rq.lock.isHeldByCurrentThread();
    rq.ensureCapacity(20 + 12 + (numStops*4*2));
    RenderBuffer buf = rq.getBuffer();
    buf.putInt(SET_LINEAR_GRADIENT_PAINT);
    buf.putInt(useMask ? 1 : 0);
    buf.putInt(linear  ? 1 : 0);
    buf.putInt(cycleMethod);
    buf.putInt(numStops);
    buf.putFloat(p0);
    buf.putFloat(p1);
    buf.putFloat(p3);
    buf.put(fractions);
    buf.put(pixels);
}
 
Example 18
Source File: BufferedPaints.java    From jdk8u-jdk with GNU General Public License v2.0 4 votes vote down vote up
/**
 * This method uses techniques that are nearly identical to those
 * employed in setGradientPaint() above.  The primary difference
 * is that at the native level we use a fragment shader to manually
 * apply the plane equation constants to the current fragment position
 * to calculate the gradient position in the range [0,1] (the native
 * code for GradientPaint does the same, except that it uses OpenGL's
 * automatic texture coordinate generation facilities).
 *
 * One other minor difference worth mentioning is that
 * setGradientPaint() calculates the plane equation constants
 * such that the gradient end points are positioned at 0.25 and 0.75
 * (for reasons discussed in the comments for that method).  In
 * contrast, for LinearGradientPaint we setup the equation constants
 * such that the gradient end points fall at 0.0 and 1.0.  The
 * reason for this difference is that in the fragment shader we
 * have more control over how the gradient values are interpreted
 * (depending on the paint's CycleMethod).
 */
private static void setLinearGradientPaint(RenderQueue rq,
                                           SunGraphics2D sg2d,
                                           LinearGradientPaint paint,
                                           boolean useMask)
{
    boolean linear =
        (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
    Color[] colors = paint.getColors();
    int numStops = colors.length;
    Point2D pt1 = paint.getStartPoint();
    Point2D pt2 = paint.getEndPoint();
    AffineTransform at = paint.getTransform();
    at.preConcatenate(sg2d.transform);

    if (!linear && numStops == 2 &&
        paint.getCycleMethod() != CycleMethod.REPEAT)
    {
        // delegate to the optimized two-color gradient codepath
        boolean isCyclic =
            (paint.getCycleMethod() != CycleMethod.NO_CYCLE);
        setGradientPaint(rq, at,
                         colors[0], colors[1],
                         pt1, pt2,
                         isCyclic, useMask);
        return;
    }

    int cycleMethod = paint.getCycleMethod().ordinal();
    float[] fractions = paint.getFractions();
    int[] pixels = convertToIntArgbPrePixels(colors, linear);

    // calculate plane equation constants
    double x = pt1.getX();
    double y = pt1.getY();
    at.translate(x, y);
    // now gradient point 1 is at the origin
    x = pt2.getX() - x;
    y = pt2.getY() - y;
    double len = Math.sqrt(x * x + y * y);
    at.rotate(x, y);
    // now gradient point 2 is on the positive x-axis
    at.scale(len, 1);
    // now gradient point 1 is at (0.0, 0), point 2 is at (1.0, 0)

    float p0, p1, p3;
    try {
        at.invert();
        p0 = (float)at.getScaleX();
        p1 = (float)at.getShearX();
        p3 = (float)at.getTranslateX();
    } catch (java.awt.geom.NoninvertibleTransformException e) {
        p0 = p1 = p3 = 0.0f;
    }

    // assert rq.lock.isHeldByCurrentThread();
    rq.ensureCapacity(20 + 12 + (numStops*4*2));
    RenderBuffer buf = rq.getBuffer();
    buf.putInt(SET_LINEAR_GRADIENT_PAINT);
    buf.putInt(useMask ? 1 : 0);
    buf.putInt(linear  ? 1 : 0);
    buf.putInt(cycleMethod);
    buf.putInt(numStops);
    buf.putFloat(p0);
    buf.putFloat(p1);
    buf.putFloat(p3);
    buf.put(fractions);
    buf.put(pixels);
}
 
Example 19
Source File: BufferedPaints.java    From dragonwell8_jdk with GNU General Public License v2.0 4 votes vote down vote up
/**
 * This method uses techniques that are nearly identical to those
 * employed in setGradientPaint() above.  The primary difference
 * is that at the native level we use a fragment shader to manually
 * apply the plane equation constants to the current fragment position
 * to calculate the gradient position in the range [0,1] (the native
 * code for GradientPaint does the same, except that it uses OpenGL's
 * automatic texture coordinate generation facilities).
 *
 * One other minor difference worth mentioning is that
 * setGradientPaint() calculates the plane equation constants
 * such that the gradient end points are positioned at 0.25 and 0.75
 * (for reasons discussed in the comments for that method).  In
 * contrast, for LinearGradientPaint we setup the equation constants
 * such that the gradient end points fall at 0.0 and 1.0.  The
 * reason for this difference is that in the fragment shader we
 * have more control over how the gradient values are interpreted
 * (depending on the paint's CycleMethod).
 */
private static void setLinearGradientPaint(RenderQueue rq,
                                           SunGraphics2D sg2d,
                                           LinearGradientPaint paint,
                                           boolean useMask)
{
    boolean linear =
        (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
    Color[] colors = paint.getColors();
    int numStops = colors.length;
    Point2D pt1 = paint.getStartPoint();
    Point2D pt2 = paint.getEndPoint();
    AffineTransform at = paint.getTransform();
    at.preConcatenate(sg2d.transform);

    if (!linear && numStops == 2 &&
        paint.getCycleMethod() != CycleMethod.REPEAT)
    {
        // delegate to the optimized two-color gradient codepath
        boolean isCyclic =
            (paint.getCycleMethod() != CycleMethod.NO_CYCLE);
        setGradientPaint(rq, at,
                         colors[0], colors[1],
                         pt1, pt2,
                         isCyclic, useMask);
        return;
    }

    int cycleMethod = paint.getCycleMethod().ordinal();
    float[] fractions = paint.getFractions();
    int[] pixels = convertToIntArgbPrePixels(colors, linear);

    // calculate plane equation constants
    double x = pt1.getX();
    double y = pt1.getY();
    at.translate(x, y);
    // now gradient point 1 is at the origin
    x = pt2.getX() - x;
    y = pt2.getY() - y;
    double len = Math.sqrt(x * x + y * y);
    at.rotate(x, y);
    // now gradient point 2 is on the positive x-axis
    at.scale(len, 1);
    // now gradient point 1 is at (0.0, 0), point 2 is at (1.0, 0)

    float p0, p1, p3;
    try {
        at.invert();
        p0 = (float)at.getScaleX();
        p1 = (float)at.getShearX();
        p3 = (float)at.getTranslateX();
    } catch (java.awt.geom.NoninvertibleTransformException e) {
        p0 = p1 = p3 = 0.0f;
    }

    // assert rq.lock.isHeldByCurrentThread();
    rq.ensureCapacity(20 + 12 + (numStops*4*2));
    RenderBuffer buf = rq.getBuffer();
    buf.putInt(SET_LINEAR_GRADIENT_PAINT);
    buf.putInt(useMask ? 1 : 0);
    buf.putInt(linear  ? 1 : 0);
    buf.putInt(cycleMethod);
    buf.putInt(numStops);
    buf.putFloat(p0);
    buf.putFloat(p1);
    buf.putFloat(p3);
    buf.put(fractions);
    buf.put(pixels);
}
 
Example 20
Source File: BufferedPaints.java    From jdk8u-jdk with GNU General Public License v2.0 4 votes vote down vote up
/**
 * This method uses techniques that are nearly identical to those
 * employed in setGradientPaint() above.  The primary difference
 * is that at the native level we use a fragment shader to manually
 * apply the plane equation constants to the current fragment position
 * to calculate the gradient position in the range [0,1] (the native
 * code for GradientPaint does the same, except that it uses OpenGL's
 * automatic texture coordinate generation facilities).
 *
 * One other minor difference worth mentioning is that
 * setGradientPaint() calculates the plane equation constants
 * such that the gradient end points are positioned at 0.25 and 0.75
 * (for reasons discussed in the comments for that method).  In
 * contrast, for LinearGradientPaint we setup the equation constants
 * such that the gradient end points fall at 0.0 and 1.0.  The
 * reason for this difference is that in the fragment shader we
 * have more control over how the gradient values are interpreted
 * (depending on the paint's CycleMethod).
 */
private static void setLinearGradientPaint(RenderQueue rq,
                                           SunGraphics2D sg2d,
                                           LinearGradientPaint paint,
                                           boolean useMask)
{
    boolean linear =
        (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
    Color[] colors = paint.getColors();
    int numStops = colors.length;
    Point2D pt1 = paint.getStartPoint();
    Point2D pt2 = paint.getEndPoint();
    AffineTransform at = paint.getTransform();
    at.preConcatenate(sg2d.transform);

    if (!linear && numStops == 2 &&
        paint.getCycleMethod() != CycleMethod.REPEAT)
    {
        // delegate to the optimized two-color gradient codepath
        boolean isCyclic =
            (paint.getCycleMethod() != CycleMethod.NO_CYCLE);
        setGradientPaint(rq, at,
                         colors[0], colors[1],
                         pt1, pt2,
                         isCyclic, useMask);
        return;
    }

    int cycleMethod = paint.getCycleMethod().ordinal();
    float[] fractions = paint.getFractions();
    int[] pixels = convertToIntArgbPrePixels(colors, linear);

    // calculate plane equation constants
    double x = pt1.getX();
    double y = pt1.getY();
    at.translate(x, y);
    // now gradient point 1 is at the origin
    x = pt2.getX() - x;
    y = pt2.getY() - y;
    double len = Math.sqrt(x * x + y * y);
    at.rotate(x, y);
    // now gradient point 2 is on the positive x-axis
    at.scale(len, 1);
    // now gradient point 1 is at (0.0, 0), point 2 is at (1.0, 0)

    float p0, p1, p3;
    try {
        at.invert();
        p0 = (float)at.getScaleX();
        p1 = (float)at.getShearX();
        p3 = (float)at.getTranslateX();
    } catch (java.awt.geom.NoninvertibleTransformException e) {
        p0 = p1 = p3 = 0.0f;
    }

    // assert rq.lock.isHeldByCurrentThread();
    rq.ensureCapacity(20 + 12 + (numStops*4*2));
    RenderBuffer buf = rq.getBuffer();
    buf.putInt(SET_LINEAR_GRADIENT_PAINT);
    buf.putInt(useMask ? 1 : 0);
    buf.putInt(linear  ? 1 : 0);
    buf.putInt(cycleMethod);
    buf.putInt(numStops);
    buf.putFloat(p0);
    buf.putFloat(p1);
    buf.putFloat(p3);
    buf.put(fractions);
    buf.put(pixels);
}