/*
* Copyright (c) 2005 Matthew Hall and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Matthew Hall - initial API and implementation
*/
package org.eclipse.nebula.paperclips.core;
import org.eclipse.nebula.paperclips.core.internal.util.SWTUtil;
import org.eclipse.nebula.paperclips.core.internal.util.Util;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Point;
/**
* A Print for displaying images.
*
* @author Matthew Hall
*/
public class ImagePrint implements Print {
ImageData imageData;
Point dpi;
Point size;
/**
* Constructs an ImagePrint with the given imageData, initialized at 72dpi.
*
* @param imageData
* the image to be displayed.
*/
public ImagePrint(ImageData imageData) {
this(imageData, new Point(72, 72));
}
/**
* Constructs an ImagePrint with the given imageData and dpi.
*
* @param imageData
* the image to be displayed.
* @param dpi
* the DPI that the image will be displayed at.
*/
public ImagePrint(ImageData imageData, Point dpi) {
Util.notNull(imageData, dpi);
this.imageData = imageData;
setDPI(dpi);
}
/**
* Returns the ImageData of the image being printed.
*
* @return the ImageData of the image being printed.
*/
public ImageData getImageData() {
return imageData;
}
public boolean equals(Object obj) {
if (obj == this)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ImagePrint that = (ImagePrint) obj;
return Util.equal(this.dpi, that.dpi)
&& Util.equal(this.size, that.size)
&& SWTUtil.equal(this.imageData, that.imageData);
}
public int hashCode() {
int prime = 31;
int result = 1;
result = prime * result + dpi.hashCode();
result = prime * result + size.hashCode();
result = prime * result + SWTUtil.hashCode(imageData);
return result;
}
/**
* Sets the ImagePrint to render the image at the given size, in points. 72
* points = 1".
*
* @param size
* the explicit size, in points, that the image be printed at.
*/
public void setSize(Point size) {
// The DPI is rounded up, so that the specified width and height will
// not be exceeded.
Util.notNull(size);
dpi = new Point((int) Math.ceil(imageData.width * 72d / size.x),
(int) Math.ceil(imageData.height * 72d / size.y));
this.size = size;
}
/**
* Sets the ImagePrint to render the image at the given size, in points. 72
* points = 1".
*
* @param width
* the explicit width, in points, that the image will be printed
* at.
* @param height
* the explicit height, in points, that the image will be printed
* at.
*/
public void setSize(int width, int height) {
setSize(new Point(width, height));
}
/**
* Returns the size that the image will be rendered at, in points. 72 points
* = 1".
*
* @return the size of the image, in points.
*/
public Point getSize() {
return size;
}
/**
* Sets the ImagePrint to render the image at the DPI of the argument.
*
* @param dpi
* the DPI of the image.
*/
public void setDPI(Point dpi) {
Util.notNull(dpi);
this.dpi = dpi;
size = new Point((int) Math.ceil(imageData.width * 72d / dpi.x),
(int) Math.ceil(imageData.height * 72d / dpi.y));
}
/**
* Sets the ImagePrint to render the image at the given DPI.
*
* @param dpiX
* the horizontal DPI the image will be rendered at.
* @param dpiY
* the vertical DPI the image will be rendered at.
*/
public void setDPI(int dpiX, int dpiY) {
setDPI(new Point(dpiX, dpiY));
}
/**
* Returns the DPI that this image will be rendered at.
*
* @return the DPI the image will be rendered at.
*/
public Point getDPI() {
return dpi;
}
public PrintIterator iterator(Device device, GC gc) {
return new ImageIterator(this, device);
}
}
class ImageIterator implements PrintIterator {
final Device device;
final ImageData imageData;
final Point size;
boolean hasNext;
ImageIterator(ImagePrint print, Device device) {
Util.notNull(print, device);
this.device = device;
this.imageData = print.imageData;
Point dpi = device.getDPI();
this.size = new Point(print.size.x * dpi.x / 72, print.size.y * dpi.y
/ 72);
this.hasNext = true;
}
ImageIterator(ImageIterator that) {
this.device = that.device;
this.imageData = that.imageData;
this.size = that.size;
this.hasNext = that.hasNext;
}
public boolean hasNext() {
return hasNext;
}
public PrintPiece next(int width, int height) {
if (!hasNext())
PaperClips.error("No more content."); //$NON-NLS-1$
if (width < size.x || height < size.y)
return null;
hasNext = false;
return new ImagePiece(device, imageData, size);
}
public Point minimumSize() {
return new Point(size.x, size.y);
}
public Point preferredSize() {
return new Point(size.x, size.y);
}
public PrintIterator copy() {
return hasNext ? new ImageIterator(this) : this;
}
}
class ImagePiece implements PrintPiece {
private final Device device;
private final ImageData imageData;
private final Point size;
private Image image;
ImagePiece(Device device, ImageData imageData, Point size) {
Util.notNull(device, imageData, size);
this.device = device;
this.imageData = imageData;
this.size = size;
}
public Point getSize() {
return new Point(size.x, size.y);
}
private Image getImage() {
if (image == null)
image = new Image(device, imageData);
return image;
}
public void paint(GC gc, int x, int y) {
gc.drawImage(getImage(), 0, 0, imageData.width, imageData.height, x, y,
size.x, size.y);
}
public void dispose() {
if (image != null) {
image.dispose();
image = null;
}
}
}