Instead of drawing thousands of little pieces of the background tiled,
draw but 9 images, with the non-corner ones being scaled as appropriate. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2856 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: BackgroundTiler.java,v 1.5 2002/10/22 02:05:42 shaper Exp $
|
// $Id: BackgroundTiler.java,v 1.6 2003/11/14 19:39:52 ray Exp $
|
||||||
|
|
||||||
package com.threerings.media.util;
|
package com.threerings.media.util;
|
||||||
|
|
||||||
@@ -29,18 +29,19 @@ public class BackgroundTiler
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute some values
|
// compute some values
|
||||||
_width = src.getWidth(null);
|
int width = src.getWidth(null);
|
||||||
_w3 = _width/3;
|
int height = src.getHeight(null);
|
||||||
_cw3 = _width-2*_w3;
|
|
||||||
_height = src.getHeight(null);
|
_w3 = width/3;
|
||||||
_h3 = _height/3;
|
_cw3 = width-2*_w3;
|
||||||
_ch3 = _height-2*_h3;
|
_h3 = height/3;
|
||||||
|
_ch3 = height-2*_h3;
|
||||||
|
|
||||||
// make sure the image suits our minimum useful dimensions
|
// make sure the image suits our minimum useful dimensions
|
||||||
if (_w3 <= 0 || _cw3 <= 0 || _h3 <= 0 || _ch3 <= 0) {
|
if (_w3 <= 0 || _cw3 <= 0 || _h3 <= 0 || _ch3 <= 0) {
|
||||||
Log.warning("Backgrounder given source image of insufficient " +
|
Log.warning("Backgrounder given source image of insufficient " +
|
||||||
"size for tiling " +
|
"size for tiling " +
|
||||||
"[width=" + _width + ", height=" + _height + "].");
|
"[width=" + width + ", height=" + height + "].");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +53,7 @@ public class BackgroundTiler
|
|||||||
_tiles[3*i] = src.getSubimage(0, sy[i], _w3, thei[i]);
|
_tiles[3*i] = src.getSubimage(0, sy[i], _w3, thei[i]);
|
||||||
_tiles[3*i+1] = src.getSubimage(_w3, sy[i], _cw3, thei[i]);
|
_tiles[3*i+1] = src.getSubimage(_w3, sy[i], _cw3, thei[i]);
|
||||||
_tiles[3*i+2] =
|
_tiles[3*i+2] =
|
||||||
src.getSubimage(_width-_w3, sy[i], _w3, thei[i]);
|
src.getSubimage(width-_w3, sy[i], _w3, thei[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,103 +69,105 @@ public class BackgroundTiler
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rwid = width-2*_w3, rhei = height-2*_h3, cy = y;
|
int rwid = width-2*_w3, rhei = height-2*_h3;
|
||||||
Shape oclip = g.getClip();
|
|
||||||
|
|
||||||
// tile the top row
|
g.drawImage(_tiles[0], x, y, _w3, _h3, null);
|
||||||
paintRow(0, g, x, cy, width);
|
g.drawImage(_tiles[1], x + _w3, y, rwid, _h3, null);
|
||||||
cy += _h3;
|
g.drawImage(_tiles[2], x + _w3 + rwid, y, _w3, _h3, null);
|
||||||
|
|
||||||
// tile the (complete) intermediate rows
|
y += _h3;
|
||||||
int ycount = rhei/_ch3;
|
g.drawImage(_tiles[3], x, y, _w3, rhei, null);
|
||||||
for (int row = 0; row < ycount; row++) {
|
g.drawImage(_tiles[4], x + _w3, y, rwid, rhei, null);
|
||||||
paintRow(1, g, x, cy, width);
|
g.drawImage(_tiles[5], x + _w3 + rwid, y, _w3, rhei, null);
|
||||||
cy += _ch3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the clip and paint the clipped intermediate row (if we
|
y += rhei;
|
||||||
// didn't tile evenly in the vertical direction)
|
g.drawImage(_tiles[6], x, y, _w3, _h3, null);
|
||||||
int yextra = (rhei - ycount * _ch3);
|
g.drawImage(_tiles[7], x + _w3, y, rwid, _h3, null);
|
||||||
if (yextra > 0) {
|
g.drawImage(_tiles[8], x + _w3 + rwid, y, _w3, _h3, null);
|
||||||
g.clipRect(x, cy, width, yextra);
|
|
||||||
paintRow(1, g, x, cy, width);
|
|
||||||
g.setClip(oclip);
|
|
||||||
}
|
|
||||||
|
|
||||||
// tile the last row
|
|
||||||
int lasty = y + height - _h3;
|
|
||||||
paintRow(2, g, x, lasty, width);
|
|
||||||
|
|
||||||
// now, set the clipping rectangle and render the horizontal tiles
|
|
||||||
// that we missed the first time around because we want to clip
|
|
||||||
// only once instead of once per row
|
|
||||||
int xcount = rwid/_cw3;
|
|
||||||
int xextra = (rwid - xcount * _cw3);
|
|
||||||
int xoff = x + width - _w3 - xextra;
|
|
||||||
if (xextra < width) {
|
|
||||||
cy = y; // start back at the top
|
|
||||||
g.clipRect(xoff, y, xextra, height);
|
|
||||||
g.drawImage(_tiles[1], xoff, cy, null);
|
|
||||||
cy += _h3;
|
|
||||||
for (int row = 0; row < ycount; row++) {
|
|
||||||
g.drawImage(_tiles[4], xoff, cy, null);
|
|
||||||
cy += _ch3;
|
|
||||||
}
|
|
||||||
g.drawImage(_tiles[7], xoff, lasty, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
// finally, clip the tiny region where the xextra and yextra rects
|
|
||||||
// intersect and paint that last niggling bit (we value
|
|
||||||
// correctness, so we're doing things properly)
|
|
||||||
if (xextra > 0 && yextra > 0) {
|
|
||||||
// we know the clip is still set from the xextra render, so we
|
|
||||||
// just restrict it once again to the yextra region and the
|
|
||||||
// intersection will happen automatically
|
|
||||||
g.clipRect(x, cy, width, yextra);
|
|
||||||
g.drawImage(_tiles[4], xoff, lasty - yextra, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
// phew, we're done
|
|
||||||
g.setClip(oclip);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used by {@link #paint} to render rows.
|
|
||||||
*/
|
|
||||||
protected void paintRow (int srow, Graphics g, int x, int y, int width)
|
|
||||||
{
|
|
||||||
int xcount = (width-2*_w3)/_cw3;
|
|
||||||
int tidx = 3*srow;
|
|
||||||
|
|
||||||
// draw the first image in the row
|
|
||||||
int cx = x;
|
|
||||||
g.drawImage(_tiles[tidx++], cx, y, null);
|
|
||||||
cx += _w3;
|
|
||||||
|
|
||||||
// draw the (complete) tiled middle images
|
|
||||||
for (int ii = 0; ii < xcount; ii++) {
|
|
||||||
g.drawImage(_tiles[tidx], cx, y, null);
|
|
||||||
cx += _cw3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we'll render the last (incomplete) tiled image in a final
|
|
||||||
// cleanup render so that we only have to set the clipping region
|
|
||||||
// once
|
|
||||||
|
|
||||||
// draw the end image
|
|
||||||
cx = x+width-_w3;
|
|
||||||
g.drawImage(_tiles[++tidx], cx, y, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Our nine sub-divided images. */
|
/** Our nine sub-divided images. */
|
||||||
protected BufferedImage[] _tiles;
|
protected BufferedImage[] _tiles;
|
||||||
|
|
||||||
/** The width/height of our source image. */
|
|
||||||
protected int _width, _height;
|
|
||||||
|
|
||||||
/** One third of width/height of our source image. */
|
/** One third of width/height of our source image. */
|
||||||
protected int _w3, _h3;
|
protected int _w3, _h3;
|
||||||
|
|
||||||
/** The size of the center chunk of our subdivided images. */
|
/** The size of the center chunk of our subdivided images. */
|
||||||
protected int _cw3, _ch3;
|
protected int _cw3, _ch3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Below is an alternate implementation that uses only the source image
|
||||||
|
// without chopping it up. It ends up running very slightly slower, that
|
||||||
|
// may be because the documentation for the version of drawImage used below
|
||||||
|
// states that scaled instances will not be cached, that the scaling will
|
||||||
|
// happen each time on the fly. On the other hand, maybe that's a good thing.
|
||||||
|
// I like it better because it doesn't have to have 9 separate images and
|
||||||
|
// because it does the render in a loop, which is good fun.
|
||||||
|
|
||||||
|
//public class BackgroundTiler
|
||||||
|
//{
|
||||||
|
// /**
|
||||||
|
// * Creates a background tiler with the specified source image.
|
||||||
|
// */
|
||||||
|
// public BackgroundTiler (BufferedImage src)
|
||||||
|
// {
|
||||||
|
// // make sure we were given the goods
|
||||||
|
// if (src == null) {
|
||||||
|
// Log.info("Backgrounder given null source image. Coping.");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// _src = src;
|
||||||
|
//
|
||||||
|
// // compute some values
|
||||||
|
// int width = src.getWidth(null);
|
||||||
|
// int height = src.getHeight(null);
|
||||||
|
//
|
||||||
|
// _w3 = width/3;
|
||||||
|
// _cw3 = width-2*_w3;
|
||||||
|
// _h3 = height/3;
|
||||||
|
// _ch3 = height-2*_h3;
|
||||||
|
//
|
||||||
|
// _sx = new int[] { 0, _w3, width - _w3, width };
|
||||||
|
// _sy = new int[] { 0, _h3, height - _h3, height };
|
||||||
|
// _dx = new int[4];
|
||||||
|
// _dy = new int[4];
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Fills the requested region with the background defined by our
|
||||||
|
// * source image.
|
||||||
|
// */
|
||||||
|
// public void paint (Graphics g, int x, int y, int width, int height)
|
||||||
|
// {
|
||||||
|
// _dx[0] = x;
|
||||||
|
// _dx[1] = x + _w3;
|
||||||
|
// _dx[2] = x + width - _w3;
|
||||||
|
// _dx[3] = x + width;
|
||||||
|
//
|
||||||
|
// _dy[0] = y;
|
||||||
|
// _dy[1] = y + _h3;
|
||||||
|
// _dy[2] = y + height - _h3;
|
||||||
|
// _dy[3] = y + height;
|
||||||
|
//
|
||||||
|
// for (int jj=0; jj < 3; jj++) {
|
||||||
|
// for (int ii=0; ii < 3; ii++) {
|
||||||
|
// g.drawImage(_src, _dx[ii], _dy[jj], _dx[ii + 1], _dy[jj + 1],
|
||||||
|
// _sx[ii], _sy[jj], _sx[ii + 1], _sy[jj + 1], null);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /** Our source image. */
|
||||||
|
// protected BufferedImage _src;
|
||||||
|
//
|
||||||
|
// /** Coordinates. */
|
||||||
|
// protected int[] _sx, _sy, _dx, _dy;
|
||||||
|
//
|
||||||
|
// /** One third of width/height of our source image. */
|
||||||
|
// protected int _w3, _h3;
|
||||||
|
//
|
||||||
|
// /** The size of the center chunk of our subdivided images. */
|
||||||
|
// protected int _cw3, _ch3;
|
||||||
|
//}
|
||||||
|
|||||||
Reference in New Issue
Block a user