Is it possible to control style of digits in Mathematica?
Asked Answered
D

3

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?

Dowser answered 13/9, 2011 at 15:48 Comment(6)
What do you mean by "oldstyle"? Why don't you just look for a font for which the digits are more appealing to you?Animality
@David see the link I inserted in the textMyca
@Sjoerd Thanks. That helps clarify things.Animality
I don't have time to test this, so I'm adding it in a comment only. Go to 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.Businesswoman
@Sjoerd you might be interested in it too, see aboveBusinesswoman
For 'oldstyle', how about this? Style[IntegerString[20165, "Roman"], FontFamily -> "Constantia", FontSize -> 100] :-)Escuage
C
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.

Chavannes answered 16/10, 2011 at 4:19 Comment(0)
M
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

Myca answered 13/9, 2011 at 21:28 Comment(3)
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.Dowser
Thank you @Sjoerd C. de Vries!Dowser
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.Myca
C
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.

Chavannes answered 16/10, 2011 at 4:19 Comment(0)
F
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.

Friedlander answered 14/9, 2011 at 10:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.