Mercurial > hg > release > icedtea6-1.11
view patches/openjdk/8009530-icu_kern_table_support_broken.patch @ 2903:b491c3009860
Replace Roman's fix with backported S8009530: ICU Kern table support broken
2013-04-24 Andrew John Hughes <gnu.andrew@redhat.com>
* 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.
author | Andrew John Hughes <gnu.andrew@redhat.com> |
---|---|
date | Wed, 24 Apr 2013 18:05:46 +0100 |
parents | |
children |
line wrap: on
line source
# 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<PairInfo>(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<x>::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<x>::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<getCount()) { - return ((const T*)getAlias())+i; - } else { - if(LE_SUCCESS(success)) { - LE_DEBUG_TR("getAlias(subscript) out of range"); - success = LE_INDEX_OUT_OF_BOUNDS_ERROR; - } - return ((const T*)getAlias()); // return first item, so there's no crash - } + return ((const T*)(((const char*)getAlias())+getOffsetFor(i, success))); } const T *getAliasTODO() const { LE_DEBUG_TR("getAliasTODO<>"); 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<T>::getSize()) >= fParent->getLength()) || // or off end of parent - count > LE_UINTPTR_MAX/LETableVarSizer<T>::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<T>::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<T>::getSize(), success); + verifyLength(0, LETableVarSizer<T>::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"); + } + } +}