# HG changeset patch # User Andrew John Hughes # Date 1366823146 -3600 # Node ID b491c30098607d812c8bf625cf769371418bd186 # Parent 2a08fdbf2a11caced8d155e5828c706c02365c57 Replace Roman's fix with backported S8009530: ICU Kern table support broken 2013-04-24 Andrew John Hughes * Makefile.am: (ICEDTEA_PATCHES): Add new patch, remove old. * NEWS: Mention 8009530 backport. * patches/openjdk/8009530-icu_kern_table_support_broken.patch: Backported from 7u. * patches/fix-font-layout-tck.patch: Removed. diff -r 2a08fdbf2a11 -r b491c3009860 ChangeLog --- a/ChangeLog Tue Apr 23 10:50:52 2013 +0100 +++ b/ChangeLog Wed Apr 24 18:05:46 2013 +0100 @@ -1,3 +1,12 @@ +2013-04-24 Andrew John Hughes + + * Makefile.am: + (ICEDTEA_PATCHES): Add new patch, remove old. + * NEWS: Mention 8009530 backport. + * patches/openjdk/8009530-icu_kern_table_support_broken.patch: + Backported from 7u. + * patches/fix-font-layout-tck.patch: Removed. + 2013-04-22 Andrew John Hughes * Makefile.am: diff -r 2a08fdbf2a11 -r b491c3009860 Makefile.am --- a/Makefile.am Tue Apr 23 10:50:52 2013 +0100 +++ b/Makefile.am Wed Apr 24 18:05:46 2013 +0100 @@ -540,7 +540,7 @@ patches/aarch64.patch \ patches/jaxws-tempfiles-ioutils-6.patch \ patches/object-factory-cl-internal.patch \ - patches/fix-font-layout-tck.patch + patches/openjdk/8009530-icu_kern_table_support_broken.patch if WITH_RHINO ICEDTEA_PATCHES += \ diff -r 2a08fdbf2a11 -r b491c3009860 NEWS --- a/NEWS Tue Apr 23 10:50:52 2013 +0100 +++ b/NEWS Wed Apr 24 18:05:46 2013 +0100 @@ -18,10 +18,10 @@ * Backports - S7133220: Additional patches to JAXP 1.4.5 update 1 for 7u4 (partial for S6657673) - S6657673: Issues with JAXP (include fragment dependent on S7133220) + - S8009530: ICU Kern table support broken * Bug fixes - PR1402: Support glibc < 2.17 with AArch64 patch - Give xalan/xerces access to their own internal packages. - - Fix offset problem in ICU LETableReference. New in release 1.11.10 (2013-04-17): diff -r 2a08fdbf2a11 -r b491c3009860 patches/fix-font-layout-tck.patch --- a/patches/fix-font-layout-tck.patch Tue Apr 23 10:50:52 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -diff --git a/src/share/native/sun/font/layout/LETableReference.h b/src/share/native/sun/font/layout/LETableReference.h ---- openjdk/jdk/src/share/native/sun/font/layout/LETableReference.h -+++ openjdk/jdk/src/share/native/sun/font/layout/LETableReference.h -@@ -433,7 +433,7 @@ - */ - LEReferenceTo(const LETableReference &parent, LEErrorCode &success, const void* atPtr) - : LETableReference(parent, parent.ptrToOffset(atPtr, success), LE_UINTPTR_MAX, success) { -- verifyLength(parent.ptrToOffset(atPtr,success), LETableVarSizer::getSize(), success); -+ verifyLength(0, LETableVarSizer::getSize(), success); - if(LE_FAILURE(success)) clear(); - } - /** diff -r 2a08fdbf2a11 -r b491c3009860 patches/openjdk/8009530-icu_kern_table_support_broken.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/openjdk/8009530-icu_kern_table_support_broken.patch Wed Apr 24 18:05:46 2013 +0100 @@ -0,0 +1,332 @@ +# HG changeset patch +# User srl +# Date 1362581054 28800 +# Node ID c2fff439d91a73076268c1b7a997722fa1caef21 +# Parent 98ad2f1e25d13aca196ad77b2f227f85072c9b16 +8009530: ICU Kern table support broken +Reviewed-by: prr, vadim + +diff --git a/src/share/native/sun/font/layout/KernTable.cpp b/src/share/native/sun/font/layout/KernTable.cpp +--- openjdk/jdk/src/share/native/sun/font/layout/KernTable.cpp ++++ openjdk/jdk/src/share/native/sun/font/layout/KernTable.cpp +@@ -48,7 +48,7 @@ + le_int16 value; // fword, kern value in funits + }; + #define KERN_PAIRINFO_SIZE 6 +- ++LE_CORRECT_SIZE(PairInfo, KERN_PAIRINFO_SIZE) + struct Subtable_0 { + le_uint16 nPairs; + le_uint16 searchRange; +@@ -56,6 +56,7 @@ + le_uint16 rangeShift; + }; + #define KERN_SUBTABLE_0_HEADER_SIZE 8 ++LE_CORRECT_SIZE(Subtable_0, KERN_SUBTABLE_0_HEADER_SIZE) + + // Kern table version 0 only + struct SubtableHeader { +@@ -64,6 +65,7 @@ + le_uint16 coverage; + }; + #define KERN_SUBTABLE_HEADER_SIZE 6 ++LE_CORRECT_SIZE(SubtableHeader, KERN_SUBTABLE_HEADER_SIZE) + + // Version 0 only, version 1 has different layout + struct KernTableHeader { +@@ -71,6 +73,7 @@ + le_uint16 nTables; + }; + #define KERN_TABLE_HEADER_SIZE 4 ++LE_CORRECT_SIZE(KernTableHeader, KERN_TABLE_HEADER_SIZE) + + #define COVERAGE_HORIZONTAL 0x1 + #define COVERAGE_MINIMUM 0x2 +@@ -92,8 +95,8 @@ + * TODO: support multiple subtables + * TODO: respect header flags + */ +-KernTable::KernTable(const LETableReference &table, LEErrorCode &success) +- : pairs(table, success), pairsSwapped(NULL), fTable(table) ++KernTable::KernTable(const LETableReference& base, LEErrorCode &success) ++ : pairs(), pairsSwapped(NULL), fTable(base) + { + if(LE_FAILURE(success) || (fTable.isEmpty())) { + #if DEBUG +@@ -106,7 +109,7 @@ + #if DEBUG + // dump first 32 bytes of header + for (int i = 0; i < 64; ++i) { +- fprintf(stderr, "%0.2x ", ((const char*)tableData)[i]&0xff); ++ fprintf(stderr, "%0.2x ", ((const char*)header.getAlias())[i]&0xff); + if (((i+1)&0xf) == 0) { + fprintf(stderr, "\n"); + } else if (((i+1)&0x7) == 0) { +@@ -140,7 +143,14 @@ + #endif + + if(LE_SUCCESS(success) && nPairs>0) { +- pairs.setToOffsetInParent(table, KERN_SUBTABLE_0_HEADER_SIZE, nPairs, success); ++ // pairs is an instance member, and table is on the stack. ++ // set 'pairs' based on table.getAlias(). This will range check it. ++ ++ pairs = LEReferenceToArrayOf(fTable, // based on overall table ++ success, ++ (const PairInfo*)table.getAlias(), // subtable 0 + .. ++ KERN_SUBTABLE_0_HEADER_SIZE, // .. offset of header size ++ nPairs); // count + } + if (LE_SUCCESS(success) && pairs.isValid()) { + pairsSwapped = (PairInfo*)(malloc(nPairs*sizeof(PairInfo))); +@@ -152,6 +162,11 @@ + fTable.getFont()->setKernPairs((void*)pairsSwapped); // store it + } + ++#if 0 ++ fprintf(stderr, "coverage: %0.4x nPairs: %d pairs %p\n", coverage, nPairs, pairs.getAlias()); ++ fprintf(stderr, " searchRange: %d entrySelector: %d rangeShift: %d\n", searchRange, entrySelector, rangeShift); ++ fprintf(stderr, "[[ ignored font table entries: range %d selector %d shift %d ]]\n", SWAPW(table->searchRange), SWAPW(table->entrySelector), SWAPW(table->rangeShift)); ++#endif + #if DEBUG + fprintf(stderr, "coverage: %0.4x nPairs: %d pairs 0x%x\n", coverage, nPairs, pairs); + fprintf(stderr, +@@ -208,7 +223,8 @@ + + le_uint32 key = storage[0]; // no need to mask off high bits + float adjust = 0; +- for (int i = 1, e = storage.getGlyphCount(); i < e; ++i) { ++ ++ for (int i = 1, e = storage.getGlyphCount(); LE_SUCCESS(success)&& i < e; ++i) { + key = key << 16 | (storage[i] & 0xffff); + + // argh, to do a binary search, we need to have the pair list in sorted order +diff --git a/src/share/native/sun/font/layout/LETableReference.h b/src/share/native/sun/font/layout/LETableReference.h +--- openjdk/jdk/src/share/native/sun/font/layout/LETableReference.h ++++ openjdk/jdk/src/share/native/sun/font/layout/LETableReference.h +@@ -1,4 +1,5 @@ + /* ++ * Copyright (c) 2007, 2010, 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 +@@ -20,7 +21,6 @@ + * 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. +- * + */ + + /* +@@ -52,7 +52,7 @@ + * defined in OpenTypeUtilities.cpp + * @internal + */ +-U_INTERNAL void U_EXPORT2 _debug_LETableReference(const char *f, int l, const char *msg, const LETableReference *what, const void *ptr, size_t len); ++extern void _debug_LETableReference(const char *f, int l, const char *msg, const LETableReference *what, const void *ptr, size_t len); + + #define LE_DEBUG_TR(x) _debug_LETableReference(__FILE__, __LINE__, x, this, NULL, 0); + #define LE_DEBUG_TR3(x,y,z) _debug_LETableReference(__FILE__, __LINE__, x, this, (const void*)y, (size_t)z); +@@ -204,18 +204,6 @@ + return fLength; + } + +- le_bool isSubsetOf(const LETableReference& base) const { +- if(this == &base) return true; +- if(fStart < base.fStart) return false; +- if(base.hasBounds()) { +- if(fStart >= base.fStart + base.fLength) return false; +- if(hasBounds()) { +- if(fStart + fLength > base.fStart + base.fLength) return false; +- } +- } +- return true; +- } +- + /** + * Change parent link to another + */ +@@ -278,6 +266,12 @@ + * dereferencing NULL is valid here because we never actually dereference it, just inside sizeof. + */ + #define LE_VAR_ARRAY(x,y) template<> inline size_t LETableVarSizer::getSize() { return sizeof(x) - (sizeof(((const x*)0)->y)); } ++/** ++ * \def LE_CORRECT_SIZE ++ * @param x type (T) ++ * @param y fixed size for T ++ */ ++#define LE_CORRECT_SIZE(x,y) template<> inline size_t LETableVarSizer::getSize() { return y; } + + /** + * Open a new entry based on an existing table +@@ -338,15 +332,7 @@ + using LETableReference::getAlias; + + const T *getAlias(le_uint32 i, LEErrorCode &success) const { +- if(LE_SUCCESS(success)&& i"); return (const T*)fStart; } +@@ -377,46 +363,6 @@ + LE_TRACE_TR("INFO: null RTAO") + } + +- /** +- * set this to point within our fParent, but based on 'base' as a subtable. +- */ +- void setToOffsetInParent(const LETableReference& base, size_t offset, le_uint32 count, LEErrorCode &success) { +-LE_TRACE_TR("INFO: sTOIP") +- if(LE_FAILURE(success)) return; +- if(!fParent->isSubsetOf(base)) { // Ensure that 'base' is containable within our parent. +- clear(); // otherwise, it's not a subtable of our parent. +- LE_DEBUG_TR("setToOffsetInParents called on non subsets"); +- success = LE_ILLEGAL_ARGUMENT_ERROR; return; +- } +- size_t baseOffset = fParent->ptrToOffset(((const le_uint8*)base.getAlias())+offset, success); +- if(LE_FAILURE(success)) return; // base was outside of parent's range +- if(fParent->hasBounds()) { +- if((baseOffset >= fParent->getLength()) || // start off end of parent +- (baseOffset+(count*LETableVarSizer::getSize()) >= fParent->getLength()) || // or off end of parent +- count > LE_UINTPTR_MAX/LETableVarSizer::getSize()) { // or more than would fit in memory +- LE_DEBUG_TR("setToOffsetInParent called with bad length"); +- success = LE_INDEX_OUT_OF_BOUNDS_ERROR; +- clear(); +- return; // start would go off end of parent +- } +- } +- fStart = (const le_uint8*)(fParent->getAlias()) + baseOffset; +- //fLength = count*LETableVarSizer::getSize(); - no- do not shrink fLength. +- if(fParent->hasBounds()) { +- fLength = (fParent->getLength() - (fStart-(const le_uint8*)fParent->getAlias())); // reduces fLength accordingly. +- } else { +- fLength = LE_UINTPTR_MAX; // unbounded +- } +- if((fStart < fParent->getAlias()) || +- (hasBounds()&&(fStart+fLength < fStart))) { // wrapped +- LE_DEBUG_TR("setToOffsetInParent called with bad length"); +- success = LE_INDEX_OUT_OF_BOUNDS_ERROR; +- clear(); +- return; // start would go off end of parent +- } +- fCount = count; +- } +- + private: + le_uint32 fCount; + }; +@@ -433,7 +379,7 @@ + */ + LEReferenceTo(const LETableReference &parent, LEErrorCode &success, const void* atPtr) + : LETableReference(parent, parent.ptrToOffset(atPtr, success), LE_UINTPTR_MAX, success) { +- verifyLength(parent.ptrToOffset(atPtr,success), LETableVarSizer::getSize(), success); ++ verifyLength(0, LETableVarSizer::getSize(), success); + if(LE_FAILURE(success)) clear(); + } + /** +diff --git a/test/java/awt/font/TextLayout/TestKerning.java b/test/java/awt/font/TextLayout/TestKerning.java +new file mode 100644 +--- /dev/null ++++ openjdk/jdk/test/java/awt/font/TextLayout/TestKerning.java +@@ -0,0 +1,94 @@ ++/* ++ * Copyright (c) 2011, 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 ++ * @summary Test Kerning is working. ++ * @bug 8009530 ++ */ ++ ++import java.applet.*; ++import java.awt.*; ++import java.awt.event.*; ++import java.awt.font.*; ++import java.util.Map; ++import java.util.HashMap; ++import java.util.Locale; ++ ++public class TestKerning extends Applet { ++ private Panel panel; ++ ++ static public void main(String[] args) { ++System.out.println(System.getProperty("os.name")); ++ ++ Applet test = new TestKerning(); ++ test.init(); ++ test.start(); ++ ++ Frame f = new Frame("Test Kerning"); ++ f.addWindowListener(new WindowAdapter() { ++ public void windowClosing(WindowEvent e) { ++ System.exit(0); ++ } ++ }); ++ f.add("Center", test); ++ f.pack(); ++ f.setVisible(true); ++ } ++ ++ public Dimension getPreferredSize() { ++ return new Dimension(500, 200); ++ } ++ ++ public Dimension getMaximumSize() { ++ return getPreferredSize(); ++ } ++ ++ private static final String testString = "To WAVA 1,45 office glyph."; ++ ++ public void paint(Graphics g) { ++ Graphics2D g2d = (Graphics2D)g; ++ Font f = new Font("Arial", Font.PLAIN, 36); ++ // testing Arial on Solaris. ++ if (!("SunOS".equals(System.getProperty("os.name")))) { ++ return; ++ } ++ if (!("Arial".equals(f.getFamily(Locale.ENGLISH)))) { ++ return; ++ } ++ Map m = new HashMap(); ++ m.put(TextAttribute.KERNING, TextAttribute.KERNING_ON); ++ Font kf = f.deriveFont(m); ++ g.setFont(f); ++ FontMetrics fm1 = g.getFontMetrics(); ++ int sw1 = fm1.stringWidth(testString); ++ g.drawString(testString, 10, 50); ++ g.setFont(kf); ++ FontMetrics fm2 = g.getFontMetrics(); ++ int sw2 = fm2.stringWidth(testString); ++ g.drawString(testString, 10, 90); ++ if (sw1 == sw2) { ++ System.out.println(sw1+" " + sw2); ++ throw new RuntimeException("No kerning"); ++ } ++ } ++}