Mercurial > projects > dwt2
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 } |