I am trying to place a curly brace within a plot such that the top/bottom of the curly brace line up with two horizontal lines in the plot:

I have not been able to find a way to make the curly brace have the right size without setting the size explicitly by hand. Insetting a Text object doesn't work as the font size is used to scale text, and guessing the right font size is a complete guessing game. I settled upon using "Pane" with the "ResizeToFit" ImageSizeAction set, however I am not sure how to then specify the Inset size or the ImageSize for pane to get the desired results.

Here is the code I am using to generate this plot. ImageSize being set to "5" is just a guess to get approximately the right size, but ideally I want the top/bottom of the curly brace to exactly line up with the two horizontal dashed lines:

Additionally, I would like to be able to scale the curly brace such that the original aspect ratio isn't maintained (i.e. the width of the curly brace will be a fixed value, but the height can vary). What is the best way to go about doing this?

You can place the graphic directly in place of the "{" character and it will scale nicely. The only issue is getting the character to look as high quality as the built in ones. I made my poor attempt using the "Bezier" setting from Heike's answer to this question.

Note: You will want to remove the ImageSize option from your Inset.

Here is an example using a larger brace than the one in your example as proof of concept that it scales up nicely.

Edit:

One can also use Rasterize on the character and with a little cropping achieve what you want as well.

I'd like to avoid rasterization, if possible. Perhaps if there's a way to vectorize font characters, that would be the ideal solution, as then the graphics can be scaled in a straight-forward way. There might be font issues when the graphic is exported if a font character is used.
–
GuillochonApr 17 '12 at 21:09

First, you don't have to use a Pane or even an Epilog to use it (the output of stretchText is already an Inset and can be put into a Graphics). Secondly, you can position whatever string you like very precisely by specifying its lower left corner as the second argument pos, and then its scale in the horizontal and vertical direction as the third argument scale. The scale is in the coordinates of the surrounding graphic by default. So if you want the text to be exactly 0.2 wide and 0.7 high in the coordinates of your actual plot, that's exactly what you enter as scale. No need for trial-and-error adjustments.

The scale can be entered as a single number (in which case it sets the text width and scales the height proportionally), or as a pair of numbers for independent scaling of width and height. The latter is really what makes stretchText different from normal text. The last (optional) argument in stretchText is the rotation angle away from the horizontal.

Here is an example that just combines a hyperbola plot with the dashed lines and the stretched { by using a simple Show statement. To make the stretching clearer, I made a movie of it. What really counts is inside the Table:

As this example shows, the positioning is pretty straightforward because stretchText takes care of rescaling the outlined characters (it could be a whole string, too) to the given parameters.

The essential ingredient in stretchText is the PDF export/import trick to produce FilledCurves, so it requires Mathematica 8. The ability to combine this annotation with Show means that it's easy to manipulate the output with Mathematica's graphics editor too, if needed.

Edit: note on outlining text

The reason why I convert text to outlines here is that text glyphs in a string can't be scaled by independent factors in the horizontal and vertical directions. You can only scale text proportionally, and that would make it impossible to get a stretched brace.

I decided to use "TextOutlines" -> True instead of "TextMode"->"Outlines" to get a FilledCurve representation of the glyphs. That's simply because the documentation gives it a more official status ("TextMode"->"Outlines" is used only in the examples for FilledCurve and JoinedCurve). But both of these options are in principle unnecessary because the PDF options for Import already list "TextOutlines" -> True as the default. Leaving the explicit option in is just a way to be safer in this application.

The point lists in the FilledCurve for the outlined glyphs are also used here to determine a reasonably close-cropped bounding box for the text. This is only approximate because I make no distinction between control and other points, but it is very simple and seems to work well in practice.

I've actually been doing it this way for a long time, see my web page. Too bad that "TextMode"->"Outline" only got introduced (fully) in version 8 - before that, one had to resort to more complicated work-arounds, e.g., using ghostscript; see here. That would still be a way to crearte similar functionality in older Mathematica versions...
–
JensApr 18 '12 at 2:40

Mathematica is a registered trademark of Wolfram Research, Inc. While the mark is used herein with the limited permission of Wolfram Research, Stack Exchange and this site disclaim all affiliation therewith.