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