7

I want to use tikz to custom construct the following "steel" symbols:

steel symbol

With my poor tikz practice, I get the following MWE:

\documentclass{article} \usepackage{tikz} \newcommand*\steelA{\tikz[baseline=(char.south),yshift=.8ex]{% \draw[thick] node (char) {} ellipse[x radius=.25em,y radius=.45ex]; \draw (0,-.85ex) -- (0,.85ex); }}% \newcommand*\steelB{\tikz[baseline=(char.south),yshift=.8ex]{% \draw[thick] node (char) {} ellipse[x radius=.25em,y radius=.45ex]; \draw (0,-.85ex) -- (0,.85ex) (-.3em,-.85ex) -- (.3em,-.85ex); }}% \newcommand*\steelC{\tikz[baseline=(char.south),yshift=.8ex]{% \draw[thick] node (char) {} ellipse[x radius=.25em,y radius=.45ex]; \draw[xshift=-.1em] (0,-.85ex) -- (0,.85ex); \draw[xshift=.1em] (0,-.85ex) -- (0,.85ex); \draw (-.3em,-.85ex) -- (.3em,-.85ex); }}% \newcommand*\steelD{\tikz[baseline=(char.south),yshift=.8ex]{% \draw[thick] node (char) {} ellipse[x radius=.25em,y radius=.45ex]; \draw[xshift=-.1em] (0,-.85ex) -- (0,.85ex); \draw[xshift=.1em] (0,-.85ex) -- (0,.85ex); \draw (-.3em,-.85ex) -- (.3em,-.85ex) (-.3em,.85ex) -- (.3em,.85ex); }}% \begin{document} A\steelA B A\steelB B A\steelC B A\steelD B { \Huge% A\steelA B A\steelB B A\steelC B A\steelD B }% \end{document} 

the result

But there are some drawbacks:

  • poor method to handle the absolute distance(with some hard-encoded parameters(eg. .85ex))
  • the handle of baseline is not eleagnt, and not perfectly align: I want the top of the symbol EXACTLY the same height as A and B; and the bottom of the symbol the same depth as A and B
  • When I test the different fontsize, it seemed that the symbol's thickness is too thin, is that possible to automaticallly change the thickness? Or in other word, how to better turn a tikzpicture into a "text symbol"?

Sorry for (a little) mix three requirements together, but sepreate it into three questions seemed a bit inefficient.

Thanks in advance!


Edited with the symbol's information:

but I don't know anything about these symbols, so maybe this style does not really make sense

It comes from a standard file "GB 50010-2010"(I'm sorry for I can't provide the link here) at Page.22. The steel is graded into FOUR levels:

steel symbol standard

5
  • 2
    Instead of specifying the line width in an absolute unit (via thick) and the size of the symbol in a relative unit (ex and em), you could choose one of these. Commented Jun 13 at 11:55
  • 2
    First, make sure you set inner sep=0pt in any nodes. Note that the exact height of a character is font dependent, as opposed to \ht\strutbox. Commented Jun 13 at 12:36
  • 2
    OTOH, one can use \ht0 where \sbox0{A} to correctly give the height of A. Commented Jun 13 at 12:52
  • 1
    Unrelated, but slightly helpful: (1) check out the package tikzsymbols, (2) tex.stackexchange.com/a/736087/319072 Commented Jun 13 at 15:24
  • Thanks all the advice, and tikzsymbols seemed another choice! Commented Jun 14 at 16:25

2 Answers 2

11

You should make sure that you use font-related units such as em or ex (which you already do) to draw your symbols as these will scale with the font size. However, there are certain lengths that you just need to try out, such as the height of a capital letter or a digit (which can be different). These may vary across fonts. Of course, the weights of fonts are also very diverse. And then there are fonts that have less weight when printed in larger sizes. Taken together all this, it is probably challenging to create symbols that really fit a font.

As for aligning with the baseline you should make sure that the baseline of the symbols is (for example) at (0em,0em) (via clipping or setting the bounding box of the symbol). Then, if you use lines (and not rectangles) to draw the symbol, you need to shift up the line half of its width so that this part is not below the baseline. The same is true for a line that should fit the top of capital letters (or digits).

An l3draw variant to typeset "serif-style" symbols, but I don't know anything about these symbols, so maybe this style does not really make sense:

\documentclass{article} \usepackage{l3draw} \ExplSyntaxOn \NewDocumentCommand { \Steel } { m } { \draw_begin: \draw_path_rectangle:nn { 0em , 0em } { 0.7em , 0.667em } \draw_path_use_clear:n { clip } \draw_scope_begin: \draw_evenodd_rule: \draw_path_ellipse:nnn { 0.35em , 0.333em } { 0em , 0.2em } { 0.35em , 0em } \draw_path_ellipse:nnn { 0.35em , 0.333em } { 0em , 0.175em } { 0.25em , 0em } \draw_path_use_clear:n { fill } \draw_scope_end: \draw_linewidth:n { 0.175ex } \bool_lazy_any:nT { { \tl_if_eq_p:NN #1 a } { \tl_if_eq_p:NN #1 b } } { \draw_path_moveto:n { 0.35em , 0em } \draw_path_lineto:n { 0.35em , 0.667em } \draw_path_use_clear:n { stroke } } \bool_lazy_any:nT { { \tl_if_eq_p:NN #1 c } { \tl_if_eq_p:NN #1 d } } { \draw_path_moveto:n { 0.45em , 0em } \draw_path_lineto:n { 0.45em , 0.667em } \draw_path_moveto:n { 0.25em , 0em } \draw_path_lineto:n { 0.25em , 0.667em } \draw_path_use_clear:n { stroke } } \draw_linewidth:n { 0.075ex } \bool_lazy_any:nT { { \tl_if_eq_p:NN #1 b } { \tl_if_eq_p:NN #1 c } { \tl_if_eq_p:NN #1 d } } { \draw_path_moveto:n { 0.1em , 0em + 0.075ex / 2 } \draw_path_lineto:n { 0.6em , 0em + 0.075ex / 2 } \draw_path_use_clear:n { stroke } } \bool_lazy_any:nT { { \tl_if_eq_p:NN #1 d } } { \draw_path_moveto:n { 0.1em , 0.667em - 0.075ex / 2 } \draw_path_lineto:n { 0.6em , 0.667em - 0.075ex / 2 } \draw_path_use_clear:n { stroke } } \draw_end: } \ExplSyntaxOff \begin{document} 4\Steel{a}25 4\Steel{b}25 4\Steel{c}25 4\Steel{d}25 \end{document} 

output of above code


It is not trivial to match the right weights as these depend on the font used. Also, different font sizes of Computer Modern have different weights. The symbols above will scale according to the font size, but their weight will stay the same.

Note that letters and digits can have different heights depending on the font. Also, letters with roundings, such as O or C typically have a slight larger height (and also depths) than letters without, such as I. Even serifs or sharpish corners (think top of the A) can protrude a bit from the thought box surrounding each character and may add to the height (or depth). So, you need to be careful when choosing the character to get the height from and when choosing the tool for measuring this height. In TeX, you can get the height of, say, the capital letter I of the current font with \fontcharht\font`I (see: https://tex.stackexchange.com/a/275380/47927).

You could include a switch using \f@size (which returns the current font size as floating point number) to account for larger fonts with less weight:

\documentclass{article} \usepackage{l3draw} \ExplSyntaxOn \dim_new:N \l_explorer_steel_a_dim \dim_new:N \l_explorer_steel_b_dim \dim_new:N \l_explorer_steel_c_dim \makeatletter \NewDocumentCommand { \Steel } { m } { \dim_set:Nn \l_explorer_steel_c_dim { \fontcharht\font`I } \exp_args:No \fp_compare:nNnTF { \f@size } > { 20 } { \dim_set:Nn \l_explorer_steel_a_dim { 0.15ex } \dim_set:Nn \l_explorer_steel_b_dim { 0.05ex } } { \dim_set:Nn \l_explorer_steel_a_dim { 0.175ex } \dim_set:Nn \l_explorer_steel_b_dim { 0.075ex } } \draw_begin: \draw_path_rectangle:nn { 0em , 0em } { 0.7em , \l_explorer_steel_c_dim } \draw_path_use_clear:n { clip } \draw_scope_begin: \draw_evenodd_rule: \draw_path_ellipse:nnn { 0.35em , \l_explorer_steel_c_dim / 2 } { 0em , 0.2em } { 0.35em , 0em } \draw_path_ellipse:nnn { 0.35em , \l_explorer_steel_c_dim / 2 } { 0em , 0.175em } { 0.325em - \l_explorer_steel_a_dim * 0.75 , 0em } \draw_path_use_clear:n { fill } \draw_scope_end: \draw_linewidth:n { \l_explorer_steel_a_dim } \bool_lazy_any:nT { { \tl_if_eq_p:NN #1 a } { \tl_if_eq_p:NN #1 b } } { \draw_path_moveto:n { 0.35em , 0em } \draw_path_lineto:n { 0.35em , \l_explorer_steel_c_dim } \draw_path_use_clear:n { stroke } } \bool_lazy_any:nT { { \tl_if_eq_p:NN #1 c } { \tl_if_eq_p:NN #1 d } } { \draw_path_moveto:n { 0.45em , 0em } \draw_path_lineto:n { 0.45em , \l_explorer_steel_c_dim } \draw_path_moveto:n { 0.25em , 0em } \draw_path_lineto:n { 0.25em , \l_explorer_steel_c_dim } \draw_path_use_clear:n { stroke } } \draw_linewidth:n { \l_explorer_steel_b_dim } \bool_lazy_any:nT { { \tl_if_eq_p:NN #1 b } { \tl_if_eq_p:NN #1 c } { \tl_if_eq_p:NN #1 d } } { \draw_path_moveto:n { 0.1em , 0em + \l_explorer_steel_b_dim / 2 } \draw_path_lineto:n { 0.6em , 0em + \l_explorer_steel_b_dim / 2 } \draw_path_use_clear:n { stroke } } \bool_lazy_any:nT { { \tl_if_eq_p:NN #1 d } } { \draw_path_moveto:n { 0.1em , \l_explorer_steel_c_dim - \l_explorer_steel_b_dim / 2 } \draw_path_lineto:n { 0.6em , \l_explorer_steel_c_dim - \l_explorer_steel_b_dim / 2 } \draw_path_use_clear:n { stroke } } \draw_end: } \ExplSyntaxOff \makeatother \begin{document} \scriptsize 4\Steel{a}25 \normalsize 4\Steel{b}25 \Large 4\Steel{c}25 \Huge 4\Steel{d}25 \end{document} 

output of above code

The weight adjustment is probably hardly visible, but compare the output without the adjusted weights:

output of above code without weight adjustment


Your baseline approach when using TikZ is fine. But you should use coordinates or even just dimensions, not a node for alignment. You can just say baseline=0pt to shift the TikZ box vertically, so that (0,0) sits on the baseline of the surrounding text. You can refer to the current line width using \pgflinewidth in order to adjust the alignment if you want to use \draw. To have the line width scaled proportionally with the font size, use line width=.2ex or similar.

Do show the basics with TikZ, but only schematically:

\documentclass{article} \usepackage{tikz} \newlength{\mycharht} \NewDocumentCommand{\mycharA}{}{% \setlength{\mycharht}{\fontcharht\font`I}% \begin{tikzpicture}[baseline=0pt] \fill (0,0) rectangle (1em,\mycharht); \end{tikzpicture}% } \NewDocumentCommand{\mycharB}{}{% \setlength{\mycharht}{\fontcharht\font`I}% \begin{tikzpicture}[baseline=0pt] \draw[thick] (0,0.5\pgflinewidth) rectangle (1em,\mycharht-0.5\pgflinewidth); \end{tikzpicture}% } \begin{document} \scriptsize 4\mycharA\mycharB 25 \normalsize 4\mycharA\mycharB 15 \Large 4\mycharA\mycharB 15 \Huge 4\mycharA\mycharB 15 \end{document} 

output of above code

6
  • 3
    It is a bit tricky to match the right weight as this depends on the font used. Also, different font sizes of Computer Modern have different weights. Commented Jun 13 at 13:12
  • Excellent, I have spared some time in l3draw, and get the point of your two versions extraordinary solution. Thanks! Commented Jun 14 at 16:15
  • However, as the problem of baseline remains vague for me. You have mentioned that "make sure that the baseline of the symbols is (for example) at (0em,0em) (via clipping or setting the bounding box of the symbol)." and with \draw_path_rectangle:nn { 0em , 0em } { 0.7em , 0.667em } and \draw_path_use_clear:n { clip } as l3draw version, could u paraphase the pure tikz's version to determine the baseline with bounding box or clip(just simple example)?Should I use baseline option, or clip similar rectangle? Best wishes! Commented Jun 14 at 16:18
  • 1
    @Explorer Right, your baseline approach is fine. But you should use coordinates or even just dimensions, not a node for alignment. You can just say baseline=0pt to shift the TikZ box vertically, so that (0,0) sits on the baseline of the surrounding text. The node in your code has actually no real use. Clipping is also not needed then. (I could have used a similar approach actually, but since I also wanted to define the width, I opted for a clip.) Commented Jun 14 at 17:04
  • 1
    @Explorer I added a short TikZ snippet to my answer. I think with this, it better answers you original question now. Commented Jun 16 at 5:52
2

Even if you design your symbol relative to the current font size, the lines can still look to thin or thick if you switch to a different font family or series. To avoid this, you can use the BusyPanda and CleverPanda packages, which provide estimates for how heavy a font looks like.

BusyPanda:

\documentclass{article} \usepackage{tikz} \usepackage{BusyPanda} \newlength{\IHeight} \newlength{\stroke} \newcommand*\steelD{% \setlength{\IHeight}{\fontcharht\font`I}% \setlength{\stroke}{\BusyPanda{0.1}\IHeight}% \tikz[baseline=0pt,line width=\stroke]{% \draw (-0.125\IHeight,0) -- (-0.125\IHeight,\IHeight); \draw (0.125\IHeight,0) -- (0.125\IHeight,\IHeight); \draw (-0.4\IHeight,.5\stroke) -- (0.4\IHeight,.5\stroke); \draw (-0.4\IHeight,\IHeight-.5\stroke) -- (0.4\IHeight,\IHeight-.5\stroke); \draw (0,.5\IHeight) ellipse [x radius=0.32\IHeight, y radius=0.25*(\IHeight-\stroke)]; }% }% \begin{document} A\steelD B { \Huge% A\steelD B }% \bfseries A\steelD B \normalfont \fontfamily{qbk}\selectfont A\steelD B \end{document} 

enter image description here

CleverPanda:

\documentclass{article} \usepackage{tikz} \usepackage{CleverPanda} \newlength{\IHeight} \newlength{\stroke} \newcommand*\steelD{% \setlength{\IHeight}{\fontcharht\font`I}% \setlength{\stroke}{\CleverPanda{}}% \tikz[baseline=0pt,line width=\stroke]{% \draw (-0.125\IHeight,0) -- (-0.125\IHeight,\IHeight); \draw (0.125\IHeight,0) -- (0.125\IHeight,\IHeight); \draw (-0.4\IHeight,.5\stroke) -- (0.4\IHeight,.5\stroke); \draw (-0.4\IHeight,\IHeight-.5\stroke) -- (0.4\IHeight,\IHeight-.5\stroke); \draw (0,.5\IHeight) ellipse [x radius=0.32\IHeight, y radius=0.25*(\IHeight-\stroke)]; }% }% \begin{document} A\steelD B { \Huge% A\steelD B }% \bfseries A\steelD B \normalfont \fontfamily{qbk}\selectfont A\steelD B \end{document} 

enter image description here

4
  • So interesting of these two package's name, and powerful too! Commented Oct 10 at 11:25
  • 1
    @Explorer There so many existing packages with basically all font-related names I could think of, that I instead went with a black and white animal :) Commented Oct 10 at 11:28
  • Aha, I happened to be come from China, whose national treasure animal is panda, it's not only black and white, it's quite lovely😊. Commented Oct 10 at 11:32
  • 1
    @Explorer Here a red panda: \documentclass{standalone} \usepackage{tikzlings-pandas} \begin{document} \begin{tikzpicture} \panda[body=red] \end{tikzpicture} \end{document} :) Commented Oct 10 at 11:39

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.