9

I use the Constantia font (that came with Windows 7) for my book and would like to prepare graphics for this book using the same font in Mathematica. Problem is that that Constantia by default outputs oldstyle digits. I know that, e.g. in XeTeX, it is possible to control whether oldstyle or normal digits are used for output.

Is it possible to control style of digits in Mathematica?

Igor
  • 265
  • 1
  • 9
  • What do you mean by "oldstyle"? Why don't you just look for a font for which the digits are more appealing to you? – DavidC Sep 13 '11 at 20:43
  • @David see the link I inserted in the text – Sjoerd C. de Vries Sep 13 '11 at 21:20
  • @Sjoerd Thanks. That helps clarify things. – DavidC Sep 14 '11 at 07:58
  • I don't have time to test this, so I'm adding it in a comment only. Go to http://www.nbcs.rutgers.edu/~hedrick/typography/ and scroll to "Utility for producing SC and expert OpenType fonts". That program should hopefully let you produce a new, rearranged font from Constantia, including only lining figures. Let us know if it worked. – Szabolcs Sep 14 '11 at 09:40
  • @Sjoerd you might be interested in it too, see above – Szabolcs Sep 14 '11 at 09:53
  • For 'oldstyle', how about this? `Style[IntegerString[20165, "Roman"], FontFamily -> "Constantia", FontSize -> 100]` :-) – 681234 Sep 14 '11 at 12:39

3 Answers3

9

I think this is rather difficult. Constantia is directly usable in Mathematica:

Style["0123456789", FontFamily -> "Constantia", FontSize -> 100]

enter image description here

However, the font is specifically designed to be balanced this way. If you tweak sizes and positions of the letters using FontSize and AdjustmentBox you get this:

shift = {0, 0, 0, -1, -1, -1, 0.0, -1, 0.0, -1} 0.5;
s = 0.65;
sizeScale = {1, 1, 1, s, s, s, s, s, s, s, s};
Row[Table[
   AdjustmentBox[
    Style[num, FontFamily -> "Constantia", 
     FontSize -> 100 sizeScale[[num + 1]]], 
    BoxBaselineShift -> shift[[num + 1]]], {num, 0, 
    9}]
] // DisplayForm

enter image description here

You see the shifted and scaled letters have a different body weight. Font weight can be adjusted, but only very roughly. Usually you only have Plain and Bold styles. So you can get as close as this:

body = {Plain, Plain, Plain, Bold, Bold, Bold, Bold, Bold, Bold, Bold};
Row[Table[
   AdjustmentBox[
    Style[num, FontFamily -> "Constantia" , 
     FontWeight -> body[[num + 1]], 
     FontSize -> 100 sizeScale[[num + 1]]], 
    BoxBaselineShift -> shift[[num + 1]]], {num, 0, 
    9}]] // DisplayForm

enter image description here

Somewhat better, but still ugly. I assume a complete new design of the letters is necessary for this to work. Perhaps the normal letters can be found somewhere further on in the font table?


UPDATE

Found the alternative number set. They are at positions 8320 - 8329 in the font table. You should be able to switch them using a font utility.

Style[FromCharacterCode[Range[8320, 8329]],FontFamily -> "Constantia", FontSize -> 100]

enter image description here

Sjoerd C. de Vries
  • 16,122
  • 3
  • 42
  • 94
  • 1
    Thanks for the answer but, of course, this method will not work for axes ticks as they are generated automatically by such command as Plot, Plot3D, e.t.c. – Igor Sep 14 '11 at 09:46
  • Thank you @Sjoerd C. de Vries! – Igor Sep 15 '11 at 07:12
  • 1
    Thanks! Don't you think these normal numbers still don't look good? The 9 seems to be a bit too high and the 2 is a bit too wide for my tastes. – Sjoerd C. de Vries Sep 15 '11 at 07:59
3

For ticks, there is a workaround, but it requires a bit of programming. First, there is an auxiliary function.

getDigits[n_Integer] := IntegerDigits[n]
getDigits[0.] := {0}
getDigits[n_Real] := 
 With[{rd = RealDigits[n]}, 
  Join[Take[rd[[1]], rd[[2]]], {"."}, 
   Drop[rd[[1]], rd[[2]]] ] /. {".", z___} -> {0, ".", z} /. {a__,
    0 ..} -> {a} /. {a__, Repeated[0, {4, 150}],  q__} -> {a} /.
    {b__, "."} -> {b}] 
Attributes[getDigits] = Listable

getDigits[{14.3, 2, 274, 2345.67}]
  {{1, 4, ".", 3}, {2}, {2, 7, 4}, {2, 3, 4, 5, ".", 6, 7}} 

Then, a function like this:

ConstantiaTicks[a_?VectorQ, opts : OptionsPattern[Style]] := 
 Transpose@{a, 
   Style[#, FontFamily -> "Constantia", 
      Sequence @@ {opts}] & /@ (StringJoin /@ 
      Map[ToString[
         Style[Which[IntegerQ[#], 
           FromCharacterCode[# + 8320], # === ".", "."]]] &, 
   (getDigits[a]), {2}])}

Yields the following result: enter image description here

This can then be used in a FrameTicks or Ticks option. Of course it does mean specifying your ticks rather than letting Mathematica work out their values automatically. It also means taking the default tick length unless you want to have another argument to ConstantiaTicks that specifies that.

Verbeia
  • 4,400
  • 2
  • 23
  • 44
2

I'd grab FontForge. Newer versions (I seem to remember) have a deeply hidden menu option to apply a mapping and flatten it into the font, so you can select lnum (upper case numerals) and easily output a version of Constantia with the substitution of lining for old-style numerals already made, outside Mathematica. Alternatively, a bit less high-tech, in Font-forge you can just copy and paste in the lining or tabular numerals on top of the lower-case ones.

Font-forge doesn't look pretty, but cut it some slack, because it's actually very good and is highly handy for tweaking fonts around.

As an alternative solution, have you thought of exporting the data in Mathematica to a flat file and rendering it natively in your XeTeX with TikZ? That's the approach I usually use, and the output is indeed excellent.

Mr.Wizard
  • 24,179
  • 5
  • 44
  • 125
Nicholas Wilson
  • 9,435
  • 1
  • 41
  • 80