From 90b513b09cae80472d4b4b684446d9d7ea7479ce Mon Sep 17 00:00:00 2001 From: Clemens Eisserer Date: Mon, 25 Nov 2013 09:38:32 -0800 Subject: [PATCH] 8028722: Render: Drawing strings with exactly 254 glyphs causes hangs Reviewed-by: prr, bae --- .../classes/sun/font/XRTextRenderer.java | 23 +++--- .../DrawString/XRenderElt254TextTest.java | 72 +++++++++++++++++++ 2 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 jdk/test/java/awt/Graphics2D/DrawString/XRenderElt254TextTest.java diff --git a/jdk/src/solaris/classes/sun/font/XRTextRenderer.java b/jdk/src/solaris/classes/sun/font/XRTextRenderer.java index 308de3ab300..243fa8543fb 100644 --- a/jdk/src/solaris/classes/sun/font/XRTextRenderer.java +++ b/jdk/src/solaris/classes/sun/font/XRTextRenderer.java @@ -36,6 +36,10 @@ import sun.java2d.xr.*; * @author Clemens Eisserer */ public class XRTextRenderer extends GlyphListPipe { + // Workarround for a bug in libXrender. + // In case the number of glyphs of an ELT is a multiple of 254, + // a few garbage bytes are sent to the XServer causing hangs. + static final int MAX_ELT_GLYPH_COUNT = 253; XRGlyphCache glyphCache; XRCompositeManager maskBuffer; @@ -92,8 +96,11 @@ public class XRTextRenderer extends GlyphListPipe { int posX = 0, posY = 0; if (gl.usePositions() - || (cacheEntry.getXAdvance() != ((float) cacheEntry.getXOff()) || cacheEntry.getYAdvance() != ((float) cacheEntry.getYOff())) - || eltIndex < 0 || glyphSet != activeGlyphSet) { + || cacheEntry.getXAdvance() != ((float) cacheEntry.getXOff()) + || cacheEntry.getYAdvance() != ((float) cacheEntry.getYOff()) + || glyphSet != activeGlyphSet + || eltIndex < 0 + || eltList.getCharCnt(eltIndex) == MAX_ELT_GLYPH_COUNT) { eltIndex = eltList.getNextIndex(); eltList.setCharCnt(eltIndex, 1); @@ -101,7 +108,7 @@ public class XRTextRenderer extends GlyphListPipe { eltList.setGlyphSet(eltIndex, glyphSet); if (gl.usePositions()) { - // /*In this case advX only stores rounding errors*/ + // In this case advX only stores rounding errors float x = positions[i * 2] + advX; float y = positions[i * 2 + 1] + advY; posX = (int) Math.floor(x); @@ -120,16 +127,14 @@ public class XRTextRenderer extends GlyphListPipe { posX = (int) Math.floor(advX); posY = (int) Math.floor(advY); - // Advance of ELT = difference between stored - // relative + // Advance of ELT = difference between stored relative // positioning information and required float. advX += (cacheEntry.getXAdvance() - cacheEntry.getXOff()); advY += (cacheEntry.getYAdvance() - cacheEntry.getYOff()); } - /* - * Offset of the current glyph is the difference to the last - * glyph and this one - */ + + // Offset of the current glyph is the difference + // to the last glyph and this one eltList.setXOff(eltIndex, (posX - oldPosX)); eltList.setYOff(eltIndex, (posY - oldPosY)); diff --git a/jdk/test/java/awt/Graphics2D/DrawString/XRenderElt254TextTest.java b/jdk/test/java/awt/Graphics2D/DrawString/XRenderElt254TextTest.java new file mode 100644 index 00000000000..33e834fb752 --- /dev/null +++ b/jdk/test/java/awt/Graphics2D/DrawString/XRenderElt254TextTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2008, 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. + */ + +import java.awt.*; +import java.awt.MultipleGradientPaint.*; +import java.awt.image.*; +import java.io.*; + +import javax.imageio.*; +import javax.swing.*; + +/** + * @test + * @bug 8028722 + * @summary tests wether drawString with 254 characters causes the xrender + * pipeline to hang. + * @author ceisserer + */ +public class XRenderElt254TextTest extends Frame implements Runnable { + public volatile boolean success = false; + + public void run() { + Image dstImg = getGraphicsConfiguration().createCompatibleVolatileImage(400, 400); + Graphics2D g = (Graphics2D) dstImg.getGraphics(); + + StringBuilder strBuilder = new StringBuilder(254); + for (int c = 0; c < 254; c++) { + strBuilder.append('a'); + } + + for (int i = 0; i < 100; i++) { + g.drawString(strBuilder.toString(), 20, 20); + Toolkit.getDefaultToolkit().sync(); + } + success = true; + } + + public static void main(String[] args) throws Exception { + XRenderElt254TextTest test = new XRenderElt254TextTest(); + new Thread(test).start(); + + for (int i = 0; i < 30; i++) { + Thread.sleep(1000); + + if (test.success) { + return; // Test finished successful + } + } + + throw new RuntimeException("Test Failed"); + } +}