1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
|
% components.tex
%
% written 2022 by Werner Lemberg <wl@gnu.org>
% This file contains graphics used for the 'FreeType Design' documentation,
% part 1, 'Components and APIs'.
% Here is one possibility to convert this LaTeX file to both PNG and SVG
% formats.
%
% xelatex components.tex
%
% pdftoppm -png -f 1 -l 2 -r 120 components.pdf components
% optipng components-*.png
%
% for i in 1 2; do
% pdf2svg components.pdf components-$i.svg $i
% done
\documentclass[tikz,
svgnames, % for xcolor
border=3mm]{standalone}
\usepackage{libertinus}
\usetikzlibrary{
calc,
decorations.pathreplacing, % for "show path construction"
fit,
positioning,
shapes.geometric
}
% Node styles.
\tikzset{
% 'Elastic dashes' adapt spaces between dashes to the line length so that
% the last dash doesn't get cut off partially.
%
% Taken from https://github.com/pgf-tikz/pgf/issues/629
elastic dashes/.code args={on #1 off #2 ends #3}{%
% Use csname so catcode of @ doesn't have do be changed.
\csname tikz@addoption\endcsname{
\pgfgetpath\currentpath
\pgfprocessround{\currentpath}{\currentpath}
\csname pgf@decorate@parsesoftpath\endcsname
{\currentpath}{\currentpath}
%
\pgfmathparse{max(#1 - #3, 0)}
\let\dashphase=\pgfmathresult
\pgfmathparse{\csname pgf@decorate@totalpathlength\endcsname
- #1
+ 2 * \dashphase}
\let\rest=\pgfmathresult
\pgfmathparse{#1 + #2}
\let\onoff=\pgfmathresult
\pgfmathparse{max(floor(\rest / \onoff), 1)}
\let\nfullonoff=\pgfmathresult
\pgfmathparse{max((\rest - \onoff * \nfullonoff) / \nfullonoff + #2,
#2)}
\let\offexpand=\pgfmathresult
%
\pgfsetdash{{#1}{\offexpand}}{\dashphase pt}}
},
%
% Elastic dashes for boxes and the like.
elastic dashes per segment/.style args={on #1 off #2 ends #3}{
/utils/exec=\csname tikz@options\endcsname,
decoration={
show path construction,
lineto code={
\draw [elastic dashes=on #1 off #2 ends #3]
(\tikzinputsegmentfirst)
-- (\tikzinputsegmentlast);},
curveto code={
\draw [elastic dashes=on #1 off #2 ends #3]
(\tikzinputsegmentfirst)
.. controls (\tikzinputsegmentsupporta)
and (\tikzinputsegmentsupportb)
.. (\tikzinputsegmentlast);},
closepath code={
\draw [elastic dashes=on #1 off #2 ends #3]
(\tikzinputsegmentfirst)
-- (\tikzinputsegmentlast);}},
decorate},
%
% The distance between 'module' nodes.
node distance=0.3cm,
%
% For normal lines.
line/.style={
line width=1pt},
%
% For thin lines.
thin line/.style={
line width=0.5pt},
%
% For arrow lines.
arrow line/.style={
thin line,
-latex},
%
% For boxes in general.
box/.style={
line,
draw,
minimum height=1cm,
line cap=rect},
%
% For base components.
base box/.style={
box,
minimum width=1.5cm,
minimum height=0.5cm,
},
%
% For optional base components.
optional base box/.style={
base box,
elastic dashes per segment=on 3pt off 3pt ends 2pt
},
%
% For module boxes.
module box/.style={
box,
outer sep=0pt,
minimum width=1.8cm},
%
% For service boxes.
service box/.style={
thin line,
draw,
outer sep=0pt,
anchor=south west,
font=\tiny},
%
% Generic triangles.
triangle/.style={
thin line,
isosceles triangle,
isosceles triangle stretches,
inner sep=0pt,
minimum width=0.25cm,
minimum height=0.2cm,
draw},
%
% For triangles pointing upwards.
triangle up/.style={
triangle,
shape border rotate=90,
fill=#1},
%
% For triangles pointing downwards.
triangle down/.style={
triangle,
shape border rotate=-90,
fill=#1},
%
% For triangle descriptions.
triangle description/.style args={#1/#2}{
triangle down=#1,
label={[label position=south,
anchor=base west]:\ #2}},
%
% We use a 'matrix' as a means to get a pre-computed bounding box node of
% a group of nodes.
%
% In particular, we use matrices to center two rows of boxes both
% horizontally (i.e., to align the center the first row of boxes with the
% center of the second row).
container/.style={
matrix,
every outer matrix/.style={
inner sep=0pt,
outer sep=0pt}}
}
% Locations on top or bottom edges of boxes.
\def\pos#1#2{($ (#1 west) !#2! (#1 east) $)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{document}
% Basic library design.
\begin{tikzpicture}
\node[module box] (M1) {Module};
\foreach \x [remember=\x as \lastx (initially 1)] in {2, 3, 4}
\node[module box] (M\x) [right=of M\lastx] {Module};
\node[inner sep=0pt,
outer sep=0pt] (Mdots) [right=of M4] {\ldots};
\node[inner sep=0pt,
outer sep=0pt,
fit=(M1) (Mdots)] (Mboxes) {};
\node[box,
minimum width=3.2cm] (B) [above=1cm of Mboxes]
{Base Layer};
\node[box,
minimum width=6cm] (C) [above=1cm of B]
{Client Application};
\foreach \i/\x in {1/0.3, 2/0.4, 3/0.5, 4/0.6, 5/0.7}
\node[triangle down=Aqua] (Btop\i) at \pos{B.north}{\x} {};
\draw[arrow line] (C.south -| Btop2) -- (Btop2);
\foreach \i/\x in {1/0.25, 2/0.35, 2/0.45, 3/0.55}
\node[triangle up=Blue] (Bbottom\i) at \pos{B.south}{\x} {};
\draw[arrow line] (M2.north -| Bbottom1) -- (Bbottom1);
\node[triangle down=Fuchsia] (M2top) at \pos{M2.north}{0.6} {};
\draw[arrow line] (B.south -| M2top) -- (M2top);
\node[triangle description=Aqua/high-level API] (T1)
[right=1cm of B.north east] {};
\node[triangle description=Blue/base API] (T2) [below=2ex of T1] {};
\node[triangle description=Fuchsia/module API] (T3) [below=2ex of T2] {};
\end{tikzpicture}
% Detailed library design.
\begin{tikzpicture}
[node distance=0.5cm,
box/.append style={
minimum height=1.2cm},
module box/.append style={
text depth=0.4cm},
service box/.append style={
text depth=0.1cm}]
\node[container] (module boxes) {
\node[module box] (M1) {Module};
\foreach \x [remember=\x as \lastx (initially 1)] in {2, 3, 4}
\node[module box,
right=of M\lastx] (M\x) {Module};
\node[inner sep=0pt,
outer sep=0pt,
right=of M4] (Mdots) {\ldots};
\node[service box] (S1A) at (M1.south west) {Service};
\node[service box] (S1B) at (S1A.south east) {Service};
\node[service box] (S2A) at (M2.south west) {Service};
\node[service box] (S2B) at (S2A.south east) {Service};
\node[service box] (S4A) at (M4.south west) {Service};
\\
};
\node[container,
above=1cm of module boxes] (base boxes) {
\node[box,
minimum width=3.2cm] (B) {Base Layer};
\node[base box,
right=of B.north east,
anchor=north west] (FI) {ftinit};
\node[base box,
right=of B.south east,
anchor=south west] (FS) {ftsystem};
\node[optional base box,
left=of B] (FM) {ftmm};
\\
};
\node[optional base box,
above=0.6cm of B.north east,
anchor=south east] (FG) {ftglyph};
\coordinate[above=0.6cm of FG] (c);
\node[box,
minimum width=6cm,
anchor=south] (C) at (B |- c) {Client Application};
\node[triangle down=Aqua] (FMtop) at \pos{FM.north}{0.7} {};
\node[triangle down=Aqua] (FGtop) at \pos{FG.north}{0.5} {};
\node[triangle down=Aqua] (Btop1) at \pos{B.north}{0.2} {};
\node[triangle down=Aqua] (Btop2) at \pos{B.north}{0.3} {};
\node[triangle down=Aqua] (Btop3) at \pos{B.north}{0.7} {};
\node[triangle down=Blue] (Btop4) at \pos{B.north}{0.9} {};
\node[triangle up=Blue] (Bbottom1) at \pos{B.south}{0.25} {};
\node[triangle up=Blue] (Bbottom2) at \pos{B.south}{0.50} {};
\node[triangle up=Blue] (Bbottom3) at \pos{B.south}{0.75} {};
\node[triangle down=Aqua] (FItop) at \pos{FI.north}{0.2} {};
\node[triangle up=Blue] (FSbottom) at \pos{FS.south}{0.3} {};
\node[triangle down=Fuchsia] (M1top) at \pos{M1.north}{0.8} {};
\node[triangle down=Fuchsia] (M2top) at \pos{M2.north}{0.6} {};
\node[triangle down=Fuchsia] (M3top) at \pos{M3.north}{0.2} {};
\node[triangle down=Fuchsia] (M4top) at \pos{M4.north}{0.8} {};
\foreach \x in {S1A, S1B, S2A, S2B, S4A}
\node[triangle up=Gold] (\x bottom) at (\x.south) {};
\draw[arrow line] (C.south -| FMtop) -- (FMtop);
\draw[arrow line] (C.south -| Btop2) -- (Btop2);
\draw[arrow line] (FG.south -| Btop3) -- (Btop3);
\draw[arrow line] (FG.south -| Btop4) -- (Btop4);
\draw[arrow line] (M3.north -| Bbottom3) -- (Bbottom3);
\draw[arrow line] (C.south -| FGtop) -- (FGtop);
\draw[arrow line] (C.south -| FItop) -- (FItop);
\draw[arrow line] (M4.north -| FSbottom) -- (FSbottom);
\draw[arrow line] (FM.south -| M1top) -- (M1top);
\draw[arrow line] (B.south -| M2top) -- (M2top);
\draw[arrow line] \pos{M2.north}{0.9} -- +(0,0.4) -| (M3top);
\coordinate[below=0.6cm of S1Abottom] (m);
\coordinate (mm) at ($ (M2) !0.5! (M3) $);
\draw[thin line] (B.south -| mm) -- (m -| mm);
\draw[thin line] (S1Abottom |- m) -- (S4Abottom |- m);
\draw[arrow line] (S1Abottom |- m) -- (S1Abottom);
\draw[arrow line] (S2Abottom |- m) -- (S2Abottom);
\draw[arrow line] (S4Abottom |- m) -- (S4Abottom);
\draw[arrow line] (M3.south) -- +(0,-0.4) -| (S1Bbottom);
\node[triangle description=Aqua/high-level API,
right=1cm of FI.north east] (T1) {};
\node[triangle description=Blue/base API,
below=2ex of T1] (T2) {};
\node[triangle description=Fuchsia/module API,
below=2ex of T2] (T3) {};
\node[triangle description=Gold/service API,
below=2ex of T3] (T4) {};
\end{tikzpicture}
\end{document}
|