Example usage for java.awt.geom AffineTransform AffineTransform

List of usage examples for java.awt.geom AffineTransform AffineTransform

Introduction

In this page you can find the example usage for java.awt.geom AffineTransform AffineTransform.

Prototype

public AffineTransform() 

Source Link

Document

Constructs a new AffineTransform representing the Identity transformation.

Usage

From source file:org.apache.fop.image.loader.batik.ImageConverterSVG2G2D.java

/**
 * Creates a user agent for Batik. Override to provide your own user agent.
 * @param pxToMillimeter the source resolution (in px per millimeter)
 * @return the newly created user agent//from   w w  w  .j a v a2 s.c  o  m
 */
protected SimpleSVGUserAgent createBatikUserAgent(float pxToMillimeter) {
    return new SimpleSVGUserAgent(pxToMillimeter, new AffineTransform()) {

        /** {@inheritDoc} */
        public void displayMessage(String message) {
            //TODO Refine and pipe through to caller
            log.info(message);
        }

        /** {@inheritDoc} */
        public void displayError(Exception e) {
            log.error("Error converting SVG to a Java2D graphic", e);
        }

        /** {@inheritDoc} */
        public void displayError(String message) {
            log.error(message);
        }

    };
}

From source file:org.jcurl.core.base.Collider.java

/**
 * Check distance, speed of approach, transform speeds to rock-coordinates,
 * call {@link #computeRC(Rock, Rock)}and transform back to wc afterwards.
 * /*from   w  ww  . j a  v  a2  s  .  c  o  m*/
 * @param xa
 * @param xb
 * @param va
 * @param vb
 * @param mat
 *            may be null. If not avoids frequent instanciations
 * @return <code>true</code> hit, <code>false</code> no hit.
 */
public boolean computeWC(final Rock xa, final Rock xb, final Rock va, final Rock vb, AffineTransform mat) {
    if (mat == null)
        mat = new AffineTransform();
    // check distance
    if (xa.distanceSq(xb) > MaxDistSq) {
        if (log.isDebugEnabled())
            log.debug("Too far away distance=" + (xa.distance(xb) - (_Rad + _Rad)));
        return false;
    }
    // change the coordinate system to rock-coordinates
    final Rock _va = (Rock) va.clone();
    final Rock _vb = (Rock) vb.clone();
    getInverseTrafo(vb, xa, xb, mat);
    try { // transform
        mat.inverseTransform(va, _va);
        mat.inverseTransform(vb, _vb);
    } catch (NoninvertibleTransformException e) {
        throw new RuntimeException("Matrix must be invertible", e);
    }
    // check speed of approach
    if (!_va.nonZero())
        return false;
    if (log.isDebugEnabled())
        log.debug("hit!");

    // physical model
    computeRC(_va, _vb);

    // re-transform
    mat.transform(_va, va);
    va.setZ(_va.getZ());
    mat.transform(_vb, vb);
    vb.setZ(_vb.getZ());
    return true;
}

From source file:org.jcurl.core.base.CollissionStrategy.java

/**
 * Check distance, speed of approach, transform speeds to rock-coordinates,
 * call {@link #computeRC(Rock, Rock)}and transform back to wc afterwards.
 * /*from  w w w  .  ja v  a 2  s. c om*/
 * @param xa
 * @param xb
 * @param va
 * @param vb
 * @param mat
 *            may be null. If not avoids frequent instanciations
 * @return <code>true</code> hit, <code>false</code> no hit.
 */
protected boolean computeWC(final Rock xa, final Rock xb, final Rock va, final Rock vb, AffineTransform mat) {
    if (mat == null)
        mat = new AffineTransform();
    // check distance
    if (xa.distanceSq(xb) > MaxDistSq) {
        if (log.isDebugEnabled())
            log.debug("Too far away distance=" + (xa.distance(xb) - (_Rad + _Rad)));
        return false;
    }
    // change the coordinate system to rock-coordinates
    final Rock _va = (Rock) va.clone();
    final Rock _vb = (Rock) vb.clone();
    getInverseTrafo(vb, xa, xb, mat);
    try { // transform
        mat.inverseTransform(va, _va);
        mat.inverseTransform(vb, _vb);
    } catch (NoninvertibleTransformException e) {
        throw new RuntimeException("Matrix must be invertible", e);
    }
    // check speed of approach
    if (!_va.nonZero())
        return false;
    if (log.isDebugEnabled())
        log.debug("hit!");

    // physical model
    computeRC(_va, _vb);

    // re-transform
    mat.transform(_va, va);
    va.setZ(_va.getZ());
    mat.transform(_vb, vb);
    vb.setZ(_vb.getZ());
    return true;
}

From source file:org.apache.hadoop.chukwa.hicc.ImageSlicer.java

public BufferedImage tile(BufferedImage image, int level, XYData quadrant, XYData size, boolean efficient)
        throws Exception {
    double scale = Math.pow(2, level);
    if (efficient) {
        /* efficient: crop out the area of interest first, then scale and copy it */
        XYData inverSize = new XYData((int) (image.getWidth(null) / (size.getX() * scale)),
                (int) (image.getHeight(null) / (size.getY() * scale)));
        XYData topLeft = new XYData(quadrant.getX() * size.getX() * inverSize.getX(),
                quadrant.getY() * size.getY() * inverSize.getY());
        XYData newSize = new XYData((size.getX() * inverSize.getX()), (size.getY() * inverSize.getY()));
        if (inverSize.getX() < 1.0 || inverSize.getY() < 1.0) {
            throw new Exception("Requested zoom level (" + level + ") is too high.");
        }/*from  ww  w.ja  va  2s  .  c  om*/
        image = image.getSubimage(topLeft.getX(), topLeft.getY(), newSize.getX(), newSize.getY());
        BufferedImage zoomed = new BufferedImage(size.getX(), size.getY(), BufferedImage.TYPE_INT_RGB);
        zoomed.getGraphics().drawImage(image, 0, 0, size.getX(), size.getY(), null);
        if (level > maxLevel) {
            maxLevel = level;
        }
        return zoomed;
    } else {
        /* inefficient: copy the whole image, scale it and then crop out the area of interest */
        XYData newSize = new XYData((int) (size.getX() * scale), (int) (size.getY() * scale));
        XYData topLeft = new XYData(quadrant.getX() * size.getX(), quadrant.getY() * size.getY());
        if (newSize.getX() > image.getWidth(null) || newSize.getY() > image.getHeight(null)) {
            throw new Exception("Requested zoom level (" + level + ") is too high.");
        }
        AffineTransform tx = new AffineTransform();
        AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
        tx.scale(scale, scale);
        image = op.filter(image, null);
        BufferedImage zoomed = image.getSubimage(topLeft.getX(), topLeft.getY(), newSize.getX(),
                newSize.getY());
        if (level > maxLevel) {
            maxLevel = level;
        }
        return zoomed;
    }
}

From source file:org.jcurl.core.base.ColliderBase.java

/**
 * Check distance, speed of approach, transform speeds to rock-coordinates,
 * call {@link #computeRC(Rock, Rock)}and transform back to wc afterwards.
 * /*from  ww w .  j a  v a2s  .  co m*/
 * @param xa
 * @param xb
 * @param va
 * @param vb
 * @param mat
 *            may be null. If not avoids frequent instanciations
 * @return <code>true</code> hit, <code>false</code> no hit.
 */
protected boolean computeWC(final Rock xa, final Rock xb, final Rock va, final Rock vb, AffineTransform mat) {
    if (mat == null)
        mat = new AffineTransform();
    // check distance
    if (xa.distanceSq(xb) > MaxDistSq) {
        if (log.isDebugEnabled())
            log.debug("Too far away distance=" + (xa.distance(xb) - (_Rad + _Rad)));
        return false;
    }
    // change the coordinate system to rock-coordinates
    final Rock _va = (Rock) va.clone();
    final Rock _vb = (Rock) vb.clone();
    getInverseTrafo(vb, xa, xb, mat);
    try { // transform
        mat.inverseTransform(va, _va);
        mat.inverseTransform(vb, _vb);
    } catch (final NoninvertibleTransformException e) {
        throw new RuntimeException("Matrix must be invertible", e);
    }
    // check speed of approach
    if (!_va.nonZero())
        return false;
    if (log.isDebugEnabled())
        log.debug("hit!");

    // physical model
    computeRC(_va, _vb);

    // re-transform
    mat.transform(_va, va);
    va.setZ(_va.getZ());
    // FIXME apply angle delta from Collission coordinates to WC
    mat.transform(_vb, vb);
    vb.setZ(_vb.getZ());
    // FIXME apply angle delta from Collission coordinates to WC
    return true;
}

From source file:WorldMapGraphDemo.java

/**
 * create an instance of a simple graph with controls to
 * demo the zoom features.//from  w ww. ja v a  2  s  .c o m
 * 
 */
public WorldMapGraphDemo() {
    setLayout(new BorderLayout());

    map.put("TYO", new String[] { "35 40 N", "139 45 E" });
    map.put("PEK", new String[] { "39 55 N", "116 26 E" });
    map.put("MOW", new String[] { "55 45 N", "37 42 E" });
    map.put("JRS", new String[] { "31 47 N", "35 13 E" });
    map.put("CAI", new String[] { "30 03 N", "31 15 E" });
    map.put("CPT", new String[] { "33 55 S", "18 22 E" });
    map.put("PAR", new String[] { "48 52 N", "2 20 E" });
    map.put("LHR", new String[] { "51 30 N", "0 10 W" });
    map.put("HNL", new String[] { "21 18 N", "157 51 W" });
    map.put("NYC", new String[] { "40 77 N", "73 98 W" });
    map.put("SFO", new String[] { "37 62 N", "122 38 W" });
    map.put("AKL", new String[] { "36 55 S", "174 47 E" });
    map.put("BNE", new String[] { "27 28 S", "153 02 E" });
    map.put("HKG", new String[] { "22 15 N", "114 10 E" });
    map.put("KTM", new String[] { "27 42 N", "85 19 E" });
    map.put("IST", new String[] { "41 01 N", "28 58 E" });
    map.put("STO", new String[] { "59 20 N", "18 03 E" });
    map.put("RIO", new String[] { "22 54 S", "43 14 W" });
    map.put("LIM", new String[] { "12 03 S", "77 03 W" });
    map.put("YTO", new String[] { "43 39 N", "79 23 W" });

    cityList = new ArrayList<String>(map.keySet());

    // create a simple graph for the demo
    graph = new DirectedSparseMultigraph<String, Number>();
    createVertices();
    createEdges();

    ImageIcon mapIcon = null;
    String imageLocation = "/images/political_world_map.jpg";
    try {
        mapIcon = new ImageIcon(getClass().getResource(imageLocation));
    } catch (Exception ex) {
        System.err.println("Can't load \"" + imageLocation + "\"");
    }
    final ImageIcon icon = mapIcon;

    Dimension layoutSize = new Dimension(2000, 1000);

    Layout<String, Number> layout = new StaticLayout<String, Number>(graph,
            new ChainedTransformer(new Transformer[] { new CityTransformer(map),
                    new LatLonPixelTransformer(new Dimension(2000, 1000)) }));

    layout.setSize(layoutSize);
    vv = new VisualizationViewer<String, Number>(layout, new Dimension(800, 400));

    if (icon != null) {
        vv.addPreRenderPaintable(new VisualizationViewer.Paintable() {
            public void paint(Graphics g) {
                Graphics2D g2d = (Graphics2D) g;
                AffineTransform oldXform = g2d.getTransform();
                AffineTransform lat = vv.getRenderContext().getMultiLayerTransformer()
                        .getTransformer(Layer.LAYOUT).getTransform();
                AffineTransform vat = vv.getRenderContext().getMultiLayerTransformer()
                        .getTransformer(Layer.VIEW).getTransform();
                AffineTransform at = new AffineTransform();
                at.concatenate(g2d.getTransform());
                at.concatenate(vat);
                at.concatenate(lat);
                g2d.setTransform(at);
                g.drawImage(icon.getImage(), 0, 0, icon.getIconWidth(), icon.getIconHeight(), vv);
                g2d.setTransform(oldXform);
            }

            public boolean useTransform() {
                return false;
            }
        });
    }

    vv.getRenderer().setVertexRenderer(new GradientVertexRenderer<String, Number>(Color.white, Color.red,
            Color.white, Color.blue, vv.getPickedVertexState(), false));

    // add my listeners for ToolTips
    vv.setVertexToolTipTransformer(new ToStringLabeller());
    vv.setEdgeToolTipTransformer(new Transformer<Number, String>() {
        public String transform(Number edge) {
            return "E" + graph.getEndpoints(edge).toString();
        }
    });

    vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
    vv.getRenderer().getVertexLabelRenderer().setPositioner(new InsidePositioner());
    vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.AUTO);

    final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv);
    add(panel);
    final AbstractModalGraphMouse graphMouse = new DefaultModalGraphMouse();
    vv.setGraphMouse(graphMouse);

    vv.addKeyListener(graphMouse.getModeKeyListener());
    vv.setToolTipText("<html><center>Type 'p' for Pick mode<p>Type 't' for Transform mode");

    final ScalingControl scaler = new CrossoverScalingControl();

    //        vv.scaleToLayout(scaler);

    JButton plus = new JButton("+");
    plus.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            scaler.scale(vv, 1.1f, vv.getCenter());
        }
    });
    JButton minus = new JButton("-");
    minus.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            scaler.scale(vv, 1 / 1.1f, vv.getCenter());
        }
    });

    JButton reset = new JButton("reset");
    reset.addActionListener(new ActionListener() {

        public void actionPerformed(ActionEvent e) {
            vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).setToIdentity();
            vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW).setToIdentity();
        }
    });

    JPanel controls = new JPanel();
    controls.add(plus);
    controls.add(minus);
    controls.add(reset);
    add(controls, BorderLayout.SOUTH);
}

From source file:org.jcurl.core.impl.ColliderBase.java

/**
 * Check distance, speed of approach, transform speeds to
 * collission-coordinates, call {@link #computeCC(Rock, Rock)} and transform
 * back to wc afterwards.//from   ww  w.  j a  v  a  2  s. co m
 * <p>
 * The angle (not the angular speed!) remains in WC and untouched!
 * </p>
 * 
 * @param xa
 *            position before the hit (WC)
 * @param xb
 *            position before the hit (WC)
 * @param va
 *            speed before the hit (CC)
 * @param vb
 *            speed before the hit (usually zero)
 * @param mat
 *            may be null. If not avoids frequent instanciations
 * @return <code>true</code> hit, <code>false</code> no hit.
 */
protected boolean computeWC(final Rock<Pos> xa, final Rock<Pos> xb, final Rock<Vel> va, final Rock<Vel> vb,
        AffineTransform mat) {
    if (mat == null)
        mat = new AffineTransform();
    // check distance
    if (xa.p().distanceSq(xb.p()) > MaxDistSq) {
        if (log.isDebugEnabled())
            log.debug("Too far away distance=" + (xa.p().distance(xb.p()) - (_Rad + _Rad)));
        return false;
    }
    // change the coordinate system to collission-coordinates
    final Rock<Vel> _va = (Rock<Vel>) va.clone();
    final Rock<Vel> _vb = (Rock<Vel>) vb.clone();
    getInverseTrafo(vb.p(), xa.p(), xb.p(), mat);
    try { // transform
        mat.inverseTransform(va.p(), _va.p());
        mat.inverseTransform(vb.p(), _vb.p());
    } catch (final NoninvertibleTransformException e) {
        throw new RuntimeException("Matrix must be invertible", e);
    }
    // check speed of approach
    if (!_va.isNotZero())
        return false;
    if (log.isDebugEnabled())
        log.debug("hit!");

    // physical model
    computeCC(_va, _vb);

    // re-transform
    mat.transform(_va.p(), va.p());
    va.setA(_va.getA());
    mat.transform(_vb.p(), vb.p());
    vb.setA(_vb.getA());
    return true;
}

From source file:Thumbnail.java

/**
* Reads an image in a file and creates a thumbnail in another file.
* largestDimension is the largest dimension of the thumbnail, the other dimension is scaled accordingly.
* Utilises weighted stepping method to gradually reduce the image size for better results,
* i.e. larger steps to start with then smaller steps to finish with.
* Note: always writes a JPEG because GIF is protected or something - so always make your outFilename end in 'jpg'.
* PNG's with transparency are given white backgrounds
*///from w  ww. j av  a  2s.  co  m
public String createThumbnail(String inFilename, String outFilename, int largestDimension) {
    try {
        double scale;
        int sizeDifference, originalImageLargestDim;
        if (!inFilename.endsWith(".jpg") && !inFilename.endsWith(".jpeg") && !inFilename.endsWith(".gif")
                && !inFilename.endsWith(".png")) {
            return "Error: Unsupported image type, please only either JPG, GIF or PNG";
        } else {
            Image inImage = Toolkit.getDefaultToolkit().getImage(inFilename);
            if (inImage.getWidth(null) == -1 || inImage.getHeight(null) == -1) {
                return "Error loading file: \"" + inFilename + "\"";
            } else {
                //find biggest dimension       
                if (inImage.getWidth(null) > inImage.getHeight(null)) {
                    scale = (double) largestDimension / (double) inImage.getWidth(null);
                    sizeDifference = inImage.getWidth(null) - largestDimension;
                    originalImageLargestDim = inImage.getWidth(null);
                } else {
                    scale = (double) largestDimension / (double) inImage.getHeight(null);
                    sizeDifference = inImage.getHeight(null) - largestDimension;
                    originalImageLargestDim = inImage.getHeight(null);
                }
                //create an image buffer to draw to
                BufferedImage outImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); //arbitrary init so code compiles
                Graphics2D g2d;
                AffineTransform tx;
                if (scale < 1.0d) //only scale if desired size is smaller than original
                {
                    int numSteps = sizeDifference / 100;
                    int stepSize = sizeDifference / numSteps;
                    int stepWeight = stepSize / 2;
                    int heavierStepSize = stepSize + stepWeight;
                    int lighterStepSize = stepSize - stepWeight;
                    int currentStepSize, centerStep;
                    double scaledW = inImage.getWidth(null);
                    double scaledH = inImage.getHeight(null);
                    if (numSteps % 2 == 1) //if there's an odd number of steps
                        centerStep = (int) Math.ceil((double) numSteps / 2d); //find the center step
                    else
                        centerStep = -1; //set it to -1 so it's ignored later
                    Integer intermediateSize = originalImageLargestDim,
                            previousIntermediateSize = originalImageLargestDim;
                    Integer calculatedDim;
                    for (Integer i = 0; i < numSteps; i++) {
                        if (i + 1 != centerStep) //if this isn't the center step
                        {
                            if (i == numSteps - 1) //if this is the last step
                            {
                                //fix the stepsize to account for decimal place errors previously
                                currentStepSize = previousIntermediateSize - largestDimension;
                            } else {
                                if (numSteps - i > numSteps / 2) //if we're in the first half of the reductions
                                    currentStepSize = heavierStepSize;
                                else
                                    currentStepSize = lighterStepSize;
                            }
                        } else //center step, use natural step size
                        {
                            currentStepSize = stepSize;
                        }
                        intermediateSize = previousIntermediateSize - currentStepSize;
                        scale = (double) intermediateSize / (double) previousIntermediateSize;
                        scaledW = (int) scaledW * scale;
                        scaledH = (int) scaledH * scale;
                        outImage = new BufferedImage((int) scaledW, (int) scaledH, BufferedImage.TYPE_INT_RGB);
                        g2d = outImage.createGraphics();
                        g2d.setBackground(Color.WHITE);
                        g2d.clearRect(0, 0, outImage.getWidth(), outImage.getHeight());
                        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                        tx = new AffineTransform();
                        tx.scale(scale, scale);
                        g2d.drawImage(inImage, tx, null);
                        g2d.dispose();
                        inImage = new ImageIcon(outImage).getImage();
                        previousIntermediateSize = intermediateSize;
                    }
                } else {
                    //just copy the original
                    outImage = new BufferedImage(inImage.getWidth(null), inImage.getHeight(null),
                            BufferedImage.TYPE_INT_RGB);
                    g2d = outImage.createGraphics();
                    g2d.setBackground(Color.WHITE);
                    g2d.clearRect(0, 0, outImage.getWidth(), outImage.getHeight());
                    tx = new AffineTransform();
                    tx.setToIdentity(); //use identity matrix so image is copied exactly
                    g2d.drawImage(inImage, tx, null);
                    g2d.dispose();
                }
                //JPEG-encode the image and write to file.
                OutputStream os = new FileOutputStream(outFilename);
                JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(os);
                encoder.encode(outImage);
                os.close();
            }
        }
    } catch (Exception ex) {
        String errorMsg = "";
        errorMsg += "<br>Exception: " + ex.toString();
        errorMsg += "<br>Cause = " + ex.getCause();
        errorMsg += "<br>Stack Trace = ";
        StackTraceElement stackTrace[] = ex.getStackTrace();
        for (int traceLine = 0; traceLine < stackTrace.length; traceLine++) {
            errorMsg += "<br>" + stackTrace[traceLine];
        }
        return errorMsg;
    }
    return ""; //success
}

From source file:org.eclipse.birt.chart.device.svg.SVGGraphics2D.java

public SVGGraphics2D(Document dom, boolean scriptable) {
    this.dom = dom;
    this.scriptable = scriptable;
    fontRenderContext = new FontRenderContext(new AffineTransform(), true, false);
    currentElement = dom.getDocumentElement();
    parentStack.push(currentElement);/*from   w  w w  .j a  va 2s.  co  m*/
    currentParent = currentElement;
    // add default styles
    currentElement = dom.createElement("g"); //$NON-NLS-1$
    definitions = dom.createElement("defs"); //$NON-NLS-1$
    // give the outer group element an ID
    currentElement.setAttribute("id", "outerG"); //$NON-NLS-1$ //$NON-NLS-2$
    currentElement.appendChild(definitions);
    currentElement.setAttribute("style", defaultStyles); //$NON-NLS-1$
    pushParent(currentElement);

    transforms = new AffineTransform();
    initializeScriptStyles();
}

From source file:org.openstreetmap.gui.jmapviewer.Tile.java

/**
 * Tries to get tiles of a lower or higher zoom level (one or two level
 * difference) from cache and use it as a placeholder until the tile has
 * been loaded.// w ww.j  a v  a 2s . co  m
 */
public void loadPlaceholderFromCache(TileCache cache) {
    BufferedImage tmpImage = new BufferedImage(SIZE, SIZE, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g = (Graphics2D) tmpImage.getGraphics();
    // g.drawImage(image, 0, 0, null);
    for (int zoomDiff = 1; zoomDiff < 5; zoomDiff++) {
        // first we check if there are already the 2^x tiles
        // of a higher detail level
        int zoom_high = zoom + zoomDiff;
        if (zoomDiff < 3 && zoom_high <= JMapViewer.MAX_ZOOM) {
            int factor = 1 << zoomDiff;
            int xtile_high = xtile << zoomDiff;
            int ytile_high = ytile << zoomDiff;
            double scale = 1.0 / factor;
            g.setTransform(AffineTransform.getScaleInstance(scale, scale));
            int paintedTileCount = 0;
            for (int x = 0; x < factor; x++) {
                for (int y = 0; y < factor; y++) {
                    Tile tile = cache.getTile(source, xtile_high + x, ytile_high + y, zoom_high);
                    if (tile != null && tile.isLoaded()) {
                        paintedTileCount++;
                        tile.paint(g, x * SIZE, y * SIZE);
                    }
                }
            }
            if (paintedTileCount == factor * factor) {
                image = tmpImage;
                return;
            }
        }

        int zoom_low = zoom - zoomDiff;
        if (zoom_low >= JMapViewer.MIN_ZOOM) {
            int xtile_low = xtile >> zoomDiff;
            int ytile_low = ytile >> zoomDiff;
            int factor = (1 << zoomDiff);
            double scale = factor;
            AffineTransform at = new AffineTransform();
            int translate_x = (xtile % factor) * SIZE;
            int translate_y = (ytile % factor) * SIZE;
            at.setTransform(scale, 0, 0, scale, -translate_x, -translate_y);
            g.setTransform(at);
            Tile tile = cache.getTile(source, xtile_low, ytile_low, zoom_low);
            if (tile != null && tile.isLoaded()) {
                tile.paint(g, 0, 0);
                image = tmpImage;
                return;
            }
        }
    }
}