I have found a post by John Fultz with pretty clear explanation of how graphics functionality works:
In version 6, the kernel has
absolutely no involvement whatsoever
in generating the rendered image.
The steps taken in displaying a
graphic in version 6 are very much
like those used in displaying
non-graphical output. It works as
follows:
1) The expression is evaluated, and
ultimately produces something with
head Graphics[]
or Graphics3D[]
.
2) The resulting expression is passed
through MakeBoxes
. MakeBoxes
has a
set of rules which turns the graphics
expression into the box language which
the front end uses to represent
graphics. E.g.,
In[9]:= MakeBoxes[Graphics[{Point[{0, 0}]}], StandardForm]
Out[9]= GraphicsBox[{PointBox[{0, 0}]}]
Internally, we call this the "typeset"
expression. It may be a little weird
thinking of graphics as being
"typeset", but it's fundamentally the
same operation which happens for
typesetting (which has worked this way
for 11 years), so I'll use the term.
3) The resulting typeset expression is
sent via MathLink to the front end.
4) The front end parses the typeset
expression and creates internal
objects which generally have a
one-to-one correspondence to the
typeset expression.
5) The front end renders the internal
objects.
This means that the conversion is performed in the Kernel by a call to MakeBoxes
.
This call can be intercepted through high-level code:
list = {};
MakeBoxes[expr_, form_] /; (AppendTo[list, HoldComplete[expr]];
True) := Null;
HoldComplete[Rotate[Style[expr, Red], 0.5]]
ClearAll[MakeBoxes];
list
Here is what we get as output:
One can see that MakeBoxes
does not respect HoldAllComplete
attribute.
The list of symbols which are auto-converted before sending to the FrontEnd one can get from FormatValues
:
In[1]:= list =
Select[Names["*"],
ToExpression[#, InputForm,
Function[symbol, Length[FormatValues@symbol] > 0, HoldAll]] &];
list // Length
During evaluation of In[1]:= General::readp: Symbol I is read-protected. >>
Out[2]= 162