comparison org.eclipse.draw2d/src/org/eclipse/draw2d/ScaledGraphics.d @ 12:bc29606a740c

Added dwt-addons in original directory structure of eclipse.org
author Frank Benoit <benoit@tionex.de>
date Sat, 14 Mar 2009 18:23:29 +0100
parents
children dbfb303e8fb0
comparison
equal deleted inserted replaced
11:43904fec5dca 12:bc29606a740c
1 /*******************************************************************************
2 * Copyright (c) 2000, 2008 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13 module org.eclipse.draw2d.ScaledGraphics;
14
15 import java.lang.all;
16
17 import org.eclipse.swt.SWT;
18 import org.eclipse.swt.graphics.Color;
19 import org.eclipse.swt.graphics.Font;
20 import org.eclipse.swt.graphics.FontData;
21 import org.eclipse.swt.graphics.FontMetrics;
22 import org.eclipse.swt.graphics.Image;
23 import org.eclipse.swt.graphics.Path;
24 import org.eclipse.swt.graphics.PathData;
25 import org.eclipse.swt.graphics.TextLayout;
26 import org.eclipse.swt.graphics.TextStyle;
27 import org.eclipse.swt.widgets.Display;
28 static import org.eclipse.swt.graphics.Rectangle;
29 import org.eclipse.draw2d.geometry.Point;
30 import org.eclipse.draw2d.geometry.PointList;
31 import org.eclipse.draw2d.geometry.Rectangle;
32 import org.eclipse.draw2d.Graphics;
33 import org.eclipse.draw2d.FigureUtilities;
34
35 /**
36 * A Graphics object able to scale all operations based on the current scale factor.
37 */
38 public class ScaledGraphics
39 : Graphics
40 {
41 alias Graphics.translate translate;
42 alias Graphics.fillRectangle fillRectangle;
43
44 private static class FontHeightCache {
45 Font font;
46 int height;
47 }
48
49 static class FontKey {
50 Font font;
51 int height;
52 protected this() { }
53 protected this(Font font, int height) {
54 this.font = font;
55 this.height = height;
56 }
57
58 public override int opEquals(Object obj) {
59 return ((cast(FontKey)obj).font.opEquals(font)
60 && (cast(FontKey)obj).height is height);
61 }
62
63 public override hash_t toHash() {
64 return font.toHash() ^ height;
65 }
66
67 protected void setValues(Font font, int height) {
68 this.font = font;
69 this.height = height;
70 }
71 }
72
73 /**
74 * The internal state of the scaled graphics.
75 */
76 protected static class State {
77 private double appliedX;
78 private double appliedY;
79 private Font font;
80 private int lineWidth;
81 private double zoom;
82
83 /**
84 * Constructs a new, uninitialized State object.
85 */
86 protected this() { }
87
88 /**
89 * Constructs a new State object and initializes the properties based on the given
90 * values.
91 *
92 * @param zoom the zoom factor
93 * @param x the x offset
94 * @param y the y offset
95 * @param font the font
96 * @param lineWidth the line width
97 */
98 protected this(double zoom, double x, double y, Font font, int lineWidth) {
99 this.zoom = zoom;
100 this.appliedX = x;
101 this.appliedY = y;
102 this.font = font;
103 this.lineWidth = lineWidth;
104 }
105
106 /**
107 * Sets all the properties of the state object.
108 * @param zoom the zoom factor
109 * @param x the x offset
110 * @param y the y offset
111 * @param font the font
112 * @param lineWidth the line width
113 */
114 protected void setValues(double zoom, double x, double y,
115 Font font, int lineWidth) {
116 this.zoom = zoom;
117 this.appliedX = x;
118 this.appliedY = y;
119 this.font = font;
120 this.lineWidth = lineWidth;
121 }
122 }
123
124 private static int[][] intArrayCache_;
125 private static int[][] intArrayCache(){
126 if( intArrayCache_ is null ){
127 synchronized( ScaledGraphics.classinfo ){
128 if( intArrayCache_ is null ){
129 intArrayCache_ = new int[][](8);
130 for (int i = 0; i < intArrayCache_.length; i++)
131 intArrayCache_[i] = new int[i + 1];
132 }
133 }
134 }
135 return intArrayCache_;
136 }
137 private const Rectangle tempRECT;
138
139 private bool allowText = true;
140 //private static final Point PT = new Point();
141 private Map fontCache;
142 private Map fontDataCache;
143 private FontKey fontKey;
144 private double fractionalX;
145 private double fractionalY;
146 private Graphics graphics;
147 private FontHeightCache localCache;
148 private Font localFont;
149 private int localLineWidth;
150 private List stack;
151 private int stackPointer = 0;
152 private FontHeightCache targetCache;
153
154 double zoom = 1.0;
155
156 /**
157 * Constructs a new ScaledGraphics based on the given Graphics object.
158 * @param g the base graphics object
159 */
160 public this(Graphics g) {
161 // instance init
162 tempRECT = new Rectangle();
163 localCache = new FontHeightCache();
164 targetCache = new FontHeightCache();
165 stack = new ArrayList();
166 fontKey = new FontKey();
167 fontDataCache = new HashMap();
168 fontCache = new HashMap();
169
170 graphics = g;
171 localFont = g.getFont();
172 localLineWidth = g.getLineWidth();
173 }
174
175 /** @see Graphics#clipRect(Rectangle) */
176 public void clipRect(Rectangle r) {
177 graphics.clipRect(zoomClipRect(r));
178 }
179
180 Font createFont(FontData data) {
181 return new Font(Display.getCurrent(), data);
182 }
183
184 private Path createScaledPath(Path path) {
185 PathData p = path.getPathData();
186 for (int i = 0; i < p.points.length; i += 2) {
187 p.points[i] = cast(float) (p.points[i] * zoom + fractionalX);
188 p.points[i + 1] = cast(float) (p.points[i + 1] * zoom + fractionalY);
189 }
190 Path scaledPath = new Path(path.getDevice());
191 int index = 0;
192 for (int i = 0; i < p.types.length; i++) {
193 byte type = p.types[i];
194 switch (type) {
195 case SWT.PATH_MOVE_TO:
196 scaledPath.moveTo(p.points[index], p.points[index + 1]);
197 index += 2;
198 break;
199 case SWT.PATH_LINE_TO:
200 scaledPath.lineTo(p.points[index], p.points[index + 1]);
201 index += 2;
202 break;
203 case SWT.PATH_CUBIC_TO:
204 scaledPath.cubicTo(p.points[index], p.points[index + 1],
205 p.points[index + 2], p.points[index + 3], p.points[index + 4],
206 p.points[index + 5]);
207 index += 6;
208 break;
209 case SWT.PATH_QUAD_TO:
210 scaledPath.quadTo(p.points[index], p.points[index + 1],
211 p.points[index + 2], p.points[index + 3]);
212 index += 4;
213 break;
214 case SWT.PATH_CLOSE:
215 scaledPath.close();
216 break;
217 default:
218 }
219 }
220 return scaledPath;
221 }
222
223 /** @see Graphics#dispose() */
224 public void dispose() {
225 //Remove all states from the stack
226 while (stackPointer > 0) {
227 popState();
228 }
229
230 //Dispose fonts
231 Iterator iter = fontCache.values().iterator();
232 while (iter.hasNext()) {
233 Font font = (cast(Font)iter.next());
234 font.dispose();
235 }
236
237 }
238
239 /** @see Graphics#drawArc(int, int, int, int, int, int) */
240 public void drawArc(int x, int y, int w, int h, int offset, int sweep) {
241 Rectangle z = zoomRect(x, y, w, h);
242 if (z.isEmpty() || sweep is 0)
243 return;
244 graphics.drawArc(z, offset, sweep);
245 }
246
247 /** @see Graphics#drawFocus(int, int, int, int) */
248 public void drawFocus(int x, int y, int w, int h) {
249 graphics.drawFocus(zoomRect(x, y, w, h));
250 }
251
252 /** @see Graphics#drawImage(Image, int, int) */
253 public void drawImage(Image srcImage, int x, int y) {
254 org.eclipse.swt.graphics.Rectangle.Rectangle size = srcImage.getBounds();
255 graphics.drawImage(srcImage, 0, 0, size.width, size.height,
256 cast(int)(Math.floor((x * zoom + fractionalX))),
257 cast(int)(Math.floor((y * zoom + fractionalY))),
258 cast(int)(Math.floor((size.width * zoom + fractionalX))),
259 cast(int)(Math.floor((size.height * zoom + fractionalY))));
260 }
261
262 /** @see Graphics#drawImage(Image, int, int, int, int, int, int, int, int) */
263 public void drawImage(Image srcImage, int sx, int sy, int sw, int sh,
264 int tx, int ty, int tw, int th) {
265 //"t" is target rectangle, "s" = source
266
267 Rectangle t = zoomRect(tx, ty, tw, th);
268 if (!t.isEmpty())
269 graphics.drawImage(srcImage, sx, sy, sw, sh, t.x, t.y, t.width, t.height);
270 }
271
272 /** @see Graphics#drawLine(int, int, int, int) */
273 public void drawLine(int x1, int y1, int x2, int y2) {
274 graphics.drawLine(
275 cast(int)(Math.floor((x1 * zoom + fractionalX))),
276 cast(int)(Math.floor((y1 * zoom + fractionalY))),
277 cast(int)(Math.floor((x2 * zoom + fractionalX))),
278 cast(int)(Math.floor((y2 * zoom + fractionalY))));
279 }
280
281 /** @see Graphics#drawOval(int, int, int, int) */
282 public void drawOval(int x, int y, int w, int h) {
283 graphics.drawOval(zoomRect(x, y, w, h));
284 }
285
286 /** @see Graphics#drawPath(Path) */
287 public void drawPath(Path path) {
288 Path scaledPath = createScaledPath(path);
289 try {
290 graphics.drawPath(scaledPath);
291 } finally {
292 scaledPath.dispose();
293 }
294 }
295
296 /** @see Graphics#drawPoint(int, int) */
297 public void drawPoint(int x, int y) {
298 graphics.drawPoint(cast(int)Math.floor(x * zoom + fractionalX),
299 cast(int)Math.floor(y * zoom + fractionalY));
300 }
301
302 /**
303 * @see Graphics#drawPolygon(int[])
304 */
305 public void drawPolygon(int[] points) {
306 graphics.drawPolygon(zoomPointList(points));
307 }
308
309 /** @see Graphics#drawPolygon(PointList) */
310 public void drawPolygon(PointList points) {
311 graphics.drawPolygon(zoomPointList(points.toIntArray()));
312 }
313
314 /**
315 * @see Graphics#drawPolyline(int[])
316 */
317 public void drawPolyline(int[] points) {
318 graphics.drawPolyline(zoomPointList(points));
319 }
320
321 /** @see Graphics#drawPolyline(PointList) */
322 public void drawPolyline(PointList points) {
323 graphics.drawPolyline(zoomPointList(points.toIntArray()));
324 }
325
326 /** @see Graphics#drawRectangle(int, int, int, int) */
327 public void drawRectangle(int x, int y, int w, int h) {
328 graphics.drawRectangle(zoomRect(x, y, w, h));
329 }
330
331 /** @see Graphics#drawRoundRectangle(Rectangle, int, int) */
332 public void drawRoundRectangle(Rectangle r, int arcWidth, int arcHeight) {
333 graphics.drawRoundRectangle(zoomRect(r.x, r.y, r.width, r.height),
334 cast(int)(arcWidth * zoom),
335 cast(int)(arcHeight * zoom));
336 }
337
338 /** @see Graphics#drawString(String, int, int) */
339 public void drawString(String s, int x, int y) {
340 if (allowText)
341 graphics.drawString(s, zoomTextPoint(x, y));
342 }
343
344 /** @see Graphics#drawText(String, int, int) */
345 public void drawText(String s, int x, int y) {
346 if (allowText)
347 graphics.drawText(s, zoomTextPoint(x, y));
348 }
349
350 /**
351 * @see Graphics#drawText(String, int, int, int)
352 */
353 public void drawText(String s, int x, int y, int style) {
354 if (allowText)
355 graphics.drawText(s, zoomTextPoint(x, y), style);
356 }
357
358 /**
359 * @see Graphics#drawTextLayout(TextLayout, int, int, int, int, Color, Color)
360 */
361 public void drawTextLayout(TextLayout layout, int x, int y, int selectionStart,
362 int selectionEnd, Color selectionForeground, Color selectionBackground) {
363 TextLayout scaled = zoomTextLayout(layout);
364 graphics.drawTextLayout(scaled,
365 cast(int)Math.floor(x * zoom + fractionalX),
366 cast(int)Math.floor(y * zoom + fractionalY),
367 selectionStart, selectionEnd, selectionBackground, selectionForeground);
368 scaled.dispose();
369 }
370
371 /** @see Graphics#fillArc(int, int, int, int, int, int) */
372 public void fillArc(int x, int y, int w, int h, int offset, int sweep) {
373 Rectangle z = zoomFillRect(x, y, w, h);
374 if (z.isEmpty() || sweep is 0)
375 return;
376 graphics.fillArc(z, offset, sweep);
377 }
378
379 /** @see Graphics#fillGradient(int, int, int, int, bool) */
380 public void fillGradient(int x, int y, int w, int h, bool vertical) {
381 graphics.fillGradient(zoomFillRect(x, y, w, h), vertical);
382 }
383
384 /** @see Graphics#fillOval(int, int, int, int) */
385 public void fillOval(int x, int y, int w, int h) {
386 graphics.fillOval(zoomFillRect(x, y, w, h));
387 }
388
389 /** @see Graphics#fillPath(Path) */
390 public void fillPath(Path path) {
391 Path scaledPath = createScaledPath(path);
392 try {
393 graphics.fillPath(scaledPath);
394 } finally {
395 scaledPath.dispose();
396 }
397 }
398
399 /**
400 * @see Graphics#fillPolygon(int[])
401 */
402 public void fillPolygon(int[] points) {
403 graphics.fillPolygon(zoomPointList(points));
404 }
405
406 /** @see Graphics#fillPolygon(PointList) */
407 public void fillPolygon(PointList points) {
408 graphics.fillPolygon(zoomPointList(points.toIntArray()));
409 }
410
411 /** @see Graphics#fillRectangle(int, int, int, int) */
412 public void fillRectangle(int x, int y, int w, int h) {
413 graphics.fillRectangle(zoomFillRect(x, y, w, h));
414 }
415
416 /** @see Graphics#fillRoundRectangle(Rectangle, int, int) */
417 public void fillRoundRectangle(Rectangle r, int arcWidth, int arcHeight) {
418 graphics.fillRoundRectangle(zoomFillRect(r.x, r.y, r.width, r.height),
419 cast(int)(arcWidth * zoom),
420 cast(int)(arcHeight * zoom));
421 }
422
423 /** @see Graphics#fillString(String, int, int) */
424 public void fillString(String s, int x, int y) {
425 if (allowText)
426 graphics.fillString(s, zoomTextPoint(x, y));
427 }
428
429 /** @see Graphics#fillText(String, int, int) */
430 public void fillText(String s, int x, int y) {
431 if (allowText)
432 graphics.fillText(s, zoomTextPoint(x, y));
433 }
434
435 /**
436 * @see Graphics#getAbsoluteScale()
437 */
438 public double getAbsoluteScale() {
439 return zoom * graphics.getAbsoluteScale();
440 }
441
442 /**
443 * @see Graphics#getAlpha()
444 */
445 public int getAlpha() {
446 return graphics.getAlpha();
447 }
448
449 /**
450 * @see Graphics#getAntialias()
451 */
452 public int getAntialias() {
453 return graphics.getAntialias();
454 }
455
456 /** @see Graphics#getBackgroundColor() */
457 public Color getBackgroundColor() {
458 return graphics.getBackgroundColor();
459 }
460
461 Font getCachedFont(FontKey key) {
462 Font font = cast(Font)fontCache.get(key);
463 if (font !is null)
464 return font;
465 key = new FontKey(key.font, key.height);
466 FontData data = key.font.getFontData()[0];
467 data.setHeight(key.height);
468 Font zoomedFont = createFont(data);
469 fontCache.put(key, zoomedFont);
470 return zoomedFont;
471 }
472
473 FontData getCachedFontData(Font f) {
474 FontData data = cast(FontData)fontDataCache.get(f);
475 if (data !is null)
476 return data;
477 data = getLocalFont().getFontData()[0];
478 fontDataCache.put(f, data);
479 return data;
480 }
481
482 /** @see Graphics#getClip(Rectangle) */
483 public Rectangle getClip(Rectangle rect) {
484 graphics.getClip(rect);
485 int x = cast(int)(rect.x / zoom);
486 int y = cast(int)(rect.y / zoom);
487 /*
488 * If the clip rectangle is queried, perform an inverse zoom, and take the ceiling of
489 * the resulting double. This is necessary because forward scaling essentially performs
490 * a floor() function. Without this, figures will think that they don't need to paint
491 * when actually they do.
492 */
493 rect.width = cast(int)Math.ceil(rect.right() / zoom) - x;
494 rect.height = cast(int)Math.ceil(rect.bottom() / zoom) - y;
495 rect.x = x;
496 rect.y = y;
497 return rect;
498 }
499
500 /**
501 * @see Graphics#getFillRule()
502 */
503 public int getFillRule() {
504 return graphics.getFillRule();
505 }
506
507 /** @see Graphics#getFont() */
508 public Font getFont() {
509 return getLocalFont();
510 }
511
512 /** @see Graphics#getFontMetrics() */
513 public FontMetrics getFontMetrics() {
514 return FigureUtilities.getFontMetrics(localFont);
515 }
516
517 /** @see Graphics#getForegroundColor() */
518 public Color getForegroundColor() {
519 return graphics.getForegroundColor();
520 }
521
522 /**
523 * @see Graphics#getInterpolation()
524 */
525 public int getInterpolation() {
526 return graphics.getInterpolation();
527 }
528
529 /**
530 * @see Graphics#getLineCap()
531 */
532 public int getLineCap() {
533 return graphics.getLineCap();
534 }
535
536 /**
537 * @see Graphics#getLineJoin()
538 */
539 public int getLineJoin() {
540 return graphics.getLineJoin();
541 }
542
543 /** @see Graphics#getLineStyle() */
544 public int getLineStyle() {
545 return graphics.getLineStyle();
546 }
547
548 /** @see Graphics#getLineWidth() */
549 public int getLineWidth() {
550 return getLocalLineWidth();
551 }
552
553 private Font getLocalFont() {
554 return localFont;
555 }
556
557 private int getLocalLineWidth() {
558 return localLineWidth;
559 }
560
561 /**
562 * @see Graphics#getTextAntialias()
563 */
564 public int getTextAntialias() {
565 return graphics.getTextAntialias();
566 }
567
568 /** @see Graphics#getXORMode() */
569 public bool getXORMode() {
570 return graphics.getXORMode();
571 }
572
573 /** @see Graphics#popState() */
574 public void popState() {
575 graphics.popState();
576 stackPointer--;
577 restoreLocalState(cast(State)stack.get(stackPointer));
578 }
579
580 /** @see Graphics#pushState() */
581 public void pushState() {
582 State s;
583 if (stack.size() > stackPointer) {
584 s = cast(State)stack.get(stackPointer);
585 s.setValues(zoom, fractionalX, fractionalY, getLocalFont(), localLineWidth);
586 } else {
587 stack.add(new State(zoom, fractionalX, fractionalY, getLocalFont(),
588 localLineWidth));
589 }
590 stackPointer++;
591
592 graphics.pushState();
593 }
594
595 private void restoreLocalState(State state) {
596 this.fractionalX = state.appliedX;
597 this.fractionalY = state.appliedY;
598 setScale(state.zoom);
599 setLocalFont(state.font);
600 setLocalLineWidth(state.lineWidth);
601 }
602
603 /** @see Graphics#restoreState() */
604 public void restoreState() {
605 graphics.restoreState();
606 restoreLocalState(cast(State)stack.get(stackPointer - 1));
607 }
608
609 /** @see Graphics#scale(double) */
610 public void scale(double amount) {
611 setScale(zoom * amount);
612 }
613
614 /**
615 * @see Graphics#setAlphacast(int)
616 */
617 public void setAlpha(int alpha) {
618 graphics.setAlpha(alpha);
619 }
620
621 /**
622 * @see Graphics#setAntialiascast(int)
623 */
624 public void setAntialias(int value) {
625 graphics.setAntialias(value);
626 }
627
628 /** @see Graphics#setBackgroundColor(Color) */
629 public void setBackgroundColor(Color rgb) {
630 graphics.setBackgroundColor(rgb);
631 }
632
633 /** @see Graphics#setClip(Path) */
634 public void setClip(Path path) {
635 Path scaledPath = createScaledPath(path);
636 try {
637 graphics.setClip(scaledPath);
638 } finally {
639 scaledPath.dispose();
640 }
641 }
642
643 /** @see Graphics#setClip(Rectangle) */
644 public void setClip(Rectangle r) {
645 graphics.setClip(zoomClipRect(r));
646 }
647
648 /**
649 * @see Graphics#setFillRulecast(int)
650 */
651 public void setFillRule(int rule) {
652 graphics.setFillRule(rule);
653 }
654
655 /** @see Graphics#setFontcast(Font) */
656 public void setFont(Font f) {
657 setLocalFont(f);
658 }
659
660 /** @see Graphics#setForegroundColor(Color) */
661 public void setForegroundColor(Color rgb) {
662 graphics.setForegroundColor(rgb);
663 }
664
665 /**
666 * @see org.eclipse.draw2d.Graphics#setInterpolationcast(int)
667 */
668 public void setInterpolation(int interpolation) {
669 graphics.setInterpolation(interpolation);
670 }
671
672 /**
673 * @see Graphics#setLineCapcast(int)
674 */
675 public void setLineCap(int cap) {
676 graphics.setLineCap(cap);
677 }
678
679 /**
680 * @see Graphics#setLineDash(int[])
681 */
682 public void setLineDash(int[] dash) {
683 graphics.setLineDash(dash);
684 }
685
686 /**
687 * @see Graphics#setLineJoincast(int)
688 */
689 public void setLineJoin(int join) {
690 graphics.setLineJoin(join);
691 }
692
693 /** @see Graphics#setLineStylecast(int) */
694 public void setLineStyle(int style) {
695 graphics.setLineStyle(style);
696 }
697
698 /** @see Graphics#setLineWidthcast(int) */
699 public void setLineWidth(int width) {
700 setLocalLineWidth(width);
701 }
702
703 private void setLocalFont(Font f) {
704 localFont = f;
705 graphics.setFont(zoomFont(f));
706 }
707
708 private void setLocalLineWidth(int width) {
709 localLineWidth = width;
710 graphics.setLineWidth(zoomLineWidth(width));
711 }
712
713 void setScale(double value) {
714 if (zoom is value)
715 return;
716 this.zoom = value;
717 graphics.setFont(zoomFont(getLocalFont()));
718 graphics.setLineWidth(zoomLineWidth(localLineWidth));
719 }
720
721 /**
722 * @see Graphics#setTextAntialiascast(int)
723 */
724 public void setTextAntialias(int value) {
725 graphics.setTextAntialias(value);
726 }
727
728 /** @see Graphics#setXORMode(bool) */
729 public void setXORMode(bool b) {
730 graphics.setXORMode(b);
731 }
732
733 /** @see Graphics#translate(int, int) */
734 public void translate(int dx, int dy) {
735 // fractionalX/Y is the fractional part left over from previous
736 // translates that gets lost in the integer approximation.
737 double dxFloat = dx * zoom + fractionalX;
738 double dyFloat = dy * zoom + fractionalY;
739 fractionalX = dxFloat - Math.floor(dxFloat);
740 fractionalY = dyFloat - Math.floor(dyFloat);
741 graphics.translate(cast(int)Math.floor(dxFloat), cast(int)Math.floor(dyFloat));
742 }
743
744 /** @see Graphics#translate(float, float) */
745 public void translate(float dx, float dy) {
746 double dxFloat = dx * zoom + fractionalX;
747 double dyFloat = dy * zoom + fractionalY;
748 fractionalX = dxFloat - Math.floor(dxFloat);
749 fractionalY = dyFloat - Math.floor(dyFloat);
750 graphics.translate(cast(int)Math.floor(dxFloat), cast(int)Math.floor(dyFloat));
751 }
752
753 private Rectangle zoomClipRect(Rectangle r) {
754 tempRECT.x = cast(int)(Math.floor(r.x * zoom + fractionalX));
755 tempRECT.y = cast(int)(Math.floor(r.y * zoom + fractionalY));
756 tempRECT.width = cast(int)(Math.ceil(((r.x + r.width) * zoom + fractionalX))) - tempRECT.x;
757 tempRECT.height = cast(int)(Math.ceil(((r.y + r.height) * zoom + fractionalY))) - tempRECT.y;
758 return tempRECT;
759 }
760
761 private Rectangle zoomFillRect(int x, int y, int w, int h) {
762 tempRECT.x = cast(int)(Math.floor((x * zoom + fractionalX)));
763 tempRECT.y = cast(int)(Math.floor((y * zoom + fractionalY)));
764 tempRECT.width = cast(int)(Math.floor(((x + w - 1) * zoom + fractionalX))) - tempRECT.x + 1;
765 tempRECT.height = cast(int)(Math.floor(((y + h - 1) * zoom + fractionalY))) - tempRECT.y + 1;
766 return tempRECT;
767 }
768
769 Font zoomFont(Font f) {
770 if (f is null)
771 f = Display.getCurrent().getSystemFont();
772 FontData data = getCachedFontData(f);
773 int zoomedFontHeight = zoomFontHeight(data.getHeight());
774 allowText = zoomedFontHeight > 0;
775 fontKey.setValues(f, zoomedFontHeight);
776 return getCachedFont(fontKey);
777 }
778
779 int zoomFontHeight(int height) {
780 return cast(int)(zoom * height);
781 }
782
783 int zoomLineWidth(int w) {
784 return w;
785 }
786
787 private int[] zoomPointList(int[] points) {
788 int[] scaled = null;
789
790 // Look in cache for a integer array with the same length as 'points'
791 for (int i = 0; i < intArrayCache.length; i++) {
792 if (intArrayCache[i].length is points.length) {
793 scaled = intArrayCache[i];
794
795 // Move this integer array up one notch in the array
796 if (i !is 0) {
797 int[] temp = intArrayCache[i - 1];
798 intArrayCache[i - 1] = scaled;
799 intArrayCache[i] = temp;
800 }
801 }
802 }
803
804 // If no match is found, take the one that is last and resize it.
805 if (scaled is null) {
806 intArrayCache[intArrayCache.length - 1] = new int[points.length];
807 scaled = intArrayCache[intArrayCache.length - 1];
808 }
809
810 // Scale the points
811 for (int i = 0; (i + 1) < points.length; i += 2) {
812 scaled[i] = cast(int)(Math.floor((points[i] * zoom + fractionalX)));
813 scaled[i + 1] = cast(int)(Math.floor((points[i + 1] * zoom + fractionalY)));
814 }
815 return scaled;
816 }
817
818 private Rectangle zoomRect(int x, int y, int w, int h) {
819 tempRECT.x = cast(int)(Math.floor(x * zoom + fractionalX));
820 tempRECT.y = cast(int)(Math.floor(y * zoom + fractionalY));
821 tempRECT.width = cast(int)(Math.floor(((x + w) * zoom + fractionalX))) - tempRECT.x;
822 tempRECT.height = cast(int)(Math.floor(((y + h) * zoom + fractionalY))) - tempRECT.y;
823 return tempRECT;
824 }
825
826 private TextLayout zoomTextLayout(TextLayout layout) {
827 TextLayout zoomed = new TextLayout(Display.getCurrent());
828 zoomed.setText(layout.getText());
829
830 int zoomWidth = -1;
831
832 if (layout.getWidth() !is -1)
833 zoomWidth = (cast(int)(layout.getWidth() * zoom));
834
835 if (zoomWidth < -1 || zoomWidth is 0)
836 return null;
837
838 zoomed.setFont(zoomFont(layout.getFont()));
839 zoomed.setAlignment(layout.getAlignment());
840 zoomed.setAscent(layout.getAscent());
841 zoomed.setDescent(layout.getDescent());
842 zoomed.setOrientation(layout.getOrientation());
843 zoomed.setSegments(layout.getSegments());
844 zoomed.setSpacing(layout.getSpacing());
845 zoomed.setTabs(layout.getTabs());
846
847 zoomed.setWidth(zoomWidth);
848 int length = layout.getText().length;
849 if (length > 0) {
850 int start = 0, offset = 1;
851 TextStyle style = null, lastStyle = layout.getStyle(0);
852 for (; offset <= length; offset++) {
853 if (offset !is length
854 && (style = layout.getStyle(offset)) is lastStyle)
855 continue;
856 int end = offset - 1;
857
858 if (lastStyle !is null) {
859 TextStyle zoomedStyle = new TextStyle(zoomFont(lastStyle.font),
860 lastStyle.foreground, lastStyle.background);
861 zoomedStyle.metrics = lastStyle.metrics;
862 zoomedStyle.rise = lastStyle.rise;
863 zoomedStyle.strikeout = lastStyle.strikeout;
864 zoomedStyle.underline = lastStyle.underline;
865 zoomed.setStyle(zoomedStyle, start, end);
866 }
867 lastStyle = style;
868 start = offset;
869 }
870 }
871 return zoomed;
872 }
873
874 private Point zoomTextPoint(int x, int y) {
875 if (localCache.font !is localFont) {
876 //Font is different, re-calculate its height
877 FontMetrics metric = FigureUtilities.getFontMetrics(localFont);
878 localCache.height = metric.getHeight() - metric.getDescent();
879 localCache.font = localFont;
880 }
881 if (targetCache.font !is graphics.getFont()) {
882 FontMetrics metric = graphics.getFontMetrics();
883 targetCache.font = graphics.getFont();
884 targetCache.height = metric.getHeight() - metric.getDescent();
885 }
886 return new Point((cast(int)(Math.floor((x * zoom) + fractionalX))),
887 cast(int)(Math.floor((y + localCache.height - 1) * zoom
888 - targetCache.height + 1 + fractionalY)));
889 }
890
891 }