// Copyright 2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package com.google.appengine.demos.mandelbrot;
/**
* {@code TileFactory} wraps a {@link FractalSource} of arbitrary size
* and complexity and vends {@link PixelSource} objects that
* correspond to tiles of the overall image.
*
* @author schwardo@google.com (Don Schwarz)
* @author nickjohnson@google.com (Nick Johnson)
*/
public class TileFactory {
/**
* The size of each tile, expressed as a power of 2. For example, a
* value of 6 corresponds to 2**6 x 2**6 tiles (or 64x64). This
* should match the value of {@code Image.TileSize} in {@code
* gigabrot.dzi}.
*/
private static final int TILEPOW = 8;
/**
* The number of pixels of overlap on each side of each tile. This
* should match the value of {@code Image.Overlap} in the {@code
* gigabrot.dzi}.
*/
private static final int OVERLAP = 1;
/**
* The {@link FractalSource} representing the overall image that is being tiled.
*/
private final FractalSource fractalSource;
/**
* Construct a {@link TileFactory} that vends tiles of {@link FractalSource}.
*/
public TileFactory(FractalSource fractalSource) {
this.fractalSource = fractalSource;
}
/**
* Constructs a {@link PixelSource} that provides the tile of {@code
* fractalSource} at coordinates ({@code x} and {@code y}) of level
* {@code level}.
*
* @param level The zoom level of the desired tile.
* @param x The x coordinate of the desired tile, starting at 0
* (measured in numbers of tiles).
* @param y The x coordinate of the desired tile, starting at 0
* (measured in numbers of tiles).
*/
public PixelSource createTile(int level, int x, int y) {
int tile_level = level - TILEPOW;
double xunits = FractalSource.XRANGE / ((double) (1 << tile_level));
double yunits = FractalSource.YRANGE / ((double) (1 << tile_level));
final double xscale = xunits / ((double) (1 << TILEPOW));
final double yscale = yunits / ((double) (1 << TILEPOW));
final double xmin = FractalSource.XMIN + xunits * x;
final double ymin = FractalSource.YMIN + yunits * y;
int sizelen = 1 << ((level > TILEPOW) ? TILEPOW : level);
final int width = sizelen + 2 * OVERLAP;
final int height = sizelen + 2 * OVERLAP;
return new PixelSource() {
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public int getPixel(int x, int y) {
return fractalSource.getValue(((double) x) * xscale + xmin,
((double) y) * yscale + ymin);
}
};
}
}