use of com.biglybt.core.disk.DiskManager in project BiglyBT by BiglySoftware.
the class HTTPNetworkConnectionFile method decodeHeader.
@Override
protected void decodeHeader(HTTPMessageDecoder decoder, final String header) throws IOException {
if (switching) {
Debug.out("new header received while paused");
throw (new IOException("Bork"));
}
if (!isSeed()) {
return;
}
PEPeerControl control = getPeerControl();
DiskManager dm = control.getDiskManager();
if (dm == null) {
Debug.out("Disk manager is null");
throw (new IOException("Disk manager unavailable"));
}
TOTorrent to_torrent = dm.getTorrent();
char[] chars = header.toCharArray();
int last_pos = 0;
int line_num = 0;
String target_str = null;
DiskManagerFileInfo target_file = null;
long file_offset = 0;
List<long[]> ranges = new ArrayList<>();
boolean keep_alive = false;
for (int i = 1; i < chars.length; i++) {
if (chars[i - 1] == '\r' && chars[i] == '\n') {
String line = new String(chars, last_pos, i - last_pos).trim();
last_pos = i;
line_num++;
if (line_num == 1) {
line = line.substring(line.indexOf("files/") + 6);
int hash_end = line.indexOf("/");
final byte[] old_hash = control.getHash();
final byte[] new_hash = URLDecoder.decode(line.substring(0, hash_end), "ISO-8859-1").getBytes("ISO-8859-1");
if (!Arrays.equals(new_hash, old_hash)) {
switching = true;
decoder.pauseInternally();
flushRequests(new flushListener() {
private boolean triggered;
@Override
public void flushed() {
synchronized (this) {
if (triggered) {
return;
}
triggered = true;
}
getManager().reRoute(HTTPNetworkConnectionFile.this, old_hash, new_hash, header);
}
});
return;
}
line = line.substring(hash_end + 1);
line = line.substring(0, line.lastIndexOf(' '));
String file = line;
if (to_torrent.isSimpleTorrent()) {
// optimise for simple torrents. also support the case where
// client has the hash but doesn't know the file name
target_file = dm.getFiles()[0];
} else {
target_str = file;
StringTokenizer tok = new StringTokenizer(file, "/");
List<byte[]> bits = new ArrayList<>();
while (tok.hasMoreTokens()) {
bits.add(URLDecoder.decode(tok.nextToken(), "ISO-8859-1").getBytes("ISO-8859-1"));
}
if (!to_torrent.isSimpleTorrent() && bits.size() > 1) {
if (Arrays.equals(to_torrent.getName(), (byte[]) bits.get(0))) {
bits.remove(0);
}
}
DiskManagerFileInfo[] files = dm.getFiles();
file_offset = 0;
for (int j = 0; j < files.length; j++) {
TOTorrentFile torrent_file = files[j].getTorrentFile();
byte[][] comps = torrent_file.getPathComponents();
if (comps.length == bits.size()) {
boolean match = true;
for (int k = 0; k < comps.length; k++) {
if (!Arrays.equals(comps[k], (byte[]) bits.get(k))) {
match = false;
break;
}
}
if (match) {
target_file = files[j];
break;
}
}
file_offset += torrent_file.getLength();
}
}
} else {
line = line.toLowerCase(MessageText.LOCALE_ENGLISH);
if (line.startsWith("range") && target_file != null) {
line = line.substring(5).trim();
if (line.startsWith(":")) {
String range_str = line.substring(1).trim();
if (range_str.startsWith("bytes=")) {
long file_length = target_file.getLength();
StringTokenizer tok2 = new StringTokenizer(range_str.substring(6), ",");
while (tok2.hasMoreTokens()) {
String range = tok2.nextToken();
try {
int pos = range.indexOf('-');
if (pos != -1) {
String lhs = range.substring(0, pos);
String rhs = range.substring(pos + 1);
long start;
long end;
if (lhs.length() == 0) {
// -222 is last 222 bytes of file
end = file_length - 1;
start = file_length - Long.parseLong(rhs);
} else if (rhs.length() == 0) {
end = file_length - 1;
start = Long.parseLong(lhs);
} else {
start = Long.parseLong(lhs);
end = Long.parseLong(rhs);
}
ranges.add(new long[] { start, end });
}
} catch (Throwable e) {
}
}
}
if (ranges.size() == 0) {
log("Invalid range specification: '" + line + "'");
sendAndClose(getManager().getRangeNotSatisfiable());
return;
}
}
} else if (line.contains("keep-alive")) {
keep_alive = true;
}
}
}
}
if (target_file == null) {
log("Failed to find file '" + target_str + "'");
sendAndClose(getManager().getNotFound());
return;
}
try {
String name = target_file.getFile(true).getName();
int pos = name.lastIndexOf(".");
if (pos != -1) {
setContentType(HTTPUtils.guessContentTypeFromFileType(name.substring(pos + 1)));
}
} catch (Throwable e) {
}
long file_length = target_file.getLength();
boolean partial_content = ranges.size() > 0;
if (!partial_content) {
ranges.add(new long[] { 0, file_length - 1 });
}
long[] offsets = new long[ranges.size()];
long[] lengths = new long[ranges.size()];
for (int i = 0; i < ranges.size(); i++) {
long[] range = (long[]) ranges.get(i);
long start = range[0];
long end = range[1];
if (start < 0 || start >= file_length || end < 0 || end >= file_length || start > end) {
log("Invalid range specification: '" + start + "-" + end + "'");
sendAndClose(getManager().getRangeNotSatisfiable());
return;
}
offsets[i] = file_offset + start;
lengths[i] = (end - start) + 1;
}
addRequest(new httpRequest(offsets, lengths, file_length, partial_content, keep_alive));
}
use of com.biglybt.core.disk.DiskManager in project BiglyBT by BiglySoftware.
the class NetworkAdminSpeedTesterBTImpl method start.
/**
* The downloads have been stopped just need to do the testing.
* @param tot - Torrent recieved from testing service.
*/
public synchronized void start(TOTorrent tot) {
if (test_started) {
Debug.out("Test already started!");
return;
}
test_started = true;
// OK lets start the test.
try {
TorrentUtils.setFlag(tot, TorrentUtils.TORRENT_FLAG_LOW_NOISE, true);
Torrent torrent = new TorrentImpl(tot);
String fileName = torrent.getName();
sendStageUpdateToListeners(MessageText.getString("SpeedTestWizard.stage.message.preparing"));
// create a blank file of specified size. (using the temporary name.)
File saveLocation = AETemporaryFileHandler.createTempFile();
File baseDir = saveLocation.getParentFile();
File blankFile = new File(baseDir, fileName);
File blankTorrentFile = new File(baseDir, "speedTestTorrent.torrent");
torrent.writeToFile(blankTorrentFile);
URL announce_url = torrent.getAnnounceURL();
if (announce_url.getProtocol().equalsIgnoreCase("https")) {
SESecurityManager.setCertificateHandler(announce_url, new SECertificateListener() {
@Override
public boolean trustCertificate(String resource, X509Certificate cert) {
return (true);
}
});
}
Download speed_download = plugin.getDownloadManager().addDownloadStopped(torrent, blankTorrentFile, blankFile);
speed_download.setBooleanAttribute(speedTestAttrib, true);
DownloadManager core_download = PluginCoreUtils.unwrap(speed_download);
core_download.setPieceCheckingEnabled(false);
// make sure we've got a bunch of upload slots
core_download.getDownloadState().setIntParameter(DownloadManagerState.PARAM_MAX_UPLOADS, 32);
core_download.getDownloadState().setIntParameter(DownloadManagerState.PARAM_MAX_UPLOADS_WHEN_SEEDING, 32);
if (use_crypto) {
core_download.setCryptoLevel(NetworkManager.CRYPTO_OVERRIDE_REQUIRED);
}
core_download.addPeerListener(new DownloadManagerPeerListener() {
@Override
public void peerManagerWillBeAdded(PEPeerManager peer_manager) {
DiskManager disk_manager = peer_manager.getDiskManager();
DiskManagerPiece[] pieces = disk_manager.getPieces();
int startPiece = setStartPieceBasedOnMode(testMode, pieces.length);
for (int i = startPiece; i < pieces.length; i++) {
pieces[i].setDone(true);
}
}
@Override
public void peerManagerAdded(PEPeerManager peer_manager) {
}
@Override
public void peerManagerRemoved(PEPeerManager manager) {
}
@Override
public void peerAdded(PEPeer peer) {
}
@Override
public void peerRemoved(PEPeer peer) {
}
});
speed_download.moveTo(1);
speed_download.setFlag(Download.FLAG_DISABLE_AUTO_FILE_MOVE, true);
core_download.initialize();
core_download.setForceStart(true);
TorrentSpeedTestMonitorThread monitor = new TorrentSpeedTestMonitorThread(speed_download);
monitor.start();
// The test has now started!!
} catch (Throwable e) {
test_completed = true;
abort("Could not start test", e);
}
}
use of com.biglybt.core.disk.DiskManager in project BiglyBT by BiglySoftware.
the class TagManagerImpl method onCompletion.
@Override
public void onCompletion(Download d) {
final DownloadManager manager = PluginCoreUtils.unwrap(d);
List<Tag> tags = getTagsForTaggable(manager);
List<Tag> cc_tags = new ArrayList<>();
for (Tag tag : tags) {
if (tag.getTagType().hasTagTypeFeature(TagFeature.TF_FILE_LOCATION)) {
TagFeatureFileLocation fl = (TagFeatureFileLocation) tag;
if (fl.supportsTagCopyOnComplete()) {
File save_loc = fl.getTagCopyOnCompleteFolder();
if (save_loc != null) {
cc_tags.add(tag);
}
}
}
}
if (cc_tags.size() > 0) {
if (cc_tags.size() > 1) {
Collections.sort(cc_tags, new Comparator<Tag>() {
@Override
public int compare(Tag o1, Tag o2) {
return (o1.getTagID() - o2.getTagID());
}
});
}
TagFeatureFileLocation fl = (TagFeatureFileLocation) cc_tags.get(0);
final File new_loc = fl.getTagCopyOnCompleteFolder();
long options = fl.getTagCopyOnCompleteOptions();
boolean copy_data = (options & TagFeatureFileLocation.FL_DATA) != 0;
boolean copy_torrent = (options & TagFeatureFileLocation.FL_TORRENT) != 0;
if (copy_data) {
File old_loc = manager.getSaveLocation();
if (!new_loc.equals(old_loc)) {
boolean do_it;
synchronized (active_copy_on_complete) {
if (active_copy_on_complete.contains(manager)) {
do_it = false;
} else {
active_copy_on_complete.add(manager);
do_it = true;
}
}
if (do_it) {
new AEThread2("tm:copy") {
@Override
public void run() {
try {
long stopped_and_incomplete_start = 0;
long looks_good_start = 0;
while (true) {
if (manager.isDestroyed()) {
throw (new Exception("Download has been removed"));
}
DiskManager dm = manager.getDiskManager();
if (dm == null) {
looks_good_start = 0;
if (!manager.getAssumedComplete()) {
long now = SystemTime.getMonotonousTime();
if (stopped_and_incomplete_start == 0) {
stopped_and_incomplete_start = now;
} else if (now - stopped_and_incomplete_start > 30 * 1000) {
throw (new Exception("Download is stopped and incomplete"));
}
} else {
break;
}
} else {
stopped_and_incomplete_start = 0;
if (manager.getAssumedComplete()) {
if (dm.getMoveProgress() == -1 && dm.getCompleteRecheckStatus() == -1) {
long now = SystemTime.getMonotonousTime();
if (looks_good_start == 0) {
looks_good_start = now;
} else if (now - looks_good_start > 5 * 1000) {
break;
}
}
} else {
looks_good_start = 0;
}
}
// System.out.println( "Waiting" );
Thread.sleep(1000);
}
manager.copyDataFiles(new_loc);
Logger.logTextResource(new LogAlert(manager, LogAlert.REPEATABLE, LogAlert.AT_INFORMATION, "alert.copy.on.comp.done"), new String[] { manager.getDisplayName(), new_loc.toString() });
} catch (Throwable e) {
Logger.logTextResource(new LogAlert(manager, LogAlert.REPEATABLE, LogAlert.AT_ERROR, "alert.copy.on.comp.fail"), new String[] { manager.getDisplayName(), new_loc.toString(), Debug.getNestedExceptionMessage(e) });
} finally {
synchronized (active_copy_on_complete) {
active_copy_on_complete.remove(manager);
}
}
}
}.start();
}
}
}
if (copy_torrent) {
File old_file = new File(manager.getTorrentFileName());
if (old_file.exists()) {
File new_file = new File(new_loc, old_file.getName());
FileUtil.copyFile(old_file, new_file);
}
}
}
}
use of com.biglybt.core.disk.DiskManager in project BiglyBT by BiglySoftware.
the class ShareRatioProgressItem method refresh.
@Override
public void refresh(TableCell cell, long timestamp) {
DownloadManager dm = (DownloadManager) cell.getDataSource();
if (dm == null || existing_sr <= 0) {
super.refresh(cell, 0);
return;
}
int dm_state = dm.getState();
long next_eta = -1;
if (dm_state == DownloadManager.STATE_DOWNLOADING || dm_state == DownloadManager.STATE_SEEDING) {
DownloadManagerStats stats = dm.getStats();
long downloaded = stats.getTotalGoodDataBytesReceived();
long uploaded = stats.getTotalDataBytesSent();
if (downloaded <= 0) {
next_eta = -2;
} else {
int current_sr = (int) ((1000 * uploaded) / downloaded);
int mult = current_sr / existing_sr;
int next_target_sr = (mult + 1) * existing_sr;
long up_speed = stats.getDataSendRate() == 0 ? 0 : stats.getSmoothedDataSendRate();
if (up_speed <= 0) {
next_eta = -2;
} else {
if (dm_state == DownloadManager.STATE_SEEDING) {
// simple case
long target_upload = (next_target_sr * downloaded) / 1000;
next_eta = (target_upload - uploaded) / up_speed;
} else {
// more complex when downloading as we have to consider the fact that
// at some point the download will complete and therefore download speed will
// drop to 0
DiskManager disk_man = dm.getDiskManager();
if (disk_man != null) {
long remaining = disk_man.getRemainingExcludingDND();
long down_speed = (dm_state == DownloadManager.STATE_SEEDING || stats.getDataReceiveRate() == 0) ? 0 : stats.getSmoothedDataReceiveRate();
if (down_speed <= 0 || remaining <= 0) {
// same as if we are just seeding
long target_upload = (next_target_sr * downloaded) / 1000;
next_eta = (target_upload - uploaded) / up_speed;
} else {
/*
time T until the target share ration is met is
uploaded + ( T * upload_speed )
------------------------------ = target_sr
downloaded + ( T * download_speed )
*/
long time_to_sr = ((next_target_sr * downloaded) / 1000 - uploaded) / (up_speed - (down_speed * next_target_sr) / 1000);
long time_to_completion = remaining / down_speed;
if (time_to_sr > 0 && time_to_sr <= time_to_completion) {
next_eta = time_to_sr;
} else {
// basic calculation shows eta is > download complete time so we need
// to refactor things
long uploaded_at_completion = uploaded + (up_speed * time_to_completion);
long downloaded_at_completion = downloaded + (down_speed * time_to_completion);
// usual seeding calculation for time after completion
long target_upload = (next_target_sr * downloaded_at_completion) / 1000;
next_eta = time_to_completion + (target_upload - uploaded_at_completion) / up_speed;
}
}
} else {
next_eta = -2;
}
}
}
}
}
long data = dm.getDownloadState().getLongAttribute(DownloadManagerState.AT_SHARE_RATIO_PROGRESS);
long sr = (int) data;
String sr_str = DisplayFormatters.formatDecimal((double) sr / 1000, 3);
timestamp = (data >>> 32) * 1000;
// feed a bit of share ratio/next eta into sort order for fun and to ensure refresh occurs when they change
long sort_order = timestamp;
sort_order += (sr & 0xff) << 8;
sort_order += (next_eta & 0xff);
String next_eta_str;
if (next_eta == -1) {
next_eta_str = "";
} else if (next_eta == -2) {
next_eta_str = Constants.INFINITY_STRING + ": ";
} else {
next_eta_str = DisplayFormatters.formatETA(next_eta) + ": ";
}
String prefix = next_eta_str + sr_str + (timestamp > 0 ? ": " : "");
super.refresh(cell, timestamp, sort_order, prefix);
}
use of com.biglybt.core.disk.DiskManager in project BiglyBT by BiglySoftware.
the class PieceGraphView method buildImage.
private void buildImage() {
if (canvas == null || canvas.isDisposed()) {
return;
}
// canvas.setBackground(ColorCache.getColor(canvas.getDisplay(), "#1b1b1b"));
Rectangle bounds = canvas.getClientArea();
if (bounds.isEmpty()) {
return;
}
if (dlm == null) {
canvas.redraw();
return;
}
PEPeerManager pm = dlm.getPeerManager();
DiskManager dm = dlm.getDiskManager();
if (pm == null || dm == null) {
canvas.redraw();
return;
}
final DiskManagerPiece[] dm_pieces = dm.getPieces();
if (dm_pieces == null || dm_pieces.length == 0) {
canvas.redraw();
return;
}
int numPieces = dm_pieces.length;
if (imgHaveAll == null || imgHaveAll.isDisposed()) {
imgHaveAll = new Image(canvas.getDisplay(), BLOCK_SIZE, BLOCK_SIZE);
GC gc = new GC(imgHaveAll);
try {
try {
gc.setAntialias(SWT.ON);
} catch (Exception e) {
// ignore
}
gc.setBackground(canvas.getBackground());
gc.fillRectangle(imgHaveAll.getBounds());
gc.setBackground(blockColors[BLOCKCOLOR_HAVEALL]);
gc.fillRoundRectangle(1, 1, BLOCK_FILLSIZE, BLOCK_FILLSIZE, BLOCK_FILLSIZE, BLOCK_FILLSIZE);
} finally {
gc.dispose();
}
}
if (imgNoHave == null || imgNoHave.isDisposed()) {
imgNoHave = new Image(canvas.getDisplay(), BLOCK_SIZE, BLOCK_SIZE);
GC gc = new GC(imgNoHave);
try {
try {
gc.setAntialias(SWT.ON);
} catch (Exception e) {
// ignore
}
gc.setBackground(canvas.getBackground());
gc.fillRectangle(imgNoHave.getBounds());
gc.setBackground(blockColors[BLOCKCOLOR_NOHAVE]);
gc.fillRoundRectangle(1, 1, BLOCK_FILLSIZE, BLOCK_FILLSIZE, BLOCK_FILLSIZE, BLOCK_FILLSIZE);
} finally {
gc.dispose();
}
}
boolean clearImage = img == null || img.isDisposed() || img.getBounds().width != bounds.width || img.getBounds().height != bounds.height;
if (clearImage) {
if (img != null && !img.isDisposed()) {
img.dispose();
}
// System.out.println("clear " + img);
img = new Image(canvas.getDisplay(), bounds.width, bounds.height);
squareCache = null;
}
PEPiece[] currentDLPieces = dlm.getCurrentPieces();
Arrays.sort(currentDLPieces, compFindPEPiece);
// find upload pieces
ArrayList currentULPieces = new ArrayList();
ArrayList futureULPieces = new ArrayList();
PEPeer[] peers = (PEPeer[]) pm.getPeers().toArray(new PEPeer[0]);
for (int i = 0; i < peers.length; i++) {
PEPeer peer = peers[i];
int[] peerRequestedPieces = peer.getIncomingRequestedPieceNumbers();
if (peerRequestedPieces != null && peerRequestedPieces.length > 0) {
currentULPieces.add(new Long(peerRequestedPieces[0]));
for (int j = 1; j < peerRequestedPieces.length; j++) {
futureULPieces.add(new Long(peerRequestedPieces[j]));
}
}
// we'll have duplicates
Collections.sort(currentULPieces);
Collections.sort(futureULPieces);
}
int iNumCols = bounds.width / BLOCK_SIZE;
int iNumRows = bounds.height / BLOCK_SIZE;
int numSquares = onePiecePerBlock ? numPieces : iNumCols * iNumRows;
double numPiecesPerSquare = numPieces / (double) numSquares;
if (squareCache == null || squareCache.length != numSquares) {
squareCache = new double[numSquares];
Arrays.fill(squareCache, -1);
}
int[] availability = pm.getAvailability();
int numRedraws = 0;
GC gc = new GC(img);
try {
int iRow = 0;
if (clearImage) {
gc.setBackground(canvas.getBackground());
gc.fillRectangle(bounds);
}
try {
gc.setAdvanced(true);
gc.setAntialias(SWT.ON);
gc.setInterpolation(SWT.HIGH);
} catch (Exception e) {
// ignore
}
int iCol = 0;
for (int squareNo = 0; squareNo < numSquares; squareNo++) {
if (iCol >= iNumCols) {
iCol = 0;
iRow++;
}
int startNo = (int) (squareNo * numPiecesPerSquare);
int count = (int) ((squareNo + 1) * numPiecesPerSquare) - startNo;
if (count == 0) {
count = 1;
}
// if (count > 1) System.out.println("!!! " + startNo);
// System.out.println(startNo + ";" + count);
double pctDone = getPercentDone(startNo, count, dm_pieces);
// System.out.print(pctDone + ";");
int colorIndex;
int iXPos = iCol * BLOCK_SIZE;
int iYPos = iRow * BLOCK_SIZE;
if (pctDone == 1) {
if (squareCache[squareNo] != pctDone) {
squareCache[squareNo] = pctDone;
gc.drawImage(imgHaveAll, iXPos, iYPos);
if (!clearImage) {
numRedraws++;
canvas.redraw(iXPos, iYPos, BLOCK_SIZE, BLOCK_SIZE, false);
}
}
} else if (pctDone == 0) {
if (squareCache[squareNo] != pctDone) {
squareCache[squareNo] = pctDone;
gc.drawImage(imgNoHave, iXPos, iYPos);
if (!clearImage) {
numRedraws++;
canvas.redraw(iXPos, iYPos, BLOCK_SIZE, BLOCK_SIZE, false);
}
}
} else {
// !done
boolean isDownloading = false;
for (int i = startNo; i < startNo + count; i++) {
if (Arrays.binarySearch(currentDLPieces, new Long(i), compFindPEPiece) >= 0) {
isDownloading = true;
break;
}
}
double val = pctDone + (isDownloading ? 0 : 1);
if (squareCache[squareNo] != val) {
squareCache[squareNo] = val;
gc.drawImage(imgNoHave, iXPos, iYPos);
int size = (int) (BLOCK_FILLSIZE * pctDone);
if (size == 0) {
size = 1;
}
int q = (int) ((BLOCK_FILLSIZE - size) / 2.0 + 0.5) + 1;
colorIndex = isDownloading ? BLOCKCOLOR_DOWNLOADING : BLOCKCOLOR_HAVESOME;
gc.setBackground(blockColors[colorIndex]);
gc.fillOval(iXPos + q, iYPos + q, size, size);
// gc.fillRoundRectangle(iXPos + q, iYPos + q, size, size, size, size);
if (!clearImage) {
numRedraws++;
canvas.redraw(iXPos, iYPos, BLOCK_SIZE, BLOCK_SIZE, false);
}
}
}
for (int i = startNo; i < startNo + count; i++) {
if (Collections.binarySearch(currentULPieces, new Long(i)) >= 0) {
colorIndex = BLOCKCOLOR_UPLOADING;
int size = BLOCK_FILLSIZE + 1;
gc.setForeground(blockColors[colorIndex]);
gc.drawRoundRectangle(iXPos, iYPos, size, size, size, size);
if (!clearImage) {
numRedraws++;
canvas.redraw(iXPos, iYPos, BLOCK_SIZE, BLOCK_SIZE, false);
}
squareCache[squareNo] = -1;
break;
} else if (Collections.binarySearch(futureULPieces, new Long(i)) >= 0) {
colorIndex = BLOCKCOLOR_UPLOADING;
int size = BLOCK_FILLSIZE + 1;
gc.setForeground(blockColors[colorIndex]);
gc.setLineStyle(SWT.LINE_DOT);
gc.drawRoundRectangle(iXPos, iYPos, size, size, size, size);
if (!clearImage) {
numRedraws++;
canvas.redraw(iXPos, iYPos, BLOCK_SIZE, BLOCK_SIZE, false);
}
gc.setLineStyle(SWT.LINE_SOLID);
squareCache[squareNo] = -1;
break;
}
}
if (availability != null) {
boolean hasNoAvail = false;
for (int i = startNo; i < startNo + count; i++) {
if (availability[i] == 0) {
hasNoAvail = true;
squareCache[squareNo] = -1;
break;
}
}
if (hasNoAvail) {
gc.setForeground(blockColors[BLOCKCOLOR_NOAVAIL]);
gc.drawRectangle(iXPos, iYPos, BLOCK_FILLSIZE + 1, BLOCK_FILLSIZE + 1);
if (!clearImage) {
numRedraws++;
canvas.redraw(iXPos, iYPos, BLOCK_SIZE, BLOCK_SIZE, false);
}
}
}
iCol++;
}
// System.out.println("redraws " + numRedraws);
} catch (Exception e) {
Debug.out(e);
} finally {
gc.dispose();
}
// canvas.redraw();
}
Aggregations