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

The following examples show how to use java.awt.geom.AffineTransform#getScaleY() . These examples are extracted from open source projects. 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 Project: pumpernickel   File: PerspectiveTransform.java    License: MIT License 6 votes vote down vote up
/**
 * Sets this transform to a given AffineTransform.
 * 
 * @throws IllegalArgumentException
 *             if Tx is null
 */
public void setTransform(AffineTransform Tx) {
	if (Tx == null) {
		throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
	}

	m00 = Tx.getScaleX();
	m01 = Tx.getShearX();
	m02 = Tx.getTranslateX();
	m10 = Tx.getShearY();
	m11 = Tx.getScaleY();
	m12 = Tx.getTranslateY();
	m20 = 0.0;
	m21 = 0.0;
	m22 = 1.0;
}
 
Example 2
public static PathConsumer2D
    inverseDeltaTransformConsumer(PathConsumer2D out,
                                  AffineTransform at)
{
    if (at == null) {
        return out;
    }
    float Mxx = (float) at.getScaleX();
    float Mxy = (float) at.getShearX();
    float Myx = (float) at.getShearY();
    float Myy = (float) at.getScaleY();
    if (Mxy == 0f && Myx == 0f) {
        if (Mxx == 1f && Myy == 1f) {
            return out;
        } else {
            return new DeltaScaleFilter(out, 1.0f/Mxx, 1.0f/Myy);
        }
    } else {
        float det = Mxx * Myy - Mxy * Myx;
        return new DeltaTransformFilter(out,
                                        Myy / det,
                                        -Mxy / det,
                                        -Myx / det,
                                        Mxx / det);
    }
}
 
Example 3
PathConsumer2D inverseDeltaTransformConsumer(PathConsumer2D out,
                                             AffineTransform at)
{
    if (at == null) {
        return out;
    }
    float mxx = (float) at.getScaleX();
    float mxy = (float) at.getShearX();
    float myx = (float) at.getShearY();
    float myy = (float) at.getScaleY();

    if (mxy == 0.0f && myx == 0.0f) {
        if (mxx == 1.0f && myy == 1.0f) {
            return out;
        } else {
            return iv_DeltaScaleFilter.init(out, 1.0f / mxx, 1.0f / myy);
        }
    } else {
        final float det = mxx * myy - mxy * myx;
        return iv_DeltaTransformFilter.init(out,
                                            myy / det,
                                           -mxy / det,
                                           -myx / det,
                                            mxx / det);
    }
}
 
Example 4
public static PathConsumer2D
    inverseDeltaTransformConsumer(PathConsumer2D out,
                                  AffineTransform at)
{
    if (at == null) {
        return out;
    }
    float Mxx = (float) at.getScaleX();
    float Mxy = (float) at.getShearX();
    float Myx = (float) at.getShearY();
    float Myy = (float) at.getScaleY();
    if (Mxy == 0f && Myx == 0f) {
        if (Mxx == 1f && Myy == 1f) {
            return out;
        } else {
            return new DeltaScaleFilter(out, 1.0f/Mxx, 1.0f/Myy);
        }
    } else {
        float det = Mxx * Myy - Mxy * Myx;
        return new DeltaTransformFilter(out,
                                        Myy / det,
                                        -Mxy / det,
                                        -Myx / det,
                                        Mxx / det);
    }
}
 
Example 5
public static PathConsumer2D
    inverseDeltaTransformConsumer(PathConsumer2D out,
                                  AffineTransform at)
{
    if (at == null) {
        return out;
    }
    float Mxx = (float) at.getScaleX();
    float Mxy = (float) at.getShearX();
    float Myx = (float) at.getShearY();
    float Myy = (float) at.getScaleY();
    if (Mxy == 0f && Myx == 0f) {
        if (Mxx == 1f && Myy == 1f) {
            return out;
        } else {
            return new DeltaScaleFilter(out, 1.0f/Mxx, 1.0f/Myy);
        }
    } else {
        float det = Mxx * Myy - Mxy * Myx;
        return new DeltaTransformFilter(out,
                                        Myy / det,
                                        -Mxy / det,
                                        -Myx / det,
                                        Mxx / det);
    }
}
 
Example 6
public static PathConsumer2D
    inverseDeltaTransformConsumer(PathConsumer2D out,
                                  AffineTransform at)
{
    if (at == null) {
        return out;
    }
    float Mxx = (float) at.getScaleX();
    float Mxy = (float) at.getShearX();
    float Myx = (float) at.getShearY();
    float Myy = (float) at.getScaleY();
    if (Mxy == 0f && Myx == 0f) {
        if (Mxx == 1f && Myy == 1f) {
            return out;
        } else {
            return new DeltaScaleFilter(out, 1.0f/Mxx, 1.0f/Myy);
        }
    } else {
        float det = Mxx * Myy - Mxy * Myx;
        return new DeltaTransformFilter(out,
                                        Myy / det,
                                        -Mxy / det,
                                        -Myx / det,
                                        Mxx / det);
    }
}
 
Example 7
Source Project: osp   File: Arrow.java    License: GNU General Public License v3.0 6 votes vote down vote up
/**
 * Draws the arrow.
 *
 * @param panel  the drawing panel in which the arrow is viewed
 * @param g  the graphics context upon which to draw
 */
public void draw(DrawingPanel panel, Graphics g) {
  Graphics2D g2 = (Graphics2D) g;
  AffineTransform toPixels = panel.getPixelTransform();
  g2.setPaint(color);
  // draw the shaft
  g2.draw(toPixels.createTransformedShape(new Line2D.Double(x, y, x+a, y+b)));
  Point2D pt = new Point2D.Double(x+a, y+b);
  pt = toPixels.transform(pt, pt);
  double aspect = panel.isSquareAspect() ? 1 : -toPixels.getScaleX()/toPixels.getScaleY();
  Shape head = getHead(Math.atan2(b, aspect*a));
  Shape temp = AffineTransform.getTranslateInstance(pt.getX(), pt.getY()).createTransformedShape(head);
  // draw the head
  g2.fill(temp);
  g2.setPaint(Color.BLACK);
}
 
Example 8
public static PathConsumer2D
    deltaTransformConsumer(PathConsumer2D out,
                           AffineTransform at)
{
    if (at == null) {
        return out;
    }
    float Mxx = (float) at.getScaleX();
    float Mxy = (float) at.getShearX();
    float Myx = (float) at.getShearY();
    float Myy = (float) at.getScaleY();
    if (Mxy == 0f && Myx == 0f) {
        if (Mxx == 1f && Myy == 1f) {
            return out;
        } else {
            return new DeltaScaleFilter(out, Mxx, Myy);
        }
    } else {
        return new DeltaTransformFilter(out, Mxx, Mxy, Myx, Myy);
    }
}
 
Example 9
public void fillRectangle(SunGraphics2D sg2d,
                          double rx, double ry,
                          double rw, double rh)
{
    double px, py;
    double dx1, dy1, dx2, dy2;
    AffineTransform txform = sg2d.transform;
    dx1 = txform.getScaleX();
    dy1 = txform.getShearY();
    dx2 = txform.getShearX();
    dy2 = txform.getScaleY();
    px = rx * dx1 + ry * dx2 + txform.getTranslateX();
    py = rx * dy1 + ry * dy2 + txform.getTranslateY();
    dx1 *= rw;
    dy1 *= rw;
    dx2 *= rh;
    dy2 *= rh;
    if (adjustfill &&
        sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM &&
        sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE)
    {
        double newx = normalize(px);
        double newy = normalize(py);
        dx1 = normalize(px + dx1) - newx;
        dy1 = normalize(py + dy1) - newy;
        dx2 = normalize(px + dx2) - newx;
        dy2 = normalize(py + dy2) - newy;
        px = newx;
        py = newy;
    }
    outrenderer.fillParallelogram(sg2d, rx, ry, rx+rw, ry+rh,
                                  px, py, dx1, dy1, dx2, dy2);
}
 
Example 10
public void fillRectangle(SunGraphics2D sg2d,
                          double rx, double ry,
                          double rw, double rh)
{
    double px, py;
    double dx1, dy1, dx2, dy2;
    AffineTransform txform = sg2d.transform;
    dx1 = txform.getScaleX();
    dy1 = txform.getShearY();
    dx2 = txform.getShearX();
    dy2 = txform.getScaleY();
    px = rx * dx1 + ry * dx2 + txform.getTranslateX();
    py = rx * dy1 + ry * dy2 + txform.getTranslateY();
    dx1 *= rw;
    dy1 *= rw;
    dx2 *= rh;
    dy2 *= rh;
    if (adjustfill &&
        sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM &&
        sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE)
    {
        double newx = normalize(px);
        double newy = normalize(py);
        dx1 = normalize(px + dx1) - newx;
        dy1 = normalize(py + dy1) - newy;
        dx2 = normalize(px + dx2) - newx;
        dy2 = normalize(py + dy2) - newy;
        px = newx;
        py = newy;
    }
    outrenderer.fillParallelogram(sg2d, rx, ry, rx+rw, ry+rh,
                                  px, py, dx1, dy1, dx2, dy2);
}
 
Example 11
private int getNativePointSize() {
    /* Make a copy of the glyphTX in which we will store the
     * font transform, inverting the devTx if necessary
     */
    double[] mat = new double[4];
    desc.glyphTx.getMatrix(mat);
    fontTx = new AffineTransform(mat);

    /* Now work backwards to get the font transform */
    if (!desc.devTx.isIdentity() &&
        desc.devTx.getType() != AffineTransform.TYPE_TRANSLATION) {
        try {
            invertDevTx = desc.devTx.createInverse();
            fontTx.concatenate(invertDevTx);
        } catch (NoninvertibleTransformException e) {
            e.printStackTrace();
        }
    }

    /* At this point the fontTx may be a simple +ve scale, or it
     * may be something more complex.
     */
    Point2D.Float pt = new Point2D.Float(1f,1f);
    fontTx.deltaTransform(pt, pt);
    double ptSize = Math.abs(pt.y);
    int ttype = fontTx.getType();
    if ((ttype & ~AffineTransform.TYPE_UNIFORM_SCALE) != 0 ||
        fontTx.getScaleY() <= 0) {
        /* We need to create an inverse transform that doesn't
         * include the point size (strictly the uniform scale)
         */
        fontTx.scale(1/ptSize, 1/ptSize);
    } else {
        fontTx = null; // no need
    }
    return (int)ptSize;
}
 
Example 12
public static boolean isFloatingPointScale(AffineTransform tx) {
    int type = tx.getType() & ~(TYPE_FLIP | TYPE_TRANSLATION);
    if (type == 0) {
        return false;
    } else if ((type & ~TYPE_MASK_SCALE) == 0) {
        double scaleX = tx.getScaleX();
        double scaleY = tx.getScaleY();
        return (scaleX != (int) scaleX) || (scaleY != (int) scaleY);
    } else {
        return false;
    }
}
 
Example 13
public static PathConsumer2D
    transformConsumer(PathConsumer2D out,
                      AffineTransform at)
{
    if (at == null) {
        return out;
    }
    float Mxx = (float) at.getScaleX();
    float Mxy = (float) at.getShearX();
    float Mxt = (float) at.getTranslateX();
    float Myx = (float) at.getShearY();
    float Myy = (float) at.getScaleY();
    float Myt = (float) at.getTranslateY();
    if (Mxy == 0f && Myx == 0f) {
        if (Mxx == 1f && Myy == 1f) {
            if (Mxt == 0f && Myt == 0f) {
                return out;
            } else {
                return new TranslateFilter(out, Mxt, Myt);
            }
        } else {
            if (Mxt == 0f && Myt == 0f) {
                return new DeltaScaleFilter(out, Mxx, Myy);
            } else {
                return new ScaleFilter(out, Mxx, Myy, Mxt, Myt);
            }
        }
    } else if (Mxt == 0f && Myt == 0f) {
        return new DeltaTransformFilter(out, Mxx, Mxy, Myx, Myy);
    } else {
        return new TransformFilter(out, Mxx, Mxy, Mxt, Myx, Myy, Myt);
    }
}
 
Example 14
Source Project: gcs   File: PageDrawer.java    License: Mozilla Public License 2.0 5 votes vote down vote up
private void drawBufferedImage(BufferedImage image, AffineTransform at) throws IOException
{
    graphics.setComposite(getGraphicsState().getNonStrokingJavaComposite());
    setClip();
    AffineTransform imageTransform = new AffineTransform(at);
    PDSoftMask softMask = getGraphicsState().getSoftMask();
    if( softMask != null )
    {
        imageTransform.scale(1, -1);
        imageTransform.translate(0, -1);
        Paint awtPaint = new TexturePaint(image,
                new Rectangle2D.Double(imageTransform.getTranslateX(), imageTransform.getTranslateY(),
                        imageTransform.getScaleX(), imageTransform.getScaleY()));
        awtPaint = applySoftMaskToPaint(awtPaint, softMask);
        graphics.setPaint(awtPaint);
        Rectangle2D unitRect = new Rectangle2D.Float(0, 0, 1, 1);
        if (isContentRendered())
        {
            graphics.fill(at.createTransformedShape(unitRect));
        }
    }
    else
    {
        COSBase transfer = getGraphicsState().getTransfer();
        if (transfer instanceof COSArray || transfer instanceof COSDictionary)
        {
            image = applyTransferFunction(image, transfer);
        }

        int width = image.getWidth();
        int height = image.getHeight();
        imageTransform.scale(1.0 / width, -1.0 / height);
        imageTransform.translate(0, -height);
        if (isContentRendered())
        {
            graphics.drawImage(image, imageTransform, null);
        }
    }
}
 
Example 15
private int getNativePointSize() {
    /* Make a copy of the glyphTX in which we will store the
     * font transform, inverting the devTx if necessary
     */
    double[] mat = new double[4];
    desc.glyphTx.getMatrix(mat);
    fontTx = new AffineTransform(mat);

    /* Now work backwards to get the font transform */
    if (!desc.devTx.isIdentity() &&
        desc.devTx.getType() != AffineTransform.TYPE_TRANSLATION) {
        try {
            invertDevTx = desc.devTx.createInverse();
            fontTx.concatenate(invertDevTx);
        } catch (NoninvertibleTransformException e) {
            e.printStackTrace();
        }
    }

    /* At this point the fontTx may be a simple +ve scale, or it
     * may be something more complex.
     */
    Point2D.Float pt = new Point2D.Float(1f,1f);
    fontTx.deltaTransform(pt, pt);
    double ptSize = Math.abs(pt.y);
    int ttype = fontTx.getType();
    if ((ttype & ~AffineTransform.TYPE_UNIFORM_SCALE) != 0 ||
        fontTx.getScaleY() <= 0) {
        /* We need to create an inverse transform that doesn't
         * include the point size (strictly the uniform scale)
         */
        fontTx.scale(1/ptSize, 1/ptSize);
    } else {
        fontTx = null; // no need
    }
    return (int)ptSize;
}
 
Example 16
private int getNativePointSize() {
    /* Make a copy of the glyphTX in which we will store the
     * font transform, inverting the devTx if necessary
     */
    double[] mat = new double[4];
    desc.glyphTx.getMatrix(mat);
    fontTx = new AffineTransform(mat);

    /* Now work backwards to get the font transform */
    if (!desc.devTx.isIdentity() &&
        desc.devTx.getType() != AffineTransform.TYPE_TRANSLATION) {
        try {
            invertDevTx = desc.devTx.createInverse();
            fontTx.concatenate(invertDevTx);
        } catch (NoninvertibleTransformException e) {
            e.printStackTrace();
        }
    }

    /* At this point the fontTx may be a simple +ve scale, or it
     * may be something more complex.
     */
    Point2D.Float pt = new Point2D.Float(1f,1f);
    fontTx.deltaTransform(pt, pt);
    double ptSize = Math.abs(pt.y);
    int ttype = fontTx.getType();
    if ((ttype & ~AffineTransform.TYPE_UNIFORM_SCALE) != 0 ||
        fontTx.getScaleY() <= 0) {
        /* We need to create an inverse transform that doesn't
         * include the point size (strictly the uniform scale)
         */
        fontTx.scale(1/ptSize, 1/ptSize);
    } else {
        fontTx = null; // no need
    }
    return (int)ptSize;
}
 
Example 17
private int getNativePointSize() {
    /* Make a copy of the glyphTX in which we will store the
     * font transform, inverting the devTx if necessary
     */
    double[] mat = new double[4];
    desc.glyphTx.getMatrix(mat);
    fontTx = new AffineTransform(mat);

    /* Now work backwards to get the font transform */
    if (!desc.devTx.isIdentity() &&
        desc.devTx.getType() != AffineTransform.TYPE_TRANSLATION) {
        try {
            invertDevTx = desc.devTx.createInverse();
            fontTx.concatenate(invertDevTx);
        } catch (NoninvertibleTransformException e) {
            e.printStackTrace();
        }
    }

    /* At this point the fontTx may be a simple +ve scale, or it
     * may be something more complex.
     */
    Point2D.Float pt = new Point2D.Float(1f,1f);
    fontTx.deltaTransform(pt, pt);
    double ptSize = Math.abs(pt.y);
    int ttype = fontTx.getType();
    if ((ttype & ~AffineTransform.TYPE_UNIFORM_SCALE) != 0 ||
        fontTx.getScaleY() <= 0) {
        /* We need to create an inverse transform that doesn't
         * include the point size (strictly the uniform scale)
         */
        fontTx.scale(1/ptSize, 1/ptSize);
    } else {
        fontTx = null; // no need
    }
    return (int)ptSize;
}
 
Example 18
private float userSpaceLineWidth(AffineTransform at, float lw) {

        double widthScale;

        if ((at.getType() & (AffineTransform.TYPE_GENERAL_TRANSFORM |
                            AffineTransform.TYPE_GENERAL_SCALE)) != 0) {
            widthScale = Math.sqrt(at.getDeterminant());
        } else {
            /* First calculate the "maximum scale" of this transform. */
            double A = at.getScaleX();       // m00
            double C = at.getShearX();       // m01
            double B = at.getShearY();       // m10
            double D = at.getScaleY();       // m11

            /*
             * Given a 2 x 2 affine matrix [ A B ] such that
             *                             [ C D ]
             * v' = [x' y'] = [Ax + Cy, Bx + Dy], we want to
             * find the maximum magnitude (norm) of the vector v'
             * with the constraint (x^2 + y^2 = 1).
             * The equation to maximize is
             *     |v'| = sqrt((Ax+Cy)^2+(Bx+Dy)^2)
             * or  |v'| = sqrt((AA+BB)x^2 + 2(AC+BD)xy + (CC+DD)y^2).
             * Since sqrt is monotonic we can maximize |v'|^2
             * instead and plug in the substitution y = sqrt(1 - x^2).
             * Trigonometric equalities can then be used to get
             * rid of most of the sqrt terms.
             */

            double EA = A*A + B*B;          // x^2 coefficient
            double EB = 2*(A*C + B*D);      // xy coefficient
            double EC = C*C + D*D;          // y^2 coefficient

            /*
             * There is a lot of calculus omitted here.
             *
             * Conceptually, in the interests of understanding the
             * terms that the calculus produced we can consider
             * that EA and EC end up providing the lengths along
             * the major axes and the hypot term ends up being an
             * adjustment for the additional length along the off-axis
             * angle of rotated or sheared ellipses as well as an
             * adjustment for the fact that the equation below
             * averages the two major axis lengths.  (Notice that
             * the hypot term contains a part which resolves to the
             * difference of these two axis lengths in the absence
             * of rotation.)
             *
             * In the calculus, the ratio of the EB and (EA-EC) terms
             * ends up being the tangent of 2*theta where theta is
             * the angle that the long axis of the ellipse makes
             * with the horizontal axis.  Thus, this equation is
             * calculating the length of the hypotenuse of a triangle
             * along that axis.
             */

            double hypot = Math.sqrt(EB*EB + (EA-EC)*(EA-EC));
            /* sqrt omitted, compare to squared limits below. */
            double widthsquared = ((EA + EC + hypot)/2.0);

            widthScale = Math.sqrt(widthsquared);
        }

        return (float) (lw / widthScale);
    }
 
Example 19
Source Project: birt   File: IconCanvas.java    License: Eclipse Public License 1.0 4 votes vote down vote up
/**
 * SYNC the scroll-bars with the image.
 */
public void syncScrollBars( )
{
	if ( sourceImage == null )
	{
		redraw( );
		return;
	}

	AffineTransform af = transform;
	double sx = af.getScaleX( ), sy = af.getScaleY( );
	double tx = af.getTranslateX( ), ty = af.getTranslateY( );
	if ( tx > 0 )
		tx = 0;
	if ( ty > 0 )
		ty = 0;

	Rectangle imageBound = sourceImage.getBounds( );
	int cw = getClientArea( ).width, ch = getClientArea( ).height;

	ScrollBar horizontal = getHorizontalBar( );

	if ( horizontal != null )
	{
		horizontal.setIncrement( ( getClientArea( ).width / 100 ) );
		horizontal.setPageIncrement( getClientArea( ).width );

		if ( imageBound.width * sx > cw )
		{
			horizontal.setMaximum( (int) ( imageBound.width * sx ) );
			horizontal.setEnabled( true );
			if ( ( (int) -tx ) > horizontal.getMaximum( ) - cw )
				tx = -horizontal.getMaximum( ) + cw;
		}
		else
		{
			horizontal.setEnabled( false );
			tx = ( cw - imageBound.width * sx ) / 2;
		}
		horizontal.setSelection( (int) ( -tx ) );
		horizontal.setThumb( ( getClientArea( ).width ) );
	}
	ScrollBar vertical = getVerticalBar( );
	if ( vertical != null )
	{
		vertical.setIncrement( ( getClientArea( ).height / 100 ) );
		vertical.setPageIncrement( ( getClientArea( ).height ) );
		if ( imageBound.height * sy > ch )
		{
			vertical.setMaximum( (int) ( imageBound.height * sy ) );
			vertical.setEnabled( true );
			if ( ( (int) -ty ) > vertical.getMaximum( ) - ch )
				ty = -vertical.getMaximum( ) + ch;
		}
		else
		{
			vertical.setEnabled( false );
			ty = ( ch - imageBound.height * sy ) / 2;
		}
		vertical.setSelection( (int) ( -ty ) );
		vertical.setThumb( ( getClientArea( ).height ) );
	}

	af = AffineTransform.getScaleInstance( sx, sy );
	af.preConcatenate( AffineTransform.getTranslateInstance( tx, ty ) );
	transform = af;

	redraw( );
}
 
Example 20
public void drawRectangle(SunGraphics2D sg2d,
                          double rx, double ry,
                          double rw, double rh,
                          double lw)
{
    double px, py;
    double dx1, dy1, dx2, dy2;
    double lw1, lw2;
    AffineTransform txform = sg2d.transform;
    dx1 = txform.getScaleX();
    dy1 = txform.getShearY();
    dx2 = txform.getShearX();
    dy2 = txform.getScaleY();
    px = rx * dx1 + ry * dx2 + txform.getTranslateX();
    py = rx * dy1 + ry * dy2 + txform.getTranslateY();
    // lw along dx1,dy1 scale by transformed length of dx2,dy2 vectors
    // and vice versa
    lw1 = len(dx1, dy1) * lw;
    lw2 = len(dx2, dy2) * lw;
    dx1 *= rw;
    dy1 *= rw;
    dx2 *= rh;
    dy2 *= rh;
    if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM &&
        sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE)
    {
        double newx = normalize(px);
        double newy = normalize(py);
        dx1 = normalize(px + dx1) - newx;
        dy1 = normalize(py + dy1) - newy;
        dx2 = normalize(px + dx2) - newx;
        dy2 = normalize(py + dy2) - newy;
        px = newx;
        py = newy;
    }
    lw1 = Math.max(lw1, minPenSize);
    lw2 = Math.max(lw2, minPenSize);
    double len1 = len(dx1, dy1);
    double len2 = len(dx2, dy2);
    if (lw1 >= len1 || lw2 >= len2) {
        // The line widths are large enough to consume the
        // entire hole in the middle of the parallelogram
        // so we can just fill the outer parallelogram.
        fillOuterParallelogram(sg2d,
                               rx, ry, rx+rw, ry+rh,
                               px, py, dx1, dy1, dx2, dy2,
                               len1, len2, lw1, lw2);
    } else {
        outrenderer.drawParallelogram(sg2d,
                                      rx, ry, rx+rw, ry+rh,
                                      px, py, dx1, dy1, dx2, dy2,
                                      lw1 / len1, lw2 / len2);
    }
}