alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (CGraphicsDevice.m)

This example Java source code file (CGraphicsDevice.m) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

cfarraygetcount, cfarrayref, cfindex, cfrelease, cfstr, cfstringcompare, cgdisplaymoderef, jnf_cocoa_enter, jnf_cocoa_exit, jnicall, jnienv, jniexport, nsscreen, null

The CGraphicsDevice.m Java example source code

/*
 * Copyright (c) 2012, 2013, 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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 "LWCToolkit.h"
#import "ThreadUtilities.h"

/*
 * Convert the mode string to the more convinient bits per pixel value
 */
static int getBPPFromModeString(CFStringRef mode)
{
    if ((CFStringCompare(mode, CFSTR(kIO30BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)) {
        // This is a strange mode, where we using 10 bits per RGB component and pack it into 32 bits
        // Java is not ready to work with this mode but we have to specify it as supported
        return 30;
    }
    else if (CFStringCompare(mode, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
        return 32;
    }
    else if (CFStringCompare(mode, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
        return 16;
    }
    else if (CFStringCompare(mode, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
        return 8;
    }

    return 0;
}

static BOOL isValidDisplayMode(CGDisplayModeRef mode){
    return (1 < CGDisplayModeGetWidth(mode) && 1 < CGDisplayModeGetHeight(mode));
}

static CFMutableArrayRef getAllValidDisplayModes(jint displayID){
    CFArrayRef allModes = CGDisplayCopyAllDisplayModes(displayID, NULL);

    CFIndex numModes = CFArrayGetCount(allModes);
    CFMutableArrayRef validModes = CFArrayCreateMutable(kCFAllocatorDefault, numModes + 1, NULL);

    CFIndex n;
    for (n=0; n < numModes; n++) {
        CGDisplayModeRef cRef = (CGDisplayModeRef) CFArrayGetValueAtIndex(allModes, n);
        if (cRef != NULL && isValidDisplayMode(cRef)) {
            CFArrayAppendValue(validModes, cRef);
        }
    }

    CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(displayID);

    BOOL containsCurrentMode = NO;
    numModes = CFArrayGetCount(validModes);
    for (n=0; n < numModes; n++) {
        if(CFArrayGetValueAtIndex(validModes, n) == currentMode){
            containsCurrentMode = YES;
            break;
        }
    }

    if (!containsCurrentMode) {
        CFArrayAppendValue(validModes, currentMode);
    }

    return validModes;
}

/*
 * Find the best possible match in the list of display modes that we can switch to based on
 * the provided parameters.
 */
static CGDisplayModeRef getBestModeForParameters(CFArrayRef allModes, int w, int h, int bpp, int refrate) {
    CGDisplayModeRef bestGuess = NULL;
    CFIndex numModes = CFArrayGetCount(allModes), n;
    int thisBpp = 0;
    for(n = 0; n < numModes; n++ ) {
        CGDisplayModeRef cRef = (CGDisplayModeRef) CFArrayGetValueAtIndex(allModes, n);
        if(cRef == NULL) {
            continue;
        }
        CFStringRef modeString = CGDisplayModeCopyPixelEncoding(cRef);
        thisBpp = getBPPFromModeString(modeString);
        CFRelease(modeString);
        if (thisBpp != bpp || (int)CGDisplayModeGetHeight(cRef) != h || (int)CGDisplayModeGetWidth(cRef) != w) {
            // One of the key parameters does not match
            continue;
        }

        if (refrate == 0) { // REFRESH_RATE_UNKNOWN
            return cRef;
        }

        // Refresh rate might be 0 in display mode and we ask for specific display rate
        // but if we do not find exact match then 0 refresh rate might be just Ok
        if (CGDisplayModeGetRefreshRate(cRef) == refrate) {
            // Exact match
            return cRef;
        }
        if (CGDisplayModeGetRefreshRate(cRef) == 0) {
            // Not exactly what was asked for, but may fit our needs if we don't find an exact match
            bestGuess = cRef;
        }
    }
    return bestGuess;
}

/*
 * Create a new java.awt.DisplayMode instance based on provided CGDisplayModeRef
 */
static jobject createJavaDisplayMode(CGDisplayModeRef mode, JNIEnv *env, jint displayID) {
    jobject ret = NULL;
    jint h, w, bpp, refrate;
    JNF_COCOA_ENTER(env);
    CFStringRef currentBPP = CGDisplayModeCopyPixelEncoding(mode);
    bpp = getBPPFromModeString(currentBPP);
    refrate = CGDisplayModeGetRefreshRate(mode);
    h = CGDisplayModeGetHeight(mode);
    w = CGDisplayModeGetWidth(mode);
    CFRelease(currentBPP);
    static JNF_CLASS_CACHE(jc_DisplayMode, "java/awt/DisplayMode");
    static JNF_CTOR_CACHE(jc_DisplayMode_ctor, jc_DisplayMode, "(IIII)V");
    ret = JNFNewObject(env, jc_DisplayMode_ctor, w, h, bpp, refrate);
    JNF_COCOA_EXIT(env);
    return ret;
}


/*
 * Class:     sun_awt_CGraphicsDevice
 * Method:    nativeGetXResolution
 * Signature: (I)D
 */
JNIEXPORT jdouble JNICALL
Java_sun_awt_CGraphicsDevice_nativeGetXResolution
  (JNIEnv *env, jclass class, jint displayID)
{
    // TODO: this is the physically correct answer, but we probably want
    // to use NSScreen API instead...
    CGSize size = CGDisplayScreenSize(displayID);
    CGRect rect = CGDisplayBounds(displayID);
    // 1 inch == 25.4 mm
    jfloat inches = size.width / 25.4f;
    jfloat dpi = rect.size.width / inches;
    return dpi;
}

/*
 * Class:     sun_awt_CGraphicsDevice
 * Method:    nativeGetYResolution
 * Signature: (I)D
 */
JNIEXPORT jdouble JNICALL
Java_sun_awt_CGraphicsDevice_nativeGetYResolution
  (JNIEnv *env, jclass class, jint displayID)
{
    // TODO: this is the physically correct answer, but we probably want
    // to use NSScreen API instead...
    CGSize size = CGDisplayScreenSize(displayID);
    CGRect rect = CGDisplayBounds(displayID);
    // 1 inch == 25.4 mm
    jfloat inches = size.height / 25.4f;
    jfloat dpi = rect.size.height / inches;
    return dpi;
}

/*
 * Class:     sun_awt_CGraphicsDevice
 * Method:    nativeGetScreenInsets
 * Signature: (I)D
 */
JNIEXPORT jobject JNICALL
Java_sun_awt_CGraphicsDevice_nativeGetScreenInsets
  (JNIEnv *env, jclass class, jint displayID)
{
    jobject ret = NULL;
    __block NSRect frame = NSZeroRect;
    __block NSRect visibleFrame = NSZeroRect;
JNF_COCOA_ENTER(env);
    
    [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
        NSArray *screens = [NSScreen screens];
        for (NSScreen *screen in screens) {
            NSDictionary *screenInfo = [screen deviceDescription];
            NSNumber *screenID = [screenInfo objectForKey:@"NSScreenNumber"];
            if ([screenID pointerValue] == displayID){
                frame = [screen frame];
                visibleFrame = [screen visibleFrame];
                break;
            }
        }
    }];
    // Convert between Cocoa's coordinate system and Java.
    jint bottom = visibleFrame.origin.y - frame.origin.y;
    jint top = frame.size.height - visibleFrame.size.height - bottom;
    jint left = visibleFrame.origin.x - frame.origin.x;
    jint right = frame.size.width - visibleFrame.size.width - left;
    
    static JNF_CLASS_CACHE(jc_Insets, "java/awt/Insets");
    static JNF_CTOR_CACHE(jc_Insets_ctor, jc_Insets, "(IIII)V");
    ret = JNFNewObject(env, jc_Insets_ctor, top, left, bottom, right);

JNF_COCOA_EXIT(env);

    return ret;
}

/*
 * Class:     sun_awt_CGraphicsDevice
 * Method:    nativeSetDisplayMode
 * Signature: (IIIII)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_CGraphicsDevice_nativeSetDisplayMode
(JNIEnv *env, jclass class, jint displayID, jint w, jint h, jint bpp, jint refrate)
{
    JNF_COCOA_ENTER(env);
    CFArrayRef allModes = getAllValidDisplayModes(displayID);

    CGDisplayModeRef closestMatch = getBestModeForParameters(allModes, (int)w, (int)h, (int)bpp, (int)refrate);
    __block CGError retCode = kCGErrorSuccess;
    if (closestMatch != NULL) {
        [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
            CGDisplayConfigRef config;
            retCode = CGBeginDisplayConfiguration(&config);
            if (retCode == kCGErrorSuccess) {
                CGConfigureDisplayWithDisplayMode(config, displayID, closestMatch, NULL);
                retCode = CGCompleteDisplayConfiguration(config, kCGConfigureForAppOnly);
            }
        }];
    } else {
        [JNFException raise:env as:kIllegalArgumentException reason:"Invalid display mode"];
    }

    if (retCode != kCGErrorSuccess){
        [JNFException raise:env as:kIllegalArgumentException reason:"Unable to set display mode!"];
    }    

    CFRelease(allModes);
    JNF_COCOA_EXIT(env);
}
/*
 * Class:     sun_awt_CGraphicsDevice
 * Method:    nativeGetDisplayMode
 * Signature: (I)Ljava/awt/DisplayMode
 */
JNIEXPORT jobject JNICALL
Java_sun_awt_CGraphicsDevice_nativeGetDisplayMode
(JNIEnv *env, jclass class, jint displayID)
{
    jobject ret = NULL;
    CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(displayID);
    ret = createJavaDisplayMode(currentMode, env, displayID);
    CGDisplayModeRelease(currentMode);
    return ret;
}

/*
 * Class:     sun_awt_CGraphicsDevice
 * Method:    nativeGetDisplayMode
 * Signature: (I)[Ljava/awt/DisplayModes
 */
JNIEXPORT jobjectArray JNICALL
Java_sun_awt_CGraphicsDevice_nativeGetDisplayModes
(JNIEnv *env, jclass class, jint displayID)
{
    jobjectArray jreturnArray = NULL;
    JNF_COCOA_ENTER(env);
    CFArrayRef allModes = getAllValidDisplayModes(displayID);

    CFIndex numModes = CFArrayGetCount(allModes);
    static JNF_CLASS_CACHE(jc_DisplayMode, "java/awt/DisplayMode");

    jreturnArray = JNFNewObjectArray(env, &jc_DisplayMode, (jsize) numModes);
    if (!jreturnArray) {
        NSLog(@"CGraphicsDevice can't create java array of DisplayMode objects");
        return nil;
    }

    CFIndex n;
    for (n=0; n < numModes; n++) {
        CGDisplayModeRef cRef = (CGDisplayModeRef) CFArrayGetValueAtIndex(allModes, n);
        if (cRef != NULL) {
            jobject oneMode = createJavaDisplayMode(cRef, env, displayID);
            (*env)->SetObjectArrayElement(env, jreturnArray, n, oneMode);
            if ((*env)->ExceptionOccurred(env)) {
                (*env)->ExceptionDescribe(env);
                (*env)->ExceptionClear(env);
                continue;
            }
            (*env)->DeleteLocalRef(env, oneMode);
        }
    }
    CFRelease(allModes);
    JNF_COCOA_EXIT(env);

    return jreturnArray;
}

/*
 * Class:     sun_awt_CGraphicsDevice
 * Method:    nativeGetScaleFactor
 * Signature: (I)D
 */
JNIEXPORT jdouble JNICALL
Java_sun_awt_CGraphicsDevice_nativeGetScaleFactor
(JNIEnv *env, jclass class, jint displayID)
{
    __block jdouble ret = 1.0f;

JNF_COCOA_ENTER(env);

    [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
        NSArray *screens = [NSScreen screens];
        for (NSScreen *screen in screens) {
            NSDictionary *screenInfo = [screen deviceDescription];
            NSNumber *screenID = [screenInfo objectForKey:@"NSScreenNumber"];
            if ([screenID pointerValue] == displayID){
                if ([screen respondsToSelector:@selector(backingScaleFactor)]) {
                    ret = [screen backingScaleFactor];
                }
                break;
            }
        }
    }];

JNF_COCOA_EXIT(env);
    return ret;
}

Other Java examples (source code examples)

Here is a short list of links related to this Java CGraphicsDevice.m source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.