| /* | |
| * Copyright (c) 1999, 2016, 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 4175418 8158924 | |
| * @author John Raley | |
| * @summary This insures that bug 4175418: Font substitution in TextLayout / | |
| * LineBreakMeasurer is inconsistent has been fixed. The problem was | |
| * that text was measured in one Font, but lines were produced | |
| * in a different font. | |
| */ | |
| /* | |
| * (C) Copyright IBM Corp. 1999, All Rights Reserved | |
| */ | |
| import java.text.AttributedString; | |
| import java.awt.font.LineBreakMeasurer; | |
| import java.awt.font.TextLayout; | |
| import java.awt.font.FontRenderContext; | |
| import java.awt.font.TextAttribute; | |
| /** | |
| * This insures that bug 4175418: Font substitution in TextLayout / | |
| * LineBreakMeasurer is inconsistent has been fixed. The problem was | |
| * that text was measured in one Font, but lines were produced | |
| * in a different font. One symptom of this problem is that lines are | |
| * either too short or too long. This test line-breaks a paragraph | |
| * and checks the line lengths to make sure breaks were chosen well. | |
| * This can be checked because the paragraph is so simple. | |
| */ | |
| public class TestLineBreakWithFontSub { | |
| public static void main(String[] args) { | |
| new TestLineBreakWithFontSub().test(); | |
| System.out.println("Line break / font substitution test PASSED"); | |
| } | |
| private static final String WORD = "word"; | |
| private static final String SPACING = " "; | |
| // The Hebrew character in this string can trigger font substitution | |
| private static final String MIXED = "A\u05D0"; | |
| private static final int NUM_WORDS = 12; | |
| private static final FontRenderContext DEFAULT_FRC = | |
| new FontRenderContext(null, false, false); | |
| public void test() { | |
| // construct a paragraph as follows: MIXED + [SPACING + WORD] + ... | |
| StringBuffer text = new StringBuffer(MIXED); | |
| for (int i=0; i < NUM_WORDS; i++) { | |
| text.append(SPACING); | |
| text.append(WORD); | |
| } | |
| AttributedString attrString = new AttributedString(text.toString()); | |
| attrString.addAttribute(TextAttribute.SIZE, new Float(24.0)); | |
| LineBreakMeasurer measurer = new LineBreakMeasurer(attrString.getIterator(), | |
| DEFAULT_FRC); | |
| // get width of a space-word sequence, in context | |
| int sequenceLength = WORD.length()+SPACING.length(); | |
| measurer.setPosition(text.length() - sequenceLength); | |
| TextLayout layout = measurer.nextLayout(10000.0f); | |
| if (layout.getCharacterCount() != sequenceLength) { | |
| throw new Error("layout length is incorrect!"); | |
| } | |
| final float sequenceAdvance = layout.getVisibleAdvance(); | |
| float wrappingWidth = sequenceAdvance * 2; | |
| // now run test with a variety of widths | |
| while (wrappingWidth < (sequenceAdvance*NUM_WORDS)) { | |
| measurer.setPosition(0); | |
| checkMeasurer(measurer, | |
| wrappingWidth, | |
| sequenceAdvance, | |
| text.length()); | |
| wrappingWidth += sequenceAdvance / 5; | |
| } | |
| } | |
| /** | |
| * Iterate through measurer and check that every line is | |
| * not too long and not too short, but just right. | |
| */ | |
| private void checkMeasurer(LineBreakMeasurer measurer, | |
| float wrappingWidth, | |
| float sequenceAdvance, | |
| int endPosition) { | |
| do { | |
| TextLayout layout = measurer.nextLayout(wrappingWidth); | |
| float visAdvance = layout.getVisibleAdvance(); | |
| // Check that wrappingWidth-sequenceAdvance < visAdvance | |
| // Also, if we're not at the end of the paragraph, | |
| // check that visAdvance <= wrappingWidth | |
| if (visAdvance > wrappingWidth) { | |
| // line is too long for given wrapping width | |
| throw new Error("layout is too long"); | |
| } | |
| if (measurer.getPosition() < endPosition) { | |
| if (visAdvance <= wrappingWidth - sequenceAdvance) { | |
| // line is too short for given wrapping width; | |
| // another word would have fit | |
| throw new Error("room for more words on line. diff=" + | |
| (wrappingWidth - sequenceAdvance - visAdvance)); | |
| } | |
| } | |
| } while (measurer.getPosition() != endPosition); | |
| } | |
| } |