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