]> git.donarmstrong.com Git - lilypond.git/blob - lily/freetype.cc
Web-ja: update introduction
[lilypond.git] / lily / freetype.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 2004--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
5
6   LilyPond is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10
11   LilyPond is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "freetype.hh"
21 #include "warn.hh"
22
23 #include FT_OUTLINE_H
24 #include FT_BBOX_H
25
26 FT_Library freetype2_library;
27
28 void
29 init_freetype ()
30 {
31   FT_Error errorcode = FT_Init_FreeType (&freetype2_library);
32   if (errorcode)
33     error ("cannot initialize FreeType");
34 }
35
36 Box
37 ly_FT_get_unscaled_indexed_char_dimensions (FT_Face const &face, size_t signed_idx)
38 {
39   FT_UInt idx = FT_UInt (signed_idx);
40   FT_Load_Glyph (face, idx, FT_LOAD_NO_SCALE);
41
42   FT_Glyph_Metrics m = face->glyph->metrics;
43   FT_Pos hb = m.horiBearingX;
44   FT_Pos vb = m.horiBearingY;
45
46   // is this viable for all grobs?
47   return Box (Interval (Real (hb), Real (hb + m.width)),
48               Interval (Real (vb - m.height), Real (vb)));
49 }
50
51 SCM
52 box_to_scheme_lines (Box b)
53 {
54   return scm_list_4 (scm_list_4 (scm_from_double (b[X_AXIS][LEFT]),
55                                  scm_from_double (b[Y_AXIS][DOWN]),
56                                  scm_from_double (b[X_AXIS][RIGHT]),
57                                  scm_from_double (b[Y_AXIS][DOWN])),
58                      scm_list_4 (scm_from_double (b[X_AXIS][RIGHT]),
59                                  scm_from_double (b[Y_AXIS][DOWN]),
60                                  scm_from_double (b[X_AXIS][RIGHT]),
61                                  scm_from_double (b[Y_AXIS][UP])),
62                      scm_list_4 (scm_from_double (b[X_AXIS][RIGHT]),
63                                  scm_from_double (b[Y_AXIS][UP]),
64                                  scm_from_double (b[X_AXIS][LEFT]),
65                                  scm_from_double (b[Y_AXIS][UP])),
66                      scm_list_4 (scm_from_double (b[X_AXIS][LEFT]),
67                                  scm_from_double (b[Y_AXIS][UP]),
68                                  scm_from_double (b[X_AXIS][LEFT]),
69                                  scm_from_double (b[Y_AXIS][DOWN])));
70 }
71
72 Box
73 ly_FT_get_glyph_outline_bbox (FT_Face const &face, size_t signed_idx)
74 {
75   FT_UInt idx = FT_UInt (signed_idx);
76   FT_Load_Glyph (face, idx, FT_LOAD_NO_SCALE);
77
78   if (!(face->glyph->format == FT_GLYPH_FORMAT_OUTLINE))
79     {
80 #if 0
81       // will generate a lot of warnings
82       warning ("Cannot make glyph outline");
83 #endif
84       return Box (Interval (infinity_f, -infinity_f), Interval (infinity_f, -infinity_f));
85     }
86   FT_Outline *outline;
87   outline = &(face->glyph->outline);
88
89   FT_BBox bbox;
90   FT_Outline_Get_BBox (outline, &bbox);
91
92   return Box (Interval (bbox.xMin, bbox.xMax), Interval (bbox.yMin, bbox.yMax));
93 }
94
95 SCM
96 ly_FT_get_glyph_outline (FT_Face const &face, size_t signed_idx)
97 {
98   FT_UInt idx = FT_UInt (signed_idx);
99   FT_Load_Glyph (face, idx, FT_LOAD_NO_SCALE);
100
101   if (!(face->glyph->format == FT_GLYPH_FORMAT_OUTLINE))
102     {
103 #if 0
104       // will generate a lot of warnings
105       warning ("Cannot make glyph outline");
106 #endif
107       return box_to_scheme_lines (ly_FT_get_unscaled_indexed_char_dimensions (face, signed_idx));
108     }
109
110   FT_Outline *outline;
111   outline = &(face->glyph->outline);
112   SCM out = SCM_EOL;
113   Offset lastpos;
114   Offset firstpos;
115   int j = 0;
116   while (j < outline->n_points)
117     {
118       if (j == 0)
119         {
120           firstpos = Offset (outline->points[j].x, outline->points[j].y);
121           lastpos = firstpos;
122           j++;
123         }
124       else if (outline->tags[j] & 1)
125         {
126           // it is a line
127           out = scm_cons (scm_list_4 (scm_from_double (lastpos[X_AXIS]),
128                                       scm_from_double (lastpos[Y_AXIS]),
129                                       scm_from_double (outline->points[j].x),
130                                       scm_from_double (outline->points[j].y)),
131                           out);
132           lastpos = Offset (outline->points[j].x, outline->points[j].y);
133           j++;
134         }
135       else if (outline->tags[j] & 2)
136         {
137           // it is a third order bezier
138           out = scm_cons (scm_list_n (scm_from_double (lastpos[X_AXIS]),
139                                       scm_from_double (lastpos[Y_AXIS]),
140                                       scm_from_double (outline->points[j].x),
141                                       scm_from_double (outline->points[j].y),
142                                       scm_from_double (outline->points[j + 1].x),
143                                       scm_from_double (outline->points[j + 1].y),
144                                       scm_from_double (outline->points[j + 2].x),
145                                       scm_from_double (outline->points[j + 2].y),
146                                       SCM_UNDEFINED),
147                           out);
148           lastpos = Offset (outline->points[j + 2].x, outline->points[j + 2].y);
149           j += 3;
150         }
151       else
152         {
153           // it is a second order bezier
154           Real x0 = lastpos[X_AXIS];
155           Real x1 = outline->points[j].x;
156           Real x2 = outline->points[j + 1].x;
157
158           Real y0 = lastpos[Y_AXIS];
159           Real y1 = outline->points[j].y;
160           Real y2 = outline->points[j + 1].y;
161
162           out = scm_cons (scm_list_n (scm_from_double (x0),
163                                       scm_from_double (y0),
164                                       scm_from_double ((x0 + 2*x1)/3),
165                                       scm_from_double ((y0 + 2*y1)/3),
166                                       scm_from_double ((2*x1 + x2)/3),
167                                       scm_from_double ((2*y1 + y2)/3),
168                                       scm_from_double (x2),
169                                       scm_from_double (y2),
170                                       SCM_UNDEFINED),
171                           out);
172           lastpos = Offset (outline->points[j + 1].x, outline->points[j + 1].y);
173           j += 2;
174         }
175     }
176
177   // just in case, close the figure
178   out = scm_cons (scm_list_4 (scm_from_double (lastpos[X_AXIS]),
179                               scm_from_double (lastpos[Y_AXIS]),
180                               scm_from_double (firstpos[X_AXIS]),
181                               scm_from_double (firstpos[Y_AXIS])),
182                   out);
183
184   out = scm_reverse_x (out, SCM_EOL);
185   return out;
186 }