Icon Descriptor
Describes an Icon, and can instantiate an icon, but is not itself an icon.
You may think it's better to just extend the Icon class instead of having this class in between. However, as noted in the comments to IJPL-163887, this leads to issues with IntelliJ's built-in icon mechanisms that are responsible for loading, caching, and scaling.
You may also think it's better to just create functions that return Icons directly, i.e. replace this class with a function that implements only the get function. However, this would result in a loss of metadata. For example, with TypeIcon, the returned LayeredIcon does not tell you what the original TypeIcon.text and TypeIcon.colors are, making a function such as TypeIcon.combine a real mess to implement.
Before get is called, the graphics context for Icons has not been fully initialised yet. Therefore, implementing classes must not validate or otherwise access Icon-related properties before get is called. Violating this principle, for example by checking whether an Icon passed in the constructor is square, will result in exceptions; see for example #R13 and #R44. Such validation must be deferred to when get is called for the first time.