Fixed bug 4883 - Add approximation for display DPI on iOS
authorSam Lantinga <slouken@libsdl.org>
Sun, 08 Dec 2019 11:36:40 -0800
changeset 1332137350f1e7902
parent 13320 881796f84081
child 13322 383f548aaa88
Fixed bug 4883 - Add approximation for display DPI on iOS

Aaron Barany

There appears to be no way to directly access the display DPI on iOS, so as an approximation the DPI for the iPhone 1 is used as a base value and is multiplied by the screen's scale. This should at least give a ballpark number for the various screen scales. (based on https://stackoverflow.com/questions/25756087/detecting-iphone-6-6-screen-sizes-in-point-values it appears that both 2x and 3x are used)

I have updated the patch to use a table of current devices and use a computation as a fallback. I have also updated the fallback computation to be more accurate.
src/video/uikit/SDL_uikitmodes.h
src/video/uikit/SDL_uikitmodes.m
     1.1 --- a/src/video/uikit/SDL_uikitmodes.h	Sun Dec 08 11:33:06 2019 -0800
     1.2 +++ b/src/video/uikit/SDL_uikitmodes.h	Sun Dec 08 11:36:40 2019 -0800
     1.3 @@ -27,7 +27,10 @@
     1.4  
     1.5  @interface SDL_DisplayData : NSObject
     1.6  
     1.7 +- (instancetype)init;
     1.8 +
     1.9  @property (nonatomic, strong) UIScreen *uiscreen;
    1.10 +@property (nonatomic) float screenDPI;
    1.11  
    1.12  @end
    1.13  
    1.14 @@ -41,6 +44,7 @@
    1.15  
    1.16  extern int UIKit_InitModes(_THIS);
    1.17  extern void UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
    1.18 +extern int UIKit_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdpi, float * vdpi);
    1.19  extern int UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
    1.20  extern void UIKit_QuitModes(_THIS);
    1.21  extern int UIKit_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
     2.1 --- a/src/video/uikit/SDL_uikitmodes.m	Sun Dec 08 11:33:06 2019 -0800
     2.2 +++ b/src/video/uikit/SDL_uikitmodes.m	Sun Dec 08 11:36:40 2019 -0800
     2.3 @@ -27,9 +27,150 @@
     2.4  
     2.5  #include "../../events/SDL_events_c.h"
     2.6  
     2.7 +#import <sys/utsname.h>
     2.8 +
     2.9  @implementation SDL_DisplayData
    2.10  
    2.11 +- (instancetype)initWithScreen:(UIScreen*)screen
    2.12 +{
    2.13 +    if (self = [super init]) {
    2.14 +        self.uiscreen = screen;
    2.15 +
    2.16 +        /*
    2.17 +         * A well up to date list of device info can be found here:
    2.18 +         * https://github.com/lmirosevic/GBDeviceInfo/blob/master/GBDeviceInfo/GBDeviceInfo_iOS.m
    2.19 +         */
    2.20 +        NSDictionary* devices = @{
    2.21 +            @"iPhone1,1": @163,
    2.22 +            @"iPhone1,2": @163,
    2.23 +            @"iPhone2,1": @163,
    2.24 +            @"iPhone3,1": @326,
    2.25 +            @"iPhone3,2": @326,
    2.26 +            @"iPhone3,3": @326,
    2.27 +            @"iPhone4,1": @326,
    2.28 +            @"iPhone5,1": @326,
    2.29 +            @"iPhone5,2": @326,
    2.30 +            @"iPhone5,3": @326,
    2.31 +            @"iPhone5,4": @326,
    2.32 +            @"iPhone6,1": @326,
    2.33 +            @"iPhone6,2": @326,
    2.34 +            @"iPhone7,1": @401,
    2.35 +            @"iPhone7,2": @326,
    2.36 +            @"iPhone8,1": @326,
    2.37 +            @"iPhone8,2": @401,
    2.38 +            @"iPhone8,4": @326,
    2.39 +            @"iPhone9,1": @326,
    2.40 +            @"iPhone9,2": @401,
    2.41 +            @"iPhone9,3": @326,
    2.42 +            @"iPhone9,4": @401,
    2.43 +            @"iPhone10,1": @326,
    2.44 +            @"iPhone10,2": @401,
    2.45 +            @"iPhone10,3": @458,
    2.46 +            @"iPhone10,4": @326,
    2.47 +            @"iPhone10,5": @401,
    2.48 +            @"iPhone10,6": @458,
    2.49 +            @"iPhone11,2": @458,
    2.50 +            @"iPhone11,4": @458,
    2.51 +            @"iPhone11,6": @458,
    2.52 +            @"iPhone11,8": @326,
    2.53 +            @"iPhone12,1": @326,
    2.54 +            @"iPhone12,3": @458,
    2.55 +            @"iPhone12,5": @458,
    2.56 +            @"iPad1,1": @132,
    2.57 +            @"iPad2,1": @132,
    2.58 +            @"iPad2,2": @132,
    2.59 +            @"iPad2,3": @132,
    2.60 +            @"iPad2,4": @132,
    2.61 +            @"iPad2,5": @163,
    2.62 +            @"iPad2,6": @163,
    2.63 +            @"iPad2,7": @163,
    2.64 +            @"iPad3,1": @264,
    2.65 +            @"iPad3,2": @264,
    2.66 +            @"iPad3,3": @264,
    2.67 +            @"iPad3,4": @264,
    2.68 +            @"iPad3,5": @264,
    2.69 +            @"iPad3,6": @264,
    2.70 +            @"iPad4,1": @264,
    2.71 +            @"iPad4,2": @264,
    2.72 +            @"iPad4,3": @264,
    2.73 +            @"iPad4,4": @326,
    2.74 +            @"iPad4,5": @326,
    2.75 +            @"iPad4,6": @326,
    2.76 +            @"iPad4,7": @326,
    2.77 +            @"iPad4,8": @326,
    2.78 +            @"iPad4,9": @326,
    2.79 +            @"iPad5,1": @326,
    2.80 +            @"iPad5,2": @326,
    2.81 +            @"iPad5,3": @264,
    2.82 +            @"iPad5,4": @264,
    2.83 +            @"iPad6,3": @264,
    2.84 +            @"iPad6,4": @264,
    2.85 +            @"iPad6,7": @264,
    2.86 +            @"iPad6,8": @264,
    2.87 +            @"iPad6,11": @264,
    2.88 +            @"iPad6,12": @264,
    2.89 +            @"iPad7,1": @264,
    2.90 +            @"iPad7,2": @264,
    2.91 +            @"iPad7,3": @264,
    2.92 +            @"iPad7,4": @264,
    2.93 +            @"iPad7,5": @264,
    2.94 +            @"iPad7,6": @264,
    2.95 +            @"iPad7,11": @264,
    2.96 +            @"iPad7,12": @264,
    2.97 +            @"iPad8,1": @264,
    2.98 +            @"iPad8,2": @264,
    2.99 +            @"iPad8,3": @264,
   2.100 +            @"iPad8,4": @264,
   2.101 +            @"iPad8,5": @264,
   2.102 +            @"iPad8,6": @264,
   2.103 +            @"iPad8,7": @264,
   2.104 +            @"iPad8,8": @264,
   2.105 +            @"iPad11,1": @326,
   2.106 +            @"iPad11,2": @326,
   2.107 +            @"iPad11,3": @326,
   2.108 +            @"iPad11,4": @326,
   2.109 +            @"iPod1,1": @163,
   2.110 +            @"iPod2,1": @163,
   2.111 +            @"iPod3,1": @163,
   2.112 +            @"iPod4,1": @326,
   2.113 +            @"iPod5,1": @326,
   2.114 +            @"iPod7,1": @326,
   2.115 +            @"iPod9,1": @326,
   2.116 +        };
   2.117 +
   2.118 +        struct utsname systemInfo;
   2.119 +        uname(&systemInfo);
   2.120 +        NSString* deviceName =
   2.121 +            [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
   2.122 +        id foundDPI = devices[deviceName];
   2.123 +        if (foundDPI) {
   2.124 +            self.screenDPI = (float)[foundDPI integerValue];
   2.125 +        } else {
   2.126 +            /*
   2.127 +             * Estimate the DPI based on the screen scale multiplied by the base DPI for the device
   2.128 +             * type (e.g. based on iPhone 1 and iPad 1)
   2.129 +             */
   2.130 +    #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000
   2.131 +            float scale = (float)screen.nativeScale;
   2.132 +    #else
   2.133 +            float scale = (float)screen.scale;
   2.134 +    #endif
   2.135 +            float defaultDPI;
   2.136 +            if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
   2.137 +                defaultDPI = 132.0f;
   2.138 +            } else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
   2.139 +                defaultDPI = 163.0f;
   2.140 +            } else {
   2.141 +                defaultDPI = 160.0f;
   2.142 +            }
   2.143 +            self.screenDPI = scale * defaultDPI;
   2.144 +        }
   2.145 +    }
   2.146 +    return self;
   2.147 +}
   2.148 +
   2.149  @synthesize uiscreen;
   2.150 +@synthesize screenDPI;
   2.151  
   2.152  @end
   2.153  
   2.154 @@ -153,14 +294,12 @@
   2.155      display.current_mode = mode;
   2.156  
   2.157      /* Allocate the display data */
   2.158 -    SDL_DisplayData *data = [[SDL_DisplayData alloc] init];
   2.159 +    SDL_DisplayData *data = [[SDL_DisplayData alloc] initWithScreen:uiscreen];
   2.160      if (!data) {
   2.161          UIKit_FreeDisplayModeData(&display.desktop_mode);
   2.162          return SDL_OutOfMemory();
   2.163      }
   2.164  
   2.165 -    data.uiscreen = uiscreen;
   2.166 -
   2.167      display.driverdata = (void *) CFBridgingRetain(data);
   2.168      SDL_AddVideoDisplay(&display);
   2.169  
   2.170 @@ -244,6 +383,27 @@
   2.171  }
   2.172  
   2.173  int
   2.174 +UIKit_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdpi, float * vdpi)
   2.175 +{
   2.176 +    @autoreleasepool {
   2.177 +        SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
   2.178 +        float dpi = data.screenDPI;
   2.179 +
   2.180 +        if (ddpi) {
   2.181 +            *ddpi = dpi * (float)SDL_sqrt(2.0);
   2.182 +        }
   2.183 +        if (hdpi) {
   2.184 +            *hdpi = dpi;
   2.185 +        }
   2.186 +        if (vdpi) {
   2.187 +            *vdpi = dpi;
   2.188 +        }
   2.189 +    }
   2.190 +
   2.191 +    return 0;
   2.192 +}
   2.193 +
   2.194 +int
   2.195  UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
   2.196  {
   2.197      @autoreleasepool {