1 /* |
1 /* |
2 * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 package sun.swing; |
26 package sun.swing; |
27 |
27 |
28 import java.awt.BorderLayout; |
28 import java.awt.*; |
29 import java.awt.Color; |
|
30 import java.awt.Component; |
|
31 import java.awt.Container; |
|
32 import java.awt.Dimension; |
|
33 import java.awt.EventQueue; |
|
34 import java.awt.Graphics; |
|
35 import java.awt.Graphics2D; |
|
36 import java.awt.MouseInfo; |
|
37 import java.awt.Point; |
|
38 import java.awt.Rectangle; |
|
39 import java.awt.Window; |
|
40 import java.awt.dnd.DragGestureEvent; |
29 import java.awt.dnd.DragGestureEvent; |
41 import java.awt.dnd.DragGestureListener; |
30 import java.awt.dnd.DragGestureListener; |
42 import java.awt.dnd.DragGestureRecognizer; |
31 import java.awt.dnd.DragGestureRecognizer; |
43 import java.awt.dnd.DragSource; |
32 import java.awt.dnd.DragSource; |
44 import java.awt.dnd.DropTarget; |
33 import java.awt.dnd.DropTarget; |
45 import java.awt.dnd.InvalidDnDOperationException; |
34 import java.awt.dnd.InvalidDnDOperationException; |
46 import java.awt.dnd.peer.DragSourceContextPeer; |
35 import java.awt.dnd.peer.DragSourceContextPeer; |
47 import java.awt.event.ContainerEvent; |
36 import java.awt.event.ContainerEvent; |
48 import java.awt.event.ContainerListener; |
37 import java.awt.event.ContainerListener; |
|
38 import java.awt.geom.AffineTransform; |
49 import java.awt.image.BufferedImage; |
39 import java.awt.image.BufferedImage; |
50 import java.awt.image.DataBufferInt; |
40 import java.awt.image.DataBufferInt; |
51 import java.beans.PropertyChangeEvent; |
41 import java.beans.PropertyChangeEvent; |
52 import java.beans.PropertyChangeListener; |
42 import java.beans.PropertyChangeListener; |
53 import java.security.AccessController; |
43 import java.security.AccessController; |
87 private Component component; |
77 private Component component; |
88 private JPanel contentPane; |
78 private JPanel contentPane; |
89 |
79 |
90 private BufferedImage bbImage; |
80 private BufferedImage bbImage; |
91 |
81 |
92 private volatile int scaleFactor = 1; |
82 private volatile double scaleFactorX; |
|
83 private volatile double scaleFactorY; |
93 |
84 |
94 /** |
85 /** |
95 * {@code copyBufferEnabled}, true by default, defines the following strategy. |
86 * {@code copyBufferEnabled}, true by default, defines the following strategy. |
96 * A duplicating (copy) buffer is created for the original pixel buffer. |
87 * A duplicating (copy) buffer is created for the original pixel buffer. |
97 * The copy buffer is synchronized with the original buffer every time the |
88 * The copy buffer is synchronized with the original buffer every time the |
122 * Constructs a new, initially invisible {@code JLightweightFrame} |
113 * Constructs a new, initially invisible {@code JLightweightFrame} |
123 * instance. |
114 * instance. |
124 */ |
115 */ |
125 public JLightweightFrame() { |
116 public JLightweightFrame() { |
126 super(); |
117 super(); |
|
118 AffineTransform defaultTransform = |
|
119 getGraphicsConfiguration().getDefaultTransform(); |
|
120 scaleFactorX = defaultTransform.getScaleX(); |
|
121 scaleFactorY = defaultTransform.getScaleY(); |
127 copyBufferEnabled = "true".equals(AccessController. |
122 copyBufferEnabled = "true".equals(AccessController. |
128 doPrivileged(new GetPropertyAction("swing.jlf.copyBufferEnabled", "true"))); |
123 doPrivileged(new GetPropertyAction("swing.jlf.copyBufferEnabled", "true"))); |
129 |
124 |
130 add(rootPane, BorderLayout.CENTER); |
125 add(rootPane, BorderLayout.CENTER); |
131 setFocusTraversalPolicy(new LayoutFocusTraversalPolicy()); |
126 setFocusTraversalPolicy(new LayoutFocusTraversalPolicy()); |
155 if (jlf != JLightweightFrame.this) { |
150 if (jlf != JLightweightFrame.this) { |
156 return; |
151 return; |
157 } |
152 } |
158 Point p = SwingUtilities.convertPoint(c, x, y, jlf); |
153 Point p = SwingUtilities.convertPoint(c, x, y, jlf); |
159 Rectangle r = new Rectangle(p.x, p.y, w, h).intersection( |
154 Rectangle r = new Rectangle(p.x, p.y, w, h).intersection( |
160 new Rectangle(0, 0, bbImage.getWidth() / scaleFactor, |
155 new Rectangle(0, 0, |
161 bbImage.getHeight() / scaleFactor)); |
156 (int)Math.round(bbImage.getWidth() / scaleFactorX), |
|
157 (int)Math.round(bbImage.getHeight() / scaleFactorY))); |
162 |
158 |
163 if (!r.isEmpty()) { |
159 if (!r.isEmpty()) { |
164 notifyImageUpdated(r.x, r.y, r.width, r.height); |
160 notifyImageUpdated(r.x, r.y, r.width, r.height); |
165 } |
161 } |
166 }; |
162 }; |
235 public void ungrabFocus() { |
231 public void ungrabFocus() { |
236 if (content != null) content.focusUngrabbed(); |
232 if (content != null) content.focusUngrabbed(); |
237 } |
233 } |
238 |
234 |
239 @Override |
235 @Override |
|
236 @SuppressWarnings("deprecation") |
240 public int getScaleFactor() { |
237 public int getScaleFactor() { |
241 return scaleFactor; |
238 return (int)scaleFactorX; |
|
239 } |
|
240 |
|
241 @Override |
|
242 public double getScaleFactorX() { |
|
243 return scaleFactorX; |
|
244 } |
|
245 |
|
246 @Override |
|
247 public double getScaleFactorY() { |
|
248 return scaleFactorY; |
242 } |
249 } |
243 |
250 |
244 @Override |
251 @Override |
245 public void notifyDisplayChanged(final int scaleFactor) { |
252 public void notifyDisplayChanged(final int scaleFactor) { |
246 if (scaleFactor != this.scaleFactor) { |
253 notifyDisplayChanged(scaleFactor, scaleFactor); |
|
254 } |
|
255 |
|
256 @Override |
|
257 public void notifyDisplayChanged(final double scaleFactorX, |
|
258 final double scaleFactorY) { |
|
259 if (Double.compare(scaleFactorX, this.scaleFactorX) != 0 || |
|
260 Double.compare(scaleFactorY, this.scaleFactorY) != 0) { |
247 if (!copyBufferEnabled) content.paintLock(); |
261 if (!copyBufferEnabled) content.paintLock(); |
248 try { |
262 try { |
249 if (bbImage != null) { |
263 if (bbImage != null) { |
250 resizeBuffer(getWidth(), getHeight(), scaleFactor); |
264 resizeBuffer(getWidth(), getHeight(), scaleFactorX, |
|
265 scaleFactorY); |
251 } |
266 } |
252 } finally { |
267 } finally { |
253 if (!copyBufferEnabled) content.paintUnlock(); |
268 if (!copyBufferEnabled) content.paintUnlock(); |
254 } |
269 } |
255 this.scaleFactor = scaleFactor; |
270 this.scaleFactorX = scaleFactorX; |
256 } |
271 this.scaleFactorY = scaleFactorY; |
257 final Object peer = AWTAccessor.getComponentAccessor().getPeer(this); |
272 |
258 if (peer instanceof DisplayChangedListener) { |
273 if(isVisible()) { |
259 ((DisplayChangedListener) peer).displayChanged(); |
274 final Object peer = |
260 } |
275 AWTAccessor.getComponentAccessor().getPeer(this); |
261 repaint(); |
276 if (peer instanceof DisplayChangedListener) { |
|
277 ((DisplayChangedListener) peer).displayChanged(); |
|
278 } |
|
279 repaint(); |
|
280 } |
|
281 } |
262 } |
282 } |
263 |
283 |
264 @Override |
284 @Override |
265 public void addNotify() { |
285 public void addNotify() { |
266 super.addNotify(); |
286 super.addNotify(); |
268 if (peer instanceof DisplayChangedListener) { |
288 if (peer instanceof DisplayChangedListener) { |
269 ((DisplayChangedListener) peer).displayChanged(); |
289 ((DisplayChangedListener) peer).displayChanged(); |
270 } |
290 } |
271 } |
291 } |
272 |
292 |
273 private void syncCopyBuffer(boolean reset, int x, int y, int w, int h, int scale) { |
293 private void syncCopyBuffer(boolean reset, int x, int y, int w, int h, |
|
294 double scaleX, double scaleY) { |
274 content.paintLock(); |
295 content.paintLock(); |
275 try { |
296 try { |
276 int[] srcBuffer = ((DataBufferInt)bbImage.getRaster().getDataBuffer()).getData(); |
297 int[] srcBuffer = ((DataBufferInt)bbImage.getRaster().getDataBuffer()).getData(); |
277 if (reset) { |
298 if (reset) { |
278 copyBuffer = new int[srcBuffer.length]; |
299 copyBuffer = new int[srcBuffer.length]; |
279 } |
300 } |
280 int linestride = bbImage.getWidth(); |
301 int linestride = bbImage.getWidth(); |
281 |
302 |
282 x *= scale; |
303 int startX = (int)Math.floor(x * scaleX); |
283 y *= scale; |
304 int startY = (int)Math.floor(y * scaleY); |
284 w *= scale; |
305 int width = (int)Math.ceil((x + w) * scaleX) - startX; |
285 h *= scale; |
306 int height = (int)Math.ceil((y + h) * scaleY) - startY; |
286 |
307 |
287 for (int i=0; i<h; i++) { |
308 for (int i = 0; i < height; i++) { |
288 int from = (y + i) * linestride + x; |
309 int from = (startY + i) * linestride + startX; |
289 System.arraycopy(srcBuffer, from, copyBuffer, from, w); |
310 System.arraycopy(srcBuffer, from, copyBuffer, from, width); |
290 } |
311 } |
291 } finally { |
312 } finally { |
292 content.paintUnlock(); |
313 content.paintUnlock(); |
293 } |
314 } |
294 } |
315 } |
295 |
316 |
296 private void notifyImageUpdated(int x, int y, int width, int height) { |
317 private void notifyImageUpdated(int x, int y, int width, int height) { |
297 if (copyBufferEnabled) { |
318 if (copyBufferEnabled) { |
298 syncCopyBuffer(false, x, y, width, height, scaleFactor); |
319 syncCopyBuffer(false, x, y, width, height, scaleFactorX, |
|
320 scaleFactorY); |
299 } |
321 } |
300 content.imageUpdated(x, y, width, height); |
322 content.imageUpdated(x, y, width, height); |
301 } |
323 } |
302 |
324 |
303 @SuppressWarnings("serial") // anonymous class inside |
325 @SuppressWarnings("serial") // anonymous class inside |
380 try { |
402 try { |
381 boolean createBB = (bbImage == null); |
403 boolean createBB = (bbImage == null); |
382 int newW = width; |
404 int newW = width; |
383 int newH = height; |
405 int newH = height; |
384 if (bbImage != null) { |
406 if (bbImage != null) { |
385 int imgWidth = bbImage.getWidth() / scaleFactor; |
407 int imgWidth = (int)Math.round(bbImage.getWidth() / |
386 int imgHeight = bbImage.getHeight() / scaleFactor; |
408 scaleFactorX); |
|
409 int imgHeight = (int)Math.round(bbImage.getHeight() / |
|
410 scaleFactorY); |
387 if (width != imgWidth || height != imgHeight) { |
411 if (width != imgWidth || height != imgHeight) { |
388 createBB = true; |
412 createBB = true; |
389 if (bbImage != null) { |
413 if (bbImage != null) { |
390 int oldW = imgWidth; |
414 int oldW = imgWidth; |
391 int oldH = imgHeight; |
415 int oldH = imgHeight; |
417 content.paintUnlock(); |
441 content.paintUnlock(); |
418 } |
442 } |
419 } |
443 } |
420 } |
444 } |
421 |
445 |
422 private void resizeBuffer(int width, int height, int newScaleFactor) { |
446 private void resizeBuffer(int width, int height, double newScaleFactorX, |
423 bbImage = new BufferedImage(width*newScaleFactor,height*newScaleFactor, |
447 double newScaleFactorY) { |
|
448 bbImage = new BufferedImage((int)Math.round(width * newScaleFactorX), |
|
449 (int)Math.round(height * newScaleFactorY), |
424 BufferedImage.TYPE_INT_ARGB_PRE); |
450 BufferedImage.TYPE_INT_ARGB_PRE); |
425 int[] pixels= ((DataBufferInt)bbImage.getRaster().getDataBuffer()).getData(); |
451 int[] pixels= ((DataBufferInt)bbImage.getRaster().getDataBuffer()).getData(); |
426 if (copyBufferEnabled) { |
452 if (copyBufferEnabled) { |
427 syncCopyBuffer(true, 0, 0, width, height, newScaleFactor); |
453 syncCopyBuffer(true, 0, 0, width, height, newScaleFactorX, |
|
454 newScaleFactorY); |
428 pixels = copyBuffer; |
455 pixels = copyBuffer; |
429 } |
456 } |
430 content.imageBufferReset(pixels, 0, 0, width, height, |
457 content.imageBufferReset(pixels, 0, 0, width, height, |
431 width * newScaleFactor, newScaleFactor); |
458 bbImage.getWidth(), newScaleFactorX, newScaleFactorY); |
432 } |
459 } |
433 |
460 |
434 @Override |
461 @Override |
435 public JRootPane getRootPane() { |
462 public JRootPane getRootPane() { |
436 return rootPane; |
463 return rootPane; |