8043869: [macosx] java -splash does not honor @2x hi dpi notation for retina support
Reviewed-by: pchelko, anthony, ksrini
This commit is contained in:
parent
02990e046b
commit
c0c1d91633
@ -35,6 +35,7 @@ SUNWprivate_1.1 {
|
||||
Java_java_awt_SplashScreen__1getImageFileName;
|
||||
Java_java_awt_SplashScreen__1getImageJarName;
|
||||
Java_java_awt_SplashScreen__1setImageData;
|
||||
Java_java_awt_SplashScreen__1getScaleFactor;
|
||||
|
||||
SplashLoadMemory;
|
||||
SplashLoadFile;
|
||||
|
@ -125,6 +125,39 @@ done:
|
||||
return buf;
|
||||
}
|
||||
|
||||
char* SplashGetScaledImageName(const char* jar, const char* file,
|
||||
float *scaleFactor) {
|
||||
NSAutoreleasePool *pool = [NSAutoreleasePool new];
|
||||
*scaleFactor = 1;
|
||||
char* scaledFile = nil;
|
||||
float screenScaleFactor = [SplashNSScreen() backingScaleFactor];
|
||||
|
||||
if (screenScaleFactor > 1) {
|
||||
NSString *fileName = [NSString stringWithUTF8String: file];
|
||||
NSUInteger length = [fileName length];
|
||||
NSRange range = [fileName rangeOfString: @"."
|
||||
options:NSBackwardsSearch];
|
||||
NSUInteger dotIndex = range.location;
|
||||
NSString *fileName2x = nil;
|
||||
|
||||
if (dotIndex == NSNotFound) {
|
||||
fileName2x = [fileName stringByAppendingString: @"@2x"];
|
||||
} else {
|
||||
fileName2x = [fileName substringToIndex: dotIndex];
|
||||
fileName2x = [fileName2x stringByAppendingString: @"@2x"];
|
||||
fileName2x = [fileName2x stringByAppendingString:
|
||||
[fileName substringFromIndex: dotIndex]];
|
||||
}
|
||||
|
||||
if ((fileName2x != nil) && (jar || [[NSFileManager defaultManager]
|
||||
fileExistsAtPath: fileName2x])){
|
||||
*scaleFactor = 2;
|
||||
scaledFile = strdup([fileName2x UTF8String]);
|
||||
}
|
||||
}
|
||||
[pool drain];
|
||||
return scaledFile;
|
||||
}
|
||||
|
||||
void
|
||||
SplashInitPlatform(Splash * splash) {
|
||||
@ -132,7 +165,7 @@ SplashInitPlatform(Splash * splash) {
|
||||
|
||||
splash->maskRequired = 0;
|
||||
|
||||
|
||||
|
||||
//TODO: the following is too much of a hack but should work in 90% cases.
|
||||
// besides we don't use device-dependant drawing, so probably
|
||||
// that's very fine indeed
|
||||
@ -225,7 +258,15 @@ SplashRedrawWindow(Splash * splash) {
|
||||
[image setBackgroundColor: [NSColor clearColor]];
|
||||
|
||||
[image addRepresentation: rep];
|
||||
|
||||
float scaleFactor = splash->scaleFactor;
|
||||
if (scaleFactor > 0 && scaleFactor != 1) {
|
||||
[image setScalesWhenResized:YES];
|
||||
NSSize size = [image size];
|
||||
size.width /= scaleFactor;
|
||||
size.height /= scaleFactor;
|
||||
[image setSize: size];
|
||||
}
|
||||
|
||||
NSImageView * view = [[NSImageView alloc] init];
|
||||
|
||||
[view setImage: image];
|
||||
|
@ -1816,20 +1816,48 @@ ShowSplashScreen()
|
||||
const char *jar_name = getenv(SPLASH_JAR_ENV_ENTRY);
|
||||
const char *file_name = getenv(SPLASH_FILE_ENV_ENTRY);
|
||||
int data_size;
|
||||
void *image_data;
|
||||
void *image_data = NULL;
|
||||
float scale_factor = 1;
|
||||
char *scaled_splash_name = NULL;
|
||||
|
||||
if (file_name == NULL){
|
||||
return;
|
||||
}
|
||||
|
||||
scaled_splash_name = DoSplashGetScaledImageName(
|
||||
jar_name, file_name, &scale_factor);
|
||||
if (jar_name) {
|
||||
image_data = JLI_JarUnpackFile(jar_name, file_name, &data_size);
|
||||
|
||||
if (scaled_splash_name) {
|
||||
image_data = JLI_JarUnpackFile(
|
||||
jar_name, scaled_splash_name, &data_size);
|
||||
}
|
||||
|
||||
if (!image_data) {
|
||||
scale_factor = 1;
|
||||
image_data = JLI_JarUnpackFile(
|
||||
jar_name, file_name, &data_size);
|
||||
}
|
||||
if (image_data) {
|
||||
DoSplashInit();
|
||||
DoSplashSetScaleFactor(scale_factor);
|
||||
DoSplashLoadMemory(image_data, data_size);
|
||||
JLI_MemFree(image_data);
|
||||
}
|
||||
} else if (file_name) {
|
||||
DoSplashInit();
|
||||
DoSplashLoadFile(file_name);
|
||||
} else {
|
||||
return;
|
||||
DoSplashInit();
|
||||
if (scaled_splash_name) {
|
||||
DoSplashSetScaleFactor(scale_factor);
|
||||
DoSplashLoadFile(scaled_splash_name);
|
||||
} else {
|
||||
DoSplashLoadFile(file_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (scaled_splash_name) {
|
||||
JLI_MemFree(scaled_splash_name);
|
||||
}
|
||||
|
||||
DoSplashSetFileJarName(file_name, jar_name);
|
||||
|
||||
/*
|
||||
|
@ -29,3 +29,6 @@ int DoSplashLoadFile(const char* filename);
|
||||
void DoSplashInit(void);
|
||||
void DoSplashClose(void);
|
||||
void DoSplashSetFileJarName(const char* fileName, const char* jarName);
|
||||
void DoSplashSetScaleFactor(float scaleFactor);
|
||||
char* DoSplashGetScaledImageName(const char* jarName, const char* fileName,
|
||||
float* scaleFactor);
|
||||
|
@ -37,6 +37,9 @@ typedef void (*SplashInit_t)(void);
|
||||
typedef void (*SplashClose_t)(void);
|
||||
typedef void (*SplashSetFileJarName_t)(const char* fileName,
|
||||
const char* jarName);
|
||||
typedef void (*SplashSetScaleFactor_t)(float scaleFactor);
|
||||
typedef char* (*SplashGetScaledImageName_t)(const char* fileName,
|
||||
const char* jarName, float* scaleFactor);
|
||||
|
||||
/*
|
||||
* This macro invokes a function from the shared lib.
|
||||
@ -58,11 +61,11 @@ typedef void (*SplashSetFileJarName_t)(const char* fileName,
|
||||
#define INVOKEV(name) _INVOKE(name, ,;)
|
||||
|
||||
int DoSplashLoadMemory(void* pdata, int size) {
|
||||
INVOKE(SplashLoadMemory,0)(pdata, size);
|
||||
INVOKE(SplashLoadMemory, NULL)(pdata, size);
|
||||
}
|
||||
|
||||
int DoSplashLoadFile(const char* filename) {
|
||||
INVOKE(SplashLoadFile,0)(filename);
|
||||
INVOKE(SplashLoadFile, NULL)(filename);
|
||||
}
|
||||
|
||||
void DoSplashInit(void) {
|
||||
@ -76,3 +79,12 @@ void DoSplashClose(void) {
|
||||
void DoSplashSetFileJarName(const char* fileName, const char* jarName) {
|
||||
INVOKEV(SplashSetFileJarName)(fileName, jarName);
|
||||
}
|
||||
|
||||
void DoSplashSetScaleFactor(float scaleFactor) {
|
||||
INVOKEV(SplashSetScaleFactor)(scaleFactor);
|
||||
}
|
||||
|
||||
char* DoSplashGetScaledImageName(const char* fileName, const char* jarName,
|
||||
float* scaleFactor) {
|
||||
INVOKE(SplashGetScaledImageName, NULL)(fileName, jarName, scaleFactor);
|
||||
}
|
@ -245,7 +245,14 @@ public final class SplashScreen {
|
||||
public Rectangle getBounds() throws IllegalStateException {
|
||||
synchronized (SplashScreen.class) {
|
||||
checkVisible();
|
||||
return _getBounds(splashPtr);
|
||||
float scale = _getScaleFactor(splashPtr);
|
||||
Rectangle bounds = _getBounds(splashPtr);
|
||||
assert scale > 0;
|
||||
if (scale > 0 && scale != 1) {
|
||||
bounds.setSize((int) (bounds.getWidth() / scale),
|
||||
(int) (bounds.getWidth() / scale));
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
}
|
||||
|
||||
@ -287,10 +294,19 @@ public final class SplashScreen {
|
||||
public Graphics2D createGraphics() throws IllegalStateException {
|
||||
synchronized (SplashScreen.class) {
|
||||
if (image==null) {
|
||||
Dimension dim = getSize();
|
||||
image = new BufferedImage(dim.width, dim.height, BufferedImage.TYPE_INT_ARGB);
|
||||
// get unscaled splash image size
|
||||
Dimension dim = _getBounds(splashPtr).getSize();
|
||||
image = new BufferedImage(dim.width, dim.height,
|
||||
BufferedImage.TYPE_INT_ARGB);
|
||||
}
|
||||
return image.createGraphics();
|
||||
float scale = _getScaleFactor(splashPtr);
|
||||
Graphics2D g = image.createGraphics();
|
||||
assert (scale > 0);
|
||||
if (scale <= 0) {
|
||||
scale = 1;
|
||||
}
|
||||
g.scale(scale, scale);
|
||||
return g;
|
||||
}
|
||||
}
|
||||
|
||||
@ -401,5 +417,6 @@ public final class SplashScreen {
|
||||
private native static String _getImageFileName(long splashPtr);
|
||||
private native static String _getImageJarName(long SplashPtr);
|
||||
private native static boolean _setImageData(long SplashPtr, byte[] data);
|
||||
private native static float _getScaleFactor(long SplashPtr);
|
||||
|
||||
};
|
||||
|
@ -220,3 +220,18 @@ JNIEXPORT jboolean JNICALL Java_java_awt_SplashScreen__1setImageData
|
||||
(*env)->ReleaseByteArrayElements(env, data, pBytes, JNI_ABORT);
|
||||
return rc ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_awt_SplashScreen
|
||||
* Method: _getScaleFactor
|
||||
* Signature: (J)F
|
||||
*/
|
||||
JNIEXPORT jfloat JNICALL Java_java_awt_SplashScreen__1getScaleFactor
|
||||
(JNIEnv *env, jclass thisClass, jlong jsplash)
|
||||
{
|
||||
Splash *splash = (Splash *) jlong_to_ptr(jsplash);
|
||||
if (!splash) {
|
||||
return 1;
|
||||
}
|
||||
return splash->scaleFactor;
|
||||
}
|
@ -59,6 +59,7 @@ SplashInit()
|
||||
|
||||
memset(splash, 0, sizeof(Splash));
|
||||
splash->currentFrame = -1;
|
||||
splash->scaleFactor = 1;
|
||||
initFormat(&splash->imageFormat, QUAD_RED_MASK, QUAD_GREEN_MASK,
|
||||
QUAD_BLUE_MASK, QUAD_ALPHA_MASK);
|
||||
SplashInitPlatform(splash);
|
||||
@ -101,6 +102,13 @@ SplashCleanup(Splash * splash)
|
||||
SplashSetFileJarName(NULL, NULL);
|
||||
}
|
||||
|
||||
SPLASHEXPORT void
|
||||
SplashSetScaleFactor(float scaleFactor)
|
||||
{
|
||||
Splash *splash = SplashGetInstance();
|
||||
splash->scaleFactor = scaleFactor;
|
||||
}
|
||||
|
||||
void
|
||||
SplashDone(Splash * splash)
|
||||
{
|
||||
|
@ -35,6 +35,9 @@ SPLASHEXPORT int SplashLoadFile(const char *filename); // FIXME: range checking
|
||||
SPLASHEXPORT void SplashInit(void);
|
||||
SPLASHEXPORT void SplashClose(void);
|
||||
|
||||
SPLASHEXPORT void SplashSetScaleFactor(float);
|
||||
SPLASHEXPORT char* SplashGetScaledImageName(const char*, const char*, float*);
|
||||
|
||||
SPLASHEXPORT void
|
||||
SplashSetFileJarName(const char* fileName, const char* jarName);
|
||||
|
||||
@ -79,6 +82,7 @@ typedef struct Splash
|
||||
int fileNameLen;
|
||||
char* jarName; /* stored in 16-bit unicode (jchars) */
|
||||
int jarNameLen;
|
||||
float scaleFactor;
|
||||
#if defined(WITH_WIN32)
|
||||
BOOL isLayered;
|
||||
HWND hWnd;
|
||||
@ -115,6 +119,8 @@ void SplashDonePlatform(Splash * splash);
|
||||
|
||||
unsigned SplashTime();
|
||||
char* SplashConvertStringAlloc(const char* in, int *size);
|
||||
char* SplashGetScaledImageName(const char* jarName,
|
||||
const char* fileName, float *scaleFactor);
|
||||
|
||||
void SplashLock(Splash * splash);
|
||||
void SplashUnlock(Splash * splash);
|
||||
@ -138,6 +144,7 @@ void SplashDone(Splash * splash);
|
||||
void SplashUpdateScreenData(Splash * splash);
|
||||
|
||||
void SplashCleanup(Splash * splash);
|
||||
void SplashSetScaleFactor(float scaleFactor);
|
||||
|
||||
|
||||
typedef struct SplashStream {
|
||||
|
@ -794,3 +794,11 @@ void
|
||||
SplashReconfigure(Splash * splash) {
|
||||
sendctl(splash, SPLASHCTL_RECONFIGURE);
|
||||
}
|
||||
|
||||
SPLASHEXPORT char*
|
||||
SplashGetScaledImageName(const char* jarName, const char* fileName,
|
||||
float *scaleFactor)
|
||||
{
|
||||
*scaleFactor = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -563,3 +563,11 @@ SplashReconfigure(Splash * splash)
|
||||
{
|
||||
PostMessage(splash->hWnd, WM_SPLASHRECONFIGURE, 0, 0);
|
||||
}
|
||||
|
||||
SPLASHEXPORT char*
|
||||
SplashGetScaledImageName(const char* jarName, const char* fileName,
|
||||
float *scaleFactor)
|
||||
{
|
||||
*scaleFactor = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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.Dialog;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Panel;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Robot;
|
||||
import java.awt.SplashScreen;
|
||||
import java.awt.Window;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import javax.imageio.ImageIO;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8043869
|
||||
* @author Alexander Scherbatiy
|
||||
* @summary [macosx] java -splash does not honor 2x hi dpi notation for retina
|
||||
* support
|
||||
* @run main MultiResolutionSplashTest GENERATE_IMAGES
|
||||
* @run main/othervm -splash:splash1.png MultiResolutionSplashTest TEST_SPLASH 0
|
||||
* @run main/othervm -splash:splash2 MultiResolutionSplashTest TEST_SPLASH 1
|
||||
* @run main/othervm -splash:splash3. MultiResolutionSplashTest TEST_SPLASH 2
|
||||
*/
|
||||
public class MultiResolutionSplashTest {
|
||||
|
||||
private static final int IMAGE_WIDTH = 300;
|
||||
private static final int IMAGE_HEIGHT = 200;
|
||||
|
||||
private static final ImageInfo[] tests = {
|
||||
new ImageInfo("splash1.png", "splash1@2x.png", Color.BLUE, Color.GREEN),
|
||||
new ImageInfo("splash2", "splash2@2x", Color.WHITE, Color.BLACK),
|
||||
new ImageInfo("splash3.", "splash3@2x.", Color.YELLOW, Color.RED)
|
||||
};
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
String test = args[0];
|
||||
|
||||
switch (test) {
|
||||
case "GENERATE_IMAGES":
|
||||
generateImages();
|
||||
break;
|
||||
case "TEST_SPLASH":
|
||||
int index = Integer.parseInt(args[1]);
|
||||
testSplash(tests[index]);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown test: " + test);
|
||||
}
|
||||
}
|
||||
|
||||
static void testSplash(ImageInfo test) throws Exception {
|
||||
SplashScreen splashScreen = SplashScreen.getSplashScreen();
|
||||
|
||||
if (splashScreen == null) {
|
||||
throw new RuntimeException("Splash screen is not shown!");
|
||||
}
|
||||
|
||||
Graphics2D g = splashScreen.createGraphics();
|
||||
Rectangle splashBounds = splashScreen.getBounds();
|
||||
int screenX = (int) splashBounds.getCenterX();
|
||||
int screenY = (int) splashBounds.getCenterY();
|
||||
|
||||
Robot robot = new Robot();
|
||||
Color splashScreenColor = robot.getPixelColor(screenX, screenY);
|
||||
|
||||
float scaleFactor = getScaleFactor();
|
||||
Color testColor = (1 < scaleFactor) ? test.color2x : test.color1x;
|
||||
|
||||
if (!testColor.equals(splashScreenColor)) {
|
||||
throw new RuntimeException(
|
||||
"Image with wrong resolution is used for splash screen!");
|
||||
}
|
||||
}
|
||||
|
||||
static float getScaleFactor() {
|
||||
|
||||
final Dialog dialog = new Dialog((Window) null);
|
||||
dialog.setSize(100, 100);
|
||||
dialog.setModal(true);
|
||||
final float[] scaleFactors = new float[1];
|
||||
Panel panel = new Panel() {
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
float scaleFactor = 1;
|
||||
if (g instanceof SunGraphics2D) {
|
||||
scaleFactor = ((SunGraphics2D) g).surfaceData.getDefaultScale();
|
||||
}
|
||||
scaleFactors[0] = scaleFactor;
|
||||
dialog.setVisible(false);
|
||||
}
|
||||
};
|
||||
|
||||
dialog.add(panel);
|
||||
dialog.setVisible(true);
|
||||
dialog.dispose();
|
||||
|
||||
return scaleFactors[0];
|
||||
}
|
||||
|
||||
static void generateImages() throws Exception {
|
||||
for (ImageInfo test : tests) {
|
||||
generateImage(test.name1x, test.color1x, 1);
|
||||
generateImage(test.name2x, test.color2x, 2);
|
||||
}
|
||||
}
|
||||
|
||||
static void generateImage(String name, Color color, int scale) throws Exception {
|
||||
File file = new File(name);
|
||||
if (file.exists()) {
|
||||
return;
|
||||
}
|
||||
BufferedImage image = new BufferedImage(scale * IMAGE_WIDTH, scale * IMAGE_HEIGHT,
|
||||
BufferedImage.TYPE_INT_RGB);
|
||||
Graphics g = image.getGraphics();
|
||||
g.setColor(color);
|
||||
g.fillRect(0, 0, scale * IMAGE_WIDTH, scale * IMAGE_HEIGHT);
|
||||
ImageIO.write(image, "png", file);
|
||||
}
|
||||
|
||||
static class ImageInfo {
|
||||
|
||||
final String name1x;
|
||||
final String name2x;
|
||||
final Color color1x;
|
||||
final Color color2x;
|
||||
|
||||
public ImageInfo(String name1x, String name2x, Color color1x, Color color2x) {
|
||||
this.name1x = name1x;
|
||||
this.name2x = name2x;
|
||||
this.color1x = color1x;
|
||||
this.color2x = color2x;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user