From e3f7ed0721648b013d9f3bd2474016abfa22e856 Mon Sep 17 00:00:00 2001 From: pbansal Date: Thu, 9 Jan 2020 15:11:10 +0530 Subject: [PATCH] 8224475: JTextPane does not show images in HTML rendering Reviewed-by: serb, psadhukhan --- .../javax/swing/text/html/ImageView.java | 32 ++-- .../JTextPane/TestJTextPaneHTMLRendering.java | 173 ++++++++++++++++++ test/javax/swing/JTextPane/arrow.png | Bin 0 -> 6218 bytes 3 files changed, 193 insertions(+), 12 deletions(-) create mode 100644 test/javax/swing/JTextPane/TestJTextPaneHTMLRendering.java create mode 100644 test/javax/swing/JTextPane/arrow.png diff --git a/src/share/classes/javax/swing/text/html/ImageView.java b/src/share/classes/javax/swing/text/html/ImageView.java index d50c21e38..2e8b5b682 100644 --- a/src/share/classes/javax/swing/text/html/ImageView.java +++ b/src/share/classes/javax/swing/text/html/ImageView.java @@ -734,6 +734,22 @@ public class ImageView extends View { newState |= HEIGHT_FLAG; } + Image img; + synchronized(this) { + img = image; + } + if (newWidth <= 0) { + newWidth = img.getWidth(imageObserver); + if (newWidth <= 0) { + newWidth = DEFAULT_WIDTH; + } + } + if (newHeight <= 0) { + newHeight = img.getHeight(imageObserver); + if (newHeight <= 0) { + newHeight = DEFAULT_HEIGHT; + } + } /* If synchronous loading flag is set, then make sure that the image is scaled appropriately. @@ -741,18 +757,10 @@ public class ImageView extends View { appropriately. */ if (getLoadsSynchronously()) { - Image img; - synchronized(this) { - img = image; - } - int w = img.getWidth(imageObserver); - int h = img.getHeight(imageObserver); - if (w > 0 && h > 0) { - Dimension d = adjustWidthHeight(w, h); - newWidth = d.width; - newHeight = d.height; - newState |= (WIDTH_FLAG | HEIGHT_FLAG); - } + Dimension d = adjustWidthHeight(newWidth, newHeight); + newWidth = d.width; + newHeight = d.height; + newState |= (WIDTH_FLAG | HEIGHT_FLAG); } // Make sure the image starts loading: diff --git a/test/javax/swing/JTextPane/TestJTextPaneHTMLRendering.java b/test/javax/swing/JTextPane/TestJTextPaneHTMLRendering.java new file mode 100644 index 000000000..a0b889ada --- /dev/null +++ b/test/javax/swing/JTextPane/TestJTextPaneHTMLRendering.java @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8224475 + * @summary Verify that JTextPane renders images properly for HTML text + * @run main/manual TestJTextPaneHTMLRendering + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.Image; +import java.net.URL; +import java.util.Dictionary; +import java.util.Hashtable; +import javax.swing.JButton; +import javax.swing.JTextArea; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextPane; +import javax.swing.text.EditorKit; +import javax.swing.SwingUtilities; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + + +public class TestJTextPaneHTMLRendering { + private static JFrame mainFrame = new JFrame(); + private static Dictionary cache; + private static JTextPane textPane; + private static URL urlArrow; + + private static volatile boolean testResult = false; + private static volatile CountDownLatch countDownLatch; + private static final String INSTRUCTIONS = "INSTRUCTIONS:\n\n" + + "Verify that the JTextPane is filled with green arrow images.\n" + + "There should be 200 images (10 rows of 20 images each).\n" + + "This test will run for 10 iterations and the current iteration\n" + + "is being displayed at top of JTextPane. JTextpane will be\n" + + "repainted each time and should have same output\n"+ + "If yes, Press Pass, Otherwise, Press Fail.\n"; + + public static void main(String args[]) throws Exception { + urlArrow = new URL("http:\\arrow.png"); + countDownLatch = new CountDownLatch(1); + + SwingUtilities.invokeLater(TestJTextPaneHTMLRendering::createUI); + countDownLatch.await(15, TimeUnit.MINUTES); + SwingUtilities.invokeLater(mainFrame::dispose); + + if (!testResult) { + throw new RuntimeException("Test failed!"); + } + } + + private static void createUI() { + JPanel mainControlPanel = new JPanel(new BorderLayout(20, 20)); + JPanel resultButtonPanel = new JPanel(new GridBagLayout()); + + createTestUI(mainControlPanel); + + JTextArea instructionTextArea = new JTextArea(); + instructionTextArea.setText(INSTRUCTIONS); + instructionTextArea.setEditable(false); + instructionTextArea.setBackground(Color.white); + mainControlPanel.add(instructionTextArea, BorderLayout.NORTH); + + JButton passButton = new JButton("Pass"); + passButton.setActionCommand("Pass"); + passButton.addActionListener((ActionEvent e) -> { + testResult = true; + countDownLatch.countDown(); + + }); + + JButton failButton = new JButton("Fail"); + failButton.setActionCommand("Fail"); + failButton.addActionListener(e -> { + countDownLatch.countDown(); + }); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + + resultButtonPanel.add(passButton, gbc); + + gbc.gridx = 1; + gbc.gridy = 0; + resultButtonPanel.add(failButton, gbc); + + mainControlPanel.add(resultButtonPanel, BorderLayout.SOUTH); + + mainFrame.add(mainControlPanel); + mainFrame.pack(); + + mainFrame.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + mainFrame.dispose(); + countDownLatch.countDown(); + } + }); + mainFrame.setVisible(true); + } + + static void createTestUI(JPanel panel) { + textPane = new JTextPane(); + panel.add(textPane, BorderLayout.CENTER); + + final EditorKit l_kit = textPane.getEditorKitForContentType("text/html"); + textPane.setEditable(false); + textPane.setEditorKit(l_kit); + cache = (Dictionary)textPane.getDocument().getProperty("imageCache"); + if (cache==null) { + cache=new Hashtable(); + textPane.getDocument().putProperty("imageCache",cache); + } + + URL arrowLocationUrl = TestJTextPaneHTMLRendering.class.getResource("arrow.png"); + ImageIcon imageIcon = new ImageIcon(arrowLocationUrl); + Image image = imageIcon.getImage(); + Image scaledImage = image.getScaledInstance(24, 24, java.awt.Image.SCALE_SMOOTH); + cache.put(urlArrow, scaledImage); + new Thread(TestJTextPaneHTMLRendering::runTest).start(); + } + + static void runTest() { + for (int i=0; i < 10; i++) + { + StringBuffer sb = new StringBuffer(); + sb.append("
Iteration " + (i+1) + " -> " + "
"); + for (int j=1;j<201;j++) + { + sb.append(""); + if (j%20 == 0) sb.append("
"); + } + textPane.setText(sb.toString()); + textPane.validate(); + textPane.repaint(); + try { + Thread.currentThread().sleep(1000); + } catch (InterruptedException e) { System.err.println(e); } + } + } +} diff --git a/test/javax/swing/JTextPane/arrow.png b/test/javax/swing/JTextPane/arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..472d385331d84173d00c8b26adecea838823d58f GIT binary patch literal 6218 zcmV-Q7`5k#P)EX>4Tx04R}tkv&MmKpe$iQ>A`X94si}kfAzR5EXHhDi*;)X)CnqU~=gfG-*gu zTpR`0f`cE6RREt|dh*&JNvE0V2XsE=~#9>9%C|}69 ztZ?4qtd^^+c~AbrU`|^}ah>J}Vpu{P35bwUMG0kCh|sE$Vj@ZVQ4jyH<4=%FCRYiJ z91EyGh2;3b|KNAGW`1hYO$tVV&KKMM7zF~mK%-{c-^aGyI05|6z?IhWSL(p*C+W48 z7Cr*{w}Ff6mL~53mpj1FlP(#OBl&3x`8@D`M&FbL25y0#HMh6sK29HiGxnYP^R# z-M9OmbN>JHKj$_?Rry8!G5mu6_%FWr#tnmtlF#KC8rp$+N;XPF#GP~fn7Zo#1OXHf zH>Q9Hz6hRp*!WuC_lT^53WY*}wbfPD);73&Wqix}#=1W=uw&xdwM9y$GQRI&iCCDw zh7rTyKtBtM3)I%?%+D^+-`__V)~VHMgkeN?cNZ(Gt1K>FV`X`bzP{}g3OTMVE#ey= z5uv@kivP8*f9nPV)a!NbzxQrJ5jJe#7N?3al2`~uQ3Yd6lR?~h#+gw`Ka;Vtm&eB^ zQj0ML&+}0PksOs$iDT~^zy06-&L8|$MAY)cCqDd-T3gG{wY9fXE*A;I4NjamL(ceo z@{><+^7MO5%q(#7t@nBSiAPzjEio}UL9MpNhweYb<*_TAJ$H)Hi!*%uu}9e4*~0s$ z&Qi)3@qLfs;hp&9aVw7yo~TB(%z!3(c{yN@HKqR76 zD&R{F-#6s*If{im?Z*xcjc#F+~%5RT_&>g-qxh(^z~Q77d7`@Njdw!x?GK*0EwSu>q~MgkgYafEdNk zd+vS~|FzfN`|4Y7p7>Ym8*3B_`4po6Ur4ZC4;UKgr*EK#APSrTR1qWbiX`J{leL8l zbI-(>*K|yb$rvvFG{S1IPNb2GqWDi3Mp$c8^BFPZa|OQr{7b+4=9?$J5?RaYYArS; z>F3{y1d}h;D#b#PyAIq&AR%f=Nz8~ed>St(0T*7%z6v-_8_i1cXt*?YG`S z>y{Qm8{I%?37IEjnh8azgSQjheI}%h?)-|NXmo%-S2>=z_-9z3pY>ZD)F8RFi#>vMg zr>CF)*kd35?8&#^pL*oc4--WZs*#)5$j@yDf8XAn%*`)!ibv1o(ec;~&h27EGZ02Z zG!BW>k&Sc2q2ECydw+G_PtH?BMAbS2qnb>nYqj;2#if-k$^8-I3}-E}rJItUV}0}r zm13T&qYHBMQ2O6NSZ^xl;e)A{K z{^fU$3>YI}gYn5MtU+ZUNV9=e44?@MCN$s_Ui$ltUnMzDGNVRNiv~ehC>0B+jnb$w z#$Z*Ej?EMVHm*!i$O|jW^}9!oU-;22`}aQS`_U;?Wp-|!p}{_a$UQ?EQ6FT0pT2zL zm*-}ehjKZeFpTmE8O2%#BVc1GD>q1HvTL|$YSRA&M`y1|z8i@Jms&i}LsU>P4i45r z`(}z>j`fS96mmY3le2sN^x5Zs@ZjGWe!9D->*(yvJo|3h$EAxC)Yewn*r;Qz<%5bo zKMX@j!lm3=#V?nzQ50h{c}&f)w>B-xYC?`#UP!BeOkF^lw$#SjqG>Koqg7QgxjeLW zG}Rx7pw^<*O%!(x5R8pt>M%FE)c@j(Bj4M*r}tMs^{Gc+o}XJ`Wqpy_>MCQGCh6|o zNtskeIL(cXL%2j_RVsT8p)c6NQcgY$K(` zo^#izS|q+cUAem7L&HlcNye$bA}R6u;$g8wl@@XXgVZlvBxjZ7rM2FXkxSn_aOdQ& zcXqXXyH;D_>Xiu)pWS^CuZV(`Sn7!P9%#<+8g7>tSMOysi)Y^u^6hSoR0o->{ zB`g*3hlcP*FX1h(QnwU;_`+M?*tWIW*1NUm4~GT^$mKkusLr_yqx5avN*G3XIS*?i zOjbOINNVY%(vz5!M4HElkMui@b8a?=J7~T>JD7ll&=}P?z|eL`@nux6#abG#lM`*=KQ)qQ;OL+(lta zJE9SVLY`yqocj+iyzuf@L_)^LXX)C!84*JeM69f=Qd_SzAdoy)viLOauha3WNfpo_ zvb6tWa5zZ_P+X`dq-YW*Pcda1(T9Uv+Hdd-64|DECiAHRMiFgbRMgR?zkL7@f|)sd z-{+?<9(`tFYI4&@58waKq9}~Yl@hbF3q%Cmd-t7~My878YD_>`&yjdE3xNdBo&nzj zW1RQIOQV5=0F!9B0TzuYbN4Z6%9D8RBmzmF$)vEzMyh5iR)2dx`JOI}hWNh6`^U%s z$xnX#=Ch@8p|nx2vvBPiw+`>6kT2qEHYFKB<3r*?MP04jBy!TuPo^$N8Xsbk!iP*= zcS1%)QE?vAOtEFHrb0_HbBL?S>u9SJvlx@un}ZC zLfTlIm?lFQ&x;pBGf_%*Q6{sX#sfNoG!{wIH5@*!5anvMmeS1fR54i5Xa}Z6aihgOXaO z8~n}Pl*MChbc}Mjz`4^`56;gn|K+~@gOB*C+Gty5Jm~VSHnku%VR8dlY3}mG)sqn= z1Ks9CV!*W;Obj}cvU|EXRX4v1h>h!txNnfzCOd6AL+@80Y>oe7wh(U6OXyOXB$!Rc#)!G_+_wRV|p^qH=wx2wM zq8NtzMNYfqynLMBEENc_dHtrz^8J%Fn z!7MeNbEpv^xH?L0>U6Hp$a5L`IR#`pwQJc4?_-G}!6=Y7L{zwz9& z->tp$lh^TbhLi*w6UHs5gmBW%mPu=L#|<`v)kfpYdC(1rZLpzu&Dp}3*wbDd%E%2w zCV&+Mo8f|_@8){(G5#A7gYO}crFP~$)~4sc^Ux^dvBw|$%EJ%e_vM+n1>Qe(mLL7~ zs}u`$UHA!gD)9z~ zG4XbFyxXHRRc&N8N!2C@Fc=h@7%Z(VVgZ!R@u`pzj9S#jhK?^XMw}*y)EQnR))g8@ zsh8{)G#r=9H3sXSl4vlP5 zW~Jkv=V4<>Z1CbnDRDjT7HDH)ORCTmdT~T)od1oVCzzUI?&v#66cVaXZpn?63f`|A zef!w!yLa|;@W5?cy3|H%YddXilT6P{FgrcX%+w6qd#d=E?FoXF71pQ53G0E=(MrPr znJw>h-&iv{C`qFv?f^TF+tiC1ca@O@w~gKBlnm9zFI6aBu7Kq7s10N28D|t#myYuV z)~{S)_MM{`jaUzr&7IY=kA33MQ>(T0_g;H-gjZgDo6mgaF+TROkJ8=U#pTgf+S=P` zYn$NG#Zi_P7x3#F)>BnXKF{RHyG$G#x#oUcbt+J;5?OU&oE{cyEs?co6h}dFM9Fs>|J&_1*!Y@c|G|AmPQ)1@tkuZ3 zZlcuH>t3Tty3c-&)ibA<85zOPd91BRbaYf-J^a93Pww8mW2~dI3n-!1vZZqqgG0T{ z%r5e+zxW}eqoW+Wb3a3agBX)zOIJJc&2PQ5?Y}ru}$3Y%rI8eiHqxfoTy8d&EJETQL4xlaDq*xaa57`{`Ubr{-Q0KILB_7U zpe{AW8OQe#8!`LFt1Mo)gvsTp2O%9Dh2J~;k^6qTzi&ratyZbFv@kh6&1_47Yjdl- z_S#W;&X02YfnkP*2AG>$Vs3tt;o%~EJGwaX+6jL8(wi9_K&Cq=uAB0|TYNfZt}{sX z#VT#Qa3YyPJ=p-N2OA9Z@8JIX?;`JmYNOL){5(V#miR^FGmoC9Jr_d-{msM_zF9B?qL7z`)O<6&E)tD zMrL^M!2|5w+kc$_xcNH;saKmC4UOI2B-f>5896A%!Qp0x3&N1DEuGwR&z*RlM-YaN zge~A3g0&Tuq}(*tLuHjdreF8Kb3Ay}1EyZj|dhEufKW z>1E}iMj4jN!Xc>|zIyhvyHO|vCZEk3~ zXV5T86h@RQB_4eEe#AFKVML`|VpFxkv3JirbnMva!?}D8BSIKi@_B#xz`=pfm5RA% zTdFPe4{WEU+Cr&Vq+BdhX{k_cZDDEU8n3=`gwab^85kU-Z~HdN z<-*y^tS&9GbJy0N(*T*ac>}=Gz_eyxb;(>8*YwwCj4+6}^WZQ&y<4aU0rfDT9t0E% z1xDUI{m`+aXCBJs^VI7Bg@Ql-)YA`sdjBoEzCSxV&)>ZA7Bkax^bc&OcUw2*N{Mo@ zNV!;|x~WRJTIBNBC0>5%2l+JuQx!TNd;yqU5E2bN6I#$q#+4hF%;ATx_djh3m9?qMAl-B^6tp#2adjd z_M;%QwpJ$o#lQRqPwwA8`0~o~D%F+>9i6RQx;V<~N8UlLGBngr$L4lQr4r?0iE^n# zwXKTD!N~D