Skip to content

Commit

Permalink
Merge 73b1959 into 68c22ab
Browse files Browse the repository at this point in the history
  • Loading branch information
genie-openj9 committed Sep 20, 2023
2 parents 68c22ab + 73b1959 commit e2061db
Show file tree
Hide file tree
Showing 3 changed files with 225 additions and 3 deletions.
2 changes: 1 addition & 1 deletion closed/openjdk-tag.gmk
Original file line number Diff line number Diff line change
@@ -1 +1 @@
OPENJDK_TAG := jdk-17.0.9+6
OPENJDK_TAG := jdk-17.0.9+7
5 changes: 3 additions & 2 deletions src/java.desktop/share/native/libfontmanager/freetypeScaler.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2023, 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
Expand Down Expand Up @@ -530,7 +530,8 @@ Java_sun_font_FreetypeFontScaler_createScalerContextNative(
if ((aa != TEXT_AA_ON) && (fm != TEXT_FM_ON) &&
!context->doBold && !context->doItalize &&
(context->transform.yx == 0) && (context->transform.xy == 0) &&
(context->transform.xx > 0) && (context->transform.yy > 0))
(context->transform.xx > 0) && (context->transform.yy > 0) &&
(context->transform.xx == context->transform.yy))
{
context->useSbits = 1;
}
Expand Down
221 changes: 221 additions & 0 deletions test/jdk/java/awt/font/FontScaling/StretchedFontTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
/*
* Copyright (c) 2023, 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.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.stream.Stream;

import javax.imageio.ImageIO;

import static java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment;
import static java.awt.RenderingHints.KEY_TEXT_ANTIALIASING;
import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB;
import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_OFF;
import static java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON;
import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR;

/*
* @test
* @bug 8312555
* @summary Verifies that hieroglyphs are stretched by AffineTransform.scale(2, 1)
* @run main StretchedFontTest
*/
public final class StretchedFontTest {
private static final String TEXT = "\u6F22";
private static final int FONT_SIZE = 20;

private static final Color BACKGROUND = Color.WHITE;
private static final Color[] FOREGROUNDS = {
new Color(0xFF000000, true),
new Color(0x7F000000, true)
};

private static final AffineTransform STRETCH_TRANSFORM =
AffineTransform.getScaleInstance(2.0, 1.0);

public static void main(String[] args) {
List<String> errors =
Arrays.stream(getLocalGraphicsEnvironment()
.getAvailableFontFamilyNames(Locale.ENGLISH))
.map(family -> new Font(family, Font.PLAIN, FONT_SIZE))
.filter(font -> font.canDisplay(TEXT.codePointAt(0)))
.map(font -> font.deriveFont(STRETCH_TRANSFORM))
.flatMap(StretchedFontTest::testFont)
.filter(Objects::nonNull)
.toList();

if (!errors.isEmpty()) {
errors.forEach(System.err::println);
throw new Error(errors.size() + " failure(s) found;"
+ " the first one: " + errors.get(0));
}
}

/**
* Tests the font with a set of text antialiasing hints.
*
* @param font the font to test
* @return a stream of test results
* @see #testFont(Font, Object)
*/
private static Stream<String> testFont(final Font font) {
return Stream.of(VALUE_TEXT_ANTIALIAS_OFF,
VALUE_TEXT_ANTIALIAS_ON,
VALUE_TEXT_ANTIALIAS_LCD_HRGB)
.flatMap(hint -> testFont(font, hint));
}

/**
* Tests the font with the specified text antialiasing hint and a set of
* foreground colors.
*
* @param font the font to test
* @param hint the text antialiasing hint to test
* @return a stream of test results
* @see #testFont(Font, Object, Color)
*/
private static Stream<String> testFont(final Font font, final Object hint) {
return Stream.of(FOREGROUNDS)
.map(foreground -> testFont(font, hint, foreground));
}

/**
* Tests the font with the specified text antialiasing hint and
* foreground color. In case of failure, it saves the rendered
* image to a file.
*
* @param font the font to test
* @param hint the text antialiasing hint to test
* @param foreground the foreground color to use
* @return {@code null} if the text rendered correctly; otherwise,
* a {@code String} with the font family name, the value of
* the rendering hint and the color in hex
*/
private static String testFont(final Font font,
final Object hint,
final Color foreground) {
final Dimension size = getTextSize(font);
final BufferedImage image =
new BufferedImage(size.width, size.height, TYPE_3BYTE_BGR);

final Graphics2D g2d = image.createGraphics();
try {
g2d.setColor(BACKGROUND);
g2d.fillRect(0, 0, size.width, size.height);

g2d.setRenderingHint(KEY_TEXT_ANTIALIASING, hint);
g2d.setColor(foreground);
g2d.setFont(font);
g2d.drawString(TEXT, 0, g2d.getFontMetrics(font).getAscent());
} finally {
g2d.dispose();
}

if (verifyImage(image)) {
return null;
}
String fontName = font.getFontName(Locale.ENGLISH);
String hintValue = getHintString(hint);
String hexColor = String.format("0x%08x", foreground.getRGB());
saveImage(image, fontName + "-" + hintValue + "-" + hexColor);
return "Font: " + fontName + ", Hint: " + hintValue + ", Color: " + hexColor;
}

/**
* Verifies the rendered image of the hieroglyph. The hieroglyph
* should be stretched across the entire width of the image.
* If the right half of the image contains only pixels of the background
* color, the hieroglyph isn't stretched correctly
* &mdash; it's a failure.
*
* @param image the image to verify
* @return {@code true} if the hieroglyph is stretched correctly; or
* {@code false} if right half of the image contains only
* background-colored pixels, which means the hieroglyph isn't
* stretched.
*/
private static boolean verifyImage(final BufferedImage image) {
final int width = image.getWidth();
final int height = image.getHeight();
for (int x = width / 2; x < width; x++) {
for (int y = 0; y < height; y++) {
if (image.getRGB(x, y) != BACKGROUND.getRGB()) {
// Any other color but background means the glyph is stretched
return true;
}
}
}

// The right side of the image is filled with the background color only,
// the glyph isn't stretched.
return false;
}

private static String getHintString(final Object hint) {
if (hint == VALUE_TEXT_ANTIALIAS_OFF) {
return "off";
} else if (hint == VALUE_TEXT_ANTIALIAS_ON) {
return "on";
} else if (hint == VALUE_TEXT_ANTIALIAS_LCD_HRGB) {
return "lcd";
} else {
throw new IllegalArgumentException("Unexpected hint: " + hint);
}
}

private static final BufferedImage dummyImage =
new BufferedImage(5, 5, TYPE_3BYTE_BGR);

private static Dimension getTextSize(final Font font) {
final Graphics g = dummyImage.getGraphics();
try {
return g.getFontMetrics(font)
.getStringBounds(TEXT, g)
.getBounds()
.getSize();
} finally {
g.dispose();
}
}

private static void saveImage(final BufferedImage image,
final String fileName) {
try {
ImageIO.write(image,
"png",
new File(fileName + ".png"));
} catch (IOException ignored) {
}
}
}

0 comments on commit e2061db

Please sign in to comment.