Razor-sharp text with NO code tweaks (I think so...)

This might concern many developers who have been wrestling for some time with the “Retina text” issue (blurry text on Retina devices unless you implement Jon Beebe’s scaling functions or similar). I think I have discovered a method to get razor-sharp text without doing any of that, and without creating more image assets or otherwise.

It comes down to the “config.lua” file. Compare the following:

Ansca’s example code for dynamic image scaling:

application =  
{  
 content =  
 {  
 width = 320,  
 height = 480,  
 scale = "letterbox",  
   
 imageSuffix =  
 {  
 ["@2"] = 2,  
 ["@3"] = 3,  
 ["-bar"] = 3.3,  
 ["-foo"] = 4.5,  
 },  
 },  
}  

My current code within config.lua:

application =   
{  
 content =   
 {   
 width = 800,  
 height = 1200,  
 scale = "letterbox",  
  
 imageSuffix =  
 {  
 ["\_1"] = 0.4,  
 ["\_2"] = 0.6  
 ["\_3"] = 0.85  
 }  
 }  
}  

The difference is simple: Ansca’s method sets a LOW base resolution (320x480) and then scales UP for the dynamic scaling settings. My code uses a HIGH base resolution (800x1200) and then scales DOWN, using percentages in decimal form.

The end result is the same in regards to image assets (you won’t need to remake all of your art assets if you simply recalculate the scaling factors properly). But this might make a big difference for text! In my code, the text resolution begins high, and then gets scaled down by Corona, which is exactly what Jon’s functions do (specify double-size text in the newText function, then scale it down to 0.5).

Further testing is necessary to determine if this truly works on all devices. For now, I can attest that I haven’t used any “tweaks” or functions atop the base newText function. And my text on a Retina device is brilliantly sharp, in every instance.

Can others please test this out in their code and on their devices? Knock on wood, perhaps this is the most simple solution yet… and if it does work, it spares us having to include add-on functions or “rewrite” the newText function; not to mention those add-on functions caused me endless frustration when I tried to align text using reference points other than top-left or whatever the default is.

Brent Sorrentino
Ignis Design [import]uid: 9747 topic_id: 15670 reply_id: 315670[/import]

Why did you choose those numbers and scaling factors?

Will display.newImageRect() still work, or do you have to provide an unprefixed version of the graphics scaled to work at 1200x800? [import]uid: 19626 topic_id: 15670 reply_id: 57833[/import]

I used 800x1200 basically because it’s a suitably high resolution (higher than the max iPad height of 1024), and it’s in the same 2x3 ratio as iPhone. You could probably use 640x960 for the “typical” Retina display, if that’s your target device.

The scaling numbers, however, were specifically calculated for the 800x1200 core resolution. The numbers I provided will do the following:

_3 : iPad only
_2 : iPhone4, iPod Touch 4
_1 : iPhone 3 & older

As I mentioned, you could recalculate these numbers however you wish to specify which image assets you want to appear on which devices.

“display.newImageRect” absolutely still works and I use it constantly. :slight_smile: If you’ve created “Retina” images already, you can still use them… all that’s necessary is tweaking the config file numbers and scaling appropriately. [import]uid: 9747 topic_id: 15670 reply_id: 57836[/import]

(CLARIFICATION): I should point out for everybody reading this thread, just because I set the core resolution to 800x1200, it doesn’t mean that you must create a whole new set of image assets scaled up to 1200. The suffix settings determine your scaling, just like in Ansca’s example, but in “fractional inverse”.

If my theory is correct, setting a high core resolution is what makes the *text* so razor-sharp, which is a superior solution to including add-on functions or otherwise.
[import]uid: 9747 topic_id: 15670 reply_id: 57838[/import]

I’m still a little confused about display.newImageRect.

Normally you pass it an image with no suffix, then it looks for alternate suffixes if the device isn’t scaled to 1.0.

Since no device is 1200x800, I’m guessing this works because it always has to look for an image with a prefix – Until you try and run it on a 1200x800 device.

[import]uid: 19626 topic_id: 15670 reply_id: 57877[/import]

Hi Rob,
I agree it’s a bit confusing. Here’s an explanation of how I think it all works (somebody at Ansca might be able to confirm this):

Let’s just deal with the height parameter (1200) for sake of discussion. There is no device with an actual 1200-pixel-tall resolution, but by using this value I’m telling Corona to “squeeze” the idea of 1200 pixels height into the actual device screen height.

And that is where the suffix scale numbers are crucial. Here’s what I set them to:

imageSuffix = { ["\_1"] = 0.4, ["\_2"] = 0.6, ["\_3"] = 0.85 }

And here’s how I calculated those numbers:

REAL height / configured "height" = scale percentage (decimal)

iPhone3G: 480 / 1200 = 0.4
iPhone4: 960 / 1200 = 0.8
iPad: 1024 / 1200 = 0.8533333333

When Corona runs an app, it does this exact same calculation internally… it knows the actual resolution of the device and so it has these same values which is uses for the “newImageRect” function. Based on what I entered in “config.lua” for my image suffixes, it then decides, if the calculated value is greater than the suffix value , then use that suffix as the chosen image extension.

So, in my app, because the internal calculated value for iPad is 0.8533333333, I chose “0.85” for the “_3” suffix value, and thus iPad will use that suffix for all images. I used “0.6” for the “_2” suffix, because I needed to accommodate some Android devices which aren’t in the same proportion as iPhone. On the low end (iPhone3G), the calculated scale is 0.4, so that device will always choose that suffix.

A key factor here is that I don’t set any scale suffix to “1.0” because, as you say, there is no device yet with a 1200x800 resolution. When there is a device like that, I can add that suffix as “_4” and scale up all of my images (Adobe Fireworks is brilliant for this) and I’ll have crisp, perfectly-sized images for that.

A very important point is that 1200x800 is just a representation of a screen size, not an actual screen size. I could have used 12000x8000 and set my scale values to 0.04, 0.08, and 0.0853333, and “newImageRect” would function the same. But remember that the content width/height are still used for all factory display functions , including vectors, text, circles, etc! This is why, I believe, my scenario has resulted in razor-sharp text: Corona is already displaying it at very high resolution (based on 1200x800) and then scaling it down for the various device screens, all of which are smaller.

Hopefully this clarifies things!

Brent
[import]uid: 9747 topic_id: 15670 reply_id: 57889[/import]

Hi Brent,
Very nice explanation!

I`ll keep all this info bookmarked like this I can “remember” how to get great retina text using your discovery. =]

Thanks for sharing.
Regards, [import]uid: 89165 topic_id: 15670 reply_id: 59375[/import]

bumping this in the hopes that someone at Ansca will provide either cautions, or a thumbs up on this approach…I like it! [import]uid: 6175 topic_id: 15670 reply_id: 60091[/import]

Hmmm… I think there’s a thread somewhere from my experiments on this a while back.

Scaling down won’t work in all applications because scaling down doesn’t always work so well.

For example, while you can scale UP a 1 pixel line, by multiplying it by the scaling factor… You can NOT scale DOWN a 1 pixel line… at least, not very well. I found it to be very inconsistent and slide an image causes the line to shift in and out of existence. :wink:

In particular, though, my “philosophical” issue was with designing for the smaller 320x480 iOS screen resolution, even while the new phones (and the larger market share of devices) is for 640x960…

Indeed, if you do all your imagery in the various scaling factors and don’t “draw” anything to the screen, you may be ok. In the end, I decided it was far too much thought, even working in the 640x960 and scaling down for iPhone 3xx, it just looked bad on those devices most of the time.

Best wishes,
~~Kenn

[import]uid: 13859 topic_id: 15670 reply_id: 60093[/import]

Regarding retina text:

display.newText() has been modified to handle “retina text” automatically, and therefore display.newRetinaText() has been deprecated since it is no longer needed.

The changes will be reflected in the next daily build (the one posted *after* 2012.770).
[import]uid: 52430 topic_id: 15670 reply_id: 94937[/import]