Is there a way to outline text?
Import text as a FilledCurve in graphics, using PDF as an intermediate format. Below are modified examples from Documentation Center:
text = First[First[ImportString[ExportString[Style["Hi", Italic, FontSize -> 24,
FontFamily -> "Times"], "PDF"], "PDF", "TextMode" -> "Outlines"]]];
Outline fonts using different edge and face forms:
Graphics[{EdgeForm[Directive[White, Thick]], Red, text},
Background -> Black, PlotRange -> {{-5, 25}, {-0, 20}}]
3D text effect:
Graphics[{EdgeForm[Opacity[0.5]], Table[{ColorData["TemperatureMap"][t],
Translate[text, 4 {-t, t}]}, {t, 0, 1, 1/10}]}, ImageSize -> Medium]
An important issue in the question seems to be that of speed. So as Sjoerd suggested, I wrote a solution that pre-outlines all the characters in a reasonable range of ASCII characters, and then does the replacements on an arbitrary string. The characters are stored in a table ascii
, and their graphic replacements in asciiGraphics
. I then define the replacement rule (rule
) which is part of the function makeText
:
ascii = CharacterRange[" ", "z"]
(*
==> {" ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", \
"+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", \
"9", ":", ";", "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", \
"G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", \
"U", "V", "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a", \
"b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", \
"p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}
*)
asciiGraphics =
First@ImportString[
ExportString[Style[#, FontFamily -> "Times", FontSize -> 44],
"PDF"], "TextOutlines" -> True] & /@ ascii;
rule = Dispatch[Thread[ascii -> asciiGraphics]];
Clear[makeText];
Options[makeText] = {"OutlineThickness" -> 1, "OutlineColor" -> White,
"Color" -> Red};
makeText[string_, OptionsPattern[]] :=
DisplayForm[
Row[Characters[string] /. rule] /.
FilledCurve[
x__] :> {EdgeForm[{AbsoluteThickness[
OptionValue["OutlineThickness"]],
OptionValue["OutlineColor"]}],
OptionValue["Color"],
FilledCurve[x]
}
]
The argument to makeText
is the string to be rendered as outlined text. The thickness of the outlines is specified by the option "OutlineThickness"
. The other two options are "OutlineColor"
and "Color"
(of the filled areas).
The following is a demo - you win the game by sliding the slider to the right...
Manipulate[
Style[Pane[
makeText["Player 1 has " <> ToString[Floor[p]] <> " points",
"OutlineThickness" -> .7], ImageSize -> 360],
Background -> Black,
Magnification -> 3
], {p, 0, 1000}]
Edit
In response to the question in the comment:
By using Dispatch
you can eke out a faster timing, and my focus was on getting fast execution. It won't matter much if you're dealing only with a short string. But if you're trying to translate a long text into outlined characters, the replacement is sped up when you first apply Dispatch
to the rule.
In version 10, we can bypass exporting to PDF and re-importing and can outline text directly using region discretization functions. This is shown in the documentation of BoundaryDiscretizeGraphics
.
reg = BoundaryDiscretizeGraphics[Text[Style["R", FontFamily -> "Cambria"]], _Text]
The region can then be converted back to graphics, and the FilledCurve
extracted.
WARNING: I just realized that the following line will often crash the kernel with 10.1.0 on OS X! Proceed with caution!
Cases[Normal@Show[reg], _FilledCurve, Infinity]
Normal
is for getting rid of GraphicsComplex
inside the resulting Graphics
object.
If there is a direct way to go from a BoundaryMeshRegion
to a FilledCurve
, without having to use Show
, please let me know!