blob: ecd271996eebc1bb01b699b6843de9f153396322 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation 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:
* Kentarou FUKUDA - initial API and implementation
*******************************************************************************/
package org.eclipse.actf.model.ui;
import java.io.File;
import org.eclipse.actf.model.ui.util.ModelServiceMessages;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.ui.PlatformUI;
/**
* Utility class to create a screenshot (bitmap file) of the
* {@link IModelService}
*/
public class ModelServiceImageCreator {
// 256M -> 7000000 400M->10000000
/**
* Maximum size of screenshot image
*/
public static final int DUMP_IMG_SIZE_LIMIT = 10000000;
private IModelService modelService;
/**
* Constructor of the class
*
* @param modelService
* target {@link IModelService}
*/
public ModelServiceImageCreator(IModelService modelService) {
this.modelService = modelService;
}
/**
* Generate screenshot of the {@link IModelService} and save it as bitmap
* file
*
* @param saveFileName
* target file path
* @param isWhole
* <ul>
* <li>true: try to include entire area of the content into
* screenshot</li>
* <li>false: generate screenshot of current visible area</li>
* </ul>
* @return resulting {@link File}
*/
public File getScreenImageAsBMP(String saveFileName, boolean isWhole) {
IModelServiceScrollManager scrollManager = modelService
.getScrollManager();
int[] size = scrollManager.getSize(isWhole).toArray();
boolean hugeImage = false;
if (size[0] < 1 || size[1] < 1) {
size = new int[] { 1, 1, 1, 1 };
}
if (size[2] * size[3] > DUMP_IMG_SIZE_LIMIT) {
size[3] = DUMP_IMG_SIZE_LIMIT / size[2];
if (isWhole) {
hugeImage = true;
}
}
ImageData[] wholeImgData;
if (isWhole) {
switch (scrollManager.getScrollType()) {
case IModelServiceScrollManager.ABSOLUTE_COORDINATE:
wholeImgData = getImageByAbsoluteCoordinateScroll(size,
scrollManager, true);
break;
case IModelServiceScrollManager.PAGE:
wholeImgData = getImageByPageScroll(size, scrollManager);
break;
case IModelServiceScrollManager.INCREMENTAL:
wholeImgData = getImageByIncrementalScroll(size, scrollManager);
break;
case IModelServiceScrollManager.NONE:
default:
hugeImage = false;
wholeImgData = getImageByAbsoluteCoordinateScroll(size,
scrollManager, false);
}
} else {
wholeImgData = getImageByAbsoluteCoordinateScroll(size,
scrollManager, false);
}
ImageLoader loader = new ImageLoader();
loader.data = wholeImgData;
loader.save(saveFileName, SWT.IMAGE_BMP);
if (hugeImage) {
MessageBox warn = new MessageBox(PlatformUI.getWorkbench()
.getDisplay().getActiveShell(), SWT.OK
| SWT.ICON_INFORMATION);
warn.setMessage(ModelServiceMessages
.getString("ImageCreator.ImageTooLarge"));
warn.open();
}
return new File(saveFileName);
}
private ImageData[] getImageByAbsoluteCoordinateScroll(int[] size,
IModelServiceScrollManager scrollManager, boolean isWhole) {
Image img = new Image(Display.getDefault(), size[0] + 2, size[1] + 2);
ImageData[] wholeImgData = new ImageData[1];
GC gc = new GC(modelService.getTargetComposite());
int xCnt, yCnt;
if (isWhole) {
xCnt = (size[2] + size[0] - 1) / size[0];
yCnt = (size[3] + size[1] - 1) / size[1];
} else {
xCnt = 1;
yCnt = 1;
size[2] = size[0];
size[3] = size[1];
}
ImageData[][] imgData = new ImageData[xCnt][yCnt];
// System.out.println("start a:"+xCnt+" "+yCnt);
for (int i = 0; i < xCnt; i++) {
for (int j = 0; j < yCnt; j++) {
if (isWhole) {
scrollManager.absoluteCoordinateScroll(i * size[0], j
* size[1], true);
}
gc.copyArea(img, 0, 0);
imgData[i][j] = img.getImageData();
}
}
if (isWhole) {
scrollManager.absoluteCoordinateScroll(0, 0, false);
}
int depth = imgData[0][0].depth;
// System.out.println(size[0] + " " + size[1] + " " + size[2] + " " +
// size[3] + " " + depth);
wholeImgData[0] = new ImageData(size[2], size[3], depth,
imgData[0][0].palette);
// new PaletteData(0xff,0xff,0xff));
int wholeRowBytes = ((size[2] * depth + 31) / 32) * 4;
int partRowBytes = (((size[0] + 2) * depth + 31) / 32) * 4;
depth = depth / 8;
int xBegin, yBegin;
int wholeSize = wholeImgData[0].data.length;
for (int j = 0; j < yCnt; j++) {
for (int i = 0; i < xCnt; i++) {
if (j < yCnt - 1) {
yBegin = 0;
} else {
yBegin = size[1] * yCnt - size[3];
}
if (i < xCnt - 1) {
xBegin = 0;
} else {
xBegin = size[0] * xCnt - size[2];
}
xBegin += 2;
for (int k = yBegin; k < size[1]; k++) {
// System.out.println("i:" + i + " j:" + j + " k:" + k);
int wholeBegin = (j * size[1] + (k - yBegin))
* wholeRowBytes + i * size[0] * depth;
int copySize = partRowBytes - xBegin * depth;
if (wholeSize < wholeBegin + copySize) {
copySize = wholeSize - wholeBegin;
}
System.arraycopy(imgData[i][j].data, (k + 2) * partRowBytes
+ xBegin * depth, wholeImgData[0].data, wholeBegin,
copySize);
}
}
}
gc.dispose();
// System.out.println("ImageCreator(abs): fin");
return wholeImgData;
}
private ImageData[] getImageByIncrementalScroll(int[] size,
IModelServiceScrollManager scrollManager) {
final Image img = new Image(Display.getDefault(), size[0] + 2,
size[1] + 2);
ImageData[] wholeImgData = new ImageData[1];
final GC gc = new GC(modelService.getTargetComposite());
int xCnt = 1, yCnt = 1;
// TODO use getScrollcount() method
while (scrollManager.incrementLargeScrollX(false) > 0)
;
while (scrollManager.incrementLargeScrollY(false) > 0)
;
while (scrollManager.decrementLargeScrollX(false) > 0) {
xCnt++;
}
while (scrollManager.decrementLargeScrollY(false) > 0) {
yCnt++;
}
// for rendering wait
scrollManager.decrementLargeScrollY(true);
ImageData[][] imgData = new ImageData[xCnt][yCnt];
int[] scrollX = new int[xCnt];
int[] scrollY = new int[yCnt];
// System.out.println("start:" + xCnt + " " + yCnt);
// System.out.println("X: "+scrollManager.incrementScrollX());
// System.out.println("Y: "+scrollManager.incrementScrollY());
for (int i = 0; i < xCnt; i++) {
for (int j = 0; j < yCnt; j++) {
gc.copyArea(img, 0, 0);
imgData[i][j] = img.getImageData();
// gc.copyArea(img, 0, 0);
// imgData[i][j] = img.getImageData();
scrollY[j] = scrollManager.incrementLargeScrollY(true);
}
scrollX[i] = scrollManager.incrementLargeScrollX(true);
while (scrollManager.decrementLargeScrollY(false) > 0)
;
}
int depth = imgData[0][0].depth;
// System.out.println(size[0] + " " + size[1] + " " + size[2] + " " +
// size[3] + " " + depth);
wholeImgData[0] = new ImageData(size[2], size[3], depth,
imgData[0][0].palette);
int wholeRowBytes = ((size[2] * depth + 31) / 32) * 4;
int partRowBytes = (((size[0] + 2) * depth + 31) / 32) * 4;
depth = depth / 8;
int xBegin, yBegin;
int curX = 0, curY = 0;
int finX = 0, finY = 0;
int wholeSize = wholeImgData[0].data.length;
// System.out.println("copy start");
for (int j = 0; j < yCnt; j++) {
if (j == 0) {
yBegin = 0;
} else {
yBegin = finY - curY;
}
// System.out.println("Y: " + yBegin + " " + curY + " " + finY);
for (int i = 0; i < xCnt; i++) {
if (i == 0) {
xBegin = 0;
} else {
xBegin = finX - curX;
}
xBegin += 2;
// System.out.println("X: " + xBegin + " " + curX + " " + finX);
// for (int k = yBegin; k < size[1]; k++) {
for (int k = 0; k < size[1]; k++) {
// System.out.println("i:" + i + " j:" + j + " k:" + k);
int wholeBegin = (finY + (k - yBegin)) * wholeRowBytes
+ finX * depth;
int copySize = partRowBytes - xBegin * depth;
// System.out.println(wholeBegin + " " + copySize + " " +
// wholeSize);
if (wholeSize < wholeBegin + copySize) {
copySize = wholeSize - wholeBegin;
}
if (copySize > 0) {
System.arraycopy(imgData[i][j].data, (k + 2)
* partRowBytes + xBegin * depth,
wholeImgData[0].data, wholeBegin, copySize);
}
}
curX += scrollX[i];
finX += size[0] - xBegin;
}
curY += scrollY[j];
finY += size[1] - yBegin;
}
gc.dispose();
// System.out.println("ImageCreator(inc): fin");
return wholeImgData;
}
private ImageData[] getImageByPageScroll(int[] size,
IModelServiceScrollManager scrollManager) {
final Image img = new Image(Display.getDefault(), size[0] + 2,
size[1] + 2);
ImageData[] wholeImgData = new ImageData[1];
final GC gc = new GC(modelService.getTargetComposite());
int yCnt = 1;
yCnt = scrollManager.getLastPageNumber();
if (yCnt < 1) {
// System.out.println("page count:" + yCnt);
yCnt = 1;
}
scrollManager.jumpToPage(1, true);
ImageData[] imgData = new ImageData[yCnt];
// System.out.println("start:" + " " + yCnt);
for (int j = 0; j < yCnt; j++) {
gc.copyArea(img, 0, 0);
imgData[j] = img.getImageData();
scrollManager.incrementPageScroll(true);
}
scrollManager.jumpToPage(1, false);
int depth = imgData[0].depth;
// System.out.println(size[0] + " " + size[1] + " " + size[2] + " " +
// size[3] + " " + depth);
wholeImgData[0] = new ImageData(size[2], size[3], depth,
imgData[0].palette);
int wholeRowBytes = ((size[2] * depth + 31) / 32) * 4;
int partRowBytes = (((size[0] + 2) * depth + 31) / 32) * 4;
depth = depth / 8;
int wholeSize = wholeImgData[0].data.length;
for (int j = 0; j < yCnt; j++) {
for (int k = 0; k < size[1]; k++) {
// System.out.println("i:" + i + " j:" + j + " k:" + k);
int wholeBegin = (size[1] * j + k) * wholeRowBytes;
int copySize = partRowBytes;
if (wholeSize < wholeBegin + copySize) {
copySize = wholeSize - wholeBegin;
}
if (copySize > 0) {
System.arraycopy(imgData[j].data, (k + 2) * partRowBytes,
wholeImgData[0].data, wholeBegin, copySize);
}
}
}
gc.dispose();
// System.out.println("ImageCreator(page): fin");
return wholeImgData;
}
}