High DPI Resources
Most Chrome image assets should be supplied in 1x and (for Mac Retina display) 2x scales. Eventually we'll probably also have 1.4x and 1.8x scales for Windows 8 Metro.
In addition to different scale factors, some assets come in different sizes for LAYOUT_TOUCH mode (eg. buttons that need to be larger to touch reliably). Layout is an orthogonal issue to scale factor, but both affect which assets are loaded.
If you just have to add new assets this section should cover everything you need to know. For the purposes of brevity this document assumes that you want to add a 2x asset but the same applies for any scale factor.
Resources in ui/resources/ and chrome/app/theme/ should be added to the relevant subfolder for grit to automatically discover them:
- default_100_percent: 1x resources
- default_200_percent: 2x resources
- touch_100_percent: touch optimized 1x resources
- touch_200_percent: touch optimized 2x resources
High DPI resources can be loaded in Chrome WebUI using one of three methods, which one is appropriate depends on where the image is.
Important: For grit to automatically construct a -webkit-image-set reference the relevant css file must be included from a <structure type="chrome_html"> tag. See chrome/browser/resources/shared_resources.grd for examples.
WebUI resources are those located in chrome/browser/resources/. These are also referred to using the chrome://resources/ handler. These should be referenced using a relative path to the image. For example from chrome/browser/resources/shared/css/overlay.css:
Add a 2x subfolder to the location of the base image and place the 2x image in there. In this case you would have both:
A -webkit-image-set rule will automatically be generated by grit when processing this file. If for some reason the file must be specified by a url or in script then manually write an image-set rule as in the UI Resources section below.
Theme and UI resources are those defined in chrome/app/theme/theme_resources*.grd or ui/resources/ui_resources.grd. These should be added according to the native resources convention. From WebUI, the resource is usually loaded from a chrome://theme/IDR_RESOURCE_NAME url referring to the name specified in theme_resources*.grd or ui/resources/ui_resources.grd.
- If the resource is referred to by resource name from a css rule, (i.e. background-image: url('chrome://theme/IDR_RESOURCE_NAME');) then a high DPI reference is added automatically by grit and you are done.
html: <img style="content:-webkit-image-set(url('chrome://theme/IDR_RESOURCE_NAME') 1x, url('chrome://theme/IDR_RESOURCE_NAME@2x') 2x);">
js: $('my-img').style.content = '-webkit-image-set(url(\'chrome://theme/IDR_RESOURCE_NAME\') 1x, ' +
- If the img is using the 'src' attribute to specify the url, 'srcset' can be used in addition to 'src' to specify just the 2x property (or just srcset can be used to describe both):
<img src='chrome://theme/IDR_RESOURCE_NAME' srcset='chrome://theme/IDR_RESOURCE_NAME@2x 2x'>
<img srcset='chrome://theme/IDR_RESOURCE_NAME 1x chrome://theme/IDR_RESOURCE_NAME@2x 2x'>
- If the resource is referred to using a relative path and you do not want to move this to css then follow the Theme and UI resources (Manual image set) section.
Theme and UI image resources without corresponding IDR definitions should be referenced using a relative path with an explicit -webkit-image-set. I.e. for the file ui/resources/default_100_percent/close.png being referred to from chrome/browser/resources/close.css change the CSS to the following:
The goals of the means for using high DPI resources in WebUI are the following:
- Make it obvious when changes to one size asset require a corresponding change to other size asset descriptions through code locality.
- Have a mechanism by which developers can be warned when adding only low resolution assets. Automatically get other densities when working on WebUI without having to think about it.
- Avoid including resources for densities not supported on a platform.
Given (1) and (2), we use the image-set() function when manually specifying rules. This makes it immediately obvious if you are changing one of the assets that the other density assets may need to be changed as well. In order to facilitate (3) and (4) the build process will do some conversion of CSS but only in so far as it is compatible with running the page standalone (1) (i.e. there should be no macros or otherwise incorrect CSS if you use the file directly).
In order to automatically get other densities (3) and remove unsupported densities, the build process performs some conversion of CSS properties on files included in a chrome_html structure node. In particular, if it can determine from a given CSS image rule such as content: url('../my/image/foo.png') that a 2x image is available, then it will automatically generate an image set referring to both the 1x and 2x image. This is accomplished by using a '2x' (or scale factor + 'x') subdirectory where the 1x image is located. This allows images to be located in each of the relevant component directories and can deal with any relative image path appropriately. Since native resources must be centrally located a different tradeoff was made with respect to directory structure so we have to manually reference each density asset in folders outside of chrome/browser/resources/.
Theme resources are loaded by name, and in practice can be changed dynamically. In order to fetch various density theme resources theme_source.cc was modified to accept theme source requests such as chrome://theme/IDR_RESOURCE_NAME@2x and fetch the appropriate theme image. If a high DPI theme resource is not available it falls back to returning the 1x theme resource which means that in any place where you use a theme source which may not have a 2x asset it should have the size of the image explicitly set. Otherwise, the 1x image is returned, assumed to be 2x and scaled down to half the size such that it is displayed 1:1 on a 2x screen.