diff --git a/core/src/processing/core/PGraphics.java b/core/src/processing/core/PGraphics.java index c3ba398ba..8e8c129a2 100644 --- a/core/src/processing/core/PGraphics.java +++ b/core/src/processing/core/PGraphics.java @@ -7928,4 +7928,9 @@ public class PGraphics extends PImage implements PConstants { public boolean isGL() { // ignore return false; } + + + public boolean is2X() { + return pixelFactor == 2; + } } diff --git a/core/src/processing/core/PGraphicsRetina2D.java b/core/src/processing/core/PGraphicsRetina2D.java index 786e3ba6f..3f3382af9 100644 --- a/core/src/processing/core/PGraphicsRetina2D.java +++ b/core/src/processing/core/PGraphicsRetina2D.java @@ -4,7 +4,7 @@ import java.awt.*; public class PGraphicsRetina2D extends PGraphicsJava2D { - PImage retina; +// PImage retina; // int retinaWidth; // int retinaHeight; @@ -14,21 +14,21 @@ public class PGraphicsRetina2D extends PGraphicsJava2D { // INTERNAL - public PGraphicsRetina2D() { - retina = new PImage(); - retina.format = RGB; - } +// public PGraphicsRetina2D() { +// retina = new PImage(); +// retina.format = RGB; +// } - @Override - public void setParent(PApplet parent) { - super.setParent(parent); - retina.parent = parent; - } +// @Override +// public void setParent(PApplet parent) { +// super.setParent(parent); +// retina.parent = parent; +// } - @Override - protected void allocate() { +// @Override +// protected void allocate() { // parent.setIgnoreRepaint(true); // g2 = (Graphics2D) parent.getGraphics(); @@ -80,7 +80,7 @@ public class PGraphicsRetina2D extends PGraphicsJava2D { g2 = (Graphics2D) image.getGraphics(); } */ - } +// } ////////////////////////////////////////////////////////////// @@ -88,38 +88,22 @@ public class PGraphicsRetina2D extends PGraphicsJava2D { // FRAME - @Override - public boolean canDraw() { - return parent.getGraphicsConfiguration() != null; - } +// @Override +// public boolean canDraw() { +// return parent.getGraphicsConfiguration() != null; +// } @Override public void beginDraw() { -// g2 = (Graphics2D) parent.getGraphics(); - GraphicsConfiguration gc = parent.getGraphicsConfiguration(); -// if (false) { -// if (image == null || ((VolatileImage) image).validate(gc) == VolatileImage.IMAGE_INCOMPATIBLE) { -// image = gc.createCompatibleVolatileImage(width*2, height*2); -// } -// } else { if (image == null) { retina.width = width * 2; retina.height = height * 2; image = gc.createCompatibleImage(retina.width, retina.height); -// System.out.println("image type is " + image); } -// } g2 = (Graphics2D) image.getGraphics(); -// g2.scale(2, 2); - -// if (bimage == null || -// bimage.getWidth() != width || -// bimage.getHeight() != height) { -// PApplet.debug("PGraphicsJava2D creating new image"); -// bimage = gc.createCompatibleImage(width, height); checkSettings(); resetMatrix(); // reset model matrix @@ -652,4 +636,10 @@ public class PGraphicsRetina2D extends PGraphicsJava2D { return super.save(filename); } } + + + @Override + public boolean is2X() { + return true; + } } \ No newline at end of file diff --git a/core/src/processing/core/PImage.java b/core/src/processing/core/PImage.java index ccb7623e2..906019347 100644 --- a/core/src/processing/core/PImage.java +++ b/core/src/processing/core/PImage.java @@ -3,7 +3,7 @@ /* Part of the Processing project - http://processing.org - Copyright (c) 2004-11 Ben Fry and Casey Reas + Copyright (c) 2004-14 Ben Fry and Casey Reas Copyright (c) 2001-04 Massachusetts Institute of Technology This library is free software; you can redistribute it and/or @@ -94,6 +94,13 @@ public class PImage implements PConstants, Cloneable { */ public int[] pixels; + /** 1 for most images, 2 for hi-dpi/retina */ + public int pixelFactor; + + /** Actual dimensions of pixels array, taking into account the 2x setting. */ + public int pixelWidth; + public int pixelHeight; + /** * ( begin auto-generated from PImage_width.xml ) * @@ -105,6 +112,7 @@ public class PImage implements PConstants, Cloneable { * @brief Image width */ public int width; + /** * ( begin auto-generated from PImage_height.xml ) * @@ -212,7 +220,7 @@ public class PImage implements PConstants, Cloneable { * @param height image height */ public PImage(int width, int height) { - init(width, height, RGB); + init(width, height, RGB, 1); // toxi: is it maybe better to init the image with max alpha enabled? //for(int i=0; i mx2) mx2 = PApplet.min(width - 1, x); - if (x > mx2) mx2 = PApplet.min(width, x); + if (x > mx2) mx2 = PApplet.min(pixelWidth, x); if (y < my1) my1 = PApplet.max(0, y); - //if (y > my2) my2 = y; - if (y > my2) my2 = PApplet.min(height, y); + if (y > my2) my2 = PApplet.min(pixelHeight, y); if (x2 < mx1) mx1 = PApplet.max(0, x2); - //if (x2 > mx2) mx2 = PApplet.min(width - 1, x2); - if (x2 > mx2) mx2 = PApplet.min(width, x2); + if (x2 > mx2) mx2 = PApplet.min(pixelWidth, x2); if (y2 < my1) my1 = PApplet.max(0, y2); - //if (y2 > my2) my2 = PApplet.min(height - 1, y2); - if (y2 > my2) my2 = PApplet.min(height, y2); + if (y2 > my2) my2 = PApplet.min(pixelHeight, y2); } } @@ -619,21 +623,19 @@ public class PImage implements PConstants, Cloneable { h = (int) (height * diff); } - BufferedImage img = shrinkImage((BufferedImage) getNative(), w, h); -// BufferedImage img = null; -// if (w < width && h < height) { -// img = shrinkImage((BufferedImage) getNative(), w, h); -// } else { -// img = resampleImage((BufferedImage) getNative(), w, h); -// } + BufferedImage img = + shrinkImage((BufferedImage) getNative(), w*pixelFactor, h*pixelFactor); PImage temp = new PImage(img); - this.width = temp.width; - this.height = temp.height; + this.pixelWidth = temp.width; + this.pixelHeight = temp.height; // Get the resized pixel array this.pixels = temp.pixels; + this.width = pixelWidth / pixelFactor; + this.height = pixelHeight / pixelFactor; + // Mark the pixels array as altered updatePixels(); } @@ -787,17 +789,17 @@ public class PImage implements PConstants, Cloneable { * @see PApplet#copy(PImage, int, int, int, int, int, int, int, int) */ public int get(int x, int y) { - if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) return 0; + if ((x < 0) || (y < 0) || (x >= pixelWidth) || (y >= pixelHeight)) return 0; switch (format) { case RGB: - return pixels[y*width + x] | 0xff000000; + return pixels[y*pixelWidth + x] | 0xff000000; case ARGB: - return pixels[y*width + x]; + return pixels[y*pixelWidth + x]; case ALPHA: - return (pixels[y*width + x] << 24) | 0xffffff; + return (pixels[y*pixelWidth + x] << 24) | 0xffffff; } return 0; } @@ -827,12 +829,12 @@ public class PImage implements PConstants, Cloneable { y = 0; } - if (x + w > width) { - w = width - x; + if (x + w > pixelWidth) { + w = pixelWidth - x; cropped = true; } - if (y + h > height) { - h = height - y; + if (y + h > pixelHeight) { + h = pixelHeight - y; cropped = true; } @@ -848,7 +850,9 @@ public class PImage implements PConstants, Cloneable { targetFormat = ARGB; } - PImage target = new PImage(targetWidth, targetHeight, targetFormat); + PImage target = new PImage(targetWidth / pixelFactor, + targetHeight / pixelFactor, + targetFormat, pixelFactor); target.parent = parent; // parent may be null so can't use createImage() if (w > 0 && h > 0) { getImpl(x, y, w, h, target, targetX, targetY); @@ -859,11 +863,17 @@ public class PImage implements PConstants, Cloneable { /** * Returns a copy of this PImage. Equivalent to get(0, 0, width, height). + * Deprecated, just use copy() instead. */ public PImage get() { // Formerly this used clone(), which caused memory problems. // http://code.google.com/p/processing/issues/detail?id=42 - return get(0, 0, width, height); + return get(0, 0, pixelWidth, pixelHeight); + } + + + public PImage copy() { + return get(0, 0, pixelWidth, pixelHeight); } @@ -876,12 +886,12 @@ public class PImage implements PConstants, Cloneable { protected void getImpl(int sourceX, int sourceY, int sourceWidth, int sourceHeight, PImage target, int targetX, int targetY) { - int sourceIndex = sourceY*width + sourceX; - int targetIndex = targetY*target.width + targetX; + int sourceIndex = sourceY*pixelWidth + sourceX; + int targetIndex = targetY*target.pixelWidth + targetX; for (int row = 0; row < sourceHeight; row++) { System.arraycopy(pixels, sourceIndex, target.pixels, targetIndex, sourceWidth); - sourceIndex += width; - targetIndex += target.width; + sourceIndex += pixelWidth; + targetIndex += target.pixelWidth; } } @@ -918,10 +928,9 @@ public class PImage implements PConstants, Cloneable { * @see PImage#copy(PImage, int, int, int, int, int, int, int, int) */ public void set(int x, int y, int c) { - if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) return; - pixels[y*width + x] = c; - //updatePixelsImpl(x, y, 1, 1); // slow? - updatePixels(x, y, 1, 1); // slow? + if ((x < 0) || (y < 0) || (x >= pixelWidth) || (y >= pixelHeight)) return; + pixels[y*pixelWidth + x] = c; + updatePixels(x, y, 1, 1); // slow... } @@ -936,8 +945,8 @@ public class PImage implements PConstants, Cloneable { public void set(int x, int y, PImage img) { int sx = 0; int sy = 0; - int sw = img.width; - int sh = img.height; + int sw = img.pixelWidth; + int sh = img.pixelHeight; if (x < 0) { // off left edge sx -= x; @@ -949,11 +958,11 @@ public class PImage implements PConstants, Cloneable { sh += y; y = 0; } - if (x + sw > width) { // off right edge - sw = width - x; + if (x + sw > pixelWidth) { // off right edge + sw = pixelWidth - x; } - if (y + sh > height) { // off bottom edge - sh = height - y; + if (y + sh > pixelHeight) { // off bottom edge + sh = pixelHeight - y; } // this could be nonexistent @@ -971,13 +980,13 @@ public class PImage implements PConstants, Cloneable { int sourceX, int sourceY, int sourceWidth, int sourceHeight, int targetX, int targetY) { - int sourceOffset = sourceY * sourceImage.width + sourceX; - int targetOffset = targetY * width + targetX; + int sourceOffset = sourceY * sourceImage.pixelWidth + sourceX; + int targetOffset = targetY * pixelWidth + targetX; for (int y = sourceY; y < sourceY + sourceHeight; y++) { System.arraycopy(sourceImage.pixels, sourceOffset, pixels, targetOffset, sourceWidth); - sourceOffset += sourceImage.width; - targetOffset += width; + sourceOffset += sourceImage.pixelWidth; + targetOffset += pixelWidth; } //updatePixelsImpl(targetX, targetY, sourceWidth, sourceHeight); @@ -996,7 +1005,7 @@ public class PImage implements PConstants, Cloneable { loadPixels(); // don't execute if mask image is different size if (maskArray.length != pixels.length) { - throw new RuntimeException("mask() can only be used with an image that's the same size."); + throw new IllegalArgumentException("mask() can only be used with an image that's the same size."); } for (int i = 0; i < pixels.length; i++) { pixels[i] = ((maskArray[i] & 0xff) << 24) | (pixels[i] & 0xffffff); @@ -1111,13 +1120,13 @@ public class PImage implements PConstants, Cloneable { filter(THRESHOLD, 0.5f); break; - // [toxi20050728] added new filters + // [toxi 050728] added new filters case ERODE: - dilate(true); + erode(); // former dilate(true); break; case DILATE: - dilate(false); + dilate(); // former dilate(false); break; } updatePixels(); // mark as modified @@ -1288,8 +1297,8 @@ public class PImage implements PConstants, Cloneable { buildBlurKernel(r); - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { + for (int y = 0; y < pixelHeight; y++) { + for (int x = 0; x < pixelWidth; x++) { //cb = cg = cr = sum = 0; cb = sum = 0; read = x - blurRadius; @@ -1297,15 +1306,15 @@ public class PImage implements PConstants, Cloneable { bk0=-read; read=0; } else { - if (read >= width) + if (read >= pixelWidth) break; bk0=0; } for (int i = bk0; i < blurKernelSize; i++) { - if (read >= width) + if (read >= pixelWidth) break; int c = pixels[read + yi]; - int[] bm=blurMult[i]; + int[] bm = blurMult[i]; cb += bm[c & BLUE_MASK]; sum += blurKernel[i]; read++; @@ -1313,40 +1322,39 @@ public class PImage implements PConstants, Cloneable { ri = yi + x; b2[ri] = cb / sum; } - yi += width; + yi += pixelWidth; } yi = 0; - ym=-blurRadius; - ymi=ym*width; + ym = -blurRadius; + ymi = ym * pixelWidth; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - //cb = cg = cr = sum = 0; + for (int y = 0; y < pixelHeight; y++) { + for (int x = 0; x < pixelWidth; x++) { cb = sum = 0; - if (ym<0) { + if (ym < 0) { bk0 = ri = -ym; read = x; } else { - if (ym >= height) + if (ym >= pixelHeight) break; bk0 = 0; ri = ym; read = x + ymi; } for (int i = bk0; i < blurKernelSize; i++) { - if (ri >= height) + if (ri >= pixelHeight) break; - int[] bm=blurMult[i]; + int[] bm = blurMult[i]; cb += bm[b2[read]]; sum += blurKernel[i]; ri++; - read += width; + read += pixelWidth; } pixels[x+yi] = (cb/sum); } - yi += width; - ymi += width; + yi += pixelWidth; + ymi += pixelWidth; ym++; } } @@ -1362,23 +1370,25 @@ public class PImage implements PConstants, Cloneable { buildBlurKernel(r); - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { + for (int y = 0; y < pixelHeight; y++) { + for (int x = 0; x < pixelWidth; x++) { cb = cg = cr = sum = 0; read = x - blurRadius; - if (read<0) { - bk0=-read; - read=0; + if (read < 0) { + bk0 = -read; + read = 0; } else { - if (read >= width) + if (read >= pixelWidth) { break; - bk0=0; + } + bk0 = 0; } for (int i = bk0; i < blurKernelSize; i++) { - if (read >= width) + if (read >= pixelWidth) { break; + } int c = pixels[read + yi]; - int[] bm=blurMult[i]; + int[] bm = blurMult[i]; cr += bm[(c & RED_MASK) >> 16]; cg += bm[(c & GREEN_MASK) >> 8]; cb += bm[c & BLUE_MASK]; @@ -1390,41 +1400,43 @@ public class PImage implements PConstants, Cloneable { g2[ri] = cg / sum; b2[ri] = cb / sum; } - yi += width; + yi += pixelWidth; } yi = 0; - ym=-blurRadius; - ymi=ym*width; + ym = -blurRadius; + ymi = ym * pixelWidth; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { + for (int y = 0; y < pixelHeight; y++) { + for (int x = 0; x < pixelWidth; x++) { cb = cg = cr = sum = 0; - if (ym<0) { + if (ym < 0) { bk0 = ri = -ym; read = x; } else { - if (ym >= height) + if (ym >= pixelHeight) { break; + } bk0 = 0; ri = ym; read = x + ymi; } for (int i = bk0; i < blurKernelSize; i++) { - if (ri >= height) + if (ri >= pixelHeight) { break; - int[] bm=blurMult[i]; + } + int[] bm = blurMult[i]; cr += bm[r2[read]]; cg += bm[g2[read]]; cb += bm[b2[read]]; sum += blurKernel[i]; ri++; - read += width; + read += pixelWidth; } pixels[x+yi] = 0xff000000 | (cr/sum)<<16 | (cg/sum)<<8 | (cb/sum); } - yi += width; - ymi += width; + yi += pixelWidth; + ymi += pixelWidth; ym++; } } @@ -1442,21 +1454,23 @@ public class PImage implements PConstants, Cloneable { buildBlurKernel(r); - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { + for (int y = 0; y < pixelHeight; y++) { + for (int x = 0; x < pixelWidth; x++) { cb = cg = cr = ca = sum = 0; read = x - blurRadius; - if (read<0) { - bk0=-read; - read=0; + if (read < 0) { + bk0 = -read; + read = 0; } else { - if (read >= width) + if (read >= pixelWidth) { break; + } bk0=0; } for (int i = bk0; i < blurKernelSize; i++) { - if (read >= width) + if (read >= pixelWidth) { break; + } int c = pixels[read + yi]; int[] bm=blurMult[i]; ca += bm[(c & ALPHA_MASK) >>> 24]; @@ -1472,29 +1486,31 @@ public class PImage implements PConstants, Cloneable { g2[ri] = cg / sum; b2[ri] = cb / sum; } - yi += width; + yi += pixelWidth; } yi = 0; - ym=-blurRadius; - ymi=ym*width; + ym = -blurRadius; + ymi = ym * pixelWidth; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { + for (int y = 0; y < pixelHeight; y++) { + for (int x = 0; x < pixelWidth; x++) { cb = cg = cr = ca = sum = 0; - if (ym<0) { + if (ym < 0) { bk0 = ri = -ym; read = x; } else { - if (ym >= height) + if (ym >= pixelHeight) { break; + } bk0 = 0; ri = ym; read = x + ymi; } for (int i = bk0; i < blurKernelSize; i++) { - if (ri >= height) + if (ri >= pixelHeight) { break; + } int[] bm=blurMult[i]; ca += bm[a2[read]]; cr += bm[r2[read]]; @@ -1502,12 +1518,12 @@ public class PImage implements PConstants, Cloneable { cb += bm[b2[read]]; sum += blurKernel[i]; ri++; - read += width; + read += pixelWidth; } pixels[x+yi] = (ca/sum)<<24 | (cr/sum)<<16 | (cg/sum)<<8 | (cb/sum); } - yi += width; - ymi += width; + yi += pixelWidth; + ymi += pixelWidth; ym++; } } @@ -1517,127 +1533,141 @@ public class PImage implements PConstants, Cloneable { * Generic dilate/erode filter using luminance values * as decision factor. [toxi 050728] */ - protected void dilate(boolean isInverted) { - int currIdx=0; - int maxIdx=pixels.length; - int[] out=new int[maxIdx]; + protected void dilate() { // formerly dilate(false) + int index = 0; + int maxIndex = pixels.length; + int[] outgoing = new int[maxIndex]; - if (!isInverted) { - // erosion (grow light areas) - while (currIdx=maxRowIdx) - idxRight=currIdx; - if (idxUp<0) - idxUp=currIdx; - if (idxDown>=maxIdx) - idxDown=currIdx; - - int colUp=pixels[idxUp]; - int colLeft=pixels[idxLeft]; - int colDown=pixels[idxDown]; - int colRight=pixels[idxRight]; - - // compute luminance - int currLum = - 77*(colOrig>>16&0xff) + 151*(colOrig>>8&0xff) + 28*(colOrig&0xff); - int lumLeft = - 77*(colLeft>>16&0xff) + 151*(colLeft>>8&0xff) + 28*(colLeft&0xff); - int lumRight = - 77*(colRight>>16&0xff) + 151*(colRight>>8&0xff) + 28*(colRight&0xff); - int lumUp = - 77*(colUp>>16&0xff) + 151*(colUp>>8&0xff) + 28*(colUp&0xff); - int lumDown = - 77*(colDown>>16&0xff) + 151*(colDown>>8&0xff) + 28*(colDown&0xff); - - if (lumLeft>currLum) { - colOut=colLeft; - currLum=lumLeft; - } - if (lumRight>currLum) { - colOut=colRight; - currLum=lumRight; - } - if (lumUp>currLum) { - colOut=colUp; - currLum=lumUp; - } - if (lumDown>currLum) { - colOut=colDown; - currLum=lumDown; - } - out[currIdx++]=colOut; + // erosion (grow light areas) + while (index < maxIndex) { + int curRowIndex = index; + int maxRowIndex = index + pixelWidth; + while (index < maxRowIndex) { + int orig = pixels[index]; + int result = orig; + int idxLeft = index - 1; + int idxRight = index + 1; + int idxUp = index - pixelWidth; + int idxDown = index + pixelWidth; + if (idxLeft < curRowIndex) { + idxLeft = index; } - } - } else { - // dilate (grow dark areas) - while (currIdx=maxRowIdx) - idxRight=currIdx; - if (idxUp<0) - idxUp=currIdx; - if (idxDown>=maxIdx) - idxDown=currIdx; - - int colUp=pixels[idxUp]; - int colLeft=pixels[idxLeft]; - int colDown=pixels[idxDown]; - int colRight=pixels[idxRight]; - - // compute luminance - int currLum = - 77*(colOrig>>16&0xff) + 151*(colOrig>>8&0xff) + 28*(colOrig&0xff); - int lumLeft = - 77*(colLeft>>16&0xff) + 151*(colLeft>>8&0xff) + 28*(colLeft&0xff); - int lumRight = - 77*(colRight>>16&0xff) + 151*(colRight>>8&0xff) + 28*(colRight&0xff); - int lumUp = - 77*(colUp>>16&0xff) + 151*(colUp>>8&0xff) + 28*(colUp&0xff); - int lumDown = - 77*(colDown>>16&0xff) + 151*(colDown>>8&0xff) + 28*(colDown&0xff); - - if (lumLeft= maxRowIndex) { + idxRight = index; } + if (idxUp < 0) { + idxUp = index; + } + if (idxDown >= maxIndex) { + idxDown = index; + } + + int colUp = pixels[idxUp]; + int colLeft = pixels[idxLeft]; + int colDown = pixels[idxDown]; + int colRight = pixels[idxRight]; + + // compute luminance + int currLum = + 77*(orig>>16&0xff) + 151*(orig>>8&0xff) + 28*(orig&0xff); + int lumLeft = + 77*(colLeft>>16&0xff) + 151*(colLeft>>8&0xff) + 28*(colLeft&0xff); + int lumRight = + 77*(colRight>>16&0xff) + 151*(colRight>>8&0xff) + 28*(colRight&0xff); + int lumUp = + 77*(colUp>>16&0xff) + 151*(colUp>>8&0xff) + 28*(colUp&0xff); + int lumDown = + 77*(colDown>>16&0xff) + 151*(colDown>>8&0xff) + 28*(colDown&0xff); + + if (lumLeft > currLum) { + result = colLeft; + currLum = lumLeft; + } + if (lumRight > currLum) { + result = colRight; + currLum = lumRight; + } + if (lumUp > currLum) { + result = colUp; + currLum = lumUp; + } + if (lumDown > currLum) { + result = colDown; + currLum = lumDown; + } + outgoing[index++] = result; } } - System.arraycopy(out,0,pixels,0,maxIdx); + System.arraycopy(outgoing, 0, pixels, 0, maxIndex); + } + + + protected void erode() { // formerly dilate(true) + int index = 0; + int maxIndex = pixels.length; + int[] outgoing = new int[maxIndex]; + + // dilate (grow dark areas) + while (index < maxIndex) { + int curRowIndex = index; + int maxRowIndex = index + pixelWidth; + while (index < maxRowIndex) { + int orig = pixels[index]; + int result = orig; + int idxLeft = index - 1; + int idxRight = index + 1; + int idxUp = index - pixelWidth; + int idxDown = index + pixelWidth; + if (idxLeft < curRowIndex) { + idxLeft = index; + } + if (idxRight >= maxRowIndex) { + idxRight = index; + } + if (idxUp < 0) { + idxUp = index; + } + if (idxDown >= maxIndex) { + idxDown = index; + } + + int colUp = pixels[idxUp]; + int colLeft = pixels[idxLeft]; + int colDown = pixels[idxDown]; + int colRight = pixels[idxRight]; + + // compute luminance + int currLum = + 77*(orig>>16&0xff) + 151*(orig>>8&0xff) + 28*(orig&0xff); + int lumLeft = + 77*(colLeft>>16&0xff) + 151*(colLeft>>8&0xff) + 28*(colLeft&0xff); + int lumRight = + 77*(colRight>>16&0xff) + 151*(colRight>>8&0xff) + 28*(colRight&0xff); + int lumUp = + 77*(colUp>>16&0xff) + 151*(colUp>>8&0xff) + 28*(colUp&0xff); + int lumDown = + 77*(colDown>>16&0xff) + 151*(colDown>>8&0xff) + 28*(colDown&0xff); + + if (lumLeft < currLum) { + result = colLeft; + currLum = lumLeft; + } + if (lumRight < currLum) { + result = colRight; + currLum = lumRight; + } + if (lumUp < currLum) { + result = colUp; + currLum = lumUp; + } + if (lumDown < currLum) { + result = colDown; + currLum = lumDown; + } + outgoing[index++] = result; + } + } + System.arraycopy(outgoing, 0, pixels, 0, maxIndex); } @@ -1908,16 +1938,16 @@ public class PImage implements PConstants, Cloneable { if (intersect(sx, sy, sx2, sy2, dx, dy, dx2, dy2)) { blit_resize(get(sx, sy, sx2 - sx, sy2 - sy), 0, 0, sx2 - sx - 1, sy2 - sy - 1, - pixels, width, height, dx, dy, dx2, dy2, mode); + pixels, pixelWidth, pixelHeight, dx, dy, dx2, dy2, mode); } else { // same as below, except skip the loadPixels() because it'd be redundant blit_resize(src, sx, sy, sx2, sy2, - pixels, width, height, dx, dy, dx2, dy2, mode); + pixels, pixelWidth, pixelHeight, dx, dy, dx2, dy2, mode); } } else { src.loadPixels(); blit_resize(src, sx, sy, sx2, sy2, - pixels, width, height, dx, dy, dx2, dy2, mode); + pixels, pixelWidth, pixelHeight, dx, dy, dx2, dy2, mode); //src.updatePixels(); } updatePixels(); @@ -1975,8 +2005,8 @@ public class PImage implements PConstants, Cloneable { int mode) { if (srcX1 < 0) srcX1 = 0; if (srcY1 < 0) srcY1 = 0; - if (srcX2 > img.width) srcX2 = img.width; - if (srcY2 > img.height) srcY2 = img.height; + if (srcX2 > img.pixelWidth) srcX2 = img.pixelWidth; + if (srcY2 > img.pixelHeight) srcY2 = img.pixelHeight; int srcW = srcX2 - srcX1; int srcH = srcY2 - srcY1; @@ -1992,7 +2022,7 @@ public class PImage implements PConstants, Cloneable { if (destW <= 0 || destH <= 0 || srcW <= 0 || srcH <= 0 || destX1 >= screenW || destY1 >= screenH || - srcX1 >= img.width || srcY1 >= img.height) { + srcX1 >= img.pixelWidth || srcY1 >= img.pixelHeight) { return; } @@ -2019,9 +2049,9 @@ public class PImage implements PConstants, Cloneable { if (smooth) { // use bilinear filtering - iw = img.width; - iw1 = img.width - 1; - ih1 = img.height - 1; + iw = img.pixelWidth; + iw1 = img.pixelWidth - 1; + ih1 = img.pixelHeight - 1; switch (mode) { @@ -2230,12 +2260,12 @@ public class PImage implements PConstants, Cloneable { case BLEND: for (int y = 0; y < destH; y++) { sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.width; + sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; for (int x = 0; x < destW; x++) { // davbol - renamed old blend_multiply to blend_blend destPixels[destOffset + x] = blend_blend(destPixels[destOffset + x], - srcBuffer[sY + (sX >> PRECISIONB)]); + srcBuffer[sY + (sX >> PRECISIONB)]); sX += dx; } destOffset += screenW; @@ -2246,7 +2276,7 @@ public class PImage implements PConstants, Cloneable { case ADD: for (int y = 0; y < destH; y++) { sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.width; + sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; for (int x = 0; x < destW; x++) { destPixels[destOffset + x] = blend_add_pin(destPixels[destOffset + x], @@ -2261,7 +2291,7 @@ public class PImage implements PConstants, Cloneable { case SUBTRACT: for (int y = 0; y < destH; y++) { sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.width; + sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; for (int x = 0; x < destW; x++) { destPixels[destOffset + x] = blend_sub_pin(destPixels[destOffset + x], @@ -2276,7 +2306,7 @@ public class PImage implements PConstants, Cloneable { case LIGHTEST: for (int y = 0; y < destH; y++) { sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.width; + sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; for (int x = 0; x < destW; x++) { destPixels[destOffset + x] = blend_lightest(destPixels[destOffset + x], @@ -2291,7 +2321,7 @@ public class PImage implements PConstants, Cloneable { case DARKEST: for (int y = 0; y < destH; y++) { sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.width; + sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; for (int x = 0; x < destW; x++) { destPixels[destOffset + x] = blend_darkest(destPixels[destOffset + x], @@ -2306,7 +2336,7 @@ public class PImage implements PConstants, Cloneable { case REPLACE: for (int y = 0; y < destH; y++) { sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.width; + sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; for (int x = 0; x < destW; x++) { destPixels[destOffset + x] = srcBuffer[sY + (sX >> PRECISIONB)]; sX += dx; @@ -2319,7 +2349,7 @@ public class PImage implements PConstants, Cloneable { case DIFFERENCE: for (int y = 0; y < destH; y++) { sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.width; + sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; for (int x = 0; x < destW; x++) { destPixels[destOffset + x] = blend_difference(destPixels[destOffset + x], @@ -2334,7 +2364,7 @@ public class PImage implements PConstants, Cloneable { case EXCLUSION: for (int y = 0; y < destH; y++) { sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.width; + sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; for (int x = 0; x < destW; x++) { destPixels[destOffset + x] = blend_exclusion(destPixels[destOffset + x], @@ -2349,7 +2379,7 @@ public class PImage implements PConstants, Cloneable { case MULTIPLY: for (int y = 0; y < destH; y++) { sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.width; + sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; for (int x = 0; x < destW; x++) { destPixels[destOffset + x] = blend_multiply(destPixels[destOffset + x], @@ -2364,7 +2394,7 @@ public class PImage implements PConstants, Cloneable { case SCREEN: for (int y = 0; y < destH; y++) { sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.width; + sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; for (int x = 0; x < destW; x++) { destPixels[destOffset + x] = blend_screen(destPixels[destOffset + x], @@ -2379,7 +2409,7 @@ public class PImage implements PConstants, Cloneable { case OVERLAY: for (int y = 0; y < destH; y++) { sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.width; + sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; for (int x = 0; x < destW; x++) { destPixels[destOffset + x] = blend_overlay(destPixels[destOffset + x], @@ -2394,7 +2424,7 @@ public class PImage implements PConstants, Cloneable { case HARD_LIGHT: for (int y = 0; y < destH; y++) { sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.width; + sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; for (int x = 0; x < destW; x++) { destPixels[destOffset + x] = blend_hard_light(destPixels[destOffset + x], @@ -2409,7 +2439,7 @@ public class PImage implements PConstants, Cloneable { case SOFT_LIGHT: for (int y = 0; y < destH; y++) { sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.width; + sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; for (int x = 0; x < destW; x++) { destPixels[destOffset + x] = blend_soft_light(destPixels[destOffset + x], @@ -2425,7 +2455,7 @@ public class PImage implements PConstants, Cloneable { case DODGE: for (int y = 0; y < destH; y++) { sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.width; + sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; for (int x = 0; x < destW; x++) { destPixels[destOffset + x] = blend_dodge(destPixels[destOffset + x], @@ -2440,7 +2470,7 @@ public class PImage implements PConstants, Cloneable { case BURN: for (int y = 0; y < destH; y++) { sX = srcXOffset; - sY = (srcYOffset >> PRECISIONB) * img.width; + sY = (srcYOffset >> PRECISIONB) * img.pixelWidth; for (int x = 0; x < destW; x++) { destPixels[destOffset + x] = blend_burn(destPixels[destOffset + x], @@ -2916,12 +2946,12 @@ public class PImage implements PConstants, Cloneable { byte tiff[] = new byte[768]; System.arraycopy(TIFF_HEADER, 0, tiff, 0, TIFF_HEADER.length); - tiff[30] = (byte) ((width >> 8) & 0xff); - tiff[31] = (byte) ((width) & 0xff); - tiff[42] = tiff[102] = (byte) ((height >> 8) & 0xff); - tiff[43] = tiff[103] = (byte) ((height) & 0xff); + tiff[30] = (byte) ((pixelWidth >> 8) & 0xff); + tiff[31] = (byte) ((pixelWidth) & 0xff); + tiff[42] = tiff[102] = (byte) ((pixelHeight >> 8) & 0xff); + tiff[43] = tiff[103] = (byte) ((pixelHeight) & 0xff); - int count = width*height*3; + int count = pixelWidth*pixelHeight*3; tiff[114] = (byte) ((count >> 24) & 0xff); tiff[115] = (byte) ((count >> 16) & 0xff); tiff[116] = (byte) ((count >> 8) & 0xff); @@ -2985,15 +3015,15 @@ public class PImage implements PConstants, Cloneable { throw new RuntimeException("Image format not recognized inside save()"); } // set image dimensions lo-hi byte order - header[12] = (byte) (width & 0xff); - header[13] = (byte) (width >> 8); - header[14] = (byte) (height & 0xff); - header[15] = (byte) (height >> 8); + header[12] = (byte) (pixelWidth & 0xff); + header[13] = (byte) (pixelWidth >> 8); + header[14] = (byte) (pixelHeight & 0xff); + header[15] = (byte) (pixelHeight >> 8); try { output.write(header); - int maxLen = height * width; + int maxLen = pixelHeight * pixelWidth; int index = 0; int col; //, prevCol; int[] currChunk = new int[128]; @@ -3120,8 +3150,8 @@ public class PImage implements PConstants, Cloneable { outputFormat = BufferedImage.TYPE_INT_RGB; } - BufferedImage bimage = new BufferedImage(width, height, outputFormat); - bimage.setRGB(0, 0, width, height, pixels, 0, width); + BufferedImage bimage = new BufferedImage(pixelWidth, pixelHeight, outputFormat); + bimage.setRGB(0, 0, pixelWidth, pixelHeight, pixels, 0, pixelWidth); File file = new File(path); @@ -3333,4 +3363,3 @@ public class PImage implements PConstants, Cloneable { return success; } } - diff --git a/core/src/processing/core/PSurface.java b/core/src/processing/core/PSurface.java index c5469f6a9..822b66e2b 100644 --- a/core/src/processing/core/PSurface.java +++ b/core/src/processing/core/PSurface.java @@ -48,6 +48,8 @@ public interface PSurface { public Frame initFrame(PApplet sketch, Color backgroundColor, int deviceIndex, boolean fullScreen, boolean spanDisplays); + // + /** Set the window (and dock, or whatever necessary) title. */ public void setTitle(String title); @@ -57,6 +59,8 @@ public interface PSurface { /** Set true if we want to resize things (default is not resizable) */ public void setResizable(boolean resizable); + // + public void placeWindow(int[] location); public void placeWindow(int[] location, int[] editorLocation); @@ -67,6 +71,8 @@ public interface PSurface { // Sketch is running from the PDE, set up messaging back to the PDE public void setupExternalMessages(); + // + /** Start the animation thread */ public void startThread(); @@ -87,6 +93,8 @@ public interface PSurface { public boolean isStopped(); + // + // sets displayWidth/Height inside PApplet //public void checkDisplaySize(); @@ -98,7 +106,7 @@ public interface PSurface { // receive key and mouse events public void requestFocus(); - // finish rendering to the screen + // finish rendering to the screen (called by PApplet) public void blit(); // diff --git a/core/src/processing/core/PSurfaceAWT.java b/core/src/processing/core/PSurfaceAWT.java index 4fc642889..659f5048c 100644 --- a/core/src/processing/core/PSurfaceAWT.java +++ b/core/src/processing/core/PSurfaceAWT.java @@ -786,7 +786,7 @@ public class PSurfaceAWT implements PSurface { // Formerly this was broken into separate versions based on offscreen or // not, but we may as well create a compatible image; it won't hurt, right? graphics.image = gc.createCompatibleImage(wide, high); - System.out.println(graphics.image); +// System.out.println(graphics.image); //throw new RuntimeException("implement me, see readme.md"); sketchWidth = sketch.width = wide; diff --git a/core/todo.txt b/core/todo.txt index 12efc1276..340d0c500 100644 --- a/core/todo.txt +++ b/core/todo.txt @@ -2,6 +2,8 @@ X detect CMYK JPEG images and return null X https://community.oracle.com/thread/1272045?start=0&tstart=0 +_ remove sketch path hack from PApplet + python has to use launch() instead of open() map() is bad for Python (and JavaScript?) @@ -11,6 +13,9 @@ _ https://github.com/processing/processing/issues/2924 _ why doesn't p5 punt when loadFont() is used on an otf? _ is this a GL problem? +_ show warning when display spanning is turned off +_ defaults read com.apple.spaces spans-displays + data X fix XML.getString() with a default when no attrs are present at all X was causing a NullPointerException @@ -36,7 +41,7 @@ X https://github.com/processing/processing/issues/2641 X remove isGL(), is2D(), is3D(), displayable() from PApplet X these were auto-imported from PGraphics X remove pause variable from PApplet (was not documented) -_ remove sketch path hack from PApplet +X added copy() to PImage (to work like get(), ala PVector) pulls X Fix check in loadShader() diff --git a/pdex/src/com/illposed/osc/LICENSE b/pdex/src/com/illposed/osc/LICENSE deleted file mode 100644 index 13b6c5ccb..000000000 --- a/pdex/src/com/illposed/osc/LICENSE +++ /dev/null @@ -1,10 +0,0 @@ -Copyright (c) 2002-2006, C. Ramakrishnan / Illposed Software -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - • Neither the name of the Illposed Software nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pdex/src/com/illposed/osc/OSCBundle.java b/pdex/src/com/illposed/osc/OSCBundle.java deleted file mode 100644 index 5ce38235e..000000000 --- a/pdex/src/com/illposed/osc/OSCBundle.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2003-2006, C. Ramakrishnan / Illposed Software. - * All rights reserved. - * - * This code is licensed under the BSD 3-Clause license. - * See file LICENSE (or LICENSE.html) for more information. - */ - -package com.illposed.osc; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Date; -import java.util.LinkedList; -import java.util.List; - -import com.illposed.osc.utility.OSCJavaToByteArrayConverter; - -/** - * A bundle represents a collection of OSC packets - * (either messages or other bundles) - * and has a time-tag which can be used by a scheduler to execute - * a bundle in the future, - * instead of immediately. - * {@link OSCMessage}s are executed immediately. - * - * Bundles should be used if you want to send multiple messages to be executed - * atomically together, or you want to schedule one or more messages to be - * executed in the future. - * - * @author Chandrasekhar Ramakrishnan - */ -public class OSCBundle extends OSCPacket { - - /** - * 2208988800 seconds -- includes 17 leap years - */ - public static final BigInteger SECONDS_FROM_1900_TO_1970 = - new BigInteger("2208988800"); - - /** - * The Java representation of an OSC timestamp with the semantics of - * "immediately". - */ - public static final Date TIMESTAMP_IMMEDIATE = new Date(0); - - private Date timestamp; - private List packets; - - /** - * Create a new empty OSCBundle with a timestamp of immediately. - * You can add packets to the bundle with addPacket() - */ - public OSCBundle() { - this(TIMESTAMP_IMMEDIATE); - } - - /** - * Create an OSCBundle with the specified timestamp. - * @param timestamp the time to execute the bundle - */ - public OSCBundle(Date timestamp) { - this((Collection) null, timestamp); - } - - // deprecated since version 1.0, March 2012 - /** - * Creates an OSCBundle made up of the given packets - * with a timestamp of now. - * @param packets array of OSCPackets to initialize this object with - * @deprecated - */ - public OSCBundle(OSCPacket[] packets) { - this(packets, TIMESTAMP_IMMEDIATE); - } - - /** - * Creates an OSCBundle made up of the given packets - * with a timestamp of now. - * @param packets array of OSCPackets to initialize this object with - */ - public OSCBundle(Collection packets) { - this(packets, TIMESTAMP_IMMEDIATE); - } - - // deprecated since version 1.0, March 2012 - /** - * Creates an OSCBundle, specifying the packets and timestamp. - * @param packets the packets that make up the bundle - * @param timestamp the time to execute the bundle - * @deprecated - */ - public OSCBundle(OSCPacket[] packets, Date timestamp) { - this((packets == null) - ? new LinkedList() - : Arrays.asList(packets), - timestamp); - } - - /** - * Create an OSCBundle, specifying the packets and timestamp. - * @param packets the packets that make up the bundle - * @param timestamp the time to execute the bundle - */ - public OSCBundle(Collection packets, Date timestamp) { - - if (null == packets) { - this.packets = new LinkedList(); - } else { - this.packets = new ArrayList(packets); - } - this.timestamp = timestamp; - init(); - } - - /** - * Return the time the bundle will execute. - * @return a Date - */ - public Date getTimestamp() { - return timestamp; - } - - /** - * Set the time the bundle will execute. - * @param timestamp Date - */ - public void setTimestamp(Date timestamp) { - this.timestamp = timestamp; - } - - /** - * Add a packet to the list of packets in this bundle. - * @param packet OSCMessage or OSCBundle - */ - public void addPacket(OSCPacket packet) { - packets.add(packet); - } - - /** - * Get the packets contained in this bundle. - * @return the packets contained in this bundle. - */ - public OSCPacket[] getPackets() { - OSCPacket[] packetArray = new OSCPacket[packets.size()]; - packets.toArray(packetArray); - return packetArray; - } - - /** - * Convert the time-tag (a Java Date) into the OSC byte stream. - * Used Internally. - */ - protected void computeTimeTagByteArray(OSCJavaToByteArrayConverter stream) { - if ((null == timestamp) || (timestamp == TIMESTAMP_IMMEDIATE)) { - stream.write(0); - stream.write(1); - return; - } - - long millisecs = timestamp.getTime(); - long secsSince1970 = millisecs / 1000; - long secs = secsSince1970 + SECONDS_FROM_1900_TO_1970.longValue(); - - // this line was cribbed from jakarta commons-net's NTP TimeStamp code - long fraction = ((millisecs % 1000) * 0x100000000L) / 1000; - - stream.write((int) secs); - stream.write((int) fraction); - } - - /** - * Compute the OSC byte stream representation of the bundle. - * Used Internally. - * @param stream OscPacketByteArrayConverter - */ - protected byte[] computeByteArray(OSCJavaToByteArrayConverter stream) { - stream.write("#bundle"); - computeTimeTagByteArray(stream); - byte[] packetBytes; - for (OSCPacket pkg : packets) { - packetBytes = pkg.getByteArray(); - stream.write(packetBytes.length); - stream.write(packetBytes); - } - return stream.toByteArray(); - } -} diff --git a/pdex/src/com/illposed/osc/OSCListener.java b/pdex/src/com/illposed/osc/OSCListener.java deleted file mode 100644 index d65cc9130..000000000 --- a/pdex/src/com/illposed/osc/OSCListener.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2003-2006, C. Ramakrishnan / Illposed Software. - * All rights reserved. - * - * This code is licensed under the BSD 3-Clause license. - * See file LICENSE (or LICENSE.html) for more information. - */ - -package com.illposed.osc; - -import java.util.Date; - -/** - * Interface for things that listen for incoming OSC Messages - * - * @author Chandrasekhar Ramakrishnan - */ -public interface OSCListener { - - /** - * Accept an incoming OSCMessage - * @param time The time this message is to be executed. - * null means execute now - * @param message The message to execute. - */ - public void acceptMessage(Date time, OSCMessage message); - -} diff --git a/pdex/src/com/illposed/osc/OSCMessage.java b/pdex/src/com/illposed/osc/OSCMessage.java deleted file mode 100644 index a57020ec8..000000000 --- a/pdex/src/com/illposed/osc/OSCMessage.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2003-2006, C. Ramakrishnan / Illposed Software. - * All rights reserved. - * - * This code is licensed under the BSD 3-Clause license. - * See file LICENSE (or LICENSE.html) for more information. - */ - -package com.illposed.osc; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; - -import com.illposed.osc.utility.OSCJavaToByteArrayConverter; - -/** - * An simple (non-bundle) OSC message. - * - * An OSC message is made up of an address (the receiver of the message) - * and arguments (the content of the message). - * - * @author Chandrasekhar Ramakrishnan - */ -public class OSCMessage extends OSCPacket { - - private String address; - private List arguments; - - /** - * Creates an empty OSC Message. - * In order to send this OSC message, - * you need to set the address and optionally some arguments. - */ - public OSCMessage() { - arguments = new LinkedList(); - } - - /** - * Creates an OSCMessage with an address already initialized. - * @param address the recipient of this OSC message - */ - public OSCMessage(String address) { - this(address, (Collection) null); - } - - // deprecated since version 1.0, March 2012 - /** - * Creates an OSCMessage with an address and arguments already initialized. - * @param address the recipient of this OSC message - * @param arguments the data sent to the receiver - * @deprecated - */ - public OSCMessage(String address, Object[] arguments) { - - this.address = address; - if (arguments == null) { - this.arguments = new LinkedList(); - } else { - this.arguments = new ArrayList(arguments.length); - this.arguments.addAll(Arrays.asList(arguments)); - } - init(); - } - - /** - * Creates an OSCMessage with an address - * and arguments already initialized. - * @param address the recipient of this OSC message - * @param arguments the data sent to the receiver - */ - public OSCMessage(String address, Collection arguments) { - - this.address = address; - if (arguments == null) { - this.arguments = new LinkedList(); - } else { - this.arguments = new ArrayList(arguments); - } - init(); - } - - /** - * The receiver of this message. - * @return the receiver of this OSC Message - */ - public String getAddress() { - return address; - } - - /** - * Set the address of this message. - * @param address the receiver of the message - */ - public void setAddress(String address) { - this.address = address; - } - - /** - * Add an argument to the list of arguments. - * @param argument a Float, String, Integer, BigInteger, Boolean - * or an array of these - */ - public void addArgument(Object argument) { - arguments.add(argument); - } - - /** - * The arguments of this message. - * @return the arguments to this message - */ - public Object[] getArguments() { - return arguments.toArray(); - } - - /** - * Convert the address into a byte array. - * Used internally only. - */ - protected void computeAddressByteArray(OSCJavaToByteArrayConverter stream) { - stream.write(address); - } - - /** - * Convert the arguments into a byte array. - * Used internally only. - */ - protected void computeArgumentsByteArray(OSCJavaToByteArrayConverter stream) { - stream.write(','); - if (null == arguments) { - return; - } - stream.writeTypes(arguments); - for (Object argument : arguments) { - stream.write(argument); - } - } - - /** - * Convert the message into a byte array. - * Used internally only. - */ - protected byte[] computeByteArray(OSCJavaToByteArrayConverter stream) { - computeAddressByteArray(stream); - computeArgumentsByteArray(stream); - return stream.toByteArray(); - } -} diff --git a/pdex/src/com/illposed/osc/OSCPacket.java b/pdex/src/com/illposed/osc/OSCPacket.java deleted file mode 100644 index e19524767..000000000 --- a/pdex/src/com/illposed/osc/OSCPacket.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2003-2006, C. Ramakrishnan / Illposed Software. - * All rights reserved. - * - * This code is licensed under the BSD 3-Clause license. - * See file LICENSE (or LICENSE.html) for more information. - */ - -package com.illposed.osc; - -import com.illposed.osc.utility.OSCJavaToByteArrayConverter; - -/** - * OSCPacket is the abstract superclass for the various - * kinds of OSC Messages. - * - * The actual packets are: - *
    - *
  • {@link OSCMessage}: simple OSC messages - *
  • {@link OSCBundle}: OSC messages with timestamps - * and/or made up of multiple messages - *
- * - * This implementation is based on - * Markus Gaelli and - * Iannis Zannos' OSC implementation in Squeak Smalltalk. - */ -public abstract class OSCPacket { - - private boolean isByteArrayComputed; - private byte[] byteArray; - - /** - * Default constructor for the abstract class - */ - public OSCPacket() { - } - - /** - * Generate a representation of this packet conforming to the - * the OSC byte stream specification. Used Internally. - */ - protected byte[] computeByteArray() { - OSCJavaToByteArrayConverter stream = new OSCJavaToByteArrayConverter(); - return computeByteArray(stream); - } - - /** - * Subclasses should implement this method to product a byte array - * formatted according to the OSC specification. - * @param stream OscPacketByteArrayConverter - */ - protected abstract byte[] computeByteArray(OSCJavaToByteArrayConverter stream); - - /** - * Return the OSC byte stream for this packet. - * @return byte[] - */ - public byte[] getByteArray() { - if (!isByteArrayComputed) { - byteArray = computeByteArray(); - } - return byteArray; - } - - /** - * Run any post construction initialization. (By default, do nothing.) - */ - protected void init() { - - } -} diff --git a/pdex/src/com/illposed/osc/OSCPort.java b/pdex/src/com/illposed/osc/OSCPort.java deleted file mode 100644 index 9d3f38f14..000000000 --- a/pdex/src/com/illposed/osc/OSCPort.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2003-2006, C. Ramakrishnan / Illposed Software. - * All rights reserved. - * - * This code is licensed under the BSD 3-Clause license. - * See file LICENSE (or LICENSE.html) for more information. - */ - -package com.illposed.osc; - -import java.net.DatagramSocket; - -/** - * OSCPort is an abstract superclass, to send OSC messages, - * use {@link OSCPortOut}. - * To listen for OSC messages, use {@link OSCPortIn}. - * - * @author Chandrasekhar Ramakrishnan - */ -public abstract class OSCPort { - - private DatagramSocket socket; - private int port; - - public static final int DEFAULT_SC_OSC_PORT = 57110; - public static final int DEFAULT_SC_LANG_OSC_PORT = 57120; - - protected OSCPort(DatagramSocket socket, int port) { - this.socket = socket; - this.port = port; - } - - /** - * The port that the SuperCollider synth engine - * usually listens to. - * @see #DEFAULT_SC_OSC_PORT - */ - public static int defaultSCOSCPort() { - return DEFAULT_SC_OSC_PORT; - } - - /** - * The port that the SuperCollider language engine - * usually listens to. - * @see #DEFAULT_SC_LANG_OSC_PORT - */ - public static int defaultSCLangOSCPort() { - return DEFAULT_SC_LANG_OSC_PORT; - } - - /** - * Returns the socket associated with this port. - * @return this ports socket - */ - protected DatagramSocket getSocket() { - return socket; - } - - /** - * Returns the port number associated with this port. - * @return this ports number - */ - protected int getPort() { - return port; - } - - /** - * Close the socket if this hasn't already happened. - * @see java.lang.Object#finalize() - */ - protected void finalize() throws Throwable { - super.finalize(); - socket.close(); - } - - /** - * Close the socket and free-up resources. - * It is recommended that clients call this when they are done with the - * port. - */ - public void close() { - socket.close(); - } -} diff --git a/pdex/src/com/illposed/osc/OSCPortIn.java b/pdex/src/com/illposed/osc/OSCPortIn.java deleted file mode 100644 index ca252675f..000000000 --- a/pdex/src/com/illposed/osc/OSCPortIn.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2004-2006, C. Ramakrishnan / Illposed Software. - * All rights reserved. - * - * This code is licensed under the BSD 3-Clause license. - * See file LICENSE (or LICENSE.html) for more information. - */ - -package com.illposed.osc; - -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.io.IOException; -import java.net.SocketException; - -import com.illposed.osc.utility.OSCByteArrayToJavaConverter; -import com.illposed.osc.utility.OSCPacketDispatcher; - -/** - * OSCPortIn is the class that listens for OSC messages. - * - * An example based on - * {@link com.illposed.osc.OSCPortTest#testReceiving()}: - *
-
-	receiver = new OSCPortIn(OSCPort.DEFAULT_SC_OSC_PORT());
-	OSCListener listener = new OSCListener() {
-		public void acceptMessage(java.util.Date time, OSCMessage message) {
-			System.out.println("Message received!");
-		}
-	};
-	receiver.addListener("/message/receiving", listener);
-	receiver.startListening();
-
- * 
- * - * Then, using a program such as SuperCollider or sendOSC, send a message - * to this computer, port {@link #DEFAULT_SC_OSC_PORT}, - * with the address "/message/receiving". - * - * @author Chandrasekhar Ramakrishnan - */ -public class OSCPortIn extends OSCPort implements Runnable { - - // state for listening - private boolean listening; - private OSCByteArrayToJavaConverter converter - = new OSCByteArrayToJavaConverter(); - private OSCPacketDispatcher dispatcher = new OSCPacketDispatcher(); - - /** - * Create an OSCPort that listens on the specified port. - * @param port UDP port to listen on. - * @throws SocketException - */ - public OSCPortIn(int port) throws SocketException { - super(new DatagramSocket(port), port); - } - - /** - * Buffers were 1500 bytes in size, but were - * increased to 1536, as this is a common MTU. - */ - private static final int BUFFER_SIZE = 1536; - - /** - * Run the loop that listens for OSC on a socket until - * {@link #isListening()} becomes false. - * @see java.lang.Runnable#run() - */ - public void run() { - byte[] buffer = new byte[BUFFER_SIZE]; - DatagramPacket packet = new DatagramPacket(buffer, BUFFER_SIZE); - DatagramSocket socket = getSocket(); - while (listening) { - try { - try { - socket.receive(packet); - } catch (SocketException ex) { - if (listening) { - throw ex; - } else { - // if we closed the socket while receiving data, - // the exception is expected/normal, so we hide it - continue; - } - } - OSCPacket oscPacket = converter.convert(buffer, - packet.getLength()); - dispatcher.dispatchPacket(oscPacket); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - /** - * Start listening for incoming OSCPackets - */ - public void startListening() { - listening = true; - Thread thread = new Thread(this); - thread.start(); - } - - /** - * Stop listening for incoming OSCPackets - */ - public void stopListening() { - listening = false; - } - - /** - * Am I listening for packets? - */ - public boolean isListening() { - return listening; - } - - /** - * Register the listener for incoming OSCPackets addressed to an Address - * @param anAddress the address to listen for. The address can be specified as a regex, e.g., "/m.*e/receiving" - * @param listener the object to invoke when a message comes in - */ - public void addListener(String anAddress, OSCListener listener) { - dispatcher.addListener(anAddress, listener); - } -} diff --git a/pdex/src/com/illposed/osc/OSCPortOut.java b/pdex/src/com/illposed/osc/OSCPortOut.java deleted file mode 100644 index 7dbe05dc8..000000000 --- a/pdex/src/com/illposed/osc/OSCPortOut.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2004-2006, C. Ramakrishnan / Illposed Software. - * All rights reserved. - * - * This code is licensed under the BSD 3-Clause license. - * See file LICENSE (or LICENSE.html) for more information. - */ - -package com.illposed.osc; - -import java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.net.SocketException; -import java.net.UnknownHostException; - -/** - * OSCPortOut is the class that sends OSC messages - * to a specific address and port. - * - * To send an OSC message, call send(). - * - * An example based on - * {@link com.illposed.osc.OSCPortTest#testMessageWithArgs()}: - *
-	OSCPort sender = new OSCPort();
-	Object args[] = new Object[2];
-	args[0] = new Integer(3);
-	args[1] = "hello";
-	OSCMessage msg = new OSCMessage("/sayhello", args);
-	 try {
-		sender.send(msg);
-	 } catch (Exception e) {
-		 showError("Couldn't send");
-	 }
- * 
- * - * @author Chandrasekhar Ramakrishnan - */ -public class OSCPortOut extends OSCPort { - - private InetAddress address; - - /** - * Create an OSCPort that sends to address:port. - * @param address the UDP address to send to - * @param port the UDP port to send to - */ - public OSCPortOut(InetAddress address, int port) - throws SocketException - { - super(new DatagramSocket(), port); - this.address = address; - } - - /** - * Create an OSCPort that sends to address, - * using the standard SuperCollider port. - * @param address the UDP address to send to - */ - public OSCPortOut(InetAddress address) throws SocketException { - this(address, DEFAULT_SC_OSC_PORT); - } - - /** - * Create an OSCPort that sends to "localhost", - * on the standard SuperCollider port. - */ - public OSCPortOut() throws UnknownHostException, SocketException { - this(InetAddress.getLocalHost(), DEFAULT_SC_OSC_PORT); - } - - /** - * Send an OSC packet (message or bundle) to the receiver we are bound to. - * @param aPacket the bundle or message to send - */ - public void send(OSCPacket aPacket) throws IOException { - byte[] byteArray = aPacket.getByteArray(); - DatagramPacket packet = - new DatagramPacket(byteArray, byteArray.length, address, getPort()); - getSocket().send(packet); - } -} diff --git a/pdex/src/com/illposed/osc/utility/OSCByteArrayToJavaConverter.java b/pdex/src/com/illposed/osc/utility/OSCByteArrayToJavaConverter.java deleted file mode 100644 index 803ea65c1..000000000 --- a/pdex/src/com/illposed/osc/utility/OSCByteArrayToJavaConverter.java +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright (C) 2004-2006, C. Ramakrishnan / Illposed Software. - * All rights reserved. - * - * This code is licensed under the BSD 3-Clause license. - * See file LICENSE (or LICENSE.html) for more information. - */ - -package com.illposed.osc.utility; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import com.illposed.osc.OSCBundle; -import com.illposed.osc.OSCMessage; -import com.illposed.osc.OSCPacket; - -/** - * Utility class to convert a byte array, - * conforming to the OSC byte stream format, - * into Java objects. - * - * @author Chandrasekhar Ramakrishnan - */ -public class OSCByteArrayToJavaConverter { - - private byte[] bytes; - private int bytesLength; - private int streamPosition; - - /** - * Creates a helper object for converting from a byte array - * to an {@link OSCPacket} object. - */ - public OSCByteArrayToJavaConverter() { - } - - /** - * Converts a byte array into an {@link OSCPacket} - * (either an {@link OSCMessage} or {@link OSCBundle}). - */ - public OSCPacket convert(byte[] byteArray, int bytesLength) { - this.bytes = byteArray; - this.bytesLength = bytesLength; - this.streamPosition = 0; - if (isBundle()) { - return convertBundle(); - } else { - return convertMessage(); - } - } - - /** - * Is my byte array a bundle? - * @return true if it the byte array is a bundle, false o.w. - */ - private boolean isBundle() { - // only need the first 7 to check if it is a bundle - String bytesAsString = new String(bytes, 0, 7); - return bytesAsString.startsWith("#bundle"); - } - - /** - * Converts the byte array to a bundle. - * Assumes that the byte array is a bundle. - * @return a bundle containing the data specified in the byte stream - */ - private OSCBundle convertBundle() { - // skip the "#bundle " stuff - streamPosition = 8; - Date timestamp = readTimeTag(); - OSCBundle bundle = new OSCBundle(timestamp); - OSCByteArrayToJavaConverter myConverter - = new OSCByteArrayToJavaConverter(); - while (streamPosition < bytesLength) { - // recursively read through the stream and convert packets you find - int packetLength = ((Integer) readInteger()).intValue(); - byte[] packetBytes = new byte[packetLength]; - for (int i = 0; i < packetLength; i++) { - packetBytes[i] = bytes[streamPosition++]; - } - OSCPacket packet = myConverter.convert(packetBytes, packetLength); - bundle.addPacket(packet); - } - return bundle; - } - - /** - * Converts the byte array to a simple message. - * Assumes that the byte array is a message. - * @return a message containing the data specified in the byte stream - */ - private OSCMessage convertMessage() { - OSCMessage message = new OSCMessage(); - message.setAddress(readString()); - List types = readTypes(); - if (null == types) { - // we are done - return message; - } - moveToFourByteBoundry(); - for (int i = 0; i < types.size(); ++i) { - if ('[' == types.get(i).charValue()) { - // we're looking at an array -- read it in - message.addArgument(readArray(types, ++i).toArray()); - // then increment i to the end of the array - while (types.get(i).charValue() != ']') { - i++; - } - } else { - message.addArgument(readArgument(types.get(i))); - } - } - return message; - } - - /** - * Reads a string from the byte stream. - * @return the next string in the byte stream - */ - private String readString() { - int strLen = lengthOfCurrentString(); - char[] stringChars = new char[strLen]; - for (int i = 0; i < strLen; i++) { - stringChars[i] = (char) bytes[streamPosition++]; - } - moveToFourByteBoundry(); - return new String(stringChars); - } - - /** - * Reads the types of the arguments from the byte stream. - * @return a char array with the types of the arguments - */ - private List readTypes() { - // the next byte should be a ',' - if (bytes[streamPosition] != 0x2C) { - return null; - } - streamPosition++; - // find out how long the list of types is - int typesLen = lengthOfCurrentString(); - if (0 == typesLen) { - return null; - } - - // read in the types - List typesChars = new ArrayList(typesLen); - for (int i = 0; i < typesLen; i++) { - typesChars.add((char) bytes[streamPosition++]); - } - return typesChars; - } - - /** - * Reads an object of the type specified by the type char. - * @param type type of the argument to read - * @return a Java representation of the argument - */ - private Object readArgument(char type) { - switch (type) { - case 'i' : - return readInteger(); - case 'h' : - return readBigInteger(); - case 'f' : - return readFloat(); - case 'd' : - return readDouble(); - case 's' : - return readString(); - case 'c' : - return readChar(); - case 'T' : - return Boolean.TRUE; - case 'F' : - return Boolean.FALSE; - case 't' : - return readTimeTag(); - default: - return null; - } - } - - /** - * Reads a char from the byte stream. - * @return a {@link Character} - */ - private Object readChar() { - return new Character((char) bytes[streamPosition++]); - } - - /** - * Reads a double from the byte stream. - * This just reads a float. - * @return a {@link Double} - */ - private Object readDouble() { - return readFloat(); - } - - /** - * Reads a float from the byte stream. - * @return a {@link Float} - */ - private Object readFloat() { - byte[] floatBytes = new byte[4]; - floatBytes[0] = bytes[streamPosition++]; - floatBytes[1] = bytes[streamPosition++]; - floatBytes[2] = bytes[streamPosition++]; - floatBytes[3] = bytes[streamPosition++]; -// int floatBits = -// (floatBytes[0] << 24) -// | (floatBytes[1] << 16) -// | (floatBytes[2] << 8) -// | (floatBytes[3]); - BigInteger floatBits = new BigInteger(floatBytes); - return new Float(Float.intBitsToFloat(floatBits.intValue())); - } - - /** - * Reads a Big Integer (64 bit integer) from the byte stream. - * @return a {@link BigInteger} - */ - private Object readBigInteger() { - byte[] longintBytes = new byte[8]; - longintBytes[0] = bytes[streamPosition++]; - longintBytes[1] = bytes[streamPosition++]; - longintBytes[2] = bytes[streamPosition++]; - longintBytes[3] = bytes[streamPosition++]; - longintBytes[4] = bytes[streamPosition++]; - longintBytes[5] = bytes[streamPosition++]; - longintBytes[6] = bytes[streamPosition++]; - longintBytes[7] = bytes[streamPosition++]; - return new BigInteger(longintBytes); - } - - /** - * Reads an Integer (32 bit integer) from the byte stream. - * @return an {@link Integer} - */ - private Object readInteger() { - byte[] intBytes = new byte[4]; - intBytes[0] = bytes[streamPosition++]; - intBytes[1] = bytes[streamPosition++]; - intBytes[2] = bytes[streamPosition++]; - intBytes[3] = bytes[streamPosition++]; - BigInteger intBits = new BigInteger(intBytes); - return Integer.valueOf(intBits.intValue()); - } - - /** - * Reads the time tag and convert it to a Java Date object. - * A timestamp is a 64 bit number representing the time in NTP format. - * The first 32 bits are seconds since 1900, the second 32 bits are - * fractions of a second. - * @return a {@link Date} - */ - private Date readTimeTag() { - byte[] secondBytes = new byte[8]; - byte[] fractionBytes = new byte[8]; - for (int i = 0; i < 4; i++) { - // clear the higher order 4 bytes - secondBytes[i] = 0; fractionBytes[i] = 0; - } - // while reading in the seconds & fraction, check if - // this timetag has immediate semantics - boolean isImmediate = true; - for (int i = 4; i < 8; i++) { - secondBytes[i] = bytes[streamPosition++]; - if (secondBytes[i] > 0) { - isImmediate = false; - } - } - for (int i = 4; i < 8; i++) { - fractionBytes[i] = bytes[streamPosition++]; - if (i < 7) { - if (fractionBytes[i] > 0) { - isImmediate = false; - } - } else { - if (fractionBytes[i] > 1) { - isImmediate = false; - } - } - } - - if (isImmediate) { - return OSCBundle.TIMESTAMP_IMMEDIATE; - } - - BigInteger secsSince1900 = new BigInteger(secondBytes); - long secsSince1970 = secsSince1900.longValue() - - OSCBundle.SECONDS_FROM_1900_TO_1970.longValue(); - - // no point maintaining times in the distant past - if (secsSince1970 < 0) { - secsSince1970 = 0; - } - long fraction = (new BigInteger(fractionBytes).longValue()); - - // this line was cribbed from jakarta commons-net's NTP TimeStamp code - fraction = (fraction * 1000) / 0x100000000L; - - // I do not know where, but I'm losing 1ms somewhere... - fraction = (fraction > 0) ? fraction + 1 : 0; - long millisecs = (secsSince1970 * 1000) + fraction; - return new Date(millisecs); - } - - /** - * Reads an array from the byte stream. - * @param types - * @param pos at which position to start reading - * @return the array that was read - */ - private List readArray(List types, int pos) { - int arrayLen = 0; - while (types.get(pos + arrayLen).charValue() != ']') { - arrayLen++; - } - List array = new ArrayList(arrayLen); - for (int j = 0; j < arrayLen; j++) { - array.add(readArgument(types.get(pos + j))); - } - return array; - } - - /** - * Get the length of the string currently in the byte stream. - */ - private int lengthOfCurrentString() { - int i = 0; - while (bytes[streamPosition + i] != 0) { - i++; - } - return i; - } - - /** - * Move to the next byte with an index in the byte array - * which is dividable by four. - */ - private void moveToFourByteBoundry() { - // If i am already at a 4 byte boundry, I need to move to the next one - int mod = streamPosition % 4; - streamPosition += (4 - mod); - } -} diff --git a/pdex/src/com/illposed/osc/utility/OSCJavaToByteArrayConverter.java b/pdex/src/com/illposed/osc/utility/OSCJavaToByteArrayConverter.java deleted file mode 100644 index ae1bea03a..000000000 --- a/pdex/src/com/illposed/osc/utility/OSCJavaToByteArrayConverter.java +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (C) 2003-2006, C. Ramakrishnan / Illposed Software. - * All rights reserved. - * - * This code is licensed under the BSD 3-Clause license. - * See file LICENSE (or LICENSE.html) for more information. - */ - -package com.illposed.osc.utility; - -import java.io.IOException; -import java.io.ByteArrayOutputStream; -import java.math.BigInteger; -import java.util.Collection; - -/** - * OSCJavaToByteArrayConverter is a helper class that translates - * from Java types to their byte stream representations according to - * the OSC spec. - * - * The implementation is based on - * Markus Gaelli and - * Iannis Zannos' OSC implementation in Squeak. - * - * This version includes bug fixes and improvements from - * Martin Kaltenbrunner and Alex Potsides. - * - * @author Chandrasekhar Ramakrishnan - * @author Martin Kaltenbrunner - * @author Alex Potsides - */ -public class OSCJavaToByteArrayConverter { - - private ByteArrayOutputStream stream = new ByteArrayOutputStream(); - private byte[] intBytes = new byte[4]; - private byte[] longintBytes = new byte[8]; - - public OSCJavaToByteArrayConverter() { - } - - /** - * Line up the Big end of the bytes to a 4 byte boundary. - * @return byte[] - * @param bytes byte[] - */ - private byte[] alignBigEndToFourByteBoundry(byte[] bytes) { - int mod = bytes.length % 4; - // if the remainder == 0 then return the bytes otherwise pad the bytes - // to lineup correctly - if (mod == 0) { - return bytes; - } - int pad = 4 - mod; - byte[] newBytes = new byte[pad + bytes.length]; -// for (int i = 0; i < pad; i++) -// newBytes[i] = 0; -// for (int i = 0; i < bytes.length; i++) -// newBytes[pad + i] = bytes[i]; - System.arraycopy(bytes, 0, newBytes, pad, bytes.length); - return newBytes; - } - - /** - * Pad the stream to have a size divisible by 4. - */ - public void appendNullCharToAlignStream() { - int mod = stream.size() % 4; - int pad = 4 - mod; - for (int i = 0; i < pad; i++) { - stream.write(0); - } - } - - /** - * Convert the contents of the output stream to a byte array. - * @return the byte array containing the byte stream - */ - public byte[] toByteArray() { - return stream.toByteArray(); - } - - /** - * Write bytes into the byte stream. - * @param bytes bytes to be written - */ - public void write(byte[] bytes) { - writeUnderHandler(bytes); - } - - /** - * Write an integer into the byte stream. - * @param i the integer to be written - */ - public void write(int i) { - writeInteger32ToByteArray(i); - } - - /** - * Write a float into the byte stream. - * @param f floating point number to be written - */ - public void write(Float f) { - writeInteger32ToByteArray(Float.floatToIntBits(f.floatValue())); - } - - /** - * @param i the integer to be written - */ - public void write(Integer i) { - writeInteger32ToByteArray(i.intValue()); - } - - /** - * @param i the integer to be written - */ - public void write(BigInteger i) { - writeInteger64ToByteArray(i.longValue()); - } - - /** - * Write a string into the byte stream. - * @param aString the string to be written - */ - public void write(String aString) { -/* - XXX to be revised ... - int stringLength = aString.length(); - // this is a deprecated method -- should use get char and convert - // the chars to bytes -// aString.getBytes(0, stringLength, stringBytes, 0); - aString.getChars(0, stringLength, stringChars, 0); - // pad out to align on 4 byte boundry - int mod = stringLength % 4; - int pad = 4 - mod; - for (int i = 0; i < pad; i++) - stringChars[stringLength++] = 0; - // convert the chars into bytes and write them out - for (int i = 0; i < stringLength; i++) { - stringBytes[i] = (byte) (stringChars[i] & 0x00FF); - } - stream.write(stringBytes, 0, stringLength); -*/ - byte[] stringBytes = aString.getBytes(); - - // pad out to align on 4 byte boundry - int mod = aString.length() % 4; - int pad = 4 - mod; - - byte[] newBytes = new byte[pad + stringBytes.length]; - System.arraycopy(stringBytes, 0, newBytes, 0, stringBytes.length); - - try { - stream.write(newBytes); - } catch (IOException e) { - throw new RuntimeException("You're screwed:" - + " IOException writing to a ByteArrayOutputStream", e); - } - } - - /** - * Write a char into the byte stream. - * @param c the character to be written - */ - public void write(char c) { - stream.write(c); - } - - /** - * Write an object into the byte stream. - * @param anObject one of Float, String, Integer, BigInteger, or array of - * these. - */ - public void write(Object anObject) { - // Can't do switch on class - if (null == anObject) { - } else if (anObject instanceof Object[]) { - Object[] theArray = (Object[]) anObject; - for (int i = 0; i < theArray.length; ++i) { - write(theArray[i]); - } - } else if (anObject instanceof Float) { - write((Float) anObject); - } else if (anObject instanceof String) { - write((String) anObject); - } else if (anObject instanceof Integer) { - write((Integer) anObject); - } else if (anObject instanceof BigInteger) { - write((BigInteger) anObject); - } - } - - /** - * Write the type tag for the type represented by the class - * @param c Class of a Java object in the arguments - */ - public void writeType(Class c) { - // A big ol' case statement -- what's polymorphism mean, again? - // I really wish I could extend the base classes! - - // use the appropriate flags to tell SuperCollider what kind of - // thing it is looking at - - if (Integer.class.equals(c)) { - stream.write('i'); - } else if (java.math.BigInteger.class.equals(c)) { - stream.write('h'); - } else if (Float.class.equals(c)) { - stream.write('f'); - } else if (Double.class.equals(c)) { - stream.write('d'); - } else if (String.class.equals(c)) { - stream.write('s'); - } else if (Character.class.equals(c)) { - stream.write('c'); - } - } - - /** - * Write the types for an array element in the arguments. - * @param array array of base Objects - */ - public void writeTypesArray(Object[] array) { - // A big ol' case statement in a for loop -- what's polymorphism mean, - // again? - // I really wish I could extend the base classes! - - for (int i = 0; i < array.length; i++) { - if (array[i] == null) { - } else if (Boolean.TRUE.equals(array[i])) { - // Create a way to deal with Boolean type objects - stream.write('T'); - } else if (Boolean.FALSE.equals(array[i])) { - stream.write('F'); - } else { - // this is an object -- write the type for the class - writeType(array[i].getClass()); - } - } - } - - /** - * Write types for the arguments. - * @param types the arguments to an OSCMessage - */ - public void writeTypes(Collection types) { - // A big ol' case statement in a for loop -- what's polymorphism mean, - // again? - // I really wish I could extend the base classes! - - for (Object type : types) { - if (null == type) { - continue; - } - // if the array at i is a type of array write a [ - // This is used for nested arguments - if (type.getClass().isArray()) { - stream.write('['); - // fill the [] with the SuperCollider types corresponding to - // the object (e.g., Object of type String needs -s). - writeTypesArray((Object[]) type); - // close the array - stream.write(']'); - continue; - } - // Create a way to deal with Boolean type objects - if (Boolean.TRUE.equals(type)) { - stream.write('T'); - continue; - } - if (Boolean.FALSE.equals(type)) { - stream.write('F'); - continue; - } - // go through the array and write the superCollider types as shown - // in the above method. - // The classes derived here are used as the arg to the above method. - writeType(type.getClass()); - } - // align the stream with padded bytes - appendNullCharToAlignStream(); - } - - /** - * Write bytes to the stream, catching IOExceptions and converting them to - * RuntimeExceptions. - * @param bytes byte[] - */ - private void writeUnderHandler(byte[] bytes) { - - try { - stream.write(alignBigEndToFourByteBoundry(bytes)); - } catch (IOException e) { - throw new RuntimeException("You're screwed:" - + " IOException writing to a ByteArrayOutputStream"); - } - } - - /** - * Write a 32 bit integer to the byte array without allocating memory. - * @param value a 32 bit integer. - */ - private void writeInteger32ToByteArray(int value) { - //byte[] intBytes = new byte[4]; - //I allocated the this buffer globally so the GC has less work - - intBytes[3] = (byte)value; value >>>= 8; - intBytes[2] = (byte)value; value >>>= 8; - intBytes[1] = (byte)value; value >>>= 8; - intBytes[0] = (byte)value; - - try { - stream.write(intBytes); - } catch (IOException ex) { - throw new RuntimeException("You're screwed:" - + " IOException writing to a ByteArrayOutputStream", ex); - } - } - - /** - * Write a 64 bit integer to the byte array without allocating memory. - * @param value a 64 bit integer. - */ - private void writeInteger64ToByteArray(long value) { - longintBytes[7] = (byte)value; value >>>= 8; - longintBytes[6] = (byte)value; value >>>= 8; - longintBytes[5] = (byte)value; value >>>= 8; - longintBytes[4] = (byte)value; value >>>= 8; - longintBytes[3] = (byte)value; value >>>= 8; - longintBytes[2] = (byte)value; value >>>= 8; - longintBytes[1] = (byte)value; value >>>= 8; - longintBytes[0] = (byte)value; - - try { - stream.write(longintBytes); - } catch (IOException ex) { - throw new RuntimeException("You're screwed:" - + " IOException writing to a ByteArrayOutputStream", ex); - } - } -} diff --git a/pdex/src/com/illposed/osc/utility/OSCPacketDispatcher.java b/pdex/src/com/illposed/osc/utility/OSCPacketDispatcher.java deleted file mode 100644 index dd6b5240b..000000000 --- a/pdex/src/com/illposed/osc/utility/OSCPacketDispatcher.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2003, C. Ramakrishnan / Auracle. - * All rights reserved. - * - * This code is licensed under the BSD 3-Clause license. - * See file LICENSE (or LICENSE.html) for more information. - */ - -package com.illposed.osc.utility; - -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - -import com.illposed.osc.OSCBundle; -import com.illposed.osc.OSCListener; -import com.illposed.osc.OSCMessage; -import com.illposed.osc.OSCPacket; - -/** - * Dispatches OSCMessages to registered listeners. - * - * @author Chandrasekhar Ramakrishnan - */ - -public class OSCPacketDispatcher { - - private Map addressToListener - = new HashMap(); - - /** - * - */ - public OSCPacketDispatcher() { - } - - public void addListener(String address, OSCListener listener) { - addressToListener.put(address, listener); - } - - public void dispatchPacket(OSCPacket packet) { - if (packet instanceof OSCBundle) { - dispatchBundle((OSCBundle) packet); - } else { - dispatchMessage((OSCMessage) packet); - } - } - - public void dispatchPacket(OSCPacket packet, Date timestamp) { - if (packet instanceof OSCBundle) { - dispatchBundle((OSCBundle) packet); - } else { - dispatchMessage((OSCMessage) packet, timestamp); - } - } - - private void dispatchBundle(OSCBundle bundle) { - Date timestamp = bundle.getTimestamp(); - OSCPacket[] packets = bundle.getPackets(); - for (OSCPacket packet : packets) { - dispatchPacket(packet, timestamp); - } - } - - private void dispatchMessage(OSCMessage message) { - dispatchMessage(message, null); - } - - private void dispatchMessage(OSCMessage message, Date time) { - for (Entry addrList : addressToListener.entrySet()) { - if (message.getAddress().matches(addrList.getKey())) { - addrList.getValue().acceptMessage(time, message); - } - } - } -} diff --git a/pdex/src/galsasson/mode/tweak/OSCSender.java b/pdex/src/galsasson/mode/tweak/OSCSender.java deleted file mode 100644 index b0fd8a599..000000000 --- a/pdex/src/galsasson/mode/tweak/OSCSender.java +++ /dev/null @@ -1,53 +0,0 @@ -package galsasson.mode.tweak; - -import java.net.InetAddress; -import java.util.ArrayList; - -import com.illposed.osc.*; - -public class OSCSender { - - public static void sendFloat(int index, float val, int port) throws Exception - { - OSCPortOut sender = new OSCPortOut(InetAddress.getByName("localhost"), port); - ArrayList args = new ArrayList(); - args.add(Integer.valueOf(index)); - args.add(Float.valueOf(val)); - OSCMessage msg = new OSCMessage("/tm_change_float", args); - try { - sender.send(msg); - } catch (Exception e) { - System.out.println("TweakMode: error sending new value of float " + index); - } - } - - public static void sendInt(int index, int val, int port) throws Exception - { - OSCPortOut sender = new OSCPortOut(InetAddress.getByName("localhost"), port); - ArrayList args = new ArrayList(); - args.add(Integer.valueOf(index)); - args.add(Integer.valueOf(val)); - OSCMessage msg = new OSCMessage("/tm_change_int", args); - try { - sender.send(msg); - } catch (Exception e) { - System.out.println("TweakMode: error sending new value of int " + index); - System.out.println(e.toString()); - } - } - - public static void sendLong(int index, long val, int port) throws Exception - { - OSCPortOut sender = new OSCPortOut(InetAddress.getByName("localhost"), port); - ArrayList args = new ArrayList(); - args.add(Integer.valueOf(index)); - args.add(Long.valueOf(val)); - OSCMessage msg = new OSCMessage("/tm_change_long", args); - try { - sender.send(msg); - } catch (Exception e) { - System.out.println("TweakMode: error sending new value of long " + index); - System.out.println(e.toString()); - } - } -} diff --git a/pdex/src/galsasson/mode/tweak/SketchParser.java b/pdex/src/galsasson/mode/tweak/SketchParser.java index 8c42f27e9..529eb5362 100644 --- a/pdex/src/galsasson/mode/tweak/SketchParser.java +++ b/pdex/src/galsasson/mode/tweak/SketchParser.java @@ -1,17 +1,13 @@ package galsasson.mode.tweak; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; -public class SketchParser -{ - public ArrayList colorBoxes[]; - public ArrayList allHandles[]; + +public class SketchParser { + public ArrayList[] colorBoxes; + public ArrayList[] allHandles; int intVarCount; int floatVarCount; @@ -21,10 +17,10 @@ public class SketchParser boolean requiresComment; ArrayList colorModes; - ArrayList scientificNotations[]; + ArrayList[] scientificNotations; - public SketchParser(String[] codeTabs, boolean requiresComment) - { + + public SketchParser(String[] codeTabs, boolean requiresComment) { this.codeTabs = codeTabs; this.requiresComment = requiresComment; intVarCount=0; @@ -49,8 +45,8 @@ public class SketchParser handleMultipleColorModes(); } - public void addAllNumbers() - { + + public void addAllNumbers() { allHandles = new ArrayList[codeTabs.length]; addAllDecimalNumbers(); addAllHexNumbers(); @@ -60,25 +56,23 @@ public class SketchParser } } + /** * Get a list of all the numbers in this sketch * @return * list of all numbers in the sketch (excluding hexadecimals) */ - private void addAllDecimalNumbers() - { - /* for every number found: - * save its type (int/float), name, value and position in code. - */ + private void addAllDecimalNumbers() { + // for every number found: + // save its type (int/float), name, value and position in code. + Pattern p = Pattern.compile("[\\[\\{<>(),\\t\\s\\+\\-\\/\\*^%!|&=?:~]\\d+\\.?\\d*"); - for (int i=0; i(); String c = codeTabs[i]; Matcher m = p.matcher(c); - while (m.find()) - { + while (m.find()) { boolean forceFloat = false; int start = m.start()+1; int end = m.end(); @@ -536,8 +530,8 @@ public class SketchParser } } - public ArrayList[] getAllScientificNotations() - { + + public ArrayList[] getAllScientificNotations() { ArrayList notations[] = new ArrayList[codeTabs.length]; Pattern p = Pattern.compile("[+\\-]?(?:0|[1-9]\\d*)(?:\\.\\d*)?[eE][+\\-]?\\d+"); @@ -554,20 +548,17 @@ public class SketchParser } - public static boolean containsTweakComment(String[] codeTabs) - { + public static boolean containsTweakComment(String[] codeTabs) { for (String tab : codeTabs) { if (hasTweakComment(tab)) { return true; } } - return false; - } + - public static boolean lineHasTweakComment(int pos, String code) - { + static public boolean lineHasTweakComment(int pos, String code) { int lineEnd = getEndOfLine(pos, code); if (lineEnd < 0) { return false; @@ -576,62 +567,48 @@ public class SketchParser String line = code.substring(pos, lineEnd); return hasTweakComment(line); } + - private static boolean hasTweakComment(String code) - { + static private boolean hasTweakComment(String code) { Pattern p = Pattern.compile("\\/\\/.*tweak", Pattern.CASE_INSENSITIVE); Matcher m = p.matcher(code); - if (m.find()) { - return true; - } - - return false; + return m.find(); } - private boolean isNegativeSign(int pos, String code) - { + static private boolean isNegativeSign(int pos, String code) { // go back and look for ,{[(=?+-/*%<>:&|^!~ - for (int i=pos; i>=0; i--) - { + for (int i = pos; i >= 0; i--) { char c = code.charAt(i); - if (c == ' ' || c == '\t') { - continue; - } - if (c==',' || c=='{' || c=='[' || c=='(' || - c=='=' || c=='?' || c=='+' || c=='-' || - c=='/' || c=='*' || c=='%' || c=='<' || - c=='>' || c==':' || c=='&' || c=='|' || - c=='^' || c=='!' || c=='~') { - return true; - } - else { - return false; + if (c != ' ' && c != '\t') { + return (c==',' || c=='{' || c=='[' || c=='(' || + c=='=' || c=='?' || c=='+' || c=='-' || + c=='/' || c=='*' || c=='%' || c=='<' || + c=='>' || c==':' || c=='&' || c=='|' || + c=='^' || c=='!' || c=='~'); } } - return false; } - private int getNumDigitsAfterPoint(String number) - { + + static private int getNumDigitsAfterPoint(String number) { Pattern p = Pattern.compile("\\.[0-9]+"); Matcher m = p.matcher(number); if (m.find()) { return m.end() - m.start() - 1; } - else { - return 0; - } + return 0; } - private int countLines(String str) - { + + static private int countLines(String str) { String[] lines = str.split("\r\n|\n\r|\n|\r"); return lines.length; } + /** * Are we inside a string? (TODO: ignore comments in the code) * @param pos @@ -640,12 +617,10 @@ public class SketchParser * the code * @return */ - private boolean isInsideString(int pos, String code) - { + static private boolean isInsideString(int pos, String code) { int quoteNum = 0; // count '"' - for (int c = pos; c>=0 && code.charAt(c) != '\n'; c--) - { + for (int c = pos; c>=0 && code.charAt(c) != '\n'; c--) { if (code.charAt(c) == '"') { quoteNum++; } @@ -665,8 +640,7 @@ public class SketchParser * @return * true if the position 'pos' is in global scope in the code 'code' */ - private boolean isGlobal(int pos, String code) - { + static private boolean isGlobal(int pos, String code) { int curlyScope = 0; // count '{-}' for (int c=pos; c>=0; c--) @@ -711,8 +685,7 @@ public class SketchParser return false; }; - private boolean isInComment(int pos, String code) - { + static private boolean isInComment(int pos, String code) { // look for one line comment int lineStart = getStartOfLine(pos, code); if (lineStart < 0) { @@ -723,17 +696,16 @@ public class SketchParser } // TODO: look for block comments - return false; } - public static int getEndOfLine(int pos, String code) - { + + static private int getEndOfLine(int pos, String code) { return code.indexOf("\n", pos); } - public static int getStartOfLine(int pos, String code) - { + + static private int getStartOfLine(int pos, String code) { while (pos >= 0) { if (code.charAt(pos) == '\n') { return pos+1; @@ -744,14 +716,14 @@ public class SketchParser return 0; } + /** returns the object of the function starting at 'pos' * * @param pos * @param code * @return */ - private String getObject(int pos, String code) - { + static private String getObject(int pos, String code) { boolean readObject = false; String obj = "this"; @@ -772,30 +744,28 @@ public class SketchParser obj = code.charAt(pos) + obj; } } - return obj; } - public static int getSetupStart(String code) - { - Pattern p = Pattern.compile("void[\\s\\t\\r\\n]*setup[\\s\\t]*\\(\\)[\\s\\t\\r\\n]*\\{"); - Matcher m = p.matcher(code); - - if (m.find()) { - return m.end(); - } - - return -1; - } + +// static private int getSetupStart(String code) { +// Pattern p = Pattern.compile("void[\\s\\t\\r\\n]*setup[\\s\\t]*\\(\\)[\\s\\t\\r\\n]*\\{"); +// Matcher m = p.matcher(code); +// +// if (m.find()) { +// return m.end(); +// } +// +// return -1; +// } - private String replaceString(String str, int start, int end, String put) - { - return str.substring(0, start) + put + str.substring(end, str.length()); - } +// private String replaceString(String str, int start, int end, String put) { +// return str.substring(0, start) + put + str.substring(end, str.length()); +// } - class Range - { + + class Range { int start; int end; @@ -804,13 +774,8 @@ public class SketchParser end = e; } - public boolean contains(int v) - { - if (v>=start && v= start && v < end; } } } diff --git a/todo.txt b/todo.txt index a3923fdbc..593a311ac 100644 --- a/todo.txt +++ b/todo.txt @@ -55,6 +55,8 @@ X sketches should only write to the console of their editor window X https://github.com/processing/processing/issues/153 X https://github.com/processing/processing/issues/2858 X https://github.com/processing/processing/pull/2827 +X extend translations and update German language +X https://github.com/processing/processing/pull/2949 pulls (net) X NullPointerException message when Server writes to a disconnected client @@ -66,8 +68,6 @@ X https://github.com/processing/processing/pull/2588 _ Add support for localizing contributions _ https://github.com/processing/processing/pull/2833 -_ Fix renaming from RGB to Rgb.java and others -_ https://github.com/processing/processing/pull/2825 _ check on pull for mnemonics _ https://github.com/processing/processing/pull/2382