1 /* 2 * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 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 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.awt.windows; 27 28 import sun.awt.*; 29 import java.awt.*; 30 import java.awt.event.InvocationEvent; 31 import java.awt.peer.ComponentPeer; 32 import java.awt.image.*; 33 34 import sun.awt.image.ByteInterleavedRaster; 35 import sun.security.action.GetPropertyAction; 36 37 import java.awt.peer.FramePeer; 38 import java.security.PrivilegedAction; 39 import java.security.AccessController; 40 41 @SuppressWarnings("serial") // JDK-implementation class 42 public class WEmbeddedFrame extends EmbeddedFrame { 43 44 static { 45 initIDs(); 46 } 47 48 private long handle; 49 50 private int bandWidth = 0; 51 private int bandHeight = 0; 52 private int imgWid = 0; 53 private int imgHgt = 0; 54 55 private static int pScale = 0; 56 private static final int MAX_BAND_SIZE = (1024*30); 57 58 /** 59 * This flag is set to {@code true} if this embedded frame is hosted by Internet Explorer. 60 */ 61 private boolean isEmbeddedInIE = false; 62 63 private static String printScale = AccessController.doPrivileged( 64 new GetPropertyAction("sun.java2d.print.pluginscalefactor")); 65 66 public WEmbeddedFrame() { 67 this((long)0); 68 } 69 70 /** 71 * @deprecated This constructor will be removed in 1.5 72 */ 73 @Deprecated 74 public WEmbeddedFrame(int handle) { 75 this((long)handle); 76 } 77 78 public WEmbeddedFrame(long handle) { 79 this.handle = handle; 80 if (handle != 0) { 81 addNotify(); 82 show(); 83 } 84 } 85 86 public void addNotify() { 87 if (!isDisplayable()) { 88 WToolkit toolkit = (WToolkit)Toolkit.getDefaultToolkit(); 89 setPeer(toolkit.createEmbeddedFrame(this)); 90 } 91 super.addNotify(); 92 } 93 94 /* 95 * Get the native handle 96 */ 97 public long getEmbedderHandle() { 98 return handle; 99 } 100 101 /* 102 * Print the embedded frame and its children using the specified HDC. 103 */ 104 105 void print(long hdc) { 106 BufferedImage bandImage = null; 107 108 int xscale = 1; 109 int yscale = 1; 110 111 /* Is this is either a printer DC or an enhanced meta file DC ? 112 * Mozilla passes in a printer DC, IE passes plug-in a DC for an 113 * enhanced meta file. Its possible we may be passed to a memory 114 * DC. If we here create a larger image, draw in to it and have 115 * that memory DC then lose the image resolution only to scale it 116 * back up again when sending to a printer it will look really bad. 117 * So, is this is either a printer DC or an enhanced meta file DC ? 118 * Scale only if it is. Use a 4x scale factor, partly since for 119 * an enhanced meta file we don't know anything about the 120 * real resolution of the destination. 121 * 122 * For a printer DC we could probably derive the scale factor to use 123 * by querying LOGPIXELSX/Y, and dividing that by the screen 124 * resolution (typically 96 dpi or 120 dpi) but that would typically 125 * make for even bigger output for marginal extra quality. 126 * But for enhanced meta file we don't know anything about the 127 * real resolution of the destination so 128 */ 129 if (isPrinterDC(hdc)) { 130 xscale = yscale = getPrintScaleFactor(); 131 } 132 133 int frameHeight = getHeight(); 134 if (bandImage == null) { 135 bandWidth = getWidth(); 136 if (bandWidth % 4 != 0) { 137 bandWidth += (4 - (bandWidth % 4)); 138 } 139 if (bandWidth <= 0) { 140 return; 141 } 142 143 bandHeight = Math.min(MAX_BAND_SIZE/bandWidth, frameHeight); 144 145 imgWid = bandWidth * xscale; 146 imgHgt = bandHeight * yscale; 147 bandImage = new BufferedImage(imgWid, imgHgt, 148 BufferedImage.TYPE_3BYTE_BGR); 149 } 150 151 Graphics clearGraphics = bandImage.getGraphics(); 152 clearGraphics.setColor(Color.white); 153 Graphics2D g2d = (Graphics2D)bandImage.getGraphics(); 154 g2d.translate(0, imgHgt); 155 g2d.scale(xscale, -yscale); 156 157 ByteInterleavedRaster ras = (ByteInterleavedRaster)bandImage.getRaster(); 158 byte[] data = ras.getDataStorage(); 159 160 for (int bandTop = 0; bandTop < frameHeight; bandTop += bandHeight) { 161 clearGraphics.fillRect(0, 0, bandWidth, bandHeight); 162 163 printComponents(g2d); 164 int imageOffset =0; 165 int currBandHeight = bandHeight; 166 int currImgHeight = imgHgt; 167 if ((bandTop+bandHeight) > frameHeight) { 168 // last band 169 currBandHeight = frameHeight - bandTop; 170 currImgHeight = currBandHeight*yscale; 171 172 // multiply by 3 because the image is a 3 byte BGR 173 imageOffset = imgWid*(imgHgt-currImgHeight)*3; 174 } 175 176 printBand(hdc, data, imageOffset, 177 0, 0, imgWid, currImgHeight, 178 0, bandTop, bandWidth, currBandHeight); 179 g2d.translate(0, -bandHeight); 180 } 181 } 182 183 protected static int getPrintScaleFactor() { 184 // check if value is already cached 185 if (pScale != 0) 186 return pScale; 187 if (printScale == null) { 188 // if no system property is specified, 189 // check for environment setting 190 printScale = AccessController.doPrivileged( 191 new PrivilegedAction<String>() { 192 public String run() { 193 return System.getenv("JAVA2D_PLUGIN_PRINT_SCALE"); 194 } 195 } 196 ); 197 } 198 int default_printDC_scale = 4; 199 int scale = default_printDC_scale; 200 if (printScale != null) { 201 try { 202 scale = Integer.parseInt(printScale); 203 if (scale > 8 || scale < 1) { 204 scale = default_printDC_scale; 205 } 206 } catch (NumberFormatException nfe) { 207 } 208 } 209 pScale = scale; 210 return pScale; 211 } 212 213 214 private native boolean isPrinterDC(long hdc); 215 216 private native void printBand(long hdc, byte[] data, int offset, int sx, 217 int sy, int swidth, int sheight, int dx, 218 int dy, int dwidth, int dheight); 219 220 /** 221 * Initialize JNI field IDs 222 */ 223 private static native void initIDs(); 224 225 /** 226 * This method is called from the native code when this embedded 227 * frame should be activated. It is expected to be overridden in 228 * subclasses, for example, in plugin to activate the browser 229 * window that contains this embedded frame. 230 * 231 * NOTE: This method may be called by privileged threads. 232 * DO NOT INVOKE CLIENT CODE ON THIS THREAD! 233 */ 234 public void activateEmbeddingTopLevel() { 235 } 236 237 public void synthesizeWindowActivation(final boolean activate) { 238 final FramePeer peer = AWTAccessor.getComponentAccessor().getPeer(this); 239 if (!activate || EventQueue.isDispatchThread()) { 240 peer.emulateActivation(activate); 241 } else { 242 // To avoid focus concurrence b/w IE and EmbeddedFrame 243 // activation is postponed by means of posting it to EDT. 244 Runnable r = new Runnable() { 245 public void run() { 246 peer.emulateActivation(true); 247 } 248 }; 249 WToolkit.postEvent(WToolkit.targetToAppContext(this), 250 new InvocationEvent(this, r)); 251 } 252 } 253 254 public boolean requestFocusToEmbedder() { 255 if (isEmbeddedInIE) { 256 final WEmbeddedFramePeer peer = AWTAccessor.getComponentAccessor() 257 .getPeer(this); 258 return peer.requestFocusToEmbedder(); 259 } 260 return false; 261 } 262 263 public void registerAccelerator(AWTKeyStroke stroke) {} 264 public void unregisterAccelerator(AWTKeyStroke stroke) {} 265 266 /** 267 * Should be overridden in subclasses. Call to 268 * super.notifyModalBlocked(blocker, blocked) must be present 269 * when overriding. 270 * It may occur that embedded frame is not put into its 271 * container at the moment when it is blocked, for example, 272 * when running an applet in IE. Then the call to this method 273 * should be delayed until embedded frame is reparented. 274 * 275 * NOTE: This method may be called by privileged threads. 276 * DO NOT INVOKE CLIENT CODE ON THIS THREAD! 277 */ 278 public void notifyModalBlocked(Dialog blocker, boolean blocked) { 279 try { 280 ComponentPeer thisPeer = (ComponentPeer)WToolkit.targetToPeer(this); 281 ComponentPeer blockerPeer = (ComponentPeer)WToolkit.targetToPeer(blocker); 282 notifyModalBlockedImpl((WEmbeddedFramePeer)thisPeer, 283 (WWindowPeer)blockerPeer, blocked); 284 } catch (Exception z) { 285 z.printStackTrace(System.err); 286 } 287 } 288 native void notifyModalBlockedImpl(WEmbeddedFramePeer peer, WWindowPeer blockerPeer, boolean blocked); 289 }