public SurfaceGL(GLContext ctx, float width, float height) { super(ctx); this.width = width; this.height = height; this.texWidth = ctx.scale.scaledCeil(width); this.texHeight = ctx.scale.scaledCeil(height); createTexture(); scale(ctx.scale.factor, ctx.scale.factor); }
@Override public float width() { return scale.invScaled(bitmap.getWidth()); }
/** * Configures the default scale to use for assets. This allows one to specify an intermediate * graphics scale (like 1.5) and scale the 2x imagery down to 1.5x instead of scaling the 1.5x * imagery up (or displaying nothing at all). */ public void setAssetScale(float scaleFactor) { this.assetScale = new Scale(scaleFactor); }
@Override public int width() { return scale.invScaledFloor(rootWidth); }
public RoboCanvas(RoboGLContext ctx, float width, float height, boolean interpolate) { super(width, height); // if our size is invalid, we'll fail below at CGBitmapContext, so fail here more usefully if (width <= 0 || height <= 0) throw new IllegalArgumentException( "Invalid size " + width + "x" + height); states.addFirst(new RoboCanvasState()); this.ctx = ctx; // create our raw image data texWidth = ctx.scale.scaledCeil(width); texHeight = ctx.scale.scaledCeil(height); // create the bitmap context via which we'll render into it bctx = RoboGraphics.createCGBitmap(texWidth, texHeight); if (!interpolate) { bctx.setInterpolationQuality(CGInterpolationQuality.None); } // clear the canvas before we scale our bitmap context to avoid artifacts bctx.clearRect(new CGRect(0, 0, texWidth, texHeight)); // CG coordinate system is OpenGL-style (0,0 in lower left); so we flip it bctx.translateCTM(0, ctx.scale.scaled(height)); bctx.scaleCTM(ctx.scale.factor, -ctx.scale.factor); }
@Override protected Pattern toSubPattern(AbstractImageGL<?> image, boolean repeatX, boolean repeatY, float x, float y, float width, float height) { assert isReady() : "Cannot generate a pattern from unready image."; // we have to account for the scale factor when extracting our subimage BufferedImage subImage = img.getSubimage( scale.scaledFloor(x), scale.scaledFloor(y), scale.scaledCeil(width), scale.scaledCeil(height)); Rectangle2D rect = new Rectangle2D.Float(0, 0, width, height); return new JavaPattern(image, repeatX, repeatY, new TexturePaint(subImage, rect)); }
@Override protected Image loadImage(String path, ImageReceiver<Bitmap> recv) { Exception error = null; for (Scale.ScaledResource rsrc : assetScale().getScaledResources(path)) { try { InputStream is = openAsset(rsrc.path); try { BitmapOptions options = createOptions(path, true, rsrc.scale); return recv.imageLoaded(BitmapFactory.decodeStream(is, null, options), options.scale); } finally { is.close(); } } catch (FileNotFoundException fnfe) { error = fnfe; // keep going, checking for lower resolution images } catch (Exception e) { error = e; break; // the image was broken not missing, stop here } } platform.log().warn("Could not load image: " + pathPrefix + path, error); return recv.loadFailed(error != null ? error : new FileNotFoundException(path)); }
/** * Returns an ordered series of scaled resources to try when loading an asset. The highest * resolution will be tried first, then half that resolution and so forth down to a normal * resolution image. In general this is simply {@code 2, 1}, but on a Retina iPad, it could be * {@code 4, 2, 1}. */ public List<ScaledResource> getScaledResources(String path) { List<ScaledResource> rsrcs = new ArrayList<ScaledResource>(); rsrcs.add(new ScaledResource(this, computePath(path, factor))); for (float rscale = MathUtil.ifloor(factor); rscale > 1; rscale -= 1) { if (rscale != factor) rsrcs.add( new ScaledResource(new Scale(rscale), computePath(path, rscale))); } rsrcs.add(new ScaledResource(ONE, path)); return rsrcs; }
/** Returns the supplied length scaled by our scale factor and rounded up. */ public int scaledCeil(float length) { return MathUtil.iceil(scaled(length)); }
@Override public int height() { return scale.invScaledFloor(rootHeight); }
@Override protected Pattern toSubPattern(AbstractImageGL<?> image, boolean repeatX, boolean repeatY, float x, float y, float width, float height) { assert isReady() : "Cannot generate a pattern from unready image."; // we have to account for the scale factor when extracting our subimage BufferedImage subImage = img.getSubimage( scale.scaledFloor(x), scale.scaledFloor(y), scale.scaledCeil(width), scale.scaledCeil(height)); Rectangle2D rect = new Rectangle2D.Float(0, 0, width, height); return new JavaPattern(image, repeatX, repeatY, new TexturePaint(subImage, rect)); }
@Override protected Image loadImage(String path, ImageReceiver<Bitmap> recv) { Exception error = null; for (Scale.ScaledResource rsrc : assetScale().getScaledResources(path)) { try { InputStream is = openAsset(rsrc.path); try { BitmapOptions options = createOptions(path, true, rsrc.scale); return recv.imageLoaded(BitmapFactory.decodeStream(is, null, options), options.scale); } finally { is.close(); } } catch (FileNotFoundException fnfe) { error = fnfe; // keep going, checking for lower resolution images } catch (Exception e) { error = e; break; // the image was broken not missing, stop here } } platform.log().warn("Could not load image: " + pathPrefix + path, error); return recv.loadFailed(error != null ? error : new FileNotFoundException(path)); }
/** Returns the supplied length scaled by our scale factor and rounded down. */ public int scaledFloor(float length) { return MathUtil.ifloor(scaled(length)); }
AndroidCanvasImage(AndroidGraphics gfx, float width, float height, Scale scale) { super(gfx.ctx, Bitmap.createBitmap(scale.scaledCeil(width), scale.scaledCeil(height), gfx.preferredBitmapConfig), scale); this.canvas = new AndroidCanvas(bitmap, width, height); this.canvas.scale(scale.factor, scale.factor); }
@Override public float height() { return scale.invScaled(img.getHeight()); }
/** * Sets the frame buffer to the specified width and height (in pixels). The view will potentially * be smaller than this size if a HiDPI scale factor is in effect. */ public final void setSize(int pixelWidth, int pixelHeight) { viewWidth = scale.invScaledFloor(pixelWidth); viewHeight = scale.invScaledFloor(pixelHeight); curFbufWidth = defaultFbufWidth = pixelWidth; curFbufHeight = defaultFbufHeight = pixelHeight; viewConfigChanged(); }
/** * Configures the default scale to use for assets. This allows one to specify an intermediate * graphics scale (like 1.5) and scale the 2x imagery down to 1.5x instead of scaling the 1.5x * imagery up (or displaying nothing at all). */ public void setAssetScale(float scaleFactor) { this.assetScale = new Scale(scaleFactor); }
@Override public Image getImageSync(String path) { if (imageManifest == null) throw new UnsupportedOperationException("getImageSync(" + path + ")"); else { for (Scale.ScaledResource rsrc : assetScale().getScaledResources(path)) { float[] size = imageManifest.imageSize(rsrc.path); if (size == null) continue; // try other scales HtmlImage image = getImage(rsrc.path, rsrc.scale); image.img.setWidth(MathUtil.iceil(size[0])); image.img.setHeight(MathUtil.iceil(size[1])); return image; } return createErrorImage(new Throwable("Image missing from manifest: " + path)); } }
AndroidCanvasImage(AndroidGraphics gfx, float width, float height, Scale scale) { super(gfx.ctx, Bitmap.createBitmap(scale.scaledCeil(width), scale.scaledCeil(height), gfx.preferredBitmapConfig), scale); this.canvas = new AndroidCanvas(bitmap, width, height); this.canvas.scale(scale.factor, scale.factor); }
@Override public float height() { return scale.invScaled(bitmap.getHeight()); }