Try this:
SetAttributes[createPrimitive, HoldAll]
createPrimitive[patt_, expr_] :=
Typeset`MakeBoxes[p : patt, fmt_, Graphics] :=
Typeset`MakeBoxes[Interpretation[expr, p], fmt, Graphics]
Example:
createPrimitive[face[x_: 0.1],
{Circle[{0, 0}, 1], Circle[{-0.3, 0.5}, x],
Circle[{0.3, 0.5}, x], Line[{{-0.4, -0.2}, {0.4, -0.2}}]}]
It works as expected in Graphics
:
g = Graphics[face[]]

face
has no DownValues
so it remains as face
in InputForm
:
InputForm[g]
(* Graphics[face[]] *)

(* Graphics[face[], ImageSize -> {63., Automatic}] *)
It works with GeometricTransformation
:
Graphics[GeometricTransformation[face[0.2], ShearingTransform[Pi/4, {1, 0}, {0, 1}]]]

A note about colours
A commenter asked "How would you rewrite this function to color the different components differently?" The answer is that colours can be used in the definition of the custom primitive just as in any other graphics expression, but note that the expression that goes into Typeset`MakeBoxes
must be something that the Front End understands, e.g. RGBColor[1,0,0]
rather than Red
. If you want to use named colours like Red
you will need to let the kernel evaluate the expression to convert them to RGBColor
directives.
So for example you could:
Manually specify the colours as RGBColor
directives:
createPrimitive[myprim[x_], {RGBColor[1, 0, 0], Circle[{0, 0}, x]}]
Use named colours and override the hold attribute with Evaluate
:
createPrimitive[myprim[x_], Evaluate @ {Red, Circle[{0, 0}, x]}]
Or just remove the hold attribute completely:
ClearAttributes[createPrimitive, HoldAll];
createPrimitive[myprim[x_], {Red, Circle[{0, 0}, x]}]
In the last two cases you should guard against x
already having a value, e.g. with Block
or by using \[FormalX]
instead of x
Rectangle
is a function turning some parameters into a graphics object. Such a function for rounded rectangles can be found in this post: mathematica.stackexchange.com/questions/1882/… $\endgroup$Disk
orCircle
? $\endgroup$Graphics`Arrow`
orGraphics`Spline`
to see how they implemented primitives that were once not built-in. $\endgroup$Graphics
is inert, i.e. it has noDownValues
. It is only in the formatting end of things that it is turned into an image. The same applies to the primitives, likeRectangle
, but they are only formatted when found within aGraphics(3D)
object. So,Rectangle
remains aRectangle
andGeometricTransformation
can be applied to it. $\endgroup$