1 /* 2 * Copyright (c) 1996, 2010, 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.*; 31 import java.awt.peer.ComponentPeer; 32 import java.util.*; 33 import java.awt.color.*; 34 import java.awt.image.*; 35 import sun.awt.image.ByteInterleavedRaster; 36 import sun.security.action.GetPropertyAction; 37 import java.lang.reflect.*; 38 39 public class WEmbeddedFrame extends EmbeddedFrame { 40 41 static { 42 initIDs(); 43 } 44 45 private long handle; 46 47 private int bandWidth = 0; 48 private int bandHeight = 0; 49 private int imgWid = 0; 50 private int imgHgt = 0; 51 52 private static int pScale = 0; 53 private static final int MAX_BAND_SIZE = (1024*30); 54 55 private static String printScale = (String) java.security.AccessController 56 .doPrivileged(new GetPropertyAction("sun.java2d.print.pluginscalefactor")); 57 58 public WEmbeddedFrame() { 59 this((long)0); 60 } 61 62 /** 63 * @deprecated This constructor will be removed in 1.5 64 */ 65 @Deprecated 66 public WEmbeddedFrame(int handle) { 67 this((long)handle); 68 } 69 70 public WEmbeddedFrame(long handle) { 71 this.handle = handle; 72 if (handle != 0) { 73 addNotify(); 74 show(); 75 } 76 } 77 78 public void addNotify() { 79 if (getPeer() == null) { 80 WToolkit toolkit = (WToolkit)Toolkit.getDefaultToolkit(); 81 setPeer(toolkit.createEmbeddedFrame(this)); 82 } 83 super.addNotify(); 84 } 85 86 /* 87 * Get the native handle 88 */ 89 public long getEmbedderHandle() { 90 return handle; 91 } 92 93 /* 94 * Print the embedded frame and its children using the specified HDC. 95 */ 96 97 void print(long hdc) { 98 BufferedImage bandImage = null; 99 100 int xscale = 1; 101 int yscale = 1; 102 103 /* Is this is either a printer DC or an enhanced meta file DC ? 104 * Mozilla passes in a printer DC, IE passes plug-in a DC for an 105 * enhanced meta file. Its possible we may be passed to a memory 106 * DC. If we here create a larger image, draw in to it and have 107 * that memory DC then lose the image resolution only to scale it 108 * back up again when sending to a printer it will look really bad. 109 * So, is this is either a printer DC or an enhanced meta file DC ? 110 * Scale only if it is. Use a 4x scale factor, partly since for 111 * an enhanced meta file we don't know anything about the 112 * real resolution of the destination. 113 * 114 * For a printer DC we could probably derive the scale factor to use 115 * by querying LOGPIXELSX/Y, and dividing that by the screen 116 * resolution (typically 96 dpi or 120 dpi) but that would typically 117 * make for even bigger output for marginal extra quality. 118 * But for enhanced meta file we don't know anything about the 119 * real resolution of the destination so 120 */ 121 if (isPrinterDC(hdc)) { 122 xscale = yscale = getPrintScaleFactor(); 123 } 124 125 int frameHeight = getHeight(); 126 if (bandImage == null) { 127 bandWidth = getWidth(); 128 if (bandWidth % 4 != 0) { 129 bandWidth += (4 - (bandWidth % 4)); 130 } 131 if (bandWidth <= 0) { 132 return; 133 } 134 135 bandHeight = Math.min(MAX_BAND_SIZE/bandWidth, frameHeight); 136 137 imgWid = (int)(bandWidth * xscale); 138 imgHgt = (int)(bandHeight * yscale); 139 bandImage = new BufferedImage(imgWid, imgHgt, 140 BufferedImage.TYPE_3BYTE_BGR); 141 } 142 143 Graphics clearGraphics = bandImage.getGraphics(); 144 clearGraphics.setColor(Color.white); 145 Graphics2D g2d = (Graphics2D)bandImage.getGraphics(); 146 g2d.translate(0, imgHgt); 147 g2d.scale(xscale, -yscale); 148 149 ByteInterleavedRaster ras = (ByteInterleavedRaster)bandImage.getRaster(); 150 byte[] data = ras.getDataStorage(); 151 152 for (int bandTop = 0; bandTop < frameHeight; bandTop += bandHeight) { 153 clearGraphics.fillRect(0, 0, bandWidth, bandHeight); 154 155 printComponents(g2d); 156 int imageOffset =0; 157 int currBandHeight = bandHeight; 158 int currImgHeight = imgHgt; 159 if ((bandTop+bandHeight) > frameHeight) { 160 // last band 161 currBandHeight = frameHeight - bandTop; 162 currImgHeight = (int)(currBandHeight*yscale); 163 164 // multiply by 3 because the image is a 3 byte BGR 165 imageOffset = imgWid*(imgHgt-currImgHeight)*3; 166 } 167 168 printBand(hdc, data, imageOffset, 169 0, 0, imgWid, currImgHeight, 170 0, bandTop, bandWidth, currBandHeight); 171 g2d.translate(0, -bandHeight); 172 } 173 } 174 175 protected static int getPrintScaleFactor() { 176 // check if value is already cached 177 if (pScale != 0) 178 return pScale; 179 if (printScale == null) { 180 // if no system property is specified, 181 // check for environment setting 182 printScale = (String) java.security.AccessController.doPrivileged( 183 new java.security.PrivilegedAction() { 184 public Object run() { 185 return System.getenv("JAVA2D_PLUGIN_PRINT_SCALE"); 186 } 187 } 188 ); 189 } 190 int default_printDC_scale = 4; 191 int scale = default_printDC_scale; 192 if (printScale != null) { 193 try { 194 scale = Integer.parseInt(printScale); 195 if (scale > 8 || scale < 1) { 196 scale = default_printDC_scale; 197 } 198 } catch (NumberFormatException nfe) { 199 } 200 } 201 pScale = scale; 202 return pScale; 203 } 204 205 206 protected native boolean isPrinterDC(long hdc); 207 208 protected native void printBand(long hdc, byte[] data, int offset, 209 int sx, int sy, int swidth, int sheight, 210 int dx, int dy, int dwidth, int dheight); 211 212 /** 213 * Initialize JNI field IDs 214 */ 215 private static native void initIDs(); 216 217 /** 218 * This method is called from the native code when this embedded 219 * frame should be activated. It is expected to be overridden in 220 * subclasses, for example, in plugin to activate the browser 221 * window that contains this embedded frame. 222 * 223 * NOTE: This method may be called by privileged threads. 224 * DO NOT INVOKE CLIENT CODE ON THIS THREAD! 225 */ 226 public void activateEmbeddingTopLevel() { 227 } 228 229 public void synthesizeWindowActivation(final boolean doActivate) { 230 if (!doActivate || EventQueue.isDispatchThread()) { 231 ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(doActivate); 232 } else { 233 // To avoid focus concurrence b/w IE and EmbeddedFrame 234 // activation is postponed by means of posting it to EDT. 235 EventQueue.invokeLater(new Runnable() { 236 public void run() { 237 ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(true); 238 } 239 }); 240 } 241 } 242 243 public void registerAccelerator(AWTKeyStroke stroke) {} 244 public void unregisterAccelerator(AWTKeyStroke stroke) {} 245 246 /** 247 * Should be overridden in subclasses. Call to 248 * super.notifyModalBlocked(blocker, blocked) must be present 249 * when overriding. 250 * It may occur that embedded frame is not put into its 251 * container at the moment when it is blocked, for example, 252 * when running an applet in IE. Then the call to this method 253 * should be delayed until embedded frame is reparented. 254 * 255 * NOTE: This method may be called by privileged threads. 256 * DO NOT INVOKE CLIENT CODE ON THIS THREAD! 257 */ 258 public void notifyModalBlocked(Dialog blocker, boolean blocked) { 259 try { 260 ComponentPeer thisPeer = (ComponentPeer)WToolkit.targetToPeer(this); 261 ComponentPeer blockerPeer = (ComponentPeer)WToolkit.targetToPeer(blocker); 262 notifyModalBlockedImpl((WEmbeddedFramePeer)thisPeer, 263 (WWindowPeer)blockerPeer, blocked); 264 } catch (Exception z) { 265 z.printStackTrace(System.err); 266 } 267 } 268 native void notifyModalBlockedImpl(WEmbeddedFramePeer peer, WWindowPeer blockerPeer, boolean blocked); 269 }