aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ImageOverlay.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ImageOverlay.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ImageOverlay.java447
1 files changed, 0 insertions, 447 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ImageOverlay.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ImageOverlay.java
deleted file mode 100644
index a1363ecb1..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ImageOverlay.java
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.eclipse.org/org/documents/epl-v10.php
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.ide.eclipse.adt.internal.editors.layout.gle2;
-
-import static com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageUtils.SHADOW_SIZE;
-
-import com.android.SdkConstants;
-import com.android.annotations.Nullable;
-import com.android.ide.common.api.Rect;
-import com.android.ide.common.rendering.api.IImageFactory;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.SWTException;
-import org.eclipse.swt.graphics.Device;
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.ImageData;
-import org.eclipse.swt.graphics.PaletteData;
-
-import java.awt.image.BufferedImage;
-import java.awt.image.DataBufferInt;
-import java.awt.image.WritableRaster;
-import java.lang.ref.SoftReference;
-
-/**
- * The {@link ImageOverlay} class renders an image as an overlay.
- */
-public class ImageOverlay extends Overlay implements IImageFactory {
- /**
- * Whether the image should be pre-scaled (scaled to the zoom level) once
- * instead of dynamically during each paint; this is necessary on some
- * platforms (see issue #19447)
- */
- private static final boolean PRESCALE =
- // Currently this is necessary on Linux because the "Cairo" library
- // seems to be a bottleneck
- SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_LINUX
- && !(Boolean.getBoolean("adt.noprescale")); //$NON-NLS-1$
-
- /** Current background image. Null when there's no image. */
- private Image mImage;
-
- /** A pre-scaled version of the image */
- private Image mPreScaledImage;
-
- /** Whether the rendered image should have a drop shadow */
- private boolean mShowDropShadow;
-
- /** Current background AWT image. This is created by {@link #getImage()}, which is called
- * by the LayoutLib. */
- private SoftReference<BufferedImage> mAwtImage = new SoftReference<BufferedImage>(null);
-
- /**
- * Strong reference to the image in the above soft reference, to prevent
- * garbage collection when {@link PRESCALE} is set, until the scaled image
- * is created (lazily as part of the next paint call, where this strong
- * reference is nulled out and the above soft reference becomes eligible to
- * be reclaimed when memory is low.)
- */
- @SuppressWarnings("unused") // Used by the garbage collector to keep mAwtImage non-soft
- private BufferedImage mAwtImageStrongRef;
-
- /** The associated {@link LayoutCanvas}. */
- private LayoutCanvas mCanvas;
-
- /** Vertical scaling & scrollbar information. */
- private CanvasTransform mVScale;
-
- /** Horizontal scaling & scrollbar information. */
- private CanvasTransform mHScale;
-
- /**
- * Constructs an {@link ImageOverlay} tied to the given canvas.
- *
- * @param canvas The {@link LayoutCanvas} to paint the overlay over.
- * @param hScale The horizontal scale information.
- * @param vScale The vertical scale information.
- */
- public ImageOverlay(LayoutCanvas canvas, CanvasTransform hScale, CanvasTransform vScale) {
- mCanvas = canvas;
- mHScale = hScale;
- mVScale = vScale;
- }
-
- @Override
- public void create(Device device) {
- super.create(device);
- }
-
- @Override
- public void dispose() {
- if (mImage != null) {
- mImage.dispose();
- mImage = null;
- }
- if (mPreScaledImage != null) {
- mPreScaledImage.dispose();
- mPreScaledImage = null;
- }
- }
-
- /**
- * Sets the image to be drawn as an overlay from the passed in AWT
- * {@link BufferedImage} (which will be converted to an SWT image).
- * <p/>
- * The image <b>can</b> be null, which is the case when we are dealing with
- * an empty document.
- *
- * @param awtImage The AWT image to be rendered as an SWT image.
- * @param isAlphaChannelImage whether the alpha channel of the image is relevant
- * @return The corresponding SWT image, or null.
- */
- public synchronized Image setImage(BufferedImage awtImage, boolean isAlphaChannelImage) {
- mShowDropShadow = !isAlphaChannelImage;
-
- BufferedImage oldAwtImage = mAwtImage.get();
- if (awtImage != oldAwtImage || awtImage == null) {
- mAwtImage.clear();
- mAwtImageStrongRef = null;
-
- if (mImage != null) {
- mImage.dispose();
- }
-
- if (awtImage == null) {
- mImage = null;
- } else {
- mImage = SwtUtils.convertToSwt(mCanvas.getDisplay(), awtImage,
- isAlphaChannelImage, -1);
- }
- } else {
- assert awtImage instanceof SwtReadyBufferedImage;
-
- if (isAlphaChannelImage) {
- if (mImage != null) {
- mImage.dispose();
- }
-
- mImage = SwtUtils.convertToSwt(mCanvas.getDisplay(), awtImage, true, -1);
- } else {
- Image prev = mImage;
- mImage = ((SwtReadyBufferedImage)awtImage).getSwtImage();
- if (prev != mImage && prev != null) {
- prev.dispose();
- }
- }
- }
-
- if (mPreScaledImage != null) {
- // Force refresh on next paint
- mPreScaledImage.dispose();
- mPreScaledImage = null;
- }
-
- return mImage;
- }
-
- /**
- * Returns the currently painted image, or null if none has been set
- *
- * @return the currently painted image or null
- */
- public Image getImage() {
- return mImage;
- }
-
- /**
- * Returns the currently rendered image, or null if none has been set
- *
- * @return the currently rendered image or null
- */
- @Nullable
- BufferedImage getAwtImage() {
- BufferedImage awtImage = mAwtImage.get();
- if (awtImage == null && mImage != null) {
- awtImage = SwtUtils.convertToAwt(mImage);
- }
-
- return awtImage;
- }
-
- /**
- * Returns whether this image overlay should be painted with a drop shadow.
- * This is usually the case, but not for transparent themes like the dialog
- * theme (Theme.*Dialog), which already provides its own shadow.
- *
- * @return true if the image overlay should be shown with a drop shadow.
- */
- public boolean getShowDropShadow() {
- return mShowDropShadow;
- }
-
- @Override
- public synchronized void paint(GC gc) {
- if (mImage != null) {
- boolean valid = mCanvas.getViewHierarchy().isValid();
- mCanvas.ensureZoomed();
- if (!valid) {
- gc_setAlpha(gc, 128); // half-transparent
- }
-
- CanvasTransform hi = mHScale;
- CanvasTransform vi = mVScale;
-
- // On some platforms, dynamic image scaling is very slow (see issue #19447) so
- // compute a pre-scaled version of the image once and render that instead.
- // This is done lazily in paint rather than when the image changes because
- // the image must be rescaled each time the zoom level changes, which varies
- // independently from when the image changes.
- BufferedImage awtImage = mAwtImage.get();
- if (PRESCALE && awtImage != null) {
- int imageWidth = (mPreScaledImage == null) ? 0
- : mPreScaledImage.getImageData().width
- - (mShowDropShadow ? SHADOW_SIZE : 0);
- if (mPreScaledImage == null || imageWidth != hi.getScaledImgSize()) {
- double xScale = hi.getScaledImgSize() / (double) awtImage.getWidth();
- double yScale = vi.getScaledImgSize() / (double) awtImage.getHeight();
- BufferedImage scaledAwtImage;
-
- // NOTE: == comparison on floating point numbers is okay
- // here because we normalize the scaling factor
- // to an exact 1.0 in the zooming code when the value gets
- // near 1.0 to make painting more efficient in the presence
- // of rounding errors.
- if (xScale == 1.0 && yScale == 1.0) {
- // Scaling to 100% is easy!
- scaledAwtImage = awtImage;
-
- if (mShowDropShadow) {
- // Just need to draw drop shadows
- scaledAwtImage = ImageUtils.createRectangularDropShadow(awtImage);
- }
- } else {
- if (mShowDropShadow) {
- scaledAwtImage = ImageUtils.scale(awtImage, xScale, yScale,
- SHADOW_SIZE, SHADOW_SIZE);
- ImageUtils.drawRectangleShadow(scaledAwtImage, 0, 0,
- scaledAwtImage.getWidth() - SHADOW_SIZE,
- scaledAwtImage.getHeight() - SHADOW_SIZE);
- } else {
- scaledAwtImage = ImageUtils.scale(awtImage, xScale, yScale);
- }
- }
-
- if (mPreScaledImage != null && !mPreScaledImage.isDisposed()) {
- mPreScaledImage.dispose();
- }
- mPreScaledImage = SwtUtils.convertToSwt(mCanvas.getDisplay(), scaledAwtImage,
- true /*transferAlpha*/, -1);
- // We can't just clear the mAwtImageStrongRef here, because if the
- // zooming factor changes, we may need to use it again
- }
-
- if (mPreScaledImage != null) {
- gc.drawImage(mPreScaledImage, hi.translate(0), vi.translate(0));
- }
- return;
- }
-
- // we only anti-alias when reducing the image size.
- int oldAlias = -2;
- if (hi.getScale() < 1.0) {
- oldAlias = gc_setAntialias(gc, SWT.ON);
- }
-
- int srcX = 0;
- int srcY = 0;
- int srcWidth = hi.getImgSize();
- int srcHeight = vi.getImgSize();
- int destX = hi.translate(0);
- int destY = vi.translate(0);
- int destWidth = hi.getScaledImgSize();
- int destHeight = vi.getScaledImgSize();
-
- gc.drawImage(mImage,
- srcX, srcY, srcWidth, srcHeight,
- destX, destY, destWidth, destHeight);
-
- if (mShowDropShadow) {
- SwtUtils.drawRectangleShadow(gc, destX, destY, destWidth, destHeight);
- }
-
- if (oldAlias != -2) {
- gc_setAntialias(gc, oldAlias);
- }
-
- if (!valid) {
- gc_setAlpha(gc, 255); // opaque
- }
- }
- }
-
- /**
- * Sets the alpha for the given GC.
- * <p/>
- * Alpha may not work on all platforms and may fail with an exception, which
- * is hidden here (false is returned in that case).
- *
- * @param gc the GC to change
- * @param alpha the new alpha, 0 for transparent, 255 for opaque.
- * @return True if the operation worked, false if it failed with an
- * exception.
- * @see GC#setAlpha(int)
- */
- private boolean gc_setAlpha(GC gc, int alpha) {
- try {
- gc.setAlpha(alpha);
- return true;
- } catch (SWTException e) {
- return false;
- }
- }
-
- /**
- * Sets the non-text antialias flag for the given GC.
- * <p/>
- * Antialias may not work on all platforms and may fail with an exception,
- * which is hidden here (-2 is returned in that case).
- *
- * @param gc the GC to change
- * @param alias One of {@link SWT#DEFAULT}, {@link SWT#ON}, {@link SWT#OFF}.
- * @return The previous aliasing mode if the operation worked, or -2 if it
- * failed with an exception.
- * @see GC#setAntialias(int)
- */
- private int gc_setAntialias(GC gc, int alias) {
- try {
- int old = gc.getAntialias();
- gc.setAntialias(alias);
- return old;
- } catch (SWTException e) {
- return -2;
- }
- }
-
- /**
- * Custom {@link BufferedImage} class able to convert itself into an SWT {@link Image}
- * efficiently.
- *
- * The BufferedImage also contains an instance of {@link ImageData} that's kept around
- * and used to create new SWT {@link Image} objects in {@link #getSwtImage()}.
- *
- */
- private static final class SwtReadyBufferedImage extends BufferedImage {
-
- private final ImageData mImageData;
- private final Device mDevice;
-
- /**
- * Creates the image with a given model, raster and SWT {@link ImageData}
- * @param model the color model
- * @param raster the image raster
- * @param imageData the SWT image data.
- * @param device the {@link Device} in which the SWT image will be painted.
- */
- private SwtReadyBufferedImage(int width, int height, ImageData imageData, Device device) {
- super(width, height, BufferedImage.TYPE_INT_ARGB);
- mImageData = imageData;
- mDevice = device;
- }
-
- /**
- * Returns a new {@link Image} object initialized with the content of the BufferedImage.
- * @return the image object.
- */
- private Image getSwtImage() {
- // transfer the content of the bufferedImage into the image data.
- WritableRaster raster = getRaster();
- int[] imageDataBuffer = ((DataBufferInt) raster.getDataBuffer()).getData();
-
- mImageData.setPixels(0, 0, imageDataBuffer.length, imageDataBuffer, 0);
-
- return new Image(mDevice, mImageData);
- }
-
- /**
- * Creates a new {@link SwtReadyBufferedImage}.
- * @param w the width of the image
- * @param h the height of the image
- * @param device the device in which the SWT image will be painted
- * @return a new {@link SwtReadyBufferedImage} object
- */
- private static SwtReadyBufferedImage createImage(int w, int h, Device device) {
- // NOTE: We can't make this image bigger to accommodate the drop shadow directly
- // (such that we could paint one into the image after a layoutlib render)
- // since this image is in the full resolution of the device, and gets scaled
- // to fit in the layout editor. This would have the net effect of causing
- // the drop shadow to get zoomed/scaled along with the scene, making a tiny
- // drop shadow for tablet layouts, a huge drop shadow for tiny QVGA screens, etc.
-
- ImageData imageData = new ImageData(w, h, 32,
- new PaletteData(0x00FF0000, 0x0000FF00, 0x000000FF));
-
- SwtReadyBufferedImage swtReadyImage = new SwtReadyBufferedImage(w, h,
- imageData, device);
-
- return swtReadyImage;
- }
- }
-
- /**
- * Implementation of {@link IImageFactory#getImage(int, int)}.
- */
- @Override
- public BufferedImage getImage(int w, int h) {
- BufferedImage awtImage = mAwtImage.get();
- if (awtImage == null ||
- awtImage.getWidth() != w ||
- awtImage.getHeight() != h) {
- mAwtImage.clear();
- awtImage = SwtReadyBufferedImage.createImage(w, h, getDevice());
- mAwtImage = new SoftReference<BufferedImage>(awtImage);
- if (PRESCALE) {
- mAwtImageStrongRef = awtImage;
- }
- }
-
- return awtImage;
- }
-
- /**
- * Returns the bounds of the current image, or null
- *
- * @return the bounds of the current image, or null
- */
- public Rect getImageBounds() {
- if (mImage == null) {
- return null;
- }
-
- return new Rect(0, 0, mImage.getImageData().width, mImage.getImageData().height);
- }
-}