| /******************************************************************************* |
| * Copyright (c) 2000, 2007 IBM Corporation and others. All rights reserved. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v1.0 which accompanies this distribution, |
| * and is available at http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: University of Victoria - Adapted for XY Scaled Graphics |
| *******************************************************************************/ |
| package org.eclipse.zest.core.widgets.internal; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.draw2d.FigureUtilities; |
| import org.eclipse.draw2d.Graphics; |
| import org.eclipse.draw2d.ScaledGraphics; |
| import org.eclipse.draw2d.geometry.Point; |
| import org.eclipse.draw2d.geometry.PointList; |
| import org.eclipse.draw2d.geometry.Rectangle; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.Font; |
| import org.eclipse.swt.graphics.FontData; |
| import org.eclipse.swt.graphics.FontMetrics; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.TextLayout; |
| import org.eclipse.swt.graphics.TextStyle; |
| import org.eclipse.swt.widgets.Display; |
| |
| /** |
| * This was adapted from the ScaledGraphics class to allow X and Y to scale |
| * independently. It won't require this level of coupling if some of these |
| * private methods were made protected. I will open a bug report on this. |
| * |
| * @author irbull |
| */ |
| public class XYScaledGraphics extends ScaledGraphics { |
| |
| public static final double MAX_TEXT_SIZE = 0.45; // MAX size, when to stop zooming text |
| |
| private static class FontHeightCache { |
| Font font; |
| int height; |
| } |
| |
| static class FontKey { |
| Font font; |
| int height; |
| |
| protected FontKey() { |
| } |
| |
| protected FontKey(Font font, int height) { |
| this.font = font; |
| this.height = height; |
| } |
| |
| public boolean equals(Object obj) { |
| return (((FontKey) obj).font.equals(font) && ((FontKey) obj).height == height); |
| } |
| |
| public int hashCode() { |
| return font.hashCode() ^ height; |
| } |
| |
| protected void setValues(Font font, int height) { |
| this.font = font; |
| this.height = height; |
| } |
| } |
| |
| /** |
| * The internal state of the scaled graphics. |
| */ |
| protected static class State { |
| private double appliedX; |
| private double appliedY; |
| private Font font; |
| private int lineWidth; |
| //private double zoom; // This has been replaced with xZoom and yZoom |
| private double xZoom; |
| private double yZoom; |
| |
| /** |
| * Constructs a new, uninitialized State object. |
| */ |
| protected State() { |
| } |
| |
| /** |
| * Constructs a new State object and initializes the properties based on |
| * the given values. |
| * |
| * @param zoom |
| * the zoom factor |
| * @param x |
| * the x offset |
| * @param y |
| * the y offset |
| * @param font |
| * the font |
| * @param lineWidth |
| * the line width |
| */ |
| protected State(double xZoom, double yZoom, double x, double y, Font font, int lineWidth) { |
| this.xZoom = xZoom; |
| this.yZoom = yZoom; |
| this.appliedX = x; |
| this.appliedY = y; |
| this.font = font; |
| this.lineWidth = lineWidth; |
| } |
| |
| /** |
| * Sets all the properties of the state object. |
| * |
| * @param zoom |
| * the zoom factor |
| * @param x |
| * the x offset |
| * @param y |
| * the y offset |
| * @param font |
| * the font |
| * @param lineWidth |
| * the line width |
| */ |
| protected void setValues(double xZoom, double yZoom, double x, double y, Font font, int lineWidth) { |
| this.xZoom = xZoom; |
| this.yZoom = yZoom; |
| this.appliedX = x; |
| this.appliedY = y; |
| this.font = font; |
| this.lineWidth = lineWidth; |
| } |
| } |
| |
| private static int[][] intArrayCache = new int[8][]; |
| private final Rectangle tempRECT = new Rectangle(); |
| |
| static { |
| for (int i = 0; i < intArrayCache.length; i++) { |
| intArrayCache[i] = new int[i + 1]; |
| } |
| } |
| |
| private boolean allowText = true; |
| // private static final Point PT = new Point(); |
| private Map fontCache = new HashMap(); |
| private Map fontDataCache = new HashMap(); |
| private FontKey fontKey = new FontKey(); |
| private double fractionalX; |
| private double fractionalY; |
| private Graphics graphics; |
| private FontHeightCache localCache = new FontHeightCache(); |
| private Font localFont; |
| private int localLineWidth; |
| private List stack = new ArrayList(); |
| private int stackPointer = 0; |
| private FontHeightCache targetCache = new FontHeightCache(); |
| |
| double xZoom = 1.0; |
| double yZoom = 1.0; |
| |
| /** |
| * Constructs a new ScaledGraphics based on the given Graphics object. |
| * |
| * @param g |
| * the base graphics object |
| */ |
| public XYScaledGraphics(Graphics g) { |
| super(g); |
| graphics = g; |
| localFont = g.getFont(); |
| localLineWidth = g.getLineWidth(); |
| } |
| |
| /** @see Graphics#clipRect(Rectangle) */ |
| public void clipRect(Rectangle r) { |
| graphics.clipRect(zoomClipRect(r)); |
| } |
| |
| Font createFont(FontData data) { |
| return new Font(Display.getCurrent(), data); |
| } |
| |
| /** @see Graphics#dispose() */ |
| public void dispose() { |
| //Remove all states from the stack |
| while (stackPointer > 0) { |
| popState(); |
| } |
| |
| //Dispose fonts |
| Iterator iter = fontCache.values().iterator(); |
| while (iter.hasNext()) { |
| Font font = ((Font) iter.next()); |
| font.dispose(); |
| } |
| |
| } |
| |
| /** @see Graphics#drawArc(int, int, int, int, int, int) */ |
| public void drawArc(int x, int y, int w, int h, int offset, int sweep) { |
| Rectangle z = zoomRect(x, y, w, h); |
| if (z.isEmpty() || sweep == 0) { |
| return; |
| } |
| graphics.drawArc(z, offset, sweep); |
| } |
| |
| /** @see Graphics#drawFocus(int, int, int, int) */ |
| public void drawFocus(int x, int y, int w, int h) { |
| graphics.drawFocus(zoomRect(x, y, w, h)); |
| } |
| |
| /** @see Graphics#drawImage(Image, int, int) */ |
| public void drawImage(Image srcImage, int x, int y) { |
| org.eclipse.swt.graphics.Rectangle size = srcImage.getBounds(); |
| double imageZoom = Math.min(xZoom, yZoom); |
| graphics.drawImage(srcImage, 0, 0, size.width, size.height, (int) (Math.floor((x * xZoom + fractionalX))), (int) (Math.floor((y * yZoom + fractionalY))), (int) (Math.floor((size.width * imageZoom + fractionalX))), (int) (Math.floor((size.height * imageZoom + fractionalY)))); |
| } |
| |
| /** @see Graphics#drawImage(Image, int, int, int, int, int, int, int, int) */ |
| public void drawImage(Image srcImage, int sx, int sy, int sw, int sh, int tx, int ty, int tw, int th) { |
| //"t" == target rectangle, "s" = source |
| |
| Rectangle t = zoomRect(tx, ty, tw, th); |
| if (!t.isEmpty()) { |
| graphics.drawImage(srcImage, sx, sy, sw, sh, t.x, t.y, t.width, t.height); |
| } |
| } |
| |
| /** @see Graphics#drawLine(int, int, int, int) */ |
| public void drawLine(int x1, int y1, int x2, int y2) { |
| graphics.drawLine((int) (Math.floor((x1 * xZoom + fractionalX))), (int) (Math.floor((y1 * yZoom + fractionalY))), (int) (Math.floor((x2 * xZoom + fractionalX))), (int) (Math.floor((y2 * yZoom + fractionalY)))); |
| } |
| |
| /** @see Graphics#drawOval(int, int, int, int) */ |
| public void drawOval(int x, int y, int w, int h) { |
| graphics.drawOval(zoomRect(x, y, w, h)); |
| } |
| |
| /** @see Graphics#drawPoint(int, int) */ |
| public void drawPoint(int x, int y) { |
| graphics.drawPoint((int) Math.floor(x * xZoom + fractionalX), (int) Math.floor(y * yZoom + fractionalY)); |
| } |
| |
| /** |
| * @see Graphics#drawPolygon(int[]) |
| */ |
| public void drawPolygon(int[] points) { |
| graphics.drawPolygon(zoomPointList(points)); |
| } |
| |
| /** @see Graphics#drawPolygon(PointList) */ |
| public void drawPolygon(PointList points) { |
| graphics.drawPolygon(zoomPointList(points.toIntArray())); |
| } |
| |
| /** |
| * @see Graphics#drawPolyline(int[]) |
| */ |
| public void drawPolyline(int[] points) { |
| graphics.drawPolyline(zoomPointList(points)); |
| } |
| |
| /** @see Graphics#drawPolyline(PointList) */ |
| public void drawPolyline(PointList points) { |
| graphics.drawPolyline(zoomPointList(points.toIntArray())); |
| } |
| |
| /** @see Graphics#drawRectangle(int, int, int, int) */ |
| public void drawRectangle(int x, int y, int w, int h) { |
| graphics.drawRectangle(zoomRect(x, y, w, h)); |
| } |
| |
| /** @see Graphics#drawRoundRectangle(Rectangle, int, int) */ |
| public void drawRoundRectangle(Rectangle r, int arcWidth, int arcHeight) { |
| graphics.drawRoundRectangle(zoomRect(r.x, r.y, r.width, r.height), (int) (arcWidth * xZoom), (int) (arcHeight * yZoom)); |
| } |
| |
| /** @see Graphics#drawString(String, int, int) */ |
| public void drawString(String s, int x, int y) { |
| if (allowText) { |
| graphics.drawString(s, zoomTextPoint(x, y)); |
| } |
| } |
| |
| /** @see Graphics#drawText(String, int, int) */ |
| public void drawText(String s, int x, int y) { |
| if (allowText) { |
| graphics.drawText(s, zoomTextPoint(x, y)); |
| } |
| } |
| |
| /** |
| * @see Graphics#drawText(String, int, int, int) |
| */ |
| public void drawText(String s, int x, int y, int style) { |
| if (allowText) { |
| graphics.drawText(s, zoomTextPoint(x, y), style); |
| } |
| } |
| |
| /** |
| * @see Graphics#drawTextLayout(TextLayout, int, int, int, int, Color, |
| * Color) |
| */ |
| public void drawTextLayout(TextLayout layout, int x, int y, int selectionStart, int selectionEnd, Color selectionForeground, Color selectionBackground) { |
| TextLayout scaled = zoomTextLayout(layout); |
| graphics.drawTextLayout(scaled, (int) Math.floor(x * xZoom + fractionalX), (int) Math.floor(y * yZoom + fractionalY), selectionStart, selectionEnd, selectionBackground, selectionForeground); |
| scaled.dispose(); |
| } |
| |
| /** @see Graphics#fillArc(int, int, int, int, int, int) */ |
| public void fillArc(int x, int y, int w, int h, int offset, int sweep) { |
| Rectangle z = zoomFillRect(x, y, w, h); |
| if (z.isEmpty() || sweep == 0) { |
| return; |
| } |
| graphics.fillArc(z, offset, sweep); |
| } |
| |
| /** @see Graphics#fillGradient(int, int, int, int, boolean) */ |
| public void fillGradient(int x, int y, int w, int h, boolean vertical) { |
| graphics.fillGradient(zoomFillRect(x, y, w, h), vertical); |
| } |
| |
| /** @see Graphics#fillOval(int, int, int, int) */ |
| public void fillOval(int x, int y, int w, int h) { |
| graphics.fillOval(zoomFillRect(x, y, w, h)); |
| } |
| |
| /** |
| * @see Graphics#fillPolygon(int[]) |
| */ |
| public void fillPolygon(int[] points) { |
| graphics.fillPolygon(zoomPointList(points)); |
| } |
| |
| /** @see Graphics#fillPolygon(PointList) */ |
| public void fillPolygon(PointList points) { |
| graphics.fillPolygon(zoomPointList(points.toIntArray())); |
| } |
| |
| /** @see Graphics#fillRectangle(int, int, int, int) */ |
| public void fillRectangle(int x, int y, int w, int h) { |
| graphics.fillRectangle(zoomFillRect(x, y, w, h)); |
| } |
| |
| /** @see Graphics#fillRoundRectangle(Rectangle, int, int) */ |
| public void fillRoundRectangle(Rectangle r, int arcWidth, int arcHeight) { |
| graphics.fillRoundRectangle(zoomFillRect(r.x, r.y, r.width, r.height), (int) (arcWidth * xZoom), (int) (arcHeight * yZoom)); |
| } |
| |
| /** @see Graphics#fillString(String, int, int) */ |
| public void fillString(String s, int x, int y) { |
| if (allowText) { |
| graphics.fillString(s, zoomTextPoint(x, y)); |
| } |
| } |
| |
| /** @see Graphics#fillText(String, int, int) */ |
| public void fillText(String s, int x, int y) { |
| if (allowText) { |
| graphics.fillText(s, zoomTextPoint(x, y)); |
| } |
| } |
| |
| /** |
| * @see Graphics#getAbsoluteScale() |
| */ |
| public double getAbsoluteScale() { |
| return xZoom * graphics.getAbsoluteScale(); |
| } |
| |
| /** |
| * @see Graphics#getAlpha() |
| */ |
| public int getAlpha() { |
| return graphics.getAlpha(); |
| } |
| |
| /** |
| * @see Graphics#getAntialias() |
| */ |
| public int getAntialias() { |
| return graphics.getAntialias(); |
| } |
| |
| /** @see Graphics#getBackgroundColor() */ |
| public Color getBackgroundColor() { |
| return graphics.getBackgroundColor(); |
| } |
| |
| Font getCachedFont(FontKey key) { |
| Font font = (Font) fontCache.get(key); |
| if (font != null) { |
| return font; |
| } |
| key = new FontKey(key.font, key.height); |
| FontData data = key.font.getFontData()[0]; |
| data.setHeight(key.height); |
| Font zoomedFont = createFont(data); |
| fontCache.put(key, zoomedFont); |
| return zoomedFont; |
| } |
| |
| FontData getCachedFontData(Font f) { |
| FontData data = (FontData) fontDataCache.get(f); |
| if (data != null) { |
| return data; |
| } |
| data = getLocalFont().getFontData()[0]; |
| fontDataCache.put(f, data); |
| return data; |
| } |
| |
| /** @see Graphics#getClip(Rectangle) */ |
| public Rectangle getClip(Rectangle rect) { |
| graphics.getClip(rect); |
| int x = (int) (rect.x / xZoom); |
| int y = (int) (rect.y / yZoom); |
| /* |
| * If the clip rectangle is queried, perform an inverse zoom, and take |
| * the ceiling of the resulting double. This is necessary because |
| * forward scaling essentially performs a floor() function. Without |
| * this, figures will think that they don't need to paint when actually |
| * they do. |
| */ |
| rect.width = (int) Math.ceil(rect.right() / xZoom) - x; |
| rect.height = (int) Math.ceil(rect.bottom() / yZoom) - y; |
| rect.x = x; |
| rect.y = y; |
| return rect; |
| } |
| |
| /** |
| * @see Graphics#getFillRule() |
| */ |
| public int getFillRule() { |
| return graphics.getFillRule(); |
| } |
| |
| /** @see Graphics#getFont() */ |
| public Font getFont() { |
| return getLocalFont(); |
| } |
| |
| /** @see Graphics#getFontMetrics() */ |
| public FontMetrics getFontMetrics() { |
| return FigureUtilities.getFontMetrics(localFont); |
| } |
| |
| /** @see Graphics#getForegroundColor() */ |
| public Color getForegroundColor() { |
| return graphics.getForegroundColor(); |
| } |
| |
| /** |
| * @see Graphics#getInterpolation() |
| */ |
| public int getInterpolation() { |
| return graphics.getInterpolation(); |
| } |
| |
| /** |
| * @see Graphics#getLineCap() |
| */ |
| public int getLineCap() { |
| return graphics.getLineCap(); |
| } |
| |
| /** |
| * @see Graphics#getLineJoin() |
| */ |
| public int getLineJoin() { |
| return graphics.getLineJoin(); |
| } |
| |
| /** @see Graphics#getLineStyle() */ |
| public int getLineStyle() { |
| return graphics.getLineStyle(); |
| } |
| |
| /** @see Graphics#getLineWidth() */ |
| public int getLineWidth() { |
| return getLocalLineWidth(); |
| } |
| |
| private Font getLocalFont() { |
| return localFont; |
| } |
| |
| private int getLocalLineWidth() { |
| return localLineWidth; |
| } |
| |
| /** |
| * @see Graphics#getTextAntialias() |
| */ |
| public int getTextAntialias() { |
| return graphics.getTextAntialias(); |
| } |
| |
| /** @see Graphics#getXORMode() */ |
| public boolean getXORMode() { |
| return graphics.getXORMode(); |
| } |
| |
| /** @see Graphics#popState() */ |
| public void popState() { |
| graphics.popState(); |
| stackPointer--; |
| restoreLocalState((State) stack.get(stackPointer)); |
| } |
| |
| /** @see Graphics#pushState() */ |
| public void pushState() { |
| State s; |
| if (stack.size() > stackPointer) { |
| s = (State) stack.get(stackPointer); |
| s.setValues(xZoom, yZoom, fractionalX, fractionalY, getLocalFont(), localLineWidth); |
| } else { |
| stack.add(new State(xZoom, yZoom, fractionalX, fractionalY, getLocalFont(), localLineWidth)); |
| } |
| stackPointer++; |
| |
| graphics.pushState(); |
| } |
| |
| private void restoreLocalState(State state) { |
| this.fractionalX = state.appliedX; |
| this.fractionalY = state.appliedY; |
| setScale(state.xZoom, state.yZoom); |
| setLocalFont(state.font); |
| setLocalLineWidth(state.lineWidth); |
| } |
| |
| /** @see Graphics#restoreState() */ |
| public void restoreState() { |
| graphics.restoreState(); |
| restoreLocalState((State) stack.get(stackPointer - 1)); |
| } |
| |
| public void scale(double xAmount, double yAmount) { |
| setScale(xZoom * xAmount, yZoom * yAmount); |
| |
| } |
| |
| /** @see Graphics#scale(double) */ |
| public void scale(double amount) { |
| //setScale(zoom * amount); |
| throw new RuntimeException("Operation not supported, use scale(x, y)"); |
| } |
| |
| /** |
| * @see Graphics#setAlpha(int) |
| */ |
| public void setAlpha(int alpha) { |
| graphics.setAlpha(alpha); |
| } |
| |
| /** |
| * @see Graphics#setAntialias(int) |
| */ |
| public void setAntialias(int value) { |
| graphics.setAntialias(value); |
| } |
| |
| /** @see Graphics#setBackgroundColor(Color) */ |
| public void setBackgroundColor(Color rgb) { |
| graphics.setBackgroundColor(rgb); |
| } |
| |
| /** @see Graphics#setClip(Rectangle) */ |
| public void setClip(Rectangle r) { |
| graphics.setClip(zoomClipRect(r)); |
| } |
| |
| /** |
| * @see Graphics#setFillRule(int) |
| */ |
| public void setFillRule(int rule) { |
| graphics.setFillRule(rule); |
| } |
| |
| /** @see Graphics#setFont(Font) */ |
| public void setFont(Font f) { |
| setLocalFont(f); |
| } |
| |
| /** @see Graphics#setForegroundColor(Color) */ |
| public void setForegroundColor(Color rgb) { |
| graphics.setForegroundColor(rgb); |
| } |
| |
| /** |
| * @see org.eclipse.draw2d.Graphics#setInterpolation(int) |
| */ |
| public void setInterpolation(int interpolation) { |
| graphics.setInterpolation(interpolation); |
| } |
| |
| /** |
| * @see Graphics#setLineCap(int) |
| */ |
| public void setLineCap(int cap) { |
| graphics.setLineCap(cap); |
| } |
| |
| /** |
| * @see Graphics#setLineDash(int[]) |
| */ |
| public void setLineDash(int[] dash) { |
| graphics.setLineDash(dash); |
| } |
| |
| /** |
| * @see Graphics#setLineJoin(int) |
| */ |
| public void setLineJoin(int join) { |
| graphics.setLineJoin(join); |
| } |
| |
| /** @see Graphics#setLineStyle(int) */ |
| public void setLineStyle(int style) { |
| graphics.setLineStyle(style); |
| } |
| |
| /** @see Graphics#setLineWidth(int) */ |
| public void setLineWidth(int width) { |
| setLocalLineWidth(width); |
| } |
| |
| private void setLocalFont(Font f) { |
| localFont = f; |
| graphics.setFont(zoomFont(f)); |
| } |
| |
| private void setLocalLineWidth(int width) { |
| localLineWidth = width; |
| graphics.setLineWidth(zoomLineWidth(width)); |
| } |
| |
| public void setScale(double xValue, double yValue) { |
| if (xValue == xZoom && yValue == yZoom) { |
| return; |
| } |
| this.xZoom = xValue; |
| this.yZoom = yValue; |
| graphics.setFont(zoomFont(getLocalFont())); |
| graphics.setLineWidth(zoomLineWidth(localLineWidth)); |
| } |
| |
| void setScale(double value) { |
| throw new RuntimeException("Operation not supported, use setScale(x,y)"); |
| |
| /* |
| * if (zoom == value) return; this.zoom = value; |
| * graphics.setFont(zoomFont(getLocalFont())); |
| * graphics.setLineWidth(zoomLineWidth(localLineWidth)); |
| */ |
| } |
| |
| /** |
| * @see Graphics#setTextAntialias(int) |
| */ |
| public void setTextAntialias(int value) { |
| graphics.setTextAntialias(value); |
| } |
| |
| /** @see Graphics#setXORMode(boolean) */ |
| public void setXORMode(boolean b) { |
| graphics.setXORMode(b); |
| } |
| |
| /** @see Graphics#translate(int, int) */ |
| public void translate(int dx, int dy) { |
| // fractionalX/Y is the fractional part left over from previous |
| // translates that gets lost in the integer approximation. |
| double dxFloat = dx * xZoom + fractionalX; |
| double dyFloat = dy * yZoom + fractionalY; |
| fractionalX = dxFloat - Math.floor(dxFloat); |
| fractionalY = dyFloat - Math.floor(dyFloat); |
| graphics.translate((int) Math.floor(dxFloat), (int) Math.floor(dyFloat)); |
| } |
| |
| private Rectangle zoomClipRect(Rectangle r) { |
| tempRECT.x = (int) (Math.floor(r.x * xZoom + fractionalX)); |
| tempRECT.y = (int) (Math.floor(r.y * yZoom + fractionalY)); |
| tempRECT.width = (int) (Math.ceil(((r.x + r.width) * xZoom + fractionalX))) - tempRECT.x; |
| tempRECT.height = (int) (Math.ceil(((r.y + r.height) * yZoom + fractionalY))) - tempRECT.y; |
| return tempRECT; |
| } |
| |
| private Rectangle zoomFillRect(int x, int y, int w, int h) { |
| tempRECT.x = (int) (Math.floor((x * xZoom + fractionalX))); |
| tempRECT.y = (int) (Math.floor((y * yZoom + fractionalY))); |
| tempRECT.width = (int) (Math.floor(((x + w - 1) * xZoom + fractionalX))) - tempRECT.x + 1; |
| tempRECT.height = (int) (Math.floor(((y + h - 1) * yZoom + fractionalY))) - tempRECT.y + 1; |
| return tempRECT; |
| } |
| |
| Font zoomFont(Font f) { |
| if (f == null) { |
| f = Display.getCurrent().getSystemFont(); |
| } |
| FontData data = getCachedFontData(f); |
| int zoomedFontHeight = zoomFontHeight(data.getHeight()); |
| allowText = zoomedFontHeight > 0; |
| fontKey.setValues(f, zoomedFontHeight); |
| return getCachedFont(fontKey); |
| } |
| |
| int zoomFontHeight(int height) { |
| double tmp = Math.min(yZoom, xZoom); |
| if (tmp < MAX_TEXT_SIZE) { |
| return (int) (tmp * height); |
| } else { |
| return (int) (height * tmp); |
| } |
| } |
| |
| int zoomLineWidth(int w) { |
| return w; |
| } |
| |
| private int[] zoomPointList(int[] points) { |
| int[] scaled = null; |
| |
| // Look in cache for a integer array with the same length as 'points' |
| for (int i = 0; i < intArrayCache.length; i++) { |
| if (intArrayCache[i].length == points.length) { |
| scaled = intArrayCache[i]; |
| |
| // Move this integer array up one notch in the array |
| if (i != 0) { |
| int[] temp = intArrayCache[i - 1]; |
| intArrayCache[i - 1] = scaled; |
| intArrayCache[i] = temp; |
| } |
| } |
| } |
| |
| // If no match is found, take the one that is last and resize it. |
| if (scaled == null) { |
| intArrayCache[intArrayCache.length - 1] = new int[points.length]; |
| scaled = intArrayCache[intArrayCache.length - 1]; |
| } |
| |
| // Scale the points |
| for (int i = 0; (i + 1) < points.length; i += 2) { |
| scaled[i] = (int) (Math.floor((points[i] * xZoom + fractionalX))); |
| scaled[i + 1] = (int) (Math.floor((points[i + 1] * yZoom + fractionalY))); |
| } |
| return scaled; |
| } |
| |
| private Rectangle zoomRect(int x, int y, int w, int h) { |
| tempRECT.x = (int) (Math.floor(x * xZoom + fractionalX)); |
| tempRECT.y = (int) (Math.floor(y * yZoom + fractionalY)); |
| tempRECT.width = (int) (Math.floor(((x + w) * xZoom + fractionalX))) - tempRECT.x; |
| tempRECT.height = (int) (Math.floor(((y + h) * yZoom + fractionalY))) - tempRECT.y; |
| return tempRECT; |
| } |
| |
| private TextLayout zoomTextLayout(TextLayout layout) { |
| TextLayout zoomed = new TextLayout(Display.getCurrent()); |
| zoomed.setText(layout.getText()); |
| |
| int zoomWidth = -1; |
| |
| if (layout.getWidth() != -1) { |
| zoomWidth = ((int) (layout.getWidth() * xZoom)); |
| } |
| |
| if (zoomWidth < -1 || zoomWidth == 0) { |
| return null; |
| } |
| |
| zoomed.setFont(zoomFont(layout.getFont())); |
| zoomed.setAlignment(layout.getAlignment()); |
| zoomed.setAscent(layout.getAscent()); |
| zoomed.setDescent(layout.getDescent()); |
| zoomed.setOrientation(layout.getOrientation()); |
| zoomed.setSegments(layout.getSegments()); |
| zoomed.setSpacing(layout.getSpacing()); |
| zoomed.setTabs(layout.getTabs()); |
| |
| zoomed.setWidth(zoomWidth); |
| int length = layout.getText().length(); |
| if (length > 0) { |
| int start = 0, offset = 1; |
| TextStyle style = null, lastStyle = layout.getStyle(0); |
| for (; offset <= length; offset++) { |
| if (offset != length && (style = layout.getStyle(offset)) == lastStyle) { |
| continue; |
| } |
| int end = offset - 1; |
| |
| if (lastStyle != null) { |
| TextStyle zoomedStyle = new TextStyle(zoomFont(lastStyle.font), lastStyle.foreground, lastStyle.background); |
| zoomed.setStyle(zoomedStyle, start, end); |
| } |
| lastStyle = style; |
| start = offset; |
| } |
| } |
| return zoomed; |
| } |
| |
| private Point zoomTextPoint(int x, int y) { |
| if (localCache.font != localFont) { |
| //Font is different, re-calculate its height |
| FontMetrics metric = FigureUtilities.getFontMetrics(localFont); |
| // UNSUPPORTED - getDescent() not implemented in RAP |
| // localCache.height = metric.getHeight() - metric.getDescent(); |
| localCache.height = metric.getHeight(); |
| localCache.font = localFont; |
| } |
| if (targetCache.font != graphics.getFont()) { |
| FontMetrics metric = graphics.getFontMetrics(); |
| targetCache.font = graphics.getFont(); |
| // UNSUPPORTED - getDescent() not implemented in RAP |
| // targetCache.height = metric.getHeight() - metric.getDescent(); |
| targetCache.height = metric.getHeight(); |
| } |
| return new Point(((int) (Math.floor((x * xZoom) + fractionalX))), (int) (Math.floor((y + localCache.height - 1) * yZoom - targetCache.height + 1 + fractionalY))); |
| } |
| |
| } |