|
1 /* |
|
2 * Copyright (c) 2009,2010 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 package javax.microedition.lcdui; |
|
18 |
|
19 import org.eclipse.swt.widgets.Control; |
|
20 import org.eclipse.swt.graphics.Point; |
|
21 import org.eclipse.swt.graphics.Rectangle; |
|
22 import org.eclipse.swt.internal.qt.graphics.GraphicsContext; |
|
23 import org.eclipse.swt.internal.qt.graphics.JavaCommandBuffer; |
|
24 import org.eclipse.swt.internal.qt.graphics.WindowSurface; |
|
25 |
|
26 /** |
|
27 * This class works a proxy between instances of Graphics class and common graphics |
|
28 * (command buffer and GraphicsContext). The relation of this class to Graphics is one-to-many, i.e. |
|
29 * one GraphicsBuffer instance handles multiple Graphics instances. |
|
30 * |
|
31 * Each LCDUI API class instance providing access to Graphics (Image, Canvas, GameCanvas, CustomItem), |
|
32 * must instantiate one GraphicsBuffer and use it for creating instances of Graphics class. |
|
33 * |
|
34 * The implementation is not thread safe, thus all serialization must be implemented in |
|
35 * callers, for instance the Graphics implementation serializes all calls to this class. |
|
36 * Furthermore this class does not take care of switching to UI thread, it must be done by |
|
37 * caller object. |
|
38 */ |
|
39 |
|
40 abstract class Buffer |
|
41 { |
|
42 |
|
43 // Constants for buffer host types |
|
44 final static int HOST_TYPE_IMAGE = 1; |
|
45 final static int HOST_TYPE_CANVAS = 2; |
|
46 final static int HOST_TYPE_CUSTOMITEM = 3; |
|
47 |
|
48 // Flags for raising settings validation |
|
49 private final static int NONE = 0; |
|
50 private final static int COLOR = 1; |
|
51 private final static int CLIP = 2; |
|
52 private final static int FONT = 4; |
|
53 private final static int STROKESTYLE = 8; |
|
54 private final static int COORS_TRANSLATION = 16; |
|
55 |
|
56 // Graphics settings active in buffer |
|
57 // all values are comparable to those |
|
58 // in Graphics except font which is stored |
|
59 // as handle instead of LCDUI Font |
|
60 private int bufferFontHandle; |
|
61 private int bufferColor; |
|
62 private int bufferStrokeStyle; |
|
63 private int bufferTranslateX; |
|
64 private int bufferTranslateY; |
|
65 private Rectangle bufferClip; |
|
66 |
|
67 private GraphicsContext gc; |
|
68 private JavaCommandBuffer commandBuffer; |
|
69 private Rectangle hostBounds; |
|
70 private Graphics currentClient; |
|
71 private boolean started; |
|
72 private int clientCount; |
|
73 |
|
74 // The target window surface where this |
|
75 // instance flushes draw primitives |
|
76 WindowSurface windowSurface; |
|
77 |
|
78 /** |
|
79 * Constructor |
|
80 */ |
|
81 protected Buffer() |
|
82 { |
|
83 hostBounds = new Rectangle(0,0,0,0); |
|
84 bufferClip = new Rectangle(0,0,0,0); |
|
85 bufferFontHandle = 0; |
|
86 bufferColor = 0xff000000; |
|
87 bufferStrokeStyle = Graphics.SOLID; |
|
88 bufferTranslateX = 0; |
|
89 bufferTranslateY = 0; |
|
90 } |
|
91 |
|
92 /** |
|
93 * Initializes data, called once |
|
94 */ |
|
95 void init() |
|
96 { |
|
97 clientCount = 0; |
|
98 gc = new GraphicsContext(); |
|
99 commandBuffer = new JavaCommandBuffer(); |
|
100 gc.bindTarget(commandBuffer); |
|
101 writeControlBoundsToBuffer(false); |
|
102 started = true; |
|
103 } |
|
104 |
|
105 /** |
|
106 * Defines the bounds of the host. |
|
107 * Bounds are used for restricting the rendering in |
|
108 * the area of the control that is being updated. With Images |
|
109 * the bounds are not used. |
|
110 * |
|
111 * @param crtl The Control of the host |
|
112 * @param clienArea The area of the control which can be drawn by Graphics |
|
113 */ |
|
114 void setControlBounds(final Control control) |
|
115 { |
|
116 ESWTUIThreadRunner.safeSyncExec(new Runnable() |
|
117 { |
|
118 public void run() |
|
119 { |
|
120 // This implementation is based on the fact that |
|
121 // the QWindowSurface has the size of the shell active area |
|
122 // not the whole display, thus Shell clientArea equals QWindowSurface. |
|
123 // This might change in future if/when Qt starts |
|
124 // rendering e.g. the status pane i.e. the whole display |
|
125 // to window surface |
|
126 Point controlLoc = control.toDisplay(0,0); |
|
127 Point shellLoc = control.getShell().toDisplay(0,0); |
|
128 hostBounds.x = controlLoc.x - shellLoc.x; |
|
129 hostBounds.y = controlLoc.y - shellLoc.y; |
|
130 hostBounds.width = control.getBounds().width; |
|
131 hostBounds.height = control.getBounds().height; |
|
132 } |
|
133 }); |
|
134 } |
|
135 |
|
136 /** |
|
137 * Performs binding to target in host specific way |
|
138 */ |
|
139 abstract void bindToHost(GraphicsContext gc); |
|
140 |
|
141 /** |
|
142 * Getter for the host of the buffer |
|
143 * @return The host |
|
144 */ |
|
145 abstract Object getHost(); |
|
146 |
|
147 /** |
|
148 * Getter for the host type |
|
149 * @return One of host types defined in this class |
|
150 */ |
|
151 abstract int getHostType(); |
|
152 |
|
153 /** |
|
154 * Setups the window surface if not setup already. |
|
155 * This method must be called before flushing buffer to |
|
156 * window surface |
|
157 * Note. must be called in UI thread |
|
158 */ |
|
159 abstract void setupWindowSurface(); |
|
160 |
|
161 /** |
|
162 * Creates and returns new Graphics instance |
|
163 * @return new Graphics instance |
|
164 */ |
|
165 Graphics getGraphics() |
|
166 { |
|
167 if(!started) |
|
168 { |
|
169 init(); |
|
170 } |
|
171 clientCount++; |
|
172 return new Graphics(this); |
|
173 } |
|
174 |
|
175 /** |
|
176 * Synchronizes this buffer with the actual target |
|
177 * must be called in UI thread. If no Graphics instances |
|
178 * are creates, sync has no effect |
|
179 */ |
|
180 void sync() |
|
181 { |
|
182 if(!started) |
|
183 { |
|
184 return; |
|
185 } |
|
186 // if there's nothing to flush return |
|
187 if(!commandBuffer.containsDrawnPrimitives()) |
|
188 { |
|
189 return; |
|
190 } |
|
191 doRelease(); |
|
192 bindToHost(gc); |
|
193 gc.render(commandBuffer); |
|
194 doRelease(); |
|
195 |
|
196 // Reset commands |
|
197 commandBuffer.reset(); |
|
198 |
|
199 // Write last settings to buffer |
|
200 // as they are reset in bind |
|
201 gc.bindTarget(commandBuffer); |
|
202 gc.setFont(bufferFontHandle); |
|
203 gc.setBackgroundColor(bufferColor, true); |
|
204 gc.setForegroundColor(bufferColor, true); |
|
205 writeControlBoundsToBuffer(true); |
|
206 } |
|
207 |
|
208 /** |
|
209 * Decreases the client reference count, |
|
210 * should be called by Graphics instances when |
|
211 * they are about to be disposed |
|
212 */ |
|
213 void removeRef() |
|
214 { |
|
215 clientCount--; |
|
216 } |
|
217 |
|
218 /** |
|
219 * Disposes this instance |
|
220 */ |
|
221 void dispose() |
|
222 { |
|
223 doRelease(); |
|
224 gc.dispose(); |
|
225 gc = null; |
|
226 commandBuffer = null; |
|
227 } |
|
228 |
|
229 void copyArea(int x1, int y1, int width, int height, int x2, int y2, Graphics client) |
|
230 { |
|
231 gc.copyArea(x1, y1, width, height, x2, y2); |
|
232 } |
|
233 |
|
234 void fillRect(int x, int y, int w, int h, Graphics client) |
|
235 { |
|
236 validateAndApplySettings((COLOR|CLIP|COORS_TRANSLATION), client); |
|
237 gc.fillRect(x, y, w, h); |
|
238 } |
|
239 |
|
240 void fillRoundRect(int x, int y, int w, int h, int arcW, int arcH, Graphics client) |
|
241 { |
|
242 validateAndApplySettings((COLOR|CLIP|COORS_TRANSLATION), client); |
|
243 gc.fillRoundRect(x, y, w, h, arcW, arcH); |
|
244 } |
|
245 |
|
246 void fillArc(int x, int y, int w, int h, int startAngle, int arcAngle, Graphics client) |
|
247 { |
|
248 validateAndApplySettings((COLOR|CLIP|COORS_TRANSLATION), client); |
|
249 gc.fillArc(x, y, w, h, startAngle, arcAngle); |
|
250 } |
|
251 |
|
252 void fillTriangle(int[] points, Graphics client) |
|
253 { |
|
254 validateAndApplySettings((COLOR|CLIP|COORS_TRANSLATION), client); |
|
255 gc.fillPolygon(points); |
|
256 } |
|
257 |
|
258 void setClip(int x, int y, int w, int h, Graphics client) |
|
259 { |
|
260 validateAndApplySettings(COORS_TRANSLATION, client); |
|
261 // check if given clip is already active in buffer |
|
262 if((bufferClip.x == x) && (bufferClip.y == y) && |
|
263 (bufferClip.width == w) && (bufferClip.height== h)) |
|
264 { |
|
265 return; |
|
266 } |
|
267 // Images do not need special handling |
|
268 if(getHostType() == HOST_TYPE_IMAGE) |
|
269 { |
|
270 gc.setClip(x, y, w, h, false); |
|
271 return; |
|
272 } |
|
273 |
|
274 // translate clip to display coordinates and apply |
|
275 Rectangle rect = clipToDisplayCoords(x, y, w, h); |
|
276 if(rect.isEmpty()) |
|
277 { |
|
278 // check is buffer clip is already up to date |
|
279 if(bufferClip.isEmpty()) |
|
280 { |
|
281 return; |
|
282 } |
|
283 else |
|
284 { |
|
285 // This is a special case, where the clip defines |
|
286 // an area outside control bounds and due to that the clip |
|
287 // is set to zero size, in order t prevent drawing on top of other controls. |
|
288 // In all other cases the buffer clip is always set |
|
289 // to the same values as the client, i.e. Graphics has. |
|
290 // So by setting the bufferClip here to zero means that the clip |
|
291 // in Graphics and the buffer are not in sync and not comparable, |
|
292 // however they will be back in sync when client sets clip |
|
293 // with an area partly or completely inside the host control. |
|
294 bufferClip = rect; |
|
295 } |
|
296 } |
|
297 else |
|
298 { |
|
299 bufferClip.x = x; |
|
300 bufferClip.y = y; |
|
301 bufferClip.width = w; |
|
302 bufferClip.height = h; |
|
303 } |
|
304 gc.setClip(rect.x, rect.y, rect.width, rect.height, false); |
|
305 } |
|
306 |
|
307 void setColor(int r, int g, int b, Graphics client) |
|
308 { |
|
309 // check if given color is already active in buffer |
|
310 if(bufferColor == (Graphics.OPAQUE_ALPHA | (r << 16) | (g << 8) | b)) |
|
311 { |
|
312 return; |
|
313 } |
|
314 gc.setForegroundColor(r, g, b); |
|
315 gc.setBackgroundColor(r, g, b); |
|
316 |
|
317 // Cache active color |
|
318 bufferColor = (Graphics.OPAQUE_ALPHA | (r << 16) | (g << 8) | b); |
|
319 } |
|
320 |
|
321 void setFont(int fontHandle, Graphics client) |
|
322 { |
|
323 // check if given font is already active in buffer |
|
324 if(bufferFontHandle == fontHandle) |
|
325 { |
|
326 return; |
|
327 } |
|
328 gc.setFont(fontHandle); |
|
329 // Cache active setting |
|
330 bufferFontHandle = fontHandle; |
|
331 } |
|
332 |
|
333 void setStrokeStyle(int cgfxStyle, int graphicsStyle, Graphics client) |
|
334 { |
|
335 if(bufferStrokeStyle == graphicsStyle) |
|
336 { |
|
337 return; |
|
338 } |
|
339 gc.setStrokeStyle(cgfxStyle); |
|
340 // Cache active setting |
|
341 bufferStrokeStyle = graphicsStyle; |
|
342 } |
|
343 |
|
344 void translate(int xDelta, int yDelta, Graphics client) |
|
345 { |
|
346 if((xDelta == 0) && (yDelta == 0)) |
|
347 { |
|
348 return; |
|
349 } |
|
350 gc.translate(xDelta, yDelta); |
|
351 // Cache active settings |
|
352 bufferTranslateX += xDelta; |
|
353 bufferTranslateY += yDelta; |
|
354 } |
|
355 |
|
356 void drawLine(int xStart, int yStart, int xEnd, int yEnd, Graphics client) |
|
357 { |
|
358 validateAndApplySettings((COLOR|CLIP|COORS_TRANSLATION|STROKESTYLE), client); |
|
359 gc.drawLine(xStart, yStart, xEnd, yEnd); |
|
360 } |
|
361 |
|
362 void drawRect(int x, int y, int w, int h, Graphics client) |
|
363 { |
|
364 validateAndApplySettings((COLOR|CLIP|COORS_TRANSLATION|STROKESTYLE), client); |
|
365 gc.drawRect(x, y, w, h); |
|
366 } |
|
367 |
|
368 void drawRoundRect(int x, int y, int w, int h, int arcW, int arcH, Graphics client) |
|
369 { |
|
370 validateAndApplySettings((COLOR|CLIP|COORS_TRANSLATION|STROKESTYLE), client); |
|
371 gc.drawRoundRect(x, y, w, h, arcW, arcH); |
|
372 } |
|
373 |
|
374 void drawArc(int x, int y, int w, int h, int startAngle, int arcAngle, Graphics client) |
|
375 { |
|
376 validateAndApplySettings((COLOR|CLIP|COORS_TRANSLATION|STROKESTYLE), client); |
|
377 gc.drawArc(x, y, w, h, startAngle, arcAngle); |
|
378 } |
|
379 |
|
380 void drawString(String string, int x, int y, Graphics client) |
|
381 { |
|
382 validateAndApplySettings((COLOR|CLIP|COORS_TRANSLATION|FONT), client); |
|
383 gc.drawString(string, x, y, true); |
|
384 } |
|
385 |
|
386 void drawImage(org.eclipse.swt.internal.qt.graphics.Image image, int x,int y, Graphics client) |
|
387 { |
|
388 validateAndApplySettings((CLIP|COORS_TRANSLATION), client); |
|
389 gc.drawImage(image, x, y); |
|
390 } |
|
391 |
|
392 void drawImage(org.eclipse.swt.internal.qt.graphics.Image image, int xDst, int yDst, |
|
393 int wDst, int hDst, int xSrc, int ySrc, int wSrc, int hSrc, |
|
394 int transform, Graphics client) |
|
395 { |
|
396 validateAndApplySettings((CLIP|COORS_TRANSLATION), client); |
|
397 gc.drawImage(image, xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, transform); |
|
398 } |
|
399 |
|
400 void drawRGB(int[] rgb, |
|
401 int offset, |
|
402 int scanlength, |
|
403 int x, |
|
404 int y, |
|
405 int w, |
|
406 int h, |
|
407 boolean alpha, |
|
408 Graphics client) |
|
409 { |
|
410 validateAndApplySettings((CLIP|COORS_TRANSLATION), client); |
|
411 gc.drawRGB(rgb, offset, scanlength, x, y, w, h, alpha); |
|
412 } |
|
413 |
|
414 void drawRGB(int[] rgb, |
|
415 int offset, |
|
416 int scanlength, |
|
417 int x, |
|
418 int y, |
|
419 int w, |
|
420 int h, |
|
421 boolean alpha, |
|
422 int manipulation, |
|
423 Graphics client) |
|
424 { |
|
425 validateAndApplySettings((CLIP|COORS_TRANSLATION), client); |
|
426 gc.drawRGB(rgb, offset, scanlength, x, y, w, h, alpha, manipulation); |
|
427 } |
|
428 |
|
429 void drawRGB(byte[] rgb, |
|
430 byte[] transparencyMask, |
|
431 int offset, |
|
432 int scanlength, |
|
433 int x, |
|
434 int y, |
|
435 int w, |
|
436 int h, |
|
437 int manipulation, |
|
438 int format, |
|
439 Graphics client) |
|
440 { |
|
441 validateAndApplySettings((CLIP|COORS_TRANSLATION), client); |
|
442 gc.drawRGB(rgb, transparencyMask, offset, scanlength, x, y, w, h, manipulation, format); |
|
443 } |
|
444 |
|
445 void drawRGB(short[] rgb, |
|
446 int offset, |
|
447 int scanlength, |
|
448 int x, |
|
449 int y, |
|
450 int w, |
|
451 int h, |
|
452 boolean alpha, |
|
453 int manipulation, |
|
454 int format, |
|
455 Graphics client) |
|
456 { |
|
457 validateAndApplySettings((CLIP|COORS_TRANSLATION), client); |
|
458 gc.drawRGB(rgb, offset, scanlength, x, y, w, h, alpha, manipulation, format); |
|
459 } |
|
460 |
|
461 void drawPolygon(int[] points, Graphics client) |
|
462 { |
|
463 validateAndApplySettings((COLOR|CLIP|COORS_TRANSLATION|STROKESTYLE), client); |
|
464 gc.drawPolygon(points); |
|
465 } |
|
466 |
|
467 void fillPolygon(int[] points, Graphics client) |
|
468 { |
|
469 validateAndApplySettings((COLOR|CLIP|COORS_TRANSLATION), client); |
|
470 gc.fillPolygon(points); |
|
471 } |
|
472 |
|
473 void setARGBColor(int argb, Graphics client) |
|
474 { |
|
475 if(bufferColor == argb) |
|
476 { |
|
477 return; |
|
478 } |
|
479 gc.setBackgroundColor(argb, true); |
|
480 gc.setForegroundColor(argb, true); |
|
481 // Cache active color |
|
482 bufferColor = argb; |
|
483 } |
|
484 |
|
485 /** |
|
486 * Translates given rectangle to window coordinates. |
|
487 * Coordinate system translation does not affect on this method. |
|
488 * |
|
489 * @param x The x-coordinate of the rectangle |
|
490 * @param y The y-coordinate of the rectangle |
|
491 * @param w The width of the rectangle |
|
492 * @param h The height of the rectangle |
|
493 * @return |
|
494 */ |
|
495 Rectangle toWindowCoordinates(int x, int y, int w, int h) |
|
496 { |
|
497 final int xInDpy = hostBounds.x + x; |
|
498 final int yInDpy = hostBounds.y + y; |
|
499 return new Rectangle(xInDpy, yInDpy, xInDpy + w, yInDpy + h); |
|
500 } |
|
501 |
|
502 |
|
503 /** |
|
504 * Translates given rectangle to display/window surface coordinates |
|
505 * and outlines the clip inside the control bounds. |
|
506 * |
|
507 * @param x The x-coordinate of the rectangle |
|
508 * @param y The y-coordinate of the rectangle |
|
509 * @param w The width of the rectangle |
|
510 * @param h The height of the rectangle |
|
511 * |
|
512 */ |
|
513 private Rectangle clipToDisplayCoords(int x, int y, int w, int h) |
|
514 { |
|
515 // Bottom-right corner of control bounds in window coordinates |
|
516 final int hostX2 = hostBounds.x + hostBounds.width; |
|
517 final int hostY2 = hostBounds.y + hostBounds.height; |
|
518 // clip in window coordinates |
|
519 final int clipX1Dpy = hostBounds.x + bufferTranslateX + x; |
|
520 final int clipY1Dpy = hostBounds.y + bufferTranslateY + y; |
|
521 final int clipX2Dpy = hostBounds.x + bufferTranslateX + x + w; |
|
522 final int clipY2Dpy = hostBounds.y + bufferTranslateY + y + h; |
|
523 int clipX1 = x; |
|
524 int clipY1 = y; |
|
525 int clipX2 = x + w; |
|
526 int clipY2 = y + h; |
|
527 |
|
528 // check if the clip is completely outside of control bounds |
|
529 if(!hostBounds.contains(clipX1Dpy, clipY1Dpy) && !hostBounds.contains(clipX2Dpy, clipY2Dpy)) |
|
530 { |
|
531 return new Rectangle(0,0,0,0); |
|
532 } |
|
533 |
|
534 // At least one corner is inside control bounds so |
|
535 // adjust clip coordinates so that they lie within control bounds |
|
536 clipX1 = clipX1Dpy < hostBounds.x ? (x + (hostBounds.x - clipX1Dpy)) : x; |
|
537 clipX1 = clipX1Dpy > hostX2 ? (x - (clipX1Dpy - hostX2)) : x; |
|
538 clipY1 = clipY1Dpy < hostBounds.y ? (y + (hostBounds.y - clipY1Dpy)) : y; |
|
539 clipY1 = clipY1Dpy > hostY2 ? (y - (clipY1Dpy - hostY2)) : y; |
|
540 |
|
541 clipX2 = clipX2Dpy < hostBounds.x ? (clipX2 + (hostBounds.x - clipX1Dpy)) : clipX2; |
|
542 clipX2 = clipX2Dpy > hostX2 ? (clipX2 - (clipX1Dpy - hostX2)) : clipX2; |
|
543 clipY2 = clipY2Dpy < hostBounds.y ? (clipY2 + (hostBounds.y - clipY1Dpy)) : clipY2; |
|
544 clipY2 = clipY2Dpy > hostY2 ? (clipY2 - (clipY1Dpy - hostY2)) : clipY2; |
|
545 |
|
546 return new Rectangle(clipX1, clipY1, (clipX2 - clipX1) , (clipY1 - clipY2)); |
|
547 } |
|
548 |
|
549 /** |
|
550 * Validates the current settings active in buffer against |
|
551 * caller settings and updated needed settings in buffer when |
|
552 * that is required. This method does not update anything if |
|
553 * there is only one (reference_count == 1)Graphics instance using this buffer. |
|
554 * |
|
555 * @param flags The settings that need to be checked |
|
556 * @param client The Graphics instance that made the call |
|
557 */ |
|
558 private void validateAndApplySettings(int flags, Graphics client) |
|
559 { |
|
560 if(!clientChanged(client)) |
|
561 { |
|
562 return; |
|
563 } |
|
564 if((COLOR & flags) != 0) |
|
565 { |
|
566 if(bufferColor != client.currentColor) |
|
567 { |
|
568 gc.setBackgroundColor(client.currentColor, true); |
|
569 gc.setForegroundColor(client.currentColor, true); |
|
570 bufferColor = client.currentColor; |
|
571 } |
|
572 } |
|
573 if((CLIP & flags) != 0) |
|
574 { |
|
575 if(client.currentClip[0] != bufferClip.x && |
|
576 client.currentClip[1] != bufferClip.y && |
|
577 client.currentClip[2] != bufferClip.width && |
|
578 client.currentClip[3] != bufferClip.height) |
|
579 { |
|
580 |
|
581 Rectangle rect = clipToDisplayCoords(client.currentClip[0], client.currentClip[1], |
|
582 client.currentClip[2], client.currentClip[3]); |
|
583 gc.setClip(rect.x, rect.y, rect.width, rect.height, false); |
|
584 bufferClip.x = client.currentClip[0]; |
|
585 bufferClip.y = client.currentClip[1]; |
|
586 bufferClip.width = client.currentClip[2]; |
|
587 bufferClip.height = client.currentClip[3]; |
|
588 } |
|
589 } |
|
590 if((COORS_TRANSLATION & flags) != 0) |
|
591 { |
|
592 if((bufferTranslateX != client.translateX) && (bufferTranslateY != client.translateY)) |
|
593 { |
|
594 gc.translate((client.translateX - bufferTranslateX), (client.translateY - bufferTranslateY)); |
|
595 bufferTranslateX = client.translateX; |
|
596 bufferTranslateY = client.translateY; |
|
597 } |
|
598 } |
|
599 if((FONT & flags) != 0) |
|
600 { |
|
601 int fontHandle = Font.getESWTFont(client.currentFont).handle; |
|
602 if(bufferFontHandle != fontHandle) |
|
603 { |
|
604 gc.setFont(fontHandle); |
|
605 bufferFontHandle = fontHandle; |
|
606 } |
|
607 } |
|
608 if((STROKESTYLE & flags) != 0) |
|
609 { |
|
610 if(bufferStrokeStyle != client.currentStrokeSyle) |
|
611 { |
|
612 gc.setStrokeStyle(Graphics.mapStrokeStyle(client.currentStrokeSyle)); |
|
613 bufferStrokeStyle = client.currentStrokeSyle; |
|
614 } |
|
615 } |
|
616 } |
|
617 |
|
618 private boolean clientChanged(Graphics client) |
|
619 { |
|
620 if(clientCount == 1) |
|
621 { |
|
622 return false; |
|
623 } |
|
624 if(currentClient != client) |
|
625 { |
|
626 currentClient = client; |
|
627 return true; |
|
628 } |
|
629 return false; |
|
630 } |
|
631 |
|
632 /** |
|
633 * Writes control bounds to buffer, including translation and clip |
|
634 * @param writeClientTranslation If true write also client translation to buffer, otherwise not |
|
635 */ |
|
636 private void writeControlBoundsToBuffer(boolean writeClientTranslation) |
|
637 { |
|
638 if((hostBounds.x != 0) || (hostBounds.y != 0)) |
|
639 { |
|
640 gc.translate(hostBounds.x, hostBounds.y); |
|
641 } |
|
642 gc.setClip(0, 0, hostBounds.width, hostBounds.height, false); |
|
643 // Cache buffer settings |
|
644 bufferClip.x = 0; |
|
645 bufferClip.y = 0; |
|
646 bufferClip.width = hostBounds.width; |
|
647 bufferClip.height = hostBounds.height; |
|
648 // write client translation if requested |
|
649 if(writeClientTranslation) |
|
650 { |
|
651 if((bufferTranslateX != 0) || (bufferTranslateY != 0)) |
|
652 { |
|
653 gc.translate(bufferTranslateX, bufferTranslateY); |
|
654 } |
|
655 } |
|
656 } |
|
657 |
|
658 private void doRelease() |
|
659 { |
|
660 gc.releaseTarget(); |
|
661 } |
|
662 } |