blob: 472fca810a527a2a9edc355474da3e5cfa8d26b8 [file] [log] [blame]
/*
* 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);
}
}